-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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 the PSF 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 follow the steps outlined in the CPython devguide to rectify this issue. When your account is ready, please add a comment in this pull request Thanks again for your contribution, we look forward to reviewing it! |
CLA is signed and pending. |
Due to a Python bug/missing feature. Until python/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
Due to a Python bug/missing feature. Until python/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
I don't think this is backwards-compatible- users might create an enum to refer to types deliberately: class MyTypes(Enum):
i = int
f = float
s = 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. |
Perhaps the check should be for classes actually declared within the enum, using |
5269f82
to
8c25ee3
Compare
@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__(). | ||
for key, member in classdict.items(): | ||
if isinstance(member, type): | ||
if member.__qualname__.startswith(enum_class_qualname): |
There was a problem hiding this comment.
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):
pass
class MyEnum(Enum):
oops = MyEnumInner
Should be .startswith(enum_class_qualname + '.')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again - just fixed.
@ethanfurman Were you able to find a moment to look further into this PR? Thanks again in advance. |
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 an For example:
would result in For those times when one does not want a class as a member, it's easy enough to write an |
Due to a Python bug/missing feature. Until python/cpython#7950 is merged (and Python 3.8) becomes widespread we'll have to avoid nested Enum classes.
Edward, thanks for your work. I decided to go a different route where the work is done in I'm closing this PR, but if you are up for a challenge I need a new PR that:
|
@ethanfurman |
@edwardcwang Hey, I'm adding you to the ACKS file as "Edward C Wang" -- let me know if that should be something different. |
"Edward Wang" would actually be fine too! |
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 class
Outer.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:
Demonstration of bug:
https://bugs.python.org/issue33976