Skip to content

Commit f0c5e37

Browse files
committed
Properly account for member and nonmember in TypeInfo.enum_members
1 parent 42e005c commit f0c5e37

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

mypy/nodes.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,10 +3235,20 @@ def enum_members(self) -> list[str]:
32353235
name
32363236
for name, sym in self.names.items()
32373237
if (
3238-
isinstance(sym.node, Var)
3239-
and name not in EXCLUDED_ENUM_ATTRIBUTES
3240-
and not name.startswith("__")
3241-
and sym.node.has_explicit_value
3238+
(
3239+
isinstance(sym.node, Var)
3240+
and name not in EXCLUDED_ENUM_ATTRIBUTES
3241+
and not name.startswith("__")
3242+
and sym.node.has_explicit_value
3243+
and not (isinstance(typ := mypy.types.get_proper_type(sym.node.type), mypy.types.Instance) and typ.type.fullname == "enum.nonmember")
3244+
) or (
3245+
isinstance(sym.node, Decorator)
3246+
and any(
3247+
dec.fullname == "enum.member"
3248+
for dec in sym.node.decorators
3249+
if isinstance(dec, RefExpr)
3250+
)
3251+
)
32423252
)
32433253
]
32443254

mypy/typeops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ class Status(Enum):
955955
FAILURE = 2
956956
UNKNOWN = 3
957957
958-
...and if we call `try_expanding_enum_to_union(Union[Color, Status], 'module.Color')`,
958+
...and if we call `try_expanding_sum_type_to_union(Union[Color, Status], 'module.Color')`,
959959
this function will return Literal[Color.RED, Color.BLUE, Color.YELLOW, Status].
960960
"""
961961
typ = get_proper_type(typ)

test-data/unit/check-enum.test

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,23 @@ class D(C): # E: Cannot extend enum with existing members: "C" \
19381938
x: int # E: Cannot assign to final name "x"
19391939
[builtins fixtures/bool.pyi]
19401940

1941+
[case testEnumNotFinalWithMethodsAndUninitializedValuesStubMemberAndNonMember]
1942+
# flags: --python-version 3.11
1943+
# This was added in 3.11
1944+
import lib
1945+
1946+
[file lib.pyi]
1947+
from enum import Enum, member, nonmember
1948+
1949+
class A(Enum): # E: Detected enum "lib.A" in a type stub with zero members. There is a chance this is due to a recent change in the semantics of enum membership. If so, use `member = value` to mark an enum member, instead of `member: type` \
1950+
# N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members
1951+
x = nonmember(1)
1952+
1953+
class B(Enum):
1954+
@member
1955+
def x(self) -> None: ...
1956+
[builtins fixtures/bool.pyi]
1957+
19411958
[case testEnumLiteralValues]
19421959
from enum import Enum
19431960

@@ -2330,6 +2347,28 @@ def some_a(a: A):
23302347
[builtins fixtures/dict.pyi]
23312348

23322349

2350+
[case testEnumMemberAndNonMemberSupport]
2351+
# flags: --python-version 3.11 --warn-unreachable
2352+
# This was added in 3.11
2353+
from enum import Enum, member, nonmember
2354+
2355+
class A(Enum):
2356+
x = 1
2357+
y = member(2)
2358+
z = nonmember(3)
2359+
2360+
def some_a(a: A):
2361+
if a is not A.x and a is not A.z:
2362+
reveal_type(a) # N: Revealed type is "Literal[__main__.A.y]"
2363+
if a is not A.y and a is not A.z:
2364+
reveal_type(a) # N: Revealed type is "Literal[__main__.A.x]"
2365+
if a is not A.x:
2366+
reveal_type(a) # N: Revealed type is "Literal[__main__.A.y]"
2367+
if a is not A.y:
2368+
reveal_type(a) # N: Revealed type is "Literal[__main__.A.x]"
2369+
[builtins fixtures/dict.pyi]
2370+
2371+
23332372
[case testErrorOnAnnotatedMember]
23342373
from enum import Enum
23352374

0 commit comments

Comments
 (0)