Skip to content
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

Fix enum attributes are not members #17207

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

terencehonles
Copy link
Contributor

This adds on to the change in #17182 and fixes enum attributes being used as members.

@hamdanal / @hauntsaninja I noticed there was the function get_enum_values in mypy types and instead of adding more to the case in try_expanding_sum_type_to_union it seemed like it might make sense to move the changes from #17182 there. I don't think the other code touched in that PR can use get_enum_values.

@terencehonles terencehonles force-pushed the fix-enum-with-property-match-exhaustion branch from f319685 to ba435ac Compare May 2, 2024 15:21

This comment has been minimized.

isinstance(sym.node, mypy.nodes.Var)
and name not in ENUM_REMOVED_PROPS
and not name.startswith("__")
and sym.node.has_explicit_value
Copy link
Collaborator

Choose a reason for hiding this comment

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

This last condition changes the behavior of mypy which currently considers unassigned but annotated attributes as members of the enum.
I would say the new behavior is better but it must be noted in the PR title or description that this is a breaking change that must be considered on its own.
Looking at the mypy primer output, it looks like members of enums constructed using the enum call syntax do not have the has_explicit_value set which breaks type narrowing. I suggest changing the variable here to also set this flag perhaps with a comment explaining the reason -- something like "E = Enum("E", "A") is equivalent to class E(Enum): A = auto()"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for noticing that, I've not really used them in that form, but hopefully the comment is not too wordy. I only glanced at the code that you pointed to, but I was cross referencing https://github.com/python/cpython/blob/7528b84e947f727734bd802356e380673553387d/Lib/enum.py#L828-L839 and how much of this is implemented by mypy? 🤔

This comment has been minimized.

@terencehonles
Copy link
Contributor Author

It looks like this is actually related to the ongoing discussion python/typing-council#11

Copy link
Collaborator

@hamdanal hamdanal left a comment

Choose a reason for hiding this comment

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

Thank you @terencehonles.
The typing spec change has been accepted and this PR looks good to me.

Regarding the mypy primer diff, it is related to the linked typing spec change that requires assignment for enum attributes for them to be considered members of the enumeration and the fact that tanjun vendors an old copy of the stdlib inspect module and stub that relies on the old behavior. So the new errors are expected.

def __new__(cls, value: int): pass

class Medal(int, Enum):
prize: str
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a test case with a class attribute with an assigned value, e.g., prize: str = "nothing"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup, should be able to tomorrow

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about this a bit, and this is either a request for a nonmember(...) test, which is currently not supported, or an enum like the one above. I've added a test for nonmember that's been marked as expected to fail: https://github.com/python/mypy/pull/17207/files#diff-4f8d4b202949b4cf2221e3295fbbd1774e152e44b141880981895c349599e927R1-R36

Let me know if that's what you wanted, and/or if we should keep that

This adds on to the change in python#17182
and fixes enum attributes being used as members.
@terencehonles terencehonles force-pushed the fix-enum-with-property-match-exhaustion branch from 5383c49 to dfcc0c4 Compare June 5, 2024 13:55
Copy link
Contributor

github-actions bot commented Jun 5, 2024

Diff from mypy_primer, showing the effect of this PR on open source code:

Tanjun (https://github.com/FasterSpeeding/Tanjun)
+ tanjun/_internal/__init__.py:189: error: Statement is unreachable  [unreachable]
+ tanjun/annotations.py:2646: error: Statement is unreachable  [unreachable]

@JelleZijlstra JelleZijlstra self-requested a review June 5, 2024 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants