Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@
)
from mypy.types_utils import is_invalid_recursive_alias, store_argument_type
from mypy.typevars import fill_typevars
from mypy.util import correct_relative_import, is_dunder, module_prefix, unmangle, unnamed_function
from mypy.util import correct_relative_import, module_prefix, unmangle, unnamed_function
from mypy.visitor import NodeVisitor

T = TypeVar("T")
Expand Down Expand Up @@ -3841,9 +3841,13 @@ def store_final_status(self, s: AssignmentStmt) -> None:
and isinstance(cur_node.node, Var)
and not (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)
):
# Double underscored members are writable on an `Enum`.
# Double underscored names are writable on an `Enum`:
# - Dunders (__x__) are not enum members
# - Private names (__x) are not enum members (since Python 3.11)
# (Except read-only `__members__` but that is handled in type checker)
cur_node.node.is_final = s.is_final_def = not is_dunder(cur_node.node.name)
cur_node.node.is_final = s.is_final_def = (
not cur_node.node.name.startswith("__")
)

# Special case: deferred initialization of a final attribute in __init__.
# In this case we just pretend this is a valid final definition to suppress
Expand Down
14 changes: 14 additions & 0 deletions test-data/unit/check-enum.test
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,20 @@ Medal.silver = 2 # E: Cannot assign to final attribute "silver"
[builtins fixtures/enum.pyi]


[case testEnumPrivateNameNotFinal]
# Private names (__x) are not enum members and should not be final
from enum import Enum

class MyEnum(Enum):
__config = "some_value"
A = 1
B = 2

# __config is not a member so reassignment should be allowed
MyEnum._MyEnum__config = "other_value"
[builtins fixtures/enum.pyi]


[case testEnumFinalValuesCannotRedefineValueProp]
from enum import Enum
class Types(Enum):
Expand Down