| -- 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") | |
| [builtins fixtures/enum.pyi] | |
| -- Creation from Enum call | |
| -- ----------------------- | |
| [case testEnumCreatedFromStringLiteral] | |
| from enum import Enum | |
| from typing 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 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 | |
| [builtins fixtures/enum.pyi] | |
| [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 "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 "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 testEnumValueInhomogeneous] | |
| 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 testEnumTruthyness] | |
| # mypy: warn-unreachable | |
| import enum | |
| from typing import Literal | |
| class E(enum.Enum): | |
| zero = 0 | |
| one = 1 | |
| def print(s: str) -> None: ... | |
| if E.zero: | |
| print("zero is true") | |
| if not E.zero: | |
| print("zero is false") # E: Statement is unreachable | |
| if E.one: | |
| print("one is true") | |
| if not E.one: | |
| print("one is false") # E: Statement is unreachable | |
| def main(zero: Literal[E.zero], one: Literal[E.one]) -> None: | |
| if zero: | |
| print("zero is true") | |
| if not zero: | |
| print("zero is false") # E: Statement is unreachable | |
| if one: | |
| print("one is true") | |
| if not one: | |
| print("one is false") # E: Statement is unreachable | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumTruthynessCustomDunderBool] | |
| # mypy: warn-unreachable | |
| import enum | |
| from typing import Literal | |
| class E(enum.Enum): | |
| zero = 0 | |
| one = 1 | |
| def __bool__(self) -> Literal[False]: | |
| return False | |
| def print(s: str) -> None: ... | |
| if E.zero: | |
| print("zero is true") # E: Statement is unreachable | |
| if not E.zero: | |
| print("zero is false") | |
| if E.one: | |
| print("one is true") # E: Statement is unreachable | |
| if not E.one: | |
| print("one is false") | |
| def main(zero: Literal[E.zero], one: Literal[E.one]) -> None: | |
| if zero: | |
| print("zero is true") # E: Statement is unreachable | |
| if not zero: | |
| print("zero is false") | |
| if one: | |
| print("one is true") # E: Statement is unreachable | |
| if not one: | |
| print("one is false") | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumTruthynessStrEnum] | |
| # mypy: warn-unreachable | |
| import enum | |
| from typing import Literal | |
| class E(enum.StrEnum): | |
| empty = "" | |
| not_empty = "asdf" | |
| def print(s: str) -> None: ... | |
| if E.empty: | |
| print("empty is true") | |
| if not E.empty: | |
| print("empty is false") | |
| if E.not_empty: | |
| print("not_empty is true") | |
| if not E.not_empty: | |
| print("not_empty is false") | |
| def main(empty: Literal[E.empty], not_empty: Literal[E.not_empty]) -> None: | |
| if empty: | |
| print("empty is true") | |
| if not empty: | |
| print("empty is false") | |
| if not_empty: | |
| print("not_empty is true") | |
| if not not_empty: | |
| print("not_empty is false") | |
| [builtins fixtures/enum.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 | |
| [builtins fixtures/enum.pyi] | |
| [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") | |
| [builtins fixtures/enum.pyi] | |
| [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 | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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() | |
| [builtins fixtures/enum.pyi] | |
| [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']?" | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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: int | |
| reveal_type(E(x)) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| main:5: note: Revealed type is "__main__.E" | |
| [case testEnumIndex] | |
| from enum import IntEnum | |
| class E(IntEnum): | |
| a = 1 | |
| s: str | |
| reveal_type(E[s]) | |
| [builtins fixtures/enum.pyi] | |
| [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") | |
| [builtins fixtures/enum.pyi] | |
| [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" | |
| [builtins fixtures/enum.pyi] | |
| [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) # E: Access to generic instance variables via class is ambiguous \ | |
| # N: Revealed type is "builtins.int" | |
| [builtins fixtures/enum.pyi] | |
| [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 | |
| [builtins fixtures/enum.pyi] | |
| [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 | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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") | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [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_enum2', names=['a', 'b']) | |
| fake_enum3 = Enum(value='fake_enum3', names=['a', 'b']) | |
| fake_enum4 = Enum(value='fake_enum4', names=['a', 'b'] , module=__name__) | |
| [builtins fixtures/enum.pyi] | |
| [case testFunctionalEnumErrors] | |
| from enum import Enum, IntEnum | |
| A = Enum('A') # E: Too few arguments for Enum() | |
| B = Enum('B', 42) # E: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| C = Enum('C', 'a b', 'x', 'y', 'z', 'p', 'q') # E: Too many arguments for Enum() | |
| D = Enum('D', foo) # E: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members \ | |
| # E: Name "foo" is not defined | |
| bar = 'x y z' | |
| E = Enum('E', bar) # E: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| I = IntEnum('I') # E: Too few arguments for IntEnum() | |
| J = IntEnum('I', 42) # E: Second argument of IntEnum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| K = IntEnum('I', 'p q', 'x', 'y', 'z', 'p', 'q') # E: Too many arguments for IntEnum() | |
| L = Enum('L', ' ') # E: Enum() needs at least one item | |
| M = Enum('M', ()) # E: Enum() needs at least one item | |
| N = IntEnum('M', []) # E: IntEnum() needs at least one item | |
| P = Enum('P', [42]) # E: Enum() with tuple or list expects strings or (name, value) pairs | |
| Q = Enum('Q', [('a', 42, 0)]) # E: Enum() with tuple or list expects strings or (name, value) pairs | |
| R = IntEnum('R', [[0, 42]]) # E: IntEnum() with tuple or list expects strings or (name, value) pairs | |
| S = Enum('S', {1: 1}) # E: Enum() with dict literal requires string literals | |
| T = Enum('T', keyword='a b') # E: Unexpected keyword argument "keyword" | |
| U = Enum('U', *['a']) # E: Unexpected arguments to Enum() | |
| V = Enum('U', **{'a': 1}) # E: Unexpected arguments to Enum() | |
| W = Enum('W', 'a b') | |
| W.c # E: "type[W]" has no attribute "c" | |
| X = Enum('Something', 'a b') # E: String argument 1 "Something" to enum.Enum(...) does not match variable name "X" | |
| reveal_type(X.a) # N: Revealed type is "Literal[__main__.X.a]?" | |
| X.asdf # E: "type[X]" has no attribute "asdf" | |
| [builtins fixtures/tuple.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [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']?" | |
| reveal_type(A.x.value) # N: Revealed type is "builtins.int" | |
| reveal_type(B.a.value) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/enum.pyi] | |
| [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) | |
| [builtins fixtures/enum.pyi] | |
| [out] | |
| main:7: note: Revealed type is "__main__.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") | |
| [builtins fixtures/enum.pyi] | |
| [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 | |
| [builtins fixtures/enum.pyi] | |
| [out] | |
| [case testEnumWorkWithForward2] | |
| from enum import Enum | |
| b: F | |
| F = Enum('F', {'x': 1, 'y': 2}) | |
| def fn(x: F) -> None: | |
| pass | |
| fn(b) | |
| [builtins fixtures/enum.pyi] | |
| [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 | |
| [builtins fixtures/enum.pyi] | |
| [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') | |
| [builtins fixtures/enum.pyi] | |
| [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 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 | |
| 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 "builtins.int" | |
| 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]?" | |
| 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 "builtins.int" | |
| reveal_type(C1.x._value_) # N: Revealed type is "builtins.int" | |
| 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 "builtins.int" | |
| reveal_type(D1.x._value_) # N: Revealed type is "builtins.int" | |
| 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" | |
| [builtins fixtures/enum.pyi] | |
| [out] | |
| main:2: note: Revealed type is "Literal[1]?" | |
| [out2] | |
| main:2: note: Revealed type is "Literal['foo']?" | |
| [case testEnumReachabilityChecksBasic] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing 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) # E: Statement is unreachable | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A] | Literal[__main__.Foo.B] | Literal[__main__.Foo.C]" | |
| 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) # E: Statement is unreachable | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A] | Literal[__main__.Foo.B] | Literal[__main__.Foo.C]" | |
| 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) # E: Statement 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) # E: Statement is unreachable | |
| reveal_type(y) # N: Revealed type is "__main__.Foo" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityChecksWithOrdering] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing 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) # E: Statement 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) # E: Statement 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) # E: Statement 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) # E: Statement is unreachable | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumReachabilityChecksIndirect] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing import Final, Literal | |
| 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 "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 "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 "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 "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) # E: Statement is unreachable | |
| reveal_type(z) | |
| 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) # E: Statement is unreachable | |
| reveal_type(z) | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityNarrowingForUnionMessiness] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing 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] | |
| if x is y: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.Foo.A] | Literal[__main__.Foo.B]" | |
| reveal_type(y) # N: Revealed type is "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 "Literal[__main__.Foo.A] | Literal[__main__.Foo.B]" | |
| if y is z: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.B]" | |
| else: | |
| reveal_type(y) # N: Revealed type is "Literal[__main__.Foo.A] | Literal[__main__.Foo.B]" | |
| reveal_type(z) # N: Revealed type is "Literal[__main__.Foo.B] | Literal[__main__.Foo.C]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityWithNone] | |
| # flags: --warn-unreachable | |
| 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 "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 "Literal[__main__.Foo.B] | Literal[__main__.Foo.C] | None" | |
| reveal_type(x) # N: Revealed type is "__main__.Foo | None" | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumReachabilityWithMultipleEnums] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| from typing import Literal, Union | |
| 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 "Literal[__main__.Foo.B] | __main__.Bar" | |
| reveal_type(x1) # N: Revealed type is "__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 "__main__.Foo | Literal[__main__.Bar.B]" | |
| reveal_type(x2) # N: Revealed type is "__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 "Literal[__main__.Foo.A] | Literal[__main__.Bar.A]" | |
| else: | |
| reveal_type(x3) # N: Revealed type is "Literal[__main__.Foo.B] | Literal[__main__.Bar.B]" | |
| reveal_type(x3) # N: Revealed type is "__main__.Foo | __main__.Bar" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumReachabilityPEP484ExampleWithFinal] | |
| # flags: --warn-unreachable | |
| from typing import Final, Union | |
| 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 "int | Empty | None" | |
| 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] | |
| # flags: --warn-unreachable | |
| 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: --warn-unreachable | |
| from typing import Final, Union | |
| 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 "int | Empty | None" | |
| 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: --python-version 3.11 --warn-unreachable | |
| from typing import Final, Union | |
| from enum import Enum, member | |
| class Empty(Enum): | |
| # note, that without `member` we cannot tell that `token` is a member: | |
| token = member(lambda x: x) | |
| def f(self) -> int: | |
| return 1 | |
| _empty = Empty.token | |
| reveal_type(_empty) # N: Revealed type is "__main__.Empty" | |
| reveal_type(Empty.f) # N: Revealed type is "def (self: __main__.Empty) -> builtins.int" | |
| 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 "int | Empty | None" | |
| 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("b", [("foo", "bar")]) # E: Enum type as attribute is not supported | |
| reveal_type(A().b) # N: Revealed type is "Any" | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumReachabilityWithChaining] | |
| # flags: --warn-unreachable | |
| 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 import Final, Literal | |
| 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 import Final, Literal | |
| 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 testEnumClassAttributeUnannotated] | |
| import enum | |
| from typing import ClassVar, Literal | |
| class MyEnum(enum.Enum): | |
| foo: ClassVar[str] | |
| bar: str | |
| VALUE_A = 1 | |
| VALUE_B = 2 | |
| reveal_type(MyEnum.foo) # N: Revealed type is "builtins.str" | |
| reveal_type(MyEnum.bar) # N: Revealed type is "builtins.str" | |
| x: Literal[MyEnum.foo] # E: Parameter 1 of Literal[...] is invalid | |
| y: Literal[MyEnum.bar] # E: Parameter 1 of Literal[...] is invalid | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumAttributesInheritedFromMixin] | |
| from enum import Enum | |
| from typing import TYPE_CHECKING, ClassVar, Final, Literal | |
| class A: | |
| var1 = 1 | |
| var2: ClassVar[str] | |
| var3: Final[int] = 3 | |
| var4: str | |
| class E(A, Enum): | |
| mem = 1 | |
| reveal_type(E.var1) # N: Revealed type is "builtins.int" | |
| reveal_type(E.var2) # N: Revealed type is "builtins.str" | |
| reveal_type(E.var3) # N: Revealed type is "builtins.int" | |
| reveal_type(E.var4) # N: Revealed type is "builtins.str" | |
| reveal_type(E.mem) # N: Revealed type is "Literal[__main__.E.mem]?" | |
| E.var1.value # E: "int" has no attribute "value" | |
| E.var2.name # E: "str" has no attribute "name" | |
| E.mem.name | |
| x1: Literal[E.var1] # E: Parameter 1 of Literal[...] is invalid | |
| x2: Literal[E.var2] # E: Parameter 1 of Literal[...] is invalid | |
| x3: Literal[E.var3] # E: Parameter 1 of Literal[...] is invalid | |
| x4: Literal[E.var4] # E: Parameter 1 of Literal[...] is invalid | |
| m: Literal[E.mem] | |
| [builtins fixtures/enum.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 "Literal[1]? | Literal[2]?" | |
| reveal_type(a._value_) # N: Revealed type is "Literal[1]? | Literal[2]?" | |
| [builtins fixtures/enum.pyi] | |
| [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/tuple.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 testValueTypeWithUserDataType] | |
| from enum import Enum | |
| from typing import Any | |
| class Data: | |
| def __new__(cls, value: Any) -> Data: pass | |
| class DataEnum(Data, Enum): | |
| A = Data(1) | |
| reveal_type(DataEnum.A) # N: Revealed type is "Literal[__main__.DataEnum.A]?" | |
| reveal_type(DataEnum.A.value) # N: Revealed type is "__main__.Data" | |
| reveal_type(DataEnum.A._value_) # N: Revealed type is "__main__.Data" | |
| [builtins fixtures/tuple.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 Literal, Union | |
| 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 "Literal[__main__.Foo.B] | Literal[__main__.Foo.C]" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumTypeCompatibleWithLiteralUnion] | |
| from enum import Enum | |
| from typing 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" | |
| [builtins fixtures/enum.pyi] | |
| [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" | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumFinalValuesCannotRedefineValueProp] | |
| from enum import Enum | |
| class Types(Enum): | |
| key = 0 | |
| value = 1 | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumReusedKeys] | |
| # https://github.com/python/mypy/issues/11248 | |
| from enum import Enum | |
| class Correct(Enum): | |
| x = 'y' | |
| y = 'x' | |
| class Correct2(Enum): | |
| x = 'y' | |
| __z = 'y' | |
| __z = '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 testEnumImplicitlyFinalForSubclassingWithCallableMember] | |
| # flags: --python-version 3.11 | |
| from enum import Enum, IntEnum, Flag, IntFlag, member | |
| class NonEmptyEnum(Enum): | |
| @member | |
| def call(self) -> None: ... | |
| class NonEmptyIntEnum(IntEnum): | |
| @member | |
| def call(self) -> None: ... | |
| class NonEmptyFlag(Flag): | |
| @member | |
| def call(self) -> None: ... | |
| class NonEmptyIntFlag(IntFlag): | |
| @member | |
| def call(self) -> None: ... | |
| 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 testEnumCanExtendEnumsWithNonMembers] | |
| # flags: --python-version 3.11 | |
| from enum import Enum, IntEnum, Flag, IntFlag, nonmember | |
| class NonEmptyEnum(Enum): | |
| x = nonmember(1) | |
| class NonEmptyIntEnum(IntEnum): | |
| x = nonmember(1) | |
| class NonEmptyFlag(Flag): | |
| x = nonmember(1) | |
| class NonEmptyIntFlag(IntFlag): | |
| x = nonmember(1) | |
| class ErrorEnumWithoutValue(NonEmptyEnum): | |
| pass | |
| class ErrorIntEnumWithoutValue(NonEmptyIntEnum): | |
| pass | |
| class ErrorFlagWithoutValue(NonEmptyFlag): | |
| pass | |
| class ErrorIntFlagWithoutValue(NonEmptyIntFlag): | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testLambdaIsNotEnumMember] | |
| from enum import Enum | |
| class My(Enum): | |
| x = lambda a: a | |
| class Other(My): ... | |
| [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" | |
| class A1(Enum): | |
| class __Inner: pass | |
| class B1(A1): pass | |
| [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 \ | |
| # E: Incompatible types in assignment (expression has type "B", base class "A" defined the type as "int") | |
| class A1(Enum): | |
| x: int = 1 # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members | |
| 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") \ | |
| # E: Incompatible types in assignment (expression has type "B3", base class "A3" defined the type as "int") | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumNotFinalWithMethodsAndUninitializedValuesStub] | |
| import lib | |
| [file lib.pyi] | |
| from enum import Enum | |
| 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` \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members | |
| x: int | |
| class B(A): | |
| x = 1 # E: Cannot override writable attribute "x" with a final one \ | |
| # E: Incompatible types in assignment (expression has type "B", base class "A" defined the type as "int") | |
| class C(Enum): | |
| x = 1 | |
| class D(C): # E: Cannot extend enum with existing members: "C" \ | |
| # E: Detected enum "lib.D" 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` \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members | |
| x: int # E: Incompatible types in assignment (expression has type "int", base class "C" defined the type as "C") \ | |
| # E: Cannot assign to final name "x" | |
| [builtins fixtures/bool.pyi] | |
| [case testEnumNotFinalWithMethodsAndUninitializedValuesStubMember] | |
| # flags: --python-version 3.11 | |
| # This was added in 3.11 | |
| import lib | |
| [file lib.pyi] | |
| from enum import Enum, member | |
| class A(Enum): | |
| @member | |
| def x(self) -> None: ... | |
| [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_" | |
| [builtins fixtures/enum.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 testEnumValueInhomogeneous 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]" | |
| [builtins fixtures/tuple.pyi] | |
| [case testEnumPrivateAttributeNotMember] | |
| from enum import Enum | |
| class MyEnum(Enum): | |
| A = 1 | |
| B = 2 | |
| __my_dict = {A: "ham", B: "spam"} | |
| # TODO: change the next line to use MyEnum._MyEnum__my_dict when mypy implements name mangling | |
| x: MyEnum = MyEnum.__my_dict # E: Incompatible types in assignment (expression has type "dict[int, str]", variable has type "MyEnum") | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumWithPrivateAttributeReachability] | |
| # flags: --warn-unreachable | |
| from enum import Enum | |
| class MyEnum(Enum): | |
| A = 1 | |
| B = 2 | |
| __my_dict = {A: "ham", B: "spam"} | |
| e: MyEnum | |
| if e == MyEnum.A: | |
| reveal_type(e) # N: Revealed type is "Literal[__main__.MyEnum.A]" | |
| elif e == MyEnum.B: | |
| reveal_type(e) # N: Revealed type is "Literal[__main__.MyEnum.B]" | |
| else: | |
| reveal_type(e) # E: Statement is unreachable | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumNonMemberSupport] | |
| # flags: --python-version 3.11 | |
| # This was added in 3.11 | |
| from enum import Enum, nonmember | |
| class My(Enum): | |
| a = 1 | |
| b = 2 | |
| c = nonmember(3) | |
| reveal_type(My.a) # N: Revealed type is "Literal[__main__.My.a]?" | |
| reveal_type(My.b) # N: Revealed type is "Literal[__main__.My.b]?" | |
| reveal_type(My.c) # N: Revealed type is "builtins.int" | |
| def accepts_my(my: My): | |
| reveal_type(my.value) # N: Revealed type is "Literal[1]? | Literal[2]?" | |
| class Other(Enum): | |
| a = 1 | |
| @nonmember | |
| class Support: | |
| b = 2 | |
| reveal_type(Other.a) # N: Revealed type is "Literal[__main__.Other.a]?" | |
| reveal_type(Other.Support.b) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumMemberSupport] | |
| # flags: --python-version 3.11 | |
| # This was added in 3.11 | |
| from enum import Enum, member | |
| class A(Enum): | |
| x = member(1) | |
| y = 2 | |
| reveal_type(A.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(A.x.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(A.y) # N: Revealed type is "Literal[__main__.A.y]?" | |
| reveal_type(A.y.value) # N: Revealed type is "Literal[2]?" | |
| def some_a(a: A): | |
| reveal_type(a.value) # N: Revealed type is "Literal[1]? | Literal[2]?" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumMemberAndNonMemberSupport] | |
| # flags: --python-version 3.11 --warn-unreachable | |
| # This was added in 3.11 | |
| from enum import Enum, member, nonmember | |
| class A(Enum): | |
| x = 1 | |
| y = member(2) | |
| z = nonmember(3) | |
| def some_a(a: A): | |
| if a is not A.x and a is not A.z: | |
| reveal_type(a) # N: Revealed type is "Literal[__main__.A.y]" | |
| if a is not A.y and a is not A.z: | |
| reveal_type(a) # N: Revealed type is "Literal[__main__.A.x]" | |
| if a is not A.x: | |
| reveal_type(a) # N: Revealed type is "Literal[__main__.A.y]" | |
| if a is not A.y: | |
| reveal_type(a) # N: Revealed type is "Literal[__main__.A.x]" | |
| [builtins fixtures/dict.pyi] | |
| [case testEnumAccessFromInstance] | |
| # flags: --python-version 3.11 --warn-unreachable | |
| # This was added in 3.11 | |
| from enum import Enum, member, nonmember | |
| class A(Enum): | |
| x = 1 | |
| y = member(2) | |
| z = nonmember(3) | |
| reveal_type(A.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(A.y) # N: Revealed type is "Literal[__main__.A.y]?" | |
| reveal_type(A.z) # N: Revealed type is "builtins.int" | |
| reveal_type(A.x.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(A.x.x.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(A.x.y) # N: Revealed type is "Literal[__main__.A.y]?" | |
| reveal_type(A.x.y.y) # N: Revealed type is "Literal[__main__.A.y]?" | |
| reveal_type(A.x.z) # N: Revealed type is "builtins.int" | |
| reveal_type(A.y.x) # N: Revealed type is "Literal[__main__.A.x]?" | |
| reveal_type(A.y.y) # N: Revealed type is "Literal[__main__.A.y]?" | |
| reveal_type(A.y.z) # N: Revealed type is "builtins.int" | |
| A.z.x # E: "int" has no attribute "x" | |
| class B(Enum): | |
| x = 1 | |
| value = 2 | |
| reveal_type(B.x) # N: Revealed type is "Literal[__main__.B.x]?" | |
| reveal_type(B.x.value) # N: Revealed type is "Literal[2]?" | |
| reveal_type(B.x.x.value) # N: Revealed type is "Literal[2]?" | |
| B.x.value.value # E: "int" has no attribute "value" | |
| B.x.value.value.value # E: "int" has no attribute "value" | |
| reveal_type(B.value) # N: Revealed type is "Literal[__main__.B.value]?" | |
| reveal_type(B.value.x) # N: Revealed type is "Literal[__main__.B.x]?" | |
| reveal_type(B.value.x.x) # N: Revealed type is "Literal[__main__.B.x]?" | |
| reveal_type(B.value.x.value) # N: Revealed type is "Literal[2]?" | |
| B.value.x.value.value # E: "int" has no attribute "value" | |
| B.value.value.value # E: "int" has no attribute "value" | |
| [builtins fixtures/dict.pyi] | |
| [case testErrorOnAnnotatedMember] | |
| from enum import Enum | |
| class Medal(Enum): | |
| gold: int = 1 # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members | |
| silver: str = 2 # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members \ | |
| # E: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| bronze = 3 | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumMemberWithPlaceholder] | |
| from enum import Enum | |
| class Pet(Enum): | |
| CAT = ... | |
| DOG: str = ... # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members \ | |
| # E: Incompatible types in assignment (expression has type "EllipsisType", variable has type "str") | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumValueWithPlaceholderNodeType] | |
| # https://github.com/python/mypy/issues/11971 | |
| from enum import Enum | |
| from typing import Any, Callable, Dict | |
| class Foo(Enum): | |
| Bar: Foo = Callable[[str], None] # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members \ | |
| # E: Incompatible types in assignment (expression has type "<typing special form>", variable has type "Foo") | |
| Baz: Any = Callable[[Dict[str, "Missing"]], None] # E: Enum members must be left unannotated \ | |
| # N: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members \ | |
| # E: Type application targets a non-generic function or class \ | |
| # E: Name "Missing" is not defined | |
| reveal_type(Foo.Bar) # N: Revealed type is "Literal[__main__.Foo.Bar]?" | |
| reveal_type(Foo.Bar.value) # N: Revealed type is "__main__.Foo" | |
| reveal_type(Foo.Baz) # N: Revealed type is "Literal[__main__.Foo.Baz]?" | |
| reveal_type(Foo.Baz.value) # N: Revealed type is "Any" | |
| [builtins fixtures/tuple.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testEnumWithOnlyImplicitMembersUsingAnnotationOnly] | |
| # flags: --warn-unreachable | |
| import enum | |
| class E(enum.IntEnum): | |
| A: int | |
| B: int | |
| def do_check(value: E) -> None: | |
| reveal_type(value) # N: Revealed type is "__main__.E" | |
| # this is a nonmember check, not an emum member check, and it should not narrow the value | |
| if value is E.A: | |
| return | |
| reveal_type(value) # N: Revealed type is "__main__.E" | |
| "should be reachable" | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrEnumClassCorrectIterable] | |
| from enum import StrEnum | |
| from typing import Type, TypeVar | |
| class Choices(StrEnum): | |
| LOREM = "lorem" | |
| IPSUM = "ipsum" | |
| var = list(Choices) | |
| reveal_type(var) # N: Revealed type is "builtins.list[__main__.Choices]" | |
| e: type[StrEnum] | |
| reveal_type(list(e)) # N: Revealed type is "builtins.list[enum.StrEnum]" | |
| T = TypeVar("T", bound=StrEnum) | |
| def list_vals(e: Type[T]) -> list[T]: | |
| reveal_type(list(e)) # N: Revealed type is "builtins.list[T`-1]" | |
| return list(e) | |
| reveal_type(list_vals(Choices)) # N: Revealed type is "builtins.list[__main__.Choices]" | |
| [builtins fixtures/enum.pyi] | |
| [case testEnumAsClassMemberNoCrash] | |
| # https://github.com/python/mypy/issues/18736 | |
| from enum import Enum | |
| class Base: | |
| def __init__(self, namespace: tuple[str, ...]) -> None: | |
| # Not a bug: trigger defer | |
| names = [name for name in namespace if fail] # E: Name "fail" is not defined | |
| self.o = Enum("o", names) # E: Enum type as attribute is not supported \ | |
| # E: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members | |
| [builtins fixtures/tuple.pyi] | |
| [case testSingleUnderscoreNameEnumMember] | |
| # flags: --warn-unreachable | |
| # https://github.com/python/mypy/issues/19271 | |
| from enum import Enum | |
| class Things(Enum): | |
| _ = "under score" | |
| def check(thing: Things) -> None: | |
| if thing is Things._: | |
| return None | |
| return None # E: Statement is unreachable | |
| [builtins fixtures/enum.pyi] | |
| [case testSunderValueTypeEllipsis] | |
| from foo.bar import ( | |
| Basic, FromStub, InheritedInt, InheritedStr, InheritedFlag, | |
| InheritedIntFlag, Wrapper | |
| ) | |
| reveal_type(Basic.FOO) # N: Revealed type is "Literal[foo.bar.Basic.FOO]?" | |
| reveal_type(Basic.FOO.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(Basic.FOO._value_) # N: Revealed type is "builtins.int" | |
| reveal_type(FromStub.FOO) # N: Revealed type is "Literal[foo.bar.FromStub.FOO]?" | |
| reveal_type(FromStub.FOO.value) # N: Revealed type is "builtins.int" | |
| reveal_type(FromStub.FOO._value_) # N: Revealed type is "builtins.int" | |
| reveal_type(Wrapper.Nested.FOO) # N: Revealed type is "Literal[foo.bar.Wrapper.Nested.FOO]?" | |
| reveal_type(Wrapper.Nested.FOO.value) # N: Revealed type is "builtins.int" | |
| reveal_type(Wrapper.Nested.FOO._value_) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedInt.FOO) # N: Revealed type is "Literal[foo.bar.InheritedInt.FOO]?" | |
| reveal_type(InheritedInt.FOO.value) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedInt.FOO._value_) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedStr.FOO) # N: Revealed type is "Literal[foo.bar.InheritedStr.FOO]?" | |
| reveal_type(InheritedStr.FOO.value) # N: Revealed type is "builtins.str" | |
| reveal_type(InheritedStr.FOO._value_) # N: Revealed type is "builtins.str" | |
| reveal_type(InheritedFlag.FOO) # N: Revealed type is "Literal[foo.bar.InheritedFlag.FOO]?" | |
| reveal_type(InheritedFlag.FOO.value) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedFlag.FOO._value_) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedIntFlag.FOO) # N: Revealed type is "Literal[foo.bar.InheritedIntFlag.FOO]?" | |
| reveal_type(InheritedIntFlag.FOO.value) # N: Revealed type is "builtins.int" | |
| reveal_type(InheritedIntFlag.FOO._value_) # N: Revealed type is "builtins.int" | |
| [file foo/__init__.pyi] | |
| [file foo/bar/__init__.pyi] | |
| from enum import Enum, IntEnum, StrEnum, Flag, IntFlag | |
| class Basic(Enum): | |
| _value_: int | |
| FOO = 1 | |
| class FromStub(Enum): | |
| _value_: int | |
| FOO = ... | |
| class Wrapper: | |
| class Nested(Enum): | |
| _value_: int | |
| FOO = ... | |
| class InheritedInt(IntEnum): | |
| FOO = ... | |
| class InheritedStr(StrEnum): | |
| FOO = ... | |
| class InheritedFlag(Flag): | |
| FOO = ... | |
| class InheritedIntFlag(IntFlag): | |
| FOO = ... | |
| [builtins fixtures/enum.pyi] | |
| [case testSunderValueTypeEllipsisNonStub] | |
| from enum import Enum, StrEnum | |
| class Basic(Enum): | |
| _value_: int | |
| FOO = 1 | |
| reveal_type(Basic.FOO) # N: Revealed type is "Literal[__main__.Basic.FOO]?" | |
| reveal_type(Basic.FOO.value) # N: Revealed type is "Literal[1]?" | |
| reveal_type(Basic.FOO._value_) # N: Revealed type is "builtins.int" | |
| # TODO: this and below should produce diagnostics, Ellipsis is not assignable to int | |
| # Now we do not check members against _value_ at all. | |
| class FromStub(Enum): | |
| _value_: int | |
| FOO = ... | |
| reveal_type(FromStub.FOO) # N: Revealed type is "Literal[__main__.FromStub.FOO]?" | |
| reveal_type(FromStub.FOO.value) # N: Revealed type is "types.EllipsisType" | |
| reveal_type(FromStub.FOO._value_) # N: Revealed type is "builtins.int" | |
| class InheritedStr(StrEnum): | |
| FOO = ... | |
| reveal_type(InheritedStr.FOO) # N: Revealed type is "Literal[__main__.InheritedStr.FOO]?" | |
| reveal_type(InheritedStr.FOO.value) # N: Revealed type is "types.EllipsisType" | |
| reveal_type(InheritedStr.FOO._value_) # N: Revealed type is "types.EllipsisType" | |
| class Wrapper: | |
| class Nested(StrEnum): | |
| FOO = ... | |
| reveal_type(Wrapper.Nested.FOO) # N: Revealed type is "Literal[__main__.Wrapper.Nested.FOO]?" | |
| reveal_type(Wrapper.Nested.FOO.value) # N: Revealed type is "types.EllipsisType" | |
| reveal_type(Wrapper.Nested.FOO._value_) # N: Revealed type is "types.EllipsisType" | |
| [builtins fixtures/enum.pyi] | |
| [case testStrEnumEqualityReachability] | |
| # flags: --strict-equality --warn-unreachable | |
| from __future__ import annotations | |
| import enum | |
| # https://github.com/python/mypy/issues/17162 | |
| class MyEnum(str, enum.Enum): | |
| A = 'a' | |
| class MyEnum2(enum.StrEnum): | |
| A = 'a' | |
| def f1(): | |
| if MyEnum.A == 'a': | |
| 1 + '' | |
| if MyEnum2.A == 'a': | |
| 1 + '' | |
| [builtins fixtures/primitives.pyi] | |
| [case testStrEnumEqualityNarrowing] | |
| # flags: --strict-equality --warn-unreachable | |
| from __future__ import annotations | |
| import enum | |
| from typing import Literal | |
| # https://github.com/python/mypy/issues/18029 | |
| class Foo(enum.StrEnum): | |
| A = 'a' | |
| def f1(a: Foo | Literal['foo']) -> Foo: | |
| if a == 'foo': | |
| # Ideally this is narrowed to just Literal['foo'] (if we learn to narrow based on enum value) | |
| reveal_type(a) # N: Revealed type is "__main__.Foo | Literal['foo']" | |
| return Foo.A | |
| reveal_type(a) # N: Revealed type is "__main__.Foo" | |
| return a | |
| [builtins fixtures/primitives.pyi] | |
| [case testStrEnumEqualityAlias] | |
| # flags: --strict-equality --warn-unreachable | |
| # https://github.com/python/mypy/issues/16830 | |
| from __future__ import annotations | |
| from enum import Enum, auto | |
| # https://github.com/python/mypy/issues/16830 | |
| class TrafficLight(Enum): | |
| RED = auto() | |
| AMBER = auto() | |
| GREEN = auto() | |
| YELLOW = AMBER # alias | |
| # Behaviour here is not yet ideal, because we don't model enum aliases | |
| def demo1(inst: TrafficLight) -> None: | |
| if inst is TrafficLight.AMBER: | |
| reveal_type(inst) # N: Revealed type is "Literal[__main__.TrafficLight.AMBER]" | |
| else: | |
| reveal_type(inst) # N: Revealed type is "Literal[__main__.TrafficLight.RED] | Literal[__main__.TrafficLight.GREEN] | Literal[__main__.TrafficLight.YELLOW]" | |
| if inst == TrafficLight.AMBER: | |
| reveal_type(inst) # N: Revealed type is "Literal[__main__.TrafficLight.AMBER]" | |
| else: | |
| reveal_type(inst) # N: Revealed type is "Literal[__main__.TrafficLight.RED] | Literal[__main__.TrafficLight.GREEN] | Literal[__main__.TrafficLight.YELLOW]" | |
| def demo2() -> None: | |
| if TrafficLight.AMBER is TrafficLight.YELLOW: # E: Non-overlapping identity check (left operand type: "Literal[TrafficLight.AMBER]", right operand type: "Literal[TrafficLight.YELLOW]") | |
| 1 + '' # E: Unsupported operand types for + ("int" and "str") | |
| else: | |
| 1 + '' # E: Unsupported operand types for + ("int" and "str") | |
| [builtins fixtures/primitives.pyi] | |
| [case testEnumEqualityNarrowing] | |
| # flags: --strict-equality --warn-unreachable | |
| from __future__ import annotations | |
| from typing import cast | |
| from enum import Enum, StrEnum | |
| # https://github.com/python/mypy/issues/16830 | |
| class E(Enum): | |
| A = "a" | |
| B = "b" | |
| C = "c" | |
| class Custom: | |
| def __eq__(self, other: object) -> bool: return True | |
| class SE(StrEnum): | |
| A = "a" | |
| B = "b" | |
| C = "c" | |
| def f1(x: int | str | E): | |
| if x == E.A: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.E.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str | Literal[__main__.E.B] | Literal[__main__.E.C]" | |
| if x in cast(list[E], []): | |
| reveal_type(x) # N: Revealed type is "__main__.E" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str | __main__.E" | |
| if x == str(): | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str | __main__.E" | |
| def f2(x: int | Custom | E): | |
| if x == E.A: | |
| reveal_type(x) # N: Revealed type is "__main__.Custom | Literal[__main__.E.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | Literal[__main__.E.B] | Literal[__main__.E.C]" | |
| if x in cast(list[E], []): | |
| reveal_type(x) # N: Revealed type is "__main__.Custom | __main__.E" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | __main__.E" | |
| if x == str(): | |
| reveal_type(x) # N: Revealed type is "__main__.Custom" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | __main__.E" | |
| def f3_simple(x: str | SE): | |
| if x == SE.A: | |
| # Note the union gets simplified | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| def f3(x: int | str | SE): | |
| if x == SE.A: | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str" | |
| if x in cast(list[SE], []): | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str | __main__.SE" | |
| if x == str(): | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | builtins.str | __main__.SE" | |
| def f4(x: int | Custom | SE): | |
| if x == SE.A: | |
| reveal_type(x) # N: Revealed type is "__main__.Custom | Literal[__main__.SE.A]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | Literal[__main__.SE.B] | Literal[__main__.SE.C]" | |
| if x in cast(list[SE], []): | |
| reveal_type(x) # N: Revealed type is "__main__.Custom | __main__.SE" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | __main__.SE" | |
| if x == str(): | |
| reveal_type(x) # N: Revealed type is "__main__.Custom | __main__.SE" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int | __main__.Custom | __main__.SE" | |
| def f5(x: str | Custom | SE): | |
| if x == SE.A: | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom" | |
| if x in cast(list[SE], []): | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom | __main__.SE" | |
| if x == str(): | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.str | __main__.Custom | __main__.SE" | |
| [builtins fixtures/primitives.pyi] | |
| [case testNarrowingWithIntEnumAndStrEnumUnionAmbiguous] | |
| # flags: --strict-equality --warn-unreachable | |
| from __future__ import annotations | |
| from enum import IntEnum, StrEnum | |
| class IE(IntEnum): | |
| X = 1 | |
| Y = 2 | |
| class SE(StrEnum): | |
| A = "a" | |
| B = "b" | |
| def f(x: IE | SE) -> None: | |
| if x == IE.X: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.IE.X]" | |
| else: | |
| reveal_type(x) # N: Revealed type is "Literal[__main__.IE.Y] | __main__.SE" | |
| [builtins fixtures/primitives.pyi] | |
| [case testNarrowingWithStrEnumUnionNoneAmbiguous] | |
| # flags: --strict-equality --warn-unreachable | |
| from __future__ import annotations | |
| from enum import StrEnum | |
| class SE(StrEnum): | |
| A = "a" | |
| B = "b" | |
| def f(x: SE | None) -> None: | |
| if x == "a": | |
| reveal_type(x) # N: Revealed type is "__main__.SE" | |
| else: | |
| reveal_type(x) # N: Revealed type is "__main__.SE | None" | |
| [builtins fixtures/primitives.pyi] | |
| [case testCallableEnumNarrowing] | |
| # See: https://github.com/python/mypy/issues/17222 | |
| import enum | |
| class Foo(enum.Enum): | |
| FOO1 = enum.auto() | |
| FOO2 = enum.auto() | |
| def __call__(self) -> str: | |
| return self.name | |
| foo = Foo.FOO1 | |
| match foo: | |
| case Foo.FOO1: | |
| foo() | |
| reveal_type(foo) # N: Revealed type is "Literal[__main__.Foo.FOO1]" | |
| case _: | |
| foo() | |
| reveal_type(foo) # N: Revealed type is "Literal[__main__.Foo.FOO2]" | |
| [builtins fixtures/primitives.pyi] |