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

Enum private attributes are not enum members #17182

Merged
merged 3 commits into from
Apr 27, 2024

Conversation

hamdanal
Copy link
Collaborator

Fixes #17098

This comment has been minimized.

@@ -1139,8 +1139,8 @@ def analyze_enum_class_attribute_access(
# Skip these since Enum will remove it
if name in ENUM_REMOVED_PROPS:
return report_missing_attribute(mx.original_type, itype, name, mx)
# For other names surrendered by underscores, we don't make them Enum members
if name.startswith("__") and name.endswith("__") and name.replace("_", "") != "":
# Dunders and private names are not Enum members
Copy link
Member

Choose a reason for hiding this comment

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

nit: I would call any name that starts with a single underscore a "private" (by convention) name, and any name that starts with two underscores a "mangled" name

Suggested change
# Dunders and private names are not Enum members
# Dunders and mangled names are not Enum members

(There's several other places in this PR where you also refer to them as "private" names; I'd change those too, personally)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I used the same terminology used by the enum docs: https://docs.python.org/3/howto/enum.html#private-names

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough... though I sorta think the docs there are using the wrong terminology... but hey :P

B = 2
__my_dict = {A: "ham", B: "spam"}

x: MyEnum = MyEnum.__my_dict # E: Incompatible types in assignment (expression has type "Dict[int, str]", variable has type "MyEnum")
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I'm not sure this is correct? The name is mangled at runtime, so this attempted attribute access fails with an exception unless you use the mangled name:

>>> from enum import Enum
>>> class Foo(Enum):
...     __x = 'y'
...     y = 'z'
... 
>>> Foo.__x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '__x'
>>> Foo._Foo__x
'y'

This PR definitely improves the handling of mangled names in enum class namespaces, but really mypy should be warning that MyEnum has no attribute __my_dict here (it has a _MyEnum__my_dict attribute instead). I think that's at least worth a comment, if it's not an easy fix.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, I'm not sure this is correct?

It isn't :D, but mypy doesn't understand name mangling yet and it is out of scope here. You are right however, there should be a comment.

Copy link
Member

Choose a reason for hiding this comment

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

oof, we don't understand name mangling in any context? 😬

You are right however, there should be a comment.

Thanks!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh and a PR #16715

This comment has been minimized.

Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

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

Thanks!

@hauntsaninja hauntsaninja merged commit ba6febc into python:master Apr 27, 2024
18 checks passed
@hamdanal hamdanal deleted the enum-private-attr branch April 27, 2024 22:02
terencehonles added a commit to terencehonles/mypy that referenced this pull request May 2, 2024
This adds on to the change in python#17182
and fixes enum attributes being used as members.
terencehonles added a commit to terencehonles/mypy that referenced this pull request Jun 5, 2024
This adds on to the change in python#17182
and fixes enum attributes being used as members.
hauntsaninja added a commit that referenced this pull request Oct 29, 2024
This adds on to the change in #17182
and fixes enum attributes being used as members.

Fixes: #16730

---------

Co-authored-by: Jelle Zijlstra <[email protected]>
Co-authored-by: Ali Hamdan <[email protected]>
Co-authored-by: hauntsaninja <[email protected]>
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.

An enum attribute with a private (mangled) name should not be considered an enum member
3 participants