| -- This test file checks Enum | |
| [case testEnumBasics] | |
| from enum import Enum | |
| class Medal(Enum): | |
| gold = 1 | |
| silver = 2 | |
| bronze = 3 | |
| reveal_type(Medal.bronze) # N: Revealed type is "Literal[__main__.Medal.bronze]?" | |
| m = Medal.gold | |
| if int(): | |
| m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "Medal") | |
| -- Creation from Enum call | |
| -- ----------------------- | |
| [case testEnumCreatedFromStringLiteral] | |
| from enum import Enum | |
| from typing_extensions import Literal | |
| x: Literal['ANT BEE CAT DOG'] = 'ANT BEE CAT DOG' | |
| Animal = Enum('Animal', x) | |
| reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?" | |
| reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?" | |
| reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?" | |
| reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?" | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumCreatedFromFinalValue] | |
| from enum import Enum | |
| from typing_extensions import Final | |
| x: Final['str'] = 'ANT BEE CAT DOG' | |
| Animal = Enum('Animal', x) | |
| reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?" | |
| reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?" | |
| reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?" | |
| reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?" | |
| [builtins fixtures/tuple.pyi] | |
| -- Creation from EnumMeta | |
| -- ---------------------- | |
| [case testEnumFromEnumMetaBasics] | |
| from enum import EnumMeta | |
| class Medal(metaclass=EnumMeta): | |
| gold = 1 | |
| silver = "hello" | |
| bronze = None | |
| # Without __init__ the definition fails at runtime, but we want to verify that mypy | |
| # uses `enum.EnumMeta` and not `enum.Enum` as the definition of what is enum. | |
| def __init__(self, *args): pass | |
| reveal_type(Medal.bronze) # N: Revealed type is "Literal[__main__.Medal.bronze]?" | |
| m = Medal.gold | |
| if int(): | |
| m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "Medal") | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumFromEnumMetaSubclass] | |
| from enum import EnumMeta | |
| class Achievement(metaclass=EnumMeta): pass | |
| class Medal(Achievement): | |
| gold = 1 | |
| silver = "hello" | |
| bronze = None | |
| # See comment in testEnumFromEnumMetaBasics | |
| def __init__(self, *args): pass | |
| reveal_type(Medal.bronze) # N: Revealed type is "Literal[__main__.Medal.bronze]?" | |
| m = Medal.gold | |
| if int(): | |
| m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "Medal") | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumFromEnumMetaGeneric] | |
| from enum import EnumMeta | |
| from typing import Generic, TypeVar | |
| T = TypeVar("T") | |
| class Medal(Generic[T], metaclass=EnumMeta): # E: Enum class cannot be generic | |
| q = None | |
| [case testEnumNameAndValue] | |
| from enum import Enum | |
| class Truth(Enum): | |
| true = True | |
| false = False | |
| x = '' | |
| x = Truth.true.name | |
| reveal_type(Truth.true.name) # N: Revealed type is "Literal['true']?" | |
| reveal_type(Truth.false.value) # N: Revealed type is "Literal[False]?" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumValueExtended] | |
| from enum import Enum | |
| class Truth(Enum): | |
| true = True | |
| false = False | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "Union[Literal[True]?, Literal[False]?]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumValueAllAuto] | |
| from enum import Enum, auto | |
| class Truth(Enum): | |
| true = auto() | |
| false = auto() | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumValueSomeAuto] | |
| from enum import Enum, auto | |
| class Truth(Enum): | |
| true = 8675309 | |
| false = auto() | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumValueExtraMethods] | |
| from enum import Enum | |
| class Truth(Enum): | |
| true = True | |
| false = False | |
| def foo(self) -> str: | |
| return 'bar' | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "Union[Literal[True]?, Literal[False]?]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumValueCustomAuto] | |
| from enum import Enum, auto | |
| class AutoName(Enum): | |
| # In `typeshed`, this is a staticmethod and has more arguments, | |
| # but I have lied a bit to keep the test stubs lean. | |
| def _generate_next_value_(self) -> str: | |
| return "name" | |
| class Truth(AutoName): | |
| true = auto() | |
| false = auto() | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumValueInhomogenous] | |
| from enum import Enum | |
| class Truth(Enum): | |
| true = 'True' | |
| false = 0 | |
| def cannot_infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "Any" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumValueSameType] | |
| from enum import Enum | |
| def newbool() -> bool: | |
| ... | |
| class Truth(Enum): | |
| true = newbool() | |
| false = newbool() | |
| def infer_truth(truth: Truth) -> None: | |
| reveal_type(truth.value) # N: Revealed type is "builtins.bool" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumUnique] | |
| import enum | |
| @enum.unique | |
| class E(enum.Enum): | |
| x = 1 | |
| y = 1 # NOTE: This duplicate value is not detected by mypy at the moment | |
| x = 1 | |
| x = E.x | |
| [out] | |
| main:7: error: Incompatible types in assignment (expression has type "E", variable has type "int") | |
| [case testIntEnum_assignToIntVariable] | |
| from enum import IntEnum | |
| class N(IntEnum): | |
| x = 1 | |
| y = 1 | |
| n = 1 | |
| if int(): | |
| n = N.x # Subclass of int, so it's okay | |
| s = '' | |
| if int(): | |
| s = N.y # E: Incompatible types in assignment (expression has type "N", variable has type "str") | |
| [case testIntEnum_functionTakingIntEnum] | |
| from enum import IntEnum | |
| class SomeIntEnum(IntEnum): | |
| x = 1 | |
| def takes_some_int_enum(n: SomeIntEnum): | |
| pass | |
| takes_some_int_enum(SomeIntEnum.x) | |
| takes_some_int_enum(1) # Error | |
| takes_some_int_enum(SomeIntEnum(1)) # How to deal with the above | |
| [out] | |
| main:7: error: Argument 1 to "takes_some_int_enum" has incompatible type "int"; expected "SomeIntEnum" | |
| [case testIntEnum_functionTakingInt] | |
| from enum import IntEnum | |
| class SomeIntEnum(IntEnum): | |
| x = 1 | |
| def takes_int(i: int): | |
| pass | |
| takes_int(SomeIntEnum.x) | |
| takes_int(2) | |
| [case testIntEnum_functionReturningIntEnum] | |
| from enum import IntEnum | |
| class SomeIntEnum(IntEnum): | |
| x = 1 | |
| def returns_some_int_enum() -> SomeIntEnum: | |
| return SomeIntEnum.x | |
| an_int = 1 | |
| an_int = returns_some_int_enum() | |
| an_enum = SomeIntEnum.x | |
| an_enum = returns_some_int_enum() | |
| [out] | |
| [case testStrEnumCreation] | |
| # flags: --python-version 3.11 | |
| from enum import StrEnum | |
| class MyStrEnum(StrEnum): | |
| x = 'x' | |
| y = 'y' | |
| reveal_type(MyStrEnum.x) # N: Revealed type is "Literal[__main__.MyStrEnum.x]?" | |
| reveal_type(MyStrEnum.x.value) # N: Revealed type is "Literal['x']?" | |
| reveal_type(MyStrEnum.y) # N: Revealed type is "Literal[__main__.MyStrEnum.y]?" | |
| reveal_type(MyStrEnum.y.value) # N: Revealed type is "Literal['y']?" | |
| [out] | |
| [case testEnumMethods] | |
| from enum import Enum | |
| class Color(Enum): | |
| red = 1 | |
| green = 2 | |
| def m(self, x: int): pass | |
| @staticmethod | |
| def m2(x: int): pass | |
| Color.red.m('') | |
| Color.m2('') | |
| [builtins fixtures/staticmethod.pyi] | |
| [out] | |
| main:11: error: Argument 1 to "m" of "Color" has incompatible type "str"; expected "int" | |
| main:12: error: Argument 1 to "m2" of "Color" has incompatible type "str"; expected "int" | |
| [case testIntEnum_ExtendedIntEnum_functionTakingExtendedIntEnum] | |
| from enum import IntEnum | |
| class ExtendedIntEnum(IntEnum): | |
| pass | |
| class SomeExtIntEnum(ExtendedIntEnum): | |
| x = 1 | |
| def takes_int(i: int): | |
| pass | |
| takes_int(SomeExtIntEnum.x) | |
| def takes_some_ext_int_enum(s: SomeExtIntEnum): | |
| pass | |
| takes_some_ext_int_enum(SomeExtIntEnum.x) | |
| [case testNamedTupleEnum] | |
| from typing import NamedTuple | |
| from enum import Enum | |
| N = NamedTuple('N', [('bar', int)]) | |
| class E(N, Enum): | |
| X = N(1) | |
| def f(x: E) -> None: pass | |
| f(E.X) | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumCall] | |
| from enum import IntEnum | |
| class E(IntEnum): | |
| a = 1 | |
| x = None # type: int | |
| reveal_type(E(x)) | |
| [out] | |
| main:5: note: Revealed type is "__main__.E" | |
| [case testEnumIndex] | |
| from enum import IntEnum | |
| class E(IntEnum): | |
| a = 1 | |
| s = None # type: str | |
| reveal_type(E[s]) | |
| [out] | |
| main:5: note: Revealed type is "__main__.E" | |
| [case testEnumIndexError] | |
| from enum import IntEnum | |
| class E(IntEnum): | |
| a = 1 | |
| E[1] # E: Enum index should be a string (actual index type "int") | |
| x = E[1] # E: Enum index should be a string (actual index type "int") | |
| [case testEnumIndexIsNotAnAlias] | |
| from enum import Enum | |
| class E(Enum): | |
| a = 1 | |
| b = 2 | |
| reveal_type(E['a']) # N: Revealed type is "__main__.E" | |
| E['a'] | |
| x = E['a'] | |
| reveal_type(x) # N: Revealed type is "__main__.E" | |
| def get_member(name: str) -> E: | |
| val = E[name] | |
| return val | |
| reveal_type(get_member('a')) # N: Revealed type is "__main__.E" | |
| [case testGenericEnum] | |
| from enum import Enum | |
| from typing import Generic, TypeVar | |
| T = TypeVar('T') | |
| class F(Generic[T], Enum): # E: Enum class cannot be generic | |
| x: T | |
| y: T | |
| reveal_type(F[int].x) # N: Revealed type is "__main__.F[builtins.int]" | |
| [case testEnumFlag] | |
| from enum import Flag | |
| class C(Flag): | |
| a = 1 | |
| b = 2 | |
| x = C.a | |
| if int(): | |
| x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "C") | |
| if int(): | |
| x = x | C.b | |
| [case testEnumIntFlag] | |
| from enum import IntFlag | |
| class C(IntFlag): | |
| a = 1 | |
| b = 2 | |
| x = C.a | |
| if int(): | |
| x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "C") | |
| if int(): | |
| x = x | C.b | |
| [case testAnonymousEnum] | |
| from enum import Enum | |
| class A: | |
| def f(self) -> None: | |
| class E(Enum): | |
| a = 1 | |
| self.x = E.a | |
| a = A() | |
| reveal_type(a.x) | |
| [out] | |
| main:8: note: Revealed type is "__main__.E@4" | |
| [case testEnumInClassBody] | |
| from enum import Enum | |
| class A: | |
| class E(Enum): | |
| a = 1 | |
| class B: | |
| class E(Enum): | |
| a = 1 | |
| x = A.E.a | |
| y = B.E.a | |
| if int(): | |
| x = y # E: Incompatible types in assignment (expression has type "__main__.B.E", variable has type "__main__.A.E") | |
| [case testFunctionalEnumString] | |
| from enum import Enum, IntEnum | |
| E = Enum('E', 'foo bar') | |
| I = IntEnum('I', ' bar, baz ') | |
| reveal_type(E.foo) | |
| reveal_type(E.bar.value) | |
| reveal_type(I.bar) | |
| reveal_type(I.baz.value) | |
| [out] | |
| main:4: note: Revealed type is "Literal[__main__.E.foo]?" | |
| main:5: note: Revealed type is "Any" | |
| main:6: note: Revealed type is "Literal[__main__.I.bar]?" | |
| main:7: note: Revealed type is "builtins.int" | |
| [case testFunctionalEnumListOfStrings] | |
| from enum import Enum, IntEnum | |
| E = Enum('E', ('foo', 'bar')) | |
| F = IntEnum('F', ['bar', 'baz']) | |
| reveal_type(E.foo) | |
| reveal_type(F.baz) | |
| [out] | |
| main:4: note: Revealed type is "Literal[__main__.E.foo]?" | |
| main:5: note: Revealed type is "Literal[__main__.F.baz]?" | |
| [case testFunctionalEnumListOfPairs] | |
| from enum import Enum, IntEnum | |
| E = Enum('E', [('foo', 1), ['bar', 2]]) | |
| F = IntEnum('F', (['bar', 1], ('baz', 2))) | |
| reveal_type(E.foo) | |
| reveal_type(F.baz) | |
| reveal_type(E.foo.value) | |
| reveal_type(F.bar.name) | |
| [out] | |
| main:4: note: Revealed type is "Literal[__main__.E.foo]?" | |
| main:5: note: Revealed type is "Literal[__main__.F.baz]?" | |
| main:6: note: Revealed type is "Literal[1]?" | |
| main:7: note: Revealed type is "Literal['bar']?" | |
| [case testFunctionalEnumDict] | |
| from enum import Enum, IntEnum | |
| E = Enum('E', {'foo': 1, 'bar': 2}) | |
| F = IntEnum('F', {'bar': 1, 'baz': 2}) | |
| reveal_type(E.foo) | |
| reveal_type(F.baz) | |
| reveal_type(E.foo.value) | |
| reveal_type(F.bar.name) | |
| [out] | |
| main:4: note: Revealed type is "Literal[__main__.E.foo]?" | |
| main:5: note: Revealed type is "Literal[__main__.F.baz]?" | |
| main:6: note: Revealed type is "Literal[1]?" | |
| main:7: note: Revealed type is "Literal['bar']?" | |
| [case testEnumKeywordsArgs] | |
| from enum import Enum, IntEnum | |
| PictureSize = Enum('PictureSize', 'P0 P1 P2 P3 P4 P5 P6 P7 P8', type=str, module=__name__) | |
| fake_enum1 = Enum('fake_enum1', ['a', 'b']) | |
| fake_enum2 = Enum('fake_enum1', names=['a', 'b']) | |
| fake_enum3 = Enum(value='fake_enum1', names=['a', 'b']) | |
| fake_enum4 = Enum(value='fake_enum1', names=['a', 'b'] , module=__name__) | |
| [case testFunctionalEnumErrors] | |
| from enum import Enum, IntEnum | |
| A = Enum('A') | |
| B = Enum('B', 42) | |
| C = Enum('C', 'a b', 'x', 'y', 'z', 'p', 'q') | |
| D = Enum('D', foo) | |
| bar = 'x y z' | |
| E = Enum('E', bar) | |
| I = IntEnum('I') | |
| J = IntEnum('I', 42) | |
| K = IntEnum('I', 'p q', 'x', 'y', 'z', 'p', 'q') | |
| L = Enum('L', ' ') | |
| M = Enum('M', ()) | |
| N = IntEnum('M', []) | |
| P = Enum('P', [42]) | |
| Q = Enum('Q', [('a', 42, 0)]) | |
| R = IntEnum('R', [[0, 42]]) | |
| S = Enum('S', {1: 1}) | |
| T = Enum('T', keyword='a b') | |
| U = Enum('U', *['a']) | |
| V = Enum('U', **{'a': 1}) | |
| W = Enum('W', 'a b') | |
| W.c | |
| [typing fixtures/typing-medium.pyi] | |
| [out] | |
| main:2: error: Too few arguments for Enum() | |
| main:3: error: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| main:4: error: Too many arguments for Enum() | |
| main:5: error: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| main:5: error: Name "foo" is not defined | |
| main:7: error: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| main:8: error: Too few arguments for IntEnum() | |
| main:9: error: Second argument of IntEnum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| main:10: error: Too many arguments for IntEnum() | |
| main:11: error: Enum() needs at least one item | |
| main:12: error: Enum() needs at least one item | |
| main:13: error: IntEnum() needs at least one item | |
| main:14: error: Enum() with tuple or list expects strings or (name, value) pairs | |
| main:15: error: Enum() with tuple or list expects strings or (name, value) pairs | |
| main:16: error: IntEnum() with tuple or list expects strings or (name, value) pairs | |
| main:17: error: Enum() with dict literal requires string literals | |
| main:18: error: Unexpected keyword argument "keyword" | |
| main:19: error: Unexpected arguments to Enum() | |
| main:20: error: Unexpected arguments to Enum() | |
| main:22: error: "Type[W]" has no attribute "c" | |
| [case testFunctionalEnumFlag] | |
| from enum import Flag, IntFlag | |
| A = Flag('A', 'x y') | |
| B = IntFlag('B', 'a b') | |
| reveal_type(A.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(B.a) # N: Revealed type is "Literal[__main__.B.a]?" | |
| reveal_type(A.x.name) # N: Revealed type is "Literal['x']?" | |
| reveal_type(B.a.name) # N: Revealed type is "Literal['a']?" | |
| # TODO: The revealed type should be 'int' here | |
| reveal_type(A.x.value) # N: Revealed type is "Any" | |
| reveal_type(B.a.value) # N: Revealed type is "Any" | |
| [case testAnonymousFunctionalEnum] | |
| from enum import Enum | |
| class A: | |
| def f(self) -> None: | |
| E = Enum('E', 'a b') | |
| self.x = E.a | |
| a = A() | |
| reveal_type(a.x) | |
| [out] | |
| main:7: note: Revealed type is "__main__.A.E@4" | |
| [case testFunctionalEnumInClassBody] | |
| from enum import Enum | |
| class A: | |
| E = Enum('E', 'a b') | |
| class B: | |
| E = Enum('E', 'a b') | |
| x = A.E.a | |
| y = B.E.a | |
| if int(): | |
| x = y # E: Incompatible types in assignment (expression has type "__main__.B.E", variable has type "__main__.A.E") | |
| [case testFunctionalEnumProtocols] | |
| from enum import IntEnum | |
| Color = IntEnum('Color', 'red green blue') | |
| reveal_type(Color['green']) # N: Revealed type is "__main__.Color" | |
| for c in Color: | |
| reveal_type(c) # N: Revealed type is "__main__.Color" | |
| reveal_type(list(Color)) # N: Revealed type is "builtins.list[__main__.Color]" | |
| [builtins fixtures/list.pyi] | |
| [case testEnumWorkWithForward] | |
| from enum import Enum | |
| a: E = E.x # type: ignore[used-before-def] | |
| class E(Enum): | |
| x = 1 | |
| y = 2 | |
| [out] | |
| [case testEnumWorkWithForward2] | |
| from enum import Enum | |
| b: F | |
| F = Enum('F', {'x': 1, 'y': 2}) | |
| def fn(x: F) -> None: | |
| pass | |
| fn(b) | |
| [out] | |
| [case testFunctionalEnum] | |
| # TODO: Needs to have enum34 stubs somehow | |
| from enum import Enum | |
| Eu = Enum(u'Eu', u'a b') | |
| Eb = Enum(b'Eb', b'a b') # E: Enum() expects a string literal as the first argument | |
| Gu = Enum(u'Gu', {u'a': 1}) | |
| Gb = Enum(b'Gb', {b'a': 1}) # E: Enum() expects a string literal as the first argument | |
| Hu = Enum(u'Hu', [u'a']) | |
| Hb = Enum(b'Hb', [b'a']) # E: Enum() expects a string literal as the first argument | |
| Eu.a | |
| Eb.a | |
| Gu.a | |
| Gb.a | |
| Hu.a | |
| Hb.a | |
| [out] | |
| [case testEnumIncremental] | |
| import m | |
| reveal_type(m.E.a) | |
| reveal_type(m.F.b) | |
| [file m.py] | |
| from enum import Enum | |
| class E(Enum): | |
| a = 1 | |
| b = 2 | |
| F = Enum('F', 'a b') | |
| [rechecked] | |
| [stale] | |
| [out1] | |
| main:2: note: Revealed type is "Literal[m.E.a]?" | |
| main:3: note: Revealed type is "Literal[m.F.b]?" | |
| [out2] | |
| main:2: note: Revealed type is "Literal[m.E.a]?" | |
| main:3: note: Revealed type is "Literal[m.F.b]?" | |
| [case testEnumAuto] | |
| from enum import Enum, auto | |
| class Test(Enum): | |
| a = auto() | |
| b = auto() | |
| reveal_type(Test.a) # N: Revealed type is "Literal[__main__.Test.a]?" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumAttributeAccessMatrix] | |
| from enum import Enum, IntEnum, IntFlag, Flag, EnumMeta, auto | |
| from typing_extensions import Literal | |
| def is_x(val: Literal['x']) -> None: pass | |
| A1 = Enum('A1', 'x') | |
| class A2(Enum): | |
| x = auto() | |
| class A3(Enum): | |
| x = 1 | |
| is_x(reveal_type(A1.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(A1.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(A1.x.value) # N: Revealed type is "Any" | |
| reveal_type(A1.x._value_) # N: Revealed type is "Any" | |
| is_x(reveal_type(A2.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(A2.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(A2.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(A2.x._value_) # N: Revealed type is "builtins.int" | |
| is_x(reveal_type(A3.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(A3.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(A3.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(A3.x._value_) # N: Revealed type is "Literal[1]?" | |
| B1 = IntEnum('B1', 'x') | |
| class B2(IntEnum): | |
| x = auto() | |
| class B3(IntEnum): | |
| x = 1 | |
| # TODO: getting B1.x._value_ and B2.x._value_ to have type 'int' requires a typeshed change | |
| is_x(reveal_type(B1.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(B1.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(B1.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(B1.x._value_) # N: Revealed type is "Any" | |
| is_x(reveal_type(B2.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(B2.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(B2.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(B2.x._value_) # N: Revealed type is "builtins.int" | |
| is_x(reveal_type(B3.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(B3.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(B3.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(B3.x._value_) # N: Revealed type is "Literal[1]?" | |
| # TODO: C1.x.value and C2.x.value should also be of type 'int' | |
| # This requires either a typeshed change or a plugin refinement | |
| C1 = IntFlag('C1', 'x') | |
| class C2(IntFlag): | |
| x = auto() | |
| class C3(IntFlag): | |
| x = 1 | |
| is_x(reveal_type(C1.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(C1.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(C1.x.value) # N: Revealed type is "Any" | |
| reveal_type(C1.x._value_) # N: Revealed type is "Any" | |
| is_x(reveal_type(C2.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(C2.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(C2.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(C2.x._value_) # N: Revealed type is "builtins.int" | |
| is_x(reveal_type(C3.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(C3.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(C3.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(C3.x._value_) # N: Revealed type is "Literal[1]?" | |
| D1 = Flag('D1', 'x') | |
| class D2(Flag): | |
| x = auto() | |
| class D3(Flag): | |
| x = 1 | |
| is_x(reveal_type(D1.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(D1.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(D1.x.value) # N: Revealed type is "Any" | |
| reveal_type(D1.x._value_) # N: Revealed type is "Any" | |
| is_x(reveal_type(D2.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(D2.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(D2.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(D2.x._value_) # N: Revealed type is "builtins.int" | |
| is_x(reveal_type(D3.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(D3.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(D3.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(D3.x._value_) # N: Revealed type is "Literal[1]?" | |
| # TODO: Generalize our enum functional API logic to work with subclasses of Enum | |
| # See https://github.com/python/mypy/issues/6037 | |
| class Parent(Enum): pass | |
| # E1 = Parent('E1', 'x') # See above TODO | |
| class E2(Parent): | |
| x = auto() | |
| class E3(Parent): | |
| x = 1 | |
| is_x(reveal_type(E2.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(E2.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(E2.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(E2.x._value_) # N: Revealed type is "builtins.int" | |
| is_x(reveal_type(E3.x.name)) # N: Revealed type is "Literal['x']" | |
| is_x(reveal_type(E3.x._name_)) # N: Revealed type is "Literal['x']" | |
| reveal_type(E3.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(E3.x._value_) # N: Revealed type is "Literal[1]?" | |
| # TODO: Figure out if we can construct enums using EnumMetas using the functional API. | |
| # Also figure out if we even care about supporting that use case. | |
| class F2(metaclass=EnumMeta): | |
| x = auto() | |
| class F3(metaclass=EnumMeta): | |
| x = 1 | |
| F2.x.name # E: "F2" has no attribute "name" | |
| F2.x._name_ # E: "F2" has no attribute "_name_" | |
| F2.x.value # E: "F2" has no attribute "value" | |
| F2.x._value_ # E: "F2" has no attribute "_value_" | |
| F3.x.name # E: "F3" has no attribute "name" | |
| F3.x._name_ # E: "F3" has no attribute "_name_" | |
| F3.x.value # E: "F3" has no attribute "value" | |
| F3.x._value_ # E: "F3" has no attribute "_value_" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumAttributeChangeIncremental] | |
| from a import SomeEnum | |
| reveal_type(SomeEnum.a.value) | |
| [file a.py] | |
| from b import SomeEnum | |
| [file b.py] | |
| from enum import Enum | |
| class SomeEnum(Enum): | |
| a = 1 | |
| [file b.py.2] | |
| from enum import Enum | |
| class SomeEnum(Enum): | |
| a = "foo" | |
| [out] | |
| main:2: note: Revealed type is "Literal[1]?" | |
| [out2] | |
| main:2: note: Revealed type is "Literal['foo']?" | |
| [case testEnumReachabilityChecksBasic] | |
| from enum import Enum | |
| from typing_extensions import Literal | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| x: Literal[Foo.A, Foo.B, Foo.C] | |
| if x is Foo.A: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif x is Foo.B: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| elif x is Foo.C: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.C]" | |
| else: | |
| reveal_type(x) # No output here: this branch is unreachable | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| if Foo.A is x: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif Foo.B is x: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| elif Foo.C is x: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.C]" | |
| else: | |
| reveal_type(x) # No output here: this branch is unreachable | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| y: Foo | |
| if y is Foo.A: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif y is Foo.B: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| elif y is Foo.C: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.C]" | |
| else: | |
| reveal_type(y) # No output here: this branch is unreachable | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| if Foo.A is y: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif Foo.B is y: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| elif Foo.C is y: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.C]" | |
| else: | |
| reveal_type(y) # No output here: this branch is unreachable | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityChecksWithOrdering] | |
| from enum import Enum | |
| from typing_extensions import Literal | |
| class Foo(Enum): | |
| _order_ = "A B" | |
| A = 1 | |
| B = 2 | |
| Foo._order_ # E: "Type[Foo]" has no attribute "_order_" | |
| x: Literal[Foo.A, Foo.B] | |
| if x is Foo.A: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif x is Foo.B: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(x) # No output here: this branch is unreachable | |
| class Bar(Enum): | |
| __order__ = "A B" | |
| A = 1 | |
| B = 2 | |
| Bar.__order__ # E: "Type[Bar]" has no attribute "__order__" | |
| y: Literal[Bar.A, Bar.B] | |
| if y is Bar.A: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Bar.A]" | |
| elif y is Bar.B: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Bar.B]" | |
| else: | |
| reveal_type(y) # No output here: this branch is unreachable | |
| x2: Foo | |
| if x2 is Foo.A: | |
| reveal_type(x2) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif x2 is Foo.B: | |
| reveal_type(x2) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(x2) # No output here: this branch is unreachable | |
| y2: Bar | |
| if y2 is Bar.A: | |
| reveal_type(y2) # N: Revealed type is "Literal[__main__.Bar.A]" | |
| elif y2 is Bar.B: | |
| reveal_type(y2) # N: Revealed type is "Literal[__main__.Bar.B]" | |
| else: | |
| reveal_type(y2) # No output here: this branch is unreachable | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumReachabilityChecksIndirect] | |
| from enum import Enum | |
| from typing_extensions import Literal, Final | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| def accepts_foo_a(x: Literal[Foo.A]) -> None: ... | |
| x: Foo | |
| y: Literal[Foo.A] | |
| z: Final = Foo.A | |
| if x is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| if y is x: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| if x is z: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| if z is x: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| if y is z: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| else: | |
| reveal_type(y) # No output: this branch is unreachable | |
| reveal_type(z) # No output: this branch is unreachable | |
| if z is y: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.A]?" | |
| accepts_foo_a(z) | |
| else: | |
| reveal_type(y) # No output: this branch is unreachable | |
| reveal_type(z) # No output: this branch is unreachable | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityNoNarrowingForUnionMessiness] | |
| from enum import Enum | |
| from typing_extensions import Literal | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| x: Foo | |
| y: Literal[Foo.A, Foo.B] | |
| z: Literal[Foo.B, Foo.C] | |
| # For the sake of simplicity, no narrowing is done when the narrower type is a Union. | |
| if x is y: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]" | |
| if y is z: | |
| reveal_type(y) # N: Revealed type is "Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]" | |
| reveal_type(z) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| else: | |
| reveal_type(y) # N: Revealed type is "Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]" | |
| reveal_type(z) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityWithNone] | |
| # flags: --strict-optional | |
| from enum import Enum | |
| from typing import Optional | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| x: Optional[Foo] | |
| if x: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[__main__.Foo, None]" | |
| if x is not None: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| else: | |
| reveal_type(x) # N: Revealed type is "None" | |
| if x is Foo.A: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C], None]" | |
| reveal_type(x) # N: Revealed type is "Union[__main__.Foo, None]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityWithMultipleEnums] | |
| from enum import Enum | |
| from typing import Union | |
| from typing_extensions import Literal | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| class Bar(Enum): | |
| A = 1 | |
| B = 2 | |
| x1: Union[Foo, Bar] | |
| if x1 is Foo.A: | |
| reveal_type(x1) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| else: | |
| reveal_type(x1) # N: Revealed type is "Union[Literal[__main__.Foo.B], __main__.Bar]" | |
| reveal_type(x1) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" | |
| x2: Union[Foo, Bar] | |
| if x2 is Bar.A: | |
| reveal_type(x2) # N: Revealed type is "Literal[__main__.Bar.A]" | |
| else: | |
| reveal_type(x2) # N: Revealed type is "Union[__main__.Foo, Literal[__main__.Bar.B]]" | |
| reveal_type(x2) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" | |
| x3: Union[Foo, Bar] | |
| if x3 is Foo.A or x3 is Bar.A: | |
| reveal_type(x3) # N: Revealed type is "Union[Literal[__main__.Foo.A], Literal[__main__.Bar.A]]" | |
| else: | |
| reveal_type(x3) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Bar.B]]" | |
| reveal_type(x3) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityPEP484ExampleWithFinal] | |
| # flags: --strict-optional | |
| from typing import Union | |
| from typing_extensions import Final | |
| from enum import Enum | |
| class Empty(Enum): | |
| token = 0 | |
| _empty: Final = Empty.token | |
| def func(x: Union[int, None, Empty] = _empty) -> int: | |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ | |
| # E: Unsupported left operand type for + ("Empty") \ | |
| # N: Left operand is of type "Union[int, None, Empty]" | |
| if x is _empty: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Empty.token]" | |
| return 0 | |
| elif x is None: | |
| reveal_type(x) # N: Revealed type is "None" | |
| return 1 | |
| else: # At this point typechecker knows that x can only have type int | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x + 2 | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityPEP484ExampleWithMultipleValues] | |
| from typing import Union | |
| from enum import Enum | |
| class Reason(Enum): | |
| timeout = 1 | |
| error = 2 | |
| def process(response: Union[str, Reason] = '') -> str: | |
| if response is Reason.timeout: | |
| reveal_type(response) # N: Revealed type is "Literal[__main__.Reason.timeout]" | |
| return 'TIMEOUT' | |
| elif response is Reason.error: | |
| reveal_type(response) # N: Revealed type is "Literal[__main__.Reason.error]" | |
| return 'ERROR' | |
| else: | |
| # response can be only str, all other possible values exhausted | |
| reveal_type(response) # N: Revealed type is "builtins.str" | |
| return 'PROCESSED: ' + response | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityPEP484ExampleSingleton] | |
| # flags: --strict-optional | |
| from typing import Union | |
| from typing_extensions import Final | |
| from enum import Enum | |
| class Empty(Enum): | |
| token = 0 | |
| _empty = Empty.token | |
| def func(x: Union[int, None, Empty] = _empty) -> int: | |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ | |
| # E: Unsupported left operand type for + ("Empty") \ | |
| # N: Left operand is of type "Union[int, None, Empty]" | |
| if x is _empty: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Empty.token]" | |
| return 0 | |
| elif x is None: | |
| reveal_type(x) # N: Revealed type is "None" | |
| return 1 | |
| else: # At this point typechecker knows that x can only have type int | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x + 2 | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityPEP484ExampleSingletonWithMethod] | |
| # flags: --strict-optional | |
| from typing import Union | |
| from typing_extensions import Final | |
| from enum import Enum | |
| class Empty(Enum): | |
| token = lambda x: x | |
| def f(self) -> int: | |
| return 1 | |
| _empty = Empty.token | |
| def func(x: Union[int, None, Empty] = _empty) -> int: | |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ | |
| # E: Unsupported left operand type for + ("Empty") \ | |
| # N: Left operand is of type "Union[int, None, Empty]" | |
| if x is _empty: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Empty.token]" | |
| return 0 | |
| elif x is None: | |
| reveal_type(x) # N: Revealed type is "None" | |
| return 1 | |
| else: # At this point typechecker knows that x can only have type int | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x + 2 | |
| [builtins fixtures/primitives.pyi] | |
| [case testAssignEnumAsAttribute] | |
| from enum import Enum | |
| class A: | |
| def __init__(self) -> None: | |
| self.b = Enum("x", [("foo", "bar")]) # E: Enum type as attribute is not supported | |
| reveal_type(A().b) # N: Revealed type is "Any" | |
| [case testEnumReachabilityWithChaining] | |
| from enum import Enum | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| x: Foo | |
| y: Foo | |
| # We can't narrow anything in the else cases -- what if | |
| # x is Foo.A and y is Foo.B or vice versa, for example? | |
| if x is y is Foo.A: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif x is y is Foo.B: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| if x is Foo.A is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif x is Foo.B is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| if Foo.A is x is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| elif Foo.B is x is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityWithChainingDisjoint] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| # Used to divide up a chained comparison into multiple identity groups | |
| def __lt__(self, other: object) -> bool: return True | |
| x: Foo | |
| y: Foo | |
| # No conflict | |
| if x is Foo.A < y is Foo.B: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| # Note: we can't narrow in this case. What if both x and y | |
| # are Foo.A, for example? | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| # The standard output when we end up inferring two disjoint facts about the same expr | |
| if x is Foo.A and x is Foo.B: | |
| reveal_type(x) # E: Statement is unreachable | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| # ..and we get the same result if we have two disjoint groups within the same comp expr | |
| if x is Foo.A < x is Foo.B: | |
| reveal_type(x) # E: Statement is unreachable | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityWithChainingDirectConflict] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing_extensions import Literal, Final | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| x: Foo | |
| if x is Foo.A is Foo.B: | |
| reveal_type(x) # E: Statement is unreachable | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| literal_a: Literal[Foo.A] | |
| literal_b: Literal[Foo.B] | |
| if x is literal_a is literal_b: | |
| reveal_type(x) # E: Statement is unreachable | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| final_a: Final = Foo.A | |
| final_b: Final = Foo.B | |
| if x is final_a is final_b: | |
| reveal_type(x) # E: Statement is unreachable | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumReachabilityWithChainingBigDisjoints] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing_extensions import Literal, Final | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| def __lt__(self, other: object) -> bool: return True | |
| x0: Foo | |
| x1: Foo | |
| x2: Foo | |
| x3: Foo | |
| x4: Foo | |
| x5: Foo | |
| if x0 is x1 is Foo.A is x2 < x3 is Foo.B is x4 is x5: | |
| reveal_type(x0) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(x1) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(x2) # N: Revealed type is "Literal[__main__.Foo.A]" | |
| reveal_type(x3) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(x4) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(x5) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| # We unfortunately can't narrow away anything. For example, | |
| # what if x0 == Foo.A and x1 == Foo.B or vice versa? | |
| reveal_type(x0) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x1) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x2) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x3) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x4) # N: Revealed type is "__main__.Foo" | |
| reveal_type(x5) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/primitives.pyi] | |
| [case testPrivateAttributeNotAsEnumMembers] | |
| import enum | |
| class Comparator(enum.Enum): | |
| LessThan = "<" | |
| LessThanOrEqualTo = "<=" | |
| EqualTo = "==" | |
| NotEqualTo = "!=" | |
| GreaterThanOrEqualTo = ">=" | |
| GreaterThan = ">" | |
| __foo__ = { | |
| LessThan: 1, | |
| LessThanOrEqualTo: 2, | |
| EqualTo: 3, | |
| NotEqualTo: 4, | |
| GreaterThanOrEqualTo: 5, | |
| GreaterThan: 6, | |
| } | |
| def foo(self) -> int: | |
| return Comparator.__foo__[self.value] | |
| reveal_type(Comparator.__foo__) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumWithInstanceAttributes] | |
| from enum import Enum | |
| class Foo(Enum): | |
| def __init__(self, value: int) -> None: | |
| self.foo = "bar" | |
| A = 1 | |
| B = 2 | |
| a = Foo.A | |
| reveal_type(a.value) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" | |
| reveal_type(a._value_) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" | |
| [case testNewSetsUnexpectedValueType] | |
| from enum import Enum | |
| class bytes: | |
| def __new__(cls): pass | |
| class Foo(bytes, Enum): | |
| def __new__(cls, value: int) -> 'Foo': | |
| obj = bytes.__new__(cls) | |
| obj._value_ = "Number %d" % value | |
| return obj | |
| A = 1 | |
| B = 2 | |
| a = Foo.A | |
| reveal_type(a.value) # N: Revealed type is "Any" | |
| reveal_type(a._value_) # N: Revealed type is "Any" | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testValueTypeWithNewInParentClass] | |
| from enum import Enum | |
| class bytes: | |
| def __new__(cls): pass | |
| class Foo(bytes, Enum): | |
| def __new__(cls, value: int) -> 'Foo': | |
| obj = bytes.__new__(cls) | |
| obj._value_ = "Number %d" % value | |
| return obj | |
| class Bar(Foo): | |
| A = 1 | |
| B = 2 | |
| a = Bar.A | |
| reveal_type(a.value) # N: Revealed type is "Any" | |
| reveal_type(a._value_) # N: Revealed type is "Any" | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testEnumNarrowedToTwoLiterals] | |
| # Regression test: two literals of an enum would be joined | |
| # as the full type, regardless of the amount of elements | |
| # the enum contains. | |
| from enum import Enum | |
| from typing import Union | |
| from typing_extensions import Literal | |
| class Foo(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| def f(x: Foo): | |
| if x is Foo.A: | |
| return x | |
| if x is Foo.B: | |
| pass | |
| reveal_type(x) # N: Revealed type is "Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumTypeCompatibleWithLiteralUnion] | |
| from enum import Enum | |
| from typing_extensions import Literal | |
| class E(Enum): | |
| A = 1 | |
| B = 2 | |
| C = 3 | |
| e: E | |
| a: Literal[E.A, E.B, E.C] = e | |
| b: Literal[E.A, E.B] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Literal[E.A, E.B]") | |
| c: Literal[E.A, E.C] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Literal[E.A, E.C]") | |
| b = a # E: Incompatible types in assignment (expression has type "Literal[E.A, E.B, E.C]", variable has type "Literal[E.A, E.B]") | |
| [builtins fixtures/bool.pyi] | |
| [case testIntEnumWithNewTypeValue] | |
| from typing import NewType | |
| from enum import IntEnum | |
| N = NewType("N", int) | |
| class E(IntEnum): | |
| A = N(0) | |
| reveal_type(E.A.value) # N: Revealed type is "__main__.N" | |
| [case testEnumFinalValues] | |
| from enum import Enum | |
| class Medal(Enum): | |
| gold = 1 | |
| silver = 2 | |
| # Another value: | |
| Medal.gold = 0 # E: Cannot assign to final attribute "gold" | |
| # Same value: | |
| Medal.silver = 2 # E: Cannot assign to final attribute "silver" | |
| [case testEnumFinalValuesCannotRedefineValueProp] | |
| from enum import Enum | |
| class Types(Enum): | |
| key = 0 | |
| value = 1 | |
| [case testEnumReusedKeys] | |
| # https://github.com/python/mypy/issues/11248 | |
| from enum import Enum | |
| class Correct(Enum): | |
| x = 'y' | |
| y = 'x' | |
| class Foo(Enum): | |
| A = 1 | |
| A = 'a' # E: Attempted to reuse member name "A" in Enum definition "Foo" \ | |
| # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| reveal_type(Foo.A.value) # N: Revealed type is "Literal[1]?" | |
| class Bar(Enum): | |
| A = 1 | |
| B = A = 2 # E: Attempted to reuse member name "A" in Enum definition "Bar" | |
| class Baz(Enum): | |
| A = 1 | |
| B, A = (1, 2) # E: Attempted to reuse member name "A" in Enum definition "Baz" | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumReusedKeysOverlapWithLocalVar] | |
| from enum import Enum | |
| x = 1 | |
| class Foo(Enum): | |
| x = 2 | |
| def method(self) -> None: | |
| x = 3 | |
| x = 4 | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumImplicitlyFinalForSubclassing] | |
| from enum import Enum, IntEnum, Flag, IntFlag | |
| class NonEmptyEnum(Enum): | |
| x = 1 | |
| class NonEmptyIntEnum(IntEnum): | |
| x = 1 | |
| class NonEmptyFlag(Flag): | |
| x = 1 | |
| class NonEmptyIntFlag(IntFlag): | |
| x = 1 | |
| class ErrorEnumWithValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" | |
| x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyEnum") | |
| class ErrorIntEnumWithValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" | |
| x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntEnum") | |
| class ErrorFlagWithValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" | |
| x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyFlag") | |
| class ErrorIntFlagWithValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" | |
| x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntFlag") | |
| class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" | |
| pass | |
| class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" | |
| pass | |
| class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" | |
| pass | |
| class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testSubclassingNonFinalEnums] | |
| from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta | |
| def decorator(func): | |
| return func | |
| class EmptyEnum(Enum): | |
| pass | |
| class EmptyIntEnum(IntEnum): | |
| pass | |
| class EmptyFlag(Flag): | |
| pass | |
| class EmptyIntFlag(IntFlag): | |
| pass | |
| class EmptyEnumMeta(EnumMeta): | |
| pass | |
| class NonEmptyEnumSub(EmptyEnum): | |
| x = 1 | |
| class NonEmptyIntEnumSub(EmptyIntEnum): | |
| x = 1 | |
| class NonEmptyFlagSub(EmptyFlag): | |
| x = 1 | |
| class NonEmptyIntFlagSub(EmptyIntFlag): | |
| x = 1 | |
| class NonEmptyEnumMetaSub(EmptyEnumMeta): | |
| x = 1 | |
| class EmptyEnumSub(EmptyEnum): | |
| def method(self) -> None: pass | |
| @decorator | |
| def other(self) -> None: pass | |
| class EmptyIntEnumSub(EmptyIntEnum): | |
| def method(self) -> None: pass | |
| class EmptyFlagSub(EmptyFlag): | |
| def method(self) -> None: pass | |
| class EmptyIntFlagSub(EmptyIntFlag): | |
| def method(self) -> None: pass | |
| class EmptyEnumMetaSub(EmptyEnumMeta): | |
| def method(self) -> None: pass | |
| class NestedEmptyEnumSub(EmptyEnumSub): | |
| x = 1 | |
| class NestedEmptyIntEnumSub(EmptyIntEnumSub): | |
| x = 1 | |
| class NestedEmptyFlagSub(EmptyFlagSub): | |
| x = 1 | |
| class NestedEmptyIntFlagSub(EmptyIntFlagSub): | |
| x = 1 | |
| class NestedEmptyEnumMetaSub(EmptyEnumMetaSub): | |
| x = 1 | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumExplicitlyAndImplicitlyFinal] | |
| from typing import final | |
| from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta | |
| @final | |
| class EmptyEnum(Enum): | |
| pass | |
| @final | |
| class EmptyIntEnum(IntEnum): | |
| pass | |
| @final | |
| class EmptyFlag(Flag): | |
| pass | |
| @final | |
| class EmptyIntFlag(IntFlag): | |
| pass | |
| @final | |
| class EmptyEnumMeta(EnumMeta): | |
| pass | |
| class EmptyEnumSub(EmptyEnum): # E: Cannot inherit from final class "EmptyEnum" | |
| pass | |
| class EmptyIntEnumSub(EmptyIntEnum): # E: Cannot inherit from final class "EmptyIntEnum" | |
| pass | |
| class EmptyFlagSub(EmptyFlag): # E: Cannot inherit from final class "EmptyFlag" | |
| pass | |
| class EmptyIntFlagSub(EmptyIntFlag): # E: Cannot inherit from final class "EmptyIntFlag" | |
| pass | |
| class EmptyEnumMetaSub(EmptyEnumMeta): # E: Cannot inherit from final class "EmptyEnumMeta" | |
| pass | |
| @final | |
| class NonEmptyEnum(Enum): | |
| x = 1 | |
| @final | |
| class NonEmptyIntEnum(IntEnum): | |
| x = 1 | |
| @final | |
| class NonEmptyFlag(Flag): | |
| x = 1 | |
| @final | |
| class NonEmptyIntFlag(IntFlag): | |
| x = 1 | |
| @final | |
| class NonEmptyEnumMeta(EnumMeta): | |
| x = 1 | |
| class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" \ | |
| # E: Cannot extend enum with existing members: "NonEmptyEnum" | |
| pass | |
| class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" \ | |
| # E: Cannot extend enum with existing members: "NonEmptyIntEnum" | |
| pass | |
| class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" \ | |
| # E: Cannot extend enum with existing members: "NonEmptyFlag" | |
| pass | |
| class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" \ | |
| # E: Cannot extend enum with existing members: "NonEmptyIntFlag" | |
| pass | |
| class ErrorEnumMetaWithoutValue(NonEmptyEnumMeta): # E: Cannot inherit from final class "NonEmptyEnumMeta" | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumFinalSubtypingEnumMetaSpecialCase] | |
| from enum import EnumMeta | |
| # `EnumMeta` types are not `Enum`s | |
| class SubMeta(EnumMeta): | |
| x = 1 | |
| class SubSubMeta(SubMeta): | |
| x = 2 | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumFinalSubtypingOverloadedSpecialCase] | |
| from typing import overload | |
| from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta | |
| class EmptyEnum(Enum): | |
| @overload | |
| def method(self, arg: int) -> int: | |
| pass | |
| @overload | |
| def method(self, arg: str) -> str: | |
| pass | |
| def method(self, arg): | |
| pass | |
| class EmptyIntEnum(IntEnum): | |
| @overload | |
| def method(self, arg: int) -> int: | |
| pass | |
| @overload | |
| def method(self, arg: str) -> str: | |
| pass | |
| def method(self, arg): | |
| pass | |
| class EmptyFlag(Flag): | |
| @overload | |
| def method(self, arg: int) -> int: | |
| pass | |
| @overload | |
| def method(self, arg: str) -> str: | |
| pass | |
| def method(self, arg): | |
| pass | |
| class EmptyIntFlag(IntFlag): | |
| @overload | |
| def method(self, arg: int) -> int: | |
| pass | |
| @overload | |
| def method(self, arg: str) -> str: | |
| pass | |
| def method(self, arg): | |
| pass | |
| class EmptyEnumMeta(EnumMeta): | |
| @overload | |
| def method(self, arg: int) -> int: | |
| pass | |
| @overload | |
| def method(self, arg: str) -> str: | |
| pass | |
| def method(self, arg): | |
| pass | |
| class NonEmptyEnumSub(EmptyEnum): | |
| x = 1 | |
| class NonEmptyIntEnumSub(EmptyIntEnum): | |
| x = 1 | |
| class NonEmptyFlagSub(EmptyFlag): | |
| x = 1 | |
| class NonEmptyIntFlagSub(EmptyIntFlag): | |
| x = 1 | |
| class NonEmptyEnumMetaSub(EmptyEnumMeta): | |
| x = 1 | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumFinalSubtypingMethodAndValueSpecialCase] | |
| from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta | |
| def decorator(func): | |
| return func | |
| class NonEmptyEnum(Enum): | |
| x = 1 | |
| def method(self) -> None: pass | |
| @decorator | |
| def other(self) -> None: pass | |
| class NonEmptyIntEnum(IntEnum): | |
| x = 1 | |
| def method(self) -> None: pass | |
| class NonEmptyFlag(Flag): | |
| x = 1 | |
| def method(self) -> None: pass | |
| class NonEmptyIntFlag(IntFlag): | |
| x = 1 | |
| def method(self) -> None: pass | |
| class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" | |
| pass | |
| class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" | |
| pass | |
| class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" | |
| pass | |
| class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testFinalEnumWithClassDef] | |
| from enum import Enum | |
| class A(Enum): | |
| class Inner: pass | |
| class B(A): pass # E: Cannot extend enum with existing members: "A" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumFinalSpecialProps] | |
| # https://github.com/python/mypy/issues/11699 | |
| # https://github.com/python/mypy/issues/11820 | |
| from enum import Enum, IntEnum | |
| class BaseWithSpecials: | |
| __slots__ = () | |
| __doc__ = 'doc' | |
| __module__ = 'module' | |
| __annotations__ = {'a': int} | |
| __dict__ = {'a': 1} | |
| class E(BaseWithSpecials, Enum): | |
| name = 'a' | |
| value = 'b' | |
| _name_ = 'a1' | |
| _value_ = 'b2' | |
| _order_ = 'X Y' | |
| __order__ = 'X Y' | |
| __slots__ = () | |
| __doc__ = 'doc' | |
| __module__ = 'module' | |
| __annotations__ = {'a': int} | |
| __dict__ = {'a': 1} | |
| class EI(IntEnum): | |
| name = 'a' | |
| value = 1 | |
| _name_ = 'a1' | |
| _value_ = 2 | |
| _order_ = 'X Y' | |
| __order__ = 'X Y' | |
| __slots__ = () | |
| __doc__ = 'doc' | |
| __module__ = 'module' | |
| __annotations__ = {'a': int} | |
| __dict__ = {'a': 1} | |
| E._order_ = 'a' # E: Cannot assign to final attribute "_order_" | |
| EI.value = 2 # E: Cannot assign to final attribute "value" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumNotFinalWithMethodsAndUninitializedValues] | |
| # https://github.com/python/mypy/issues/11578 | |
| from enum import Enum | |
| from typing import Final | |
| class A(Enum): | |
| x: int | |
| def method(self) -> int: pass | |
| class B(A): | |
| x = 1 # E: Cannot override writable attribute "x" with a final one | |
| class A1(Enum): | |
| x: int = 1 | |
| class B1(A1): # E: Cannot extend enum with existing members: "A1" | |
| pass | |
| class A2(Enum): | |
| x = 2 | |
| class B2(A2): # E: Cannot extend enum with existing members: "A2" | |
| pass | |
| # We leave this `Final` without a value, | |
| # because we need to test annotation only mode: | |
| class A3(Enum): | |
| x: Final[int] # type: ignore | |
| class B3(A3): | |
| x = 1 # E: Cannot override final attribute "x" (previously declared in base class "A3") | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumNotFinalWithMethodsAndUninitializedValuesStub] | |
| import lib | |
| [file lib.pyi] | |
| from enum import Enum | |
| class A(Enum): | |
| x: int | |
| class B(A): # E: Cannot extend enum with existing members: "A" | |
| x = 1 # E: Cannot override writable attribute "x" with a final one | |
| class C(Enum): | |
| x = 1 | |
| class D(C): # E: Cannot extend enum with existing members: "C" | |
| x: int # E: Cannot assign to final name "x" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumLiteralValues] | |
| from enum import Enum | |
| class A(Enum): | |
| str = "foo" | |
| int = 1 | |
| bool = False | |
| tuple = (1,) | |
| reveal_type(A.str.value) # N: Revealed type is "Literal['foo']?" | |
| reveal_type(A.int.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(A.bool.value) # N: Revealed type is "Literal[False]?" | |
| reveal_type(A.tuple.value) # N: Revealed type is "Tuple[Literal[1]?]" | |
| [builtins fixtures/tuple.pyi] | |
| [case testFinalWithPrivateAssignment] | |
| import enum | |
| class Some(enum.Enum): | |
| __priv = 1 | |
| class Other(Some): # Should pass | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testFinalWithDunderAssignment] | |
| import enum | |
| class Some(enum.Enum): | |
| __some__ = 1 | |
| class Other(Some): # Should pass | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testFinalWithSunderAssignment] | |
| import enum | |
| class Some(enum.Enum): | |
| _some_ = 1 | |
| class Other(Some): # Should pass | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testFinalWithMethodAssignment] | |
| import enum | |
| from typing import overload | |
| class Some(enum.Enum): | |
| def lor(self, other) -> bool: | |
| pass | |
| ror = lor | |
| class Other(Some): # Should pass | |
| pass | |
| class WithOverload(enum.IntEnum): | |
| @overload | |
| def meth(self, arg: int) -> int: pass | |
| @overload | |
| def meth(self, arg: str) -> str: pass | |
| def meth(self, arg): pass | |
| alias = meth | |
| class SubWithOverload(WithOverload): # Should pass | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumBaseClassesOrder] | |
| import enum | |
| # Base types: | |
| class First: | |
| def __new__(cls, val): | |
| pass | |
| class Second: | |
| def __new__(cls, val): | |
| pass | |
| class Third: | |
| def __new__(cls, val): | |
| pass | |
| class Mixin: | |
| pass | |
| class EnumWithCustomNew(enum.Enum): | |
| def __new__(cls, val): | |
| pass | |
| class SecondEnumWithCustomNew(enum.Enum): | |
| def __new__(cls, val): | |
| pass | |
| # Correct Enums: | |
| class Correct0(enum.Enum): | |
| pass | |
| class Correct1(Mixin, First, enum.Enum): | |
| pass | |
| class Correct2(First, enum.Enum): | |
| pass | |
| class Correct3(Mixin, enum.Enum): | |
| pass | |
| class RegularClass(Mixin, First, Second): | |
| pass | |
| class Correct5(enum.Enum): | |
| pass | |
| # Correct inheritance: | |
| class _InheritingDataAndMixin(Correct1): | |
| pass | |
| class _CorrectWithData(First, Correct0): | |
| pass | |
| class _CorrectWithDataAndMixin(Mixin, First, Correct0): | |
| pass | |
| class _CorrectWithMixin(Mixin, Correct2): | |
| pass | |
| class _CorrectMultipleEnumBases(Correct0, Correct5): | |
| pass | |
| class _MultipleEnumBasesAndMixin(int, Correct0, enum.Flag): | |
| pass | |
| class _MultipleEnumBasesWithCustomNew(int, EnumWithCustomNew, SecondEnumWithCustomNew): | |
| pass | |
| # Wrong Enums: | |
| class TwoDataTypesViaInheritance(Second, Correct2): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" | |
| pass | |
| class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" | |
| pass | |
| class MixinAfterEnum1(enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" | |
| pass | |
| class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" | |
| pass | |
| class TwoDataTypes(First, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" | |
| pass | |
| class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No non-enum mixin classes are allowed after "enum.IntEnum" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" | |
| pass | |
| class ThreeDataTypes(First, Second, Third, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" | |
| pass | |
| class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" | |
| pass | |
| class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" | |
| pass | |
| class FromEnumAndOther2(Correct2, Second): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ | |
| # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testRegression12258] | |
| from enum import Enum | |
| class MyEnum(Enum): ... | |
| class BytesEnum(bytes, MyEnum): ... # Should be ok | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumWithNewHierarchy] | |
| import enum | |
| class A: | |
| def __new__(cls, val): ... | |
| class B(A): | |
| def __new__(cls, val): ... | |
| class C: | |
| def __new__(cls, val): ... | |
| class E1(A, enum.Enum): ... | |
| class E2(B, enum.Enum): ... | |
| # Errors: | |
| class W1(C, E1): ... # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.E1" | |
| class W2(C, E2): ... # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.E2" | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumValueUnionSimplification] | |
| from enum import IntEnum | |
| from typing import Any | |
| class C(IntEnum): | |
| X = 0 | |
| Y = 1 | |
| Z = 2 | |
| def f1(c: C) -> None: | |
| x = {'x': c.value} | |
| reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" | |
| def f2(c: C, a: Any) -> None: | |
| x = {'x': c.value, 'y': a} | |
| reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str, Any]" | |
| y = {'y': a, 'x': c.value} | |
| reveal_type(y) # N: Revealed type is "builtins.dict[builtins.str, Any]" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumIgnoreIsDeleted] | |
| from enum import Enum | |
| class C(Enum): | |
| _ignore_ = 'X' | |
| C._ignore_ # E: "Type[C]" has no attribute "_ignore_" | |
| [typing fixtures/typing-medium.pyi] | |
| [case testCanOverrideDunderAttributes] | |
| import typing | |
| from enum import Enum, Flag | |
| class BaseEnum(Enum): | |
| __dunder__ = 1 | |
| __labels__: typing.Dict[int, str] | |
| class Override(BaseEnum): | |
| __dunder__ = 2 | |
| __labels__ = {1: "1"} | |
| Override.__dunder__ = 3 | |
| BaseEnum.__dunder__ = 3 | |
| Override.__labels__ = {2: "2"} | |
| class FlagBase(Flag): | |
| __dunder__ = 1 | |
| __labels__: typing.Dict[int, str] | |
| class FlagOverride(FlagBase): | |
| __dunder__ = 2 | |
| __labels = {1: "1"} | |
| FlagOverride.__dunder__ = 3 | |
| FlagBase.__dunder__ = 3 | |
| FlagOverride.__labels__ = {2: "2"} | |
| [builtins fixtures/dict.pyi] | |
| [case testCanNotInitialize__members__] | |
| import typing | |
| from enum import Enum | |
| class WritingMembers(Enum): | |
| __members__: typing.Dict[Enum, Enum] = {} # E: Assigned "__members__" will be overridden by "Enum" internally | |
| class OnlyAnnotatedMembers(Enum): | |
| __members__: typing.Dict[Enum, Enum] | |
| [builtins fixtures/dict.pyi] | |
| [case testCanOverrideDunderOnNonFirstBaseEnum] | |
| import typing | |
| from enum import Enum | |
| class Some: | |
| __labels__: typing.Dict[int, str] | |
| class A(Some, Enum): | |
| __labels__ = {1: "1"} | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumWithPartialTypes] | |
| from enum import Enum | |
| class Mixed(Enum): | |
| a = [] # E: Need type annotation for "a" (hint: "a: List[<type>] = ...") | |
| b = None | |
| def check(self) -> None: | |
| reveal_type(Mixed.a.value) # N: Revealed type is "builtins.list[Any]" | |
| reveal_type(Mixed.b.value) # N: Revealed type is "None" | |
| # Inferring Any here instead of a union seems to be a deliberate | |
| # choice; see the testEnumValueInhomogenous case above. | |
| reveal_type(self.value) # N: Revealed type is "Any" | |
| for field in Mixed: | |
| reveal_type(field.value) # N: Revealed type is "Any" | |
| if field.value is None: | |
| pass | |
| class AllPartialList(Enum): | |
| a = [] # E: Need type annotation for "a" (hint: "a: List[<type>] = ...") | |
| b = [] # E: Need type annotation for "b" (hint: "b: List[<type>] = ...") | |
| def check(self) -> None: | |
| reveal_type(self.value) # N: Revealed type is "builtins.list[Any]" |