Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

bpo-33976: support nested classes in Enum#7950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed

Conversation

@edwardcwang
Copy link

@edwardcwangedwardcwang commentedJun 27, 2018
edited
Loading

Methods defined in Enums behave 'normally' but classes defined in Enums get mistaken for regular values and can't be used as classes out of the box. In the example code below, the nested classOuter.Inner gets mistakenly identified as an Enum value. This PR changes it so that nested classes are treated in the same way as methods, fixing this bug.

Sample code:

fromenumimportEnumclassOuter(Enum):a=1b=2classInner(Enum):foo=10bar=11

Demonstration of bug:

>>> type(Outer)<class 'enum.EnumMeta'>>>> type(Outer.Inner)<enum 'Outer'>>>> print(Outer.Inner.foo)Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: 'Outer' object has no attribute 'foo'>>>

https://bugs.python.org/issue33976

@the-knights-who-say-ni

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed thePSF contributor agreement (CLA).

Unfortunately our records indicate you have not signed the CLA. For legal reasons we need you to sign this before we can look at your contribution. Please followthe steps outlined in the CPython devguide to rectify this issue.

When your account is ready, please add a comment in this pull request
and a Python core developer will remove theCLA not signed label
to make the bot check again.

Thanks again for your contribution, we look forward to reviewing it!

@edwardcwang
Copy link
Author

edwardcwang commentedJun 27, 2018
edited
Loading

CLA is signed and pending.

@ethanfurmanethanfurman self-assigned thisJun 27, 2018
edwardcwang added a commit to ucb-bar/hammer that referenced this pull requestJun 27, 2018
Due to a Python bug/missing feature. Untilpython/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
edwardcwang added a commit to ucb-bar/hammer that referenced this pull requestJun 27, 2018
Due to a Python bug/missing feature. Untilpython/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
@eric-wieser
Copy link
Contributor

eric-wieser commentedJun 28, 2018
edited
Loading

I don't think this is backwards-compatible- users might create an enum to refer to types deliberately:

classMyTypes(Enum):i=intf=floats=str
>>>MyTypes.i<MyTypes.i:<class'int'>>>>>MyTypes.i.value<class'int'>

This is perhaps a little strange, but I don't think your use case is any less strange, and status quo wins.

@eric-wieser
Copy link
Contributor

Perhaps the check should be for classes actually declared within the enum, using__qual_name__

@edwardcwang
Copy link
Author

@eric-wieser Thanks for the catch. Added a unit test for your example and updated the PR to fix it.

Lib/enum.py Outdated
# accessible in _EnumDict.__setitem__().
forkey,memberinclassdict.items():
ifisinstance(member,type):
ifmember.__qualname__.startswith(enum_class_qualname):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This catches

class MyEnumInner(object):    passclass MyEnum(Enum):    oops = MyEnumInner

Should be.startswith(enum_class_qualname + '.')

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks again - just fixed.

@edwardcwang
Copy link
Author

@ethanfurman Were you able to find a moment to look further into this PR? Thanks again in advance.

@ethanfurman
Copy link
Member

I have been thinking about it. At this point I'm still not sure how I want to resolve the issue. I'm thinking about having embedded/referenced classes be part of anEnum value, but also be directly callable.

For example:

MyTypes.i()

would result in0.

For those times when one does not want a class as a member, it's easy enough to write an@skip decorater -- in fact, one is included inaenum.

edwardcwang added a commit to ucb-bar/hammer that referenced this pull requestFeb 7, 2019
Due to a Python bug/missing feature. Untilpython/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
@ethanfurman
Copy link
Member

Edward, thanks for your work. I decided to go a different route where the work is done in_EnumDict instead (which you can find in myaenum project).

I'm closing this PR, but if you are up for a challenge I need a new PR that:

  • adds an@member decorator to force an object to become a member
  • adds an@nonmember decorator to protect an object from becoming a member
  • adds the_is_class() utility for deciding if an object is a class
  • updatesEnumMeta to forward the class name to_EnumDict, and_EnumDict to store and forward the class name to_is_class()
  • issues aDeprecationWarning when a bare class is present in anEnum, and still convert it to a member (warning should mention coming change in behavior, and the@member decorator to maintain the current behavior)

@dignissimus
Copy link
Contributor

Edward, thanks for your work. I decided to go a different route where the work is done in_EnumDict instead (which you can find in myaenum project).

I'm closing this PR, but if you are up for a challenge I need a new PR that:

  • adds an@member decorator to force an object to become a member

  • adds an@nonmember decorator to protect an object from becoming a member

  • adds the_is_class() utility for deciding if an object is a class

  • updatesEnumMeta to forward the class name to_EnumDict, and_EnumDict to store and forward the class name to_is_class()

  • issues aDeprecationWarning when a bare class is present in anEnum, and still convert it to a member (warning should mention coming change in behavior, and the@member decorator to maintain the current behavior)

@ethanfurman
Are these changes still required?

@ethanfurman
Copy link
Member

@edwardcwang Hey, I'm adding you to the ACKS file as "Edward C Wang" -- let me know if that should be something different.

@edwardcwang
Copy link
Author

"Edward Wang" would actually be fine too!

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

1 more reviewer

@eric-wiesereric-wiesereric-wieser left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

@ethanfurmanethanfurman

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

7 participants

@edwardcwang@the-knights-who-say-ni@eric-wieser@ethanfurman@dignissimus@methane@bedevere-bot

[8]ページ先頭

©2009-2025 Movatter.jp