Skip to content

Commit f5ac47f

Browse files
Enum now accepts String literals and final values as 2nd arg (#8664)
Related #8219 Co-authored-by: Jingchen Ye <[email protected]>
1 parent 10f6e4d commit f5ac47f

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

mypy/semanal_enum.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
)
1414
from mypy.semanal_shared import SemanticAnalyzerInterface
1515
from mypy.options import Options
16+
from mypy.types import get_proper_type, LiteralType
1617

1718
# Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use
1819
# enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes.
@@ -173,6 +174,23 @@ def parse_enum_call_args(self, call: CallExpr,
173174
"%s() with dict literal requires string literals" % class_name, call)
174175
items.append(key.value)
175176
values.append(value)
177+
elif isinstance(args[1], RefExpr) and isinstance(args[1].node, Var):
178+
proper_type = get_proper_type(args[1].node.type)
179+
if (proper_type is not None
180+
and isinstance(proper_type, LiteralType)
181+
and isinstance(proper_type.value, str)):
182+
fields = proper_type.value
183+
for field in fields.replace(',', ' ').split():
184+
items.append(field)
185+
elif args[1].node.is_final and isinstance(args[1].node.final_value, str):
186+
fields = args[1].node.final_value
187+
for field in fields.replace(',', ' ').split():
188+
items.append(field)
189+
else:
190+
return self.fail_enum_call_arg(
191+
"%s() expects a string, tuple, list or dict literal as the second argument" %
192+
class_name,
193+
call)
176194
else:
177195
# TODO: Allow dict(x=1, y=2) as a substitute for {'x': 1, 'y': 2}?
178196
return self.fail_enum_call_arg(

test-data/unit/check-enum.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,38 @@ m = Medal.gold
1111
if int():
1212
m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "Medal")
1313

14+
-- Creation from Enum call
15+
-- -----------------------
16+
17+
[case testEnumCreatedFromStringLiteral]
18+
from enum import Enum
19+
from typing_extensions import Literal
20+
21+
x: Literal['ANT BEE CAT DOG'] = 'ANT BEE CAT DOG'
22+
Animal = Enum('Animal', x)
23+
reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?"
24+
reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?"
25+
reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?"
26+
reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?"
27+
28+
[builtins fixtures/tuple.pyi]
29+
30+
[case testEnumCreatedFromFinalValue]
31+
from enum import Enum
32+
from typing_extensions import Final
33+
34+
x: Final['str'] = 'ANT BEE CAT DOG'
35+
Animal = Enum('Animal', x)
36+
reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?"
37+
reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?"
38+
reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?"
39+
reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?"
40+
41+
[builtins fixtures/tuple.pyi]
42+
43+
-- Creation from EnumMeta
44+
-- ----------------------
45+
1446
[case testEnumFromEnumMetaBasics]
1547
from enum import EnumMeta
1648
class Medal(metaclass=EnumMeta):

0 commit comments

Comments
 (0)