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