Skip to content

Commit 1a04c07

Browse files
authored
Sync enum members logic in typeanal and checkmember (#19687)
Fixes #19686. Fixes #15540. Fixes #14600.
1 parent d95531d commit 1a04c07

3 files changed

Lines changed: 53 additions & 5 deletions

File tree

mypy/checkmember.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,9 +1349,6 @@ def analyze_enum_class_attribute_access(
13491349
# Skip these since Enum will remove it
13501350
if name in EXCLUDED_ENUM_ATTRIBUTES:
13511351
return report_missing_attribute(mx.original_type, itype, name, mx)
1352-
# Dunders and private names are not Enum members
1353-
if name.startswith("__") and name.replace("_", "") != "":
1354-
return None
13551352

13561353
node = itype.type.get(name)
13571354
if node and node.type:
@@ -1364,6 +1361,9 @@ def analyze_enum_class_attribute_access(
13641361
):
13651362
return proper.args[0]
13661363

1364+
if name not in itype.type.enum_members:
1365+
return None
1366+
13671367
enum_literal = LiteralType(name, fallback=itype)
13681368
return itype.copy_modified(last_known_value=enum_literal)
13691369

mypy/typeanal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ def analyze_unbound_type_without_type_info(
988988
isinstance(sym.node, Var)
989989
and sym.node.info
990990
and sym.node.info.is_enum
991-
and not sym.node.name.startswith("__")
991+
and sym.node.name in sym.node.info.enum_members
992992
):
993993
value = sym.node.name
994994
base_enum_short_name = sym.node.info.name

test-data/unit/check-enum.test

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ class F(Generic[T], Enum): # E: Enum class cannot be generic
457457
x: T
458458
y: T
459459

460-
reveal_type(F[int].x) # N: Revealed type is "__main__.F[builtins.int]"
460+
reveal_type(F[int].x) # E: Access to generic instance variables via class is ambiguous \
461+
# N: Revealed type is "builtins.int"
461462
[builtins fixtures/enum.pyi]
462463

463464
[case testEnumFlag]
@@ -1421,6 +1422,53 @@ class Comparator(enum.Enum):
14211422
reveal_type(Comparator.__foo__) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
14221423
[builtins fixtures/dict.pyi]
14231424

1425+
[case testEnumClassAttributeUnannotated]
1426+
import enum
1427+
from typing import ClassVar, Literal
1428+
1429+
class MyEnum(enum.Enum):
1430+
foo: ClassVar[str]
1431+
bar: str
1432+
1433+
VALUE_A = 1
1434+
VALUE_B = 2
1435+
1436+
reveal_type(MyEnum.foo) # N: Revealed type is "builtins.str"
1437+
reveal_type(MyEnum.bar) # N: Revealed type is "builtins.str"
1438+
x: Literal[MyEnum.foo] # E: Parameter 1 of Literal[...] is invalid
1439+
y: Literal[MyEnum.bar] # E: Parameter 1 of Literal[...] is invalid
1440+
[builtins fixtures/enum.pyi]
1441+
1442+
[case testEnumAttributesInheritedFromMixin]
1443+
from enum import Enum
1444+
from typing import TYPE_CHECKING, ClassVar, Final, Literal
1445+
1446+
class A:
1447+
var1 = 1
1448+
var2: ClassVar[str]
1449+
var3: Final[int] = 3
1450+
var4: str
1451+
1452+
class E(A, Enum):
1453+
mem = 1
1454+
1455+
reveal_type(E.var1) # N: Revealed type is "builtins.int"
1456+
reveal_type(E.var2) # N: Revealed type is "builtins.str"
1457+
reveal_type(E.var3) # N: Revealed type is "builtins.int"
1458+
reveal_type(E.var4) # N: Revealed type is "builtins.str"
1459+
reveal_type(E.mem) # N: Revealed type is "Literal[__main__.E.mem]?"
1460+
1461+
E.var1.value # E: "int" has no attribute "value"
1462+
E.var2.name # E: "str" has no attribute "name"
1463+
E.mem.name
1464+
1465+
x1: Literal[E.var1] # E: Parameter 1 of Literal[...] is invalid
1466+
x2: Literal[E.var2] # E: Parameter 1 of Literal[...] is invalid
1467+
x3: Literal[E.var3] # E: Parameter 1 of Literal[...] is invalid
1468+
x4: Literal[E.var4] # E: Parameter 1 of Literal[...] is invalid
1469+
m: Literal[E.mem]
1470+
[builtins fixtures/enum.pyi]
1471+
14241472
[case testEnumWithInstanceAttributes]
14251473
from enum import Enum
14261474
class Foo(Enum):

0 commit comments

Comments
 (0)