Skip to content

Fix enum private names (__x) incorrectly marked as final#20832

Open
Fridayai700 wants to merge 2 commits intopython:masterfrom
Fridayai700:fix-enum-private-not-final
Open

Fix enum private names (__x) incorrectly marked as final#20832
Fridayai700 wants to merge 2 commits intopython:masterfrom
Fridayai700:fix-enum-private-not-final

Conversation

@Fridayai700
Copy link

Summary

Since Python 3.11, private names (names starting with __ but not ending with __, like __config) are not enum members and should not be treated as final. Currently, mypy incorrectly marks them as final, causing false positives.

Before:

from enum import Enum

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

MyEnum._MyEnum__config = "other_value"  # error: Cannot assign to final attribute "__config"

After: No error — private names are not enum members and can be reassigned.

Root cause

In semanal.py, the check for non-final enum names used is_dunder() which only matches __x__ (dunder names). Private names like __config were missed.

Meanwhile, TypeInfo.enum_members in nodes.py already correctly used name.startswith("__") to exclude both dunders AND private names from the member list. This created an inconsistency: __config was not listed as a member but was still treated as final.

Fix

Changed the finality check to use name.startswith("__"), matching the existing enum_members logic. This ensures consistency between member detection and finality marking.

Test plan

  • Added testEnumPrivateNameNotFinal test case
  • All 180 existing enum tests pass
  • python -m pytest mypy/test/testcheck.py -k Enum -o "addopts=" — all pass

Fixes #20789

Fridayai700 and others added 2 commits February 17, 2026 13:19
Since Python 3.11, private names (names starting with double underscore
but not ending with it, like `__config`) are not enum members and
should not be treated as final.

The semantic analyzer was using `is_dunder()` to skip only dunder names
(`__x__`), missing private names (`__x`). This caused false positives
like "Cannot assign to final attribute" when reassigning private
attributes on an enum.

The fix uses `name.startswith("__")` which matches the logic already
used by `TypeInfo.enum_members` in nodes.py, ensuring consistency
between member detection and finality marking.

Fixes python#20789
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.

Private members (_underscored) in an Enum are incorrectly considered members of the enum

1 participant

Comments