| -- 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") |
| |
| [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 'builtins.bool' |
| [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 'builtins.bool' |
| [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, auto |
| 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 'builtins.bool' |
| [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 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 testEnumMethods] |
| from enum import Enum |
| |
| class Color(Enum): |
| red = 1 |
| green = 2 |
| |
| def m(self, x: int): pass |
| @staticmethod |
| def m2(x: int): pass |
| |
| Color.red.m('') |
| Color.m2('') |
| [builtins fixtures/staticmethod.pyi] |
| [out] |
| main:11: error: Argument 1 to "m" of "Color" has incompatible type "str"; expected "int" |
| main:12: error: Argument 1 to "m2" of "Color" has incompatible type "str"; expected "int" |
| |
| [case testIntEnum_ExtendedIntEnum_functionTakingExtendedIntEnum] |
| from enum import IntEnum |
| class ExtendedIntEnum(IntEnum): |
| pass |
| class SomeExtIntEnum(ExtendedIntEnum): |
| x = 1 |
| |
| def takes_int(i: int): |
| pass |
| takes_int(SomeExtIntEnum.x) |
| |
| def takes_some_ext_int_enum(s: SomeExtIntEnum): |
| pass |
| takes_some_ext_int_enum(SomeExtIntEnum.x) |
| |
| [case testNamedTupleEnum] |
| from typing import NamedTuple |
| from enum import Enum |
| |
| N = NamedTuple('N', [('bar', int)]) |
| |
| class E(N, Enum): |
| X = N(1) |
| |
| def f(x: E) -> None: pass |
| |
| f(E.X) |
| [builtins fixtures/tuple.pyi] |
| |
| [case testEnumCall] |
| from enum import IntEnum |
| class E(IntEnum): |
| a = 1 |
| x = None # type: int |
| reveal_type(E(x)) |
| [out] |
| main:5: note: Revealed type is '__main__.E*' |
| |
| [case testEnumIndex] |
| from enum import IntEnum |
| class E(IntEnum): |
| a = 1 |
| s = None # type: str |
| reveal_type(E[s]) |
| [out] |
| main:5: note: Revealed type is '__main__.E' |
| |
| [case testEnumIndexError] |
| from enum import IntEnum |
| class E(IntEnum): |
| a = 1 |
| E[1] # E: Enum index should be a string (actual index type "int") |
| x = E[1] # E: Enum index should be a string (actual index type "int") |
| |
| [case testEnumIndexIsNotAnAlias] |
| from enum import Enum |
| |
| class E(Enum): |
| a = 1 |
| b = 2 |
| reveal_type(E['a']) # N: Revealed type is '__main__.E' |
| E['a'] |
| x = E['a'] |
| reveal_type(x) # N: Revealed type is '__main__.E' |
| |
| def get_member(name: str) -> E: |
| val = E[name] |
| return val |
| |
| reveal_type(get_member('a')) # N: Revealed type is '__main__.E' |
| |
| [case testGenericEnum] |
| from enum import Enum |
| from typing import Generic, TypeVar |
| |
| T = TypeVar('T') |
| |
| class F(Generic[T], Enum): # E: Enum class cannot be generic |
| x: T |
| y: T |
| |
| reveal_type(F[int].x) # N: Revealed type is '__main__.F[builtins.int*]' |
| |
| [case testEnumFlag] |
| from enum import Flag |
| class C(Flag): |
| a = 1 |
| b = 2 |
| x = C.a |
| if int(): |
| x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "C") |
| if int(): |
| x = x | C.b |
| |
| [case testEnumIntFlag] |
| from enum import IntFlag |
| class C(IntFlag): |
| a = 1 |
| b = 2 |
| x = C.a |
| if int(): |
| x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "C") |
| if int(): |
| x = x | C.b |
| |
| [case testAnonymousEnum] |
| from enum import Enum |
| class A: |
| def f(self) -> None: |
| class E(Enum): |
| a = 1 |
| self.x = E.a |
| a = A() |
| reveal_type(a.x) |
| [out] |
| main:8: note: Revealed type is '__main__.E@4' |
| |
| [case testEnumInClassBody] |
| from enum import Enum |
| class A: |
| class E(Enum): |
| a = 1 |
| class B: |
| class E(Enum): |
| a = 1 |
| x = A.E.a |
| y = B.E.a |
| if int(): |
| x = y # E: Incompatible types in assignment (expression has type "__main__.B.E", variable has type "__main__.A.E") |
| |
| [case testFunctionalEnumString] |
| from enum import Enum, IntEnum |
| E = Enum('E', 'foo bar') |
| I = IntEnum('I', ' bar, baz ') |
| reveal_type(E.foo) |
| reveal_type(E.bar.value) |
| reveal_type(I.bar) |
| reveal_type(I.baz.value) |
| [out] |
| main:4: note: Revealed type is 'Literal[__main__.E.foo]?' |
| main:5: note: Revealed type is 'Any' |
| main:6: note: Revealed type is 'Literal[__main__.I.bar]?' |
| main:7: note: Revealed type is 'builtins.int' |
| |
| [case testFunctionalEnumListOfStrings] |
| from enum import Enum, IntEnum |
| E = Enum('E', ('foo', 'bar')) |
| F = IntEnum('F', ['bar', 'baz']) |
| reveal_type(E.foo) |
| reveal_type(F.baz) |
| [out] |
| main:4: note: Revealed type is 'Literal[__main__.E.foo]?' |
| main:5: note: Revealed type is 'Literal[__main__.F.baz]?' |
| |
| [case testFunctionalEnumListOfPairs] |
| from enum import Enum, IntEnum |
| E = Enum('E', [('foo', 1), ['bar', 2]]) |
| F = IntEnum('F', (['bar', 1], ('baz', 2))) |
| reveal_type(E.foo) |
| reveal_type(F.baz) |
| reveal_type(E.foo.value) |
| reveal_type(F.bar.name) |
| [out] |
| main:4: note: Revealed type is 'Literal[__main__.E.foo]?' |
| main:5: note: Revealed type is 'Literal[__main__.F.baz]?' |
| main:6: note: Revealed type is 'Literal[1]?' |
| main:7: note: Revealed type is 'Literal['bar']?' |
| |
| [case testFunctionalEnumDict] |
| from enum import Enum, IntEnum |
| E = Enum('E', {'foo': 1, 'bar': 2}) |
| F = IntEnum('F', {'bar': 1, 'baz': 2}) |
| reveal_type(E.foo) |
| reveal_type(F.baz) |
| reveal_type(E.foo.value) |
| reveal_type(F.bar.name) |
| [out] |
| main:4: note: Revealed type is 'Literal[__main__.E.foo]?' |
| main:5: note: Revealed type is 'Literal[__main__.F.baz]?' |
| main:6: note: Revealed type is 'Literal[1]?' |
| main:7: note: Revealed type is 'Literal['bar']?' |
| |
| |
| [case testEnumKeywordsArgs] |
| from enum import Enum, IntEnum |
| |
| PictureSize = Enum('PictureSize', 'P0 P1 P2 P3 P4 P5 P6 P7 P8', type=str, module=__name__) |
| fake_enum1 = Enum('fake_enum1', ['a', 'b']) |
| fake_enum2 = Enum('fake_enum1', names=['a', 'b']) |
| fake_enum3 = Enum(value='fake_enum1', names=['a', 'b']) |
| fake_enum4 = Enum(value='fake_enum1', names=['a', 'b'] , module=__name__) |
| |
| [case testFunctionalEnumErrors] |
| from enum import Enum, IntEnum |
| A = Enum('A') |
| B = Enum('B', 42) |
| C = Enum('C', 'a b', 'x', 'y', 'z', 'p', 'q') |
| D = Enum('D', foo) |
| bar = 'x y z' |
| E = Enum('E', bar) |
| I = IntEnum('I') |
| J = IntEnum('I', 42) |
| K = IntEnum('I', 'p q', 'x', 'y', 'z', 'p', 'q') |
| L = Enum('L', ' ') |
| M = Enum('M', ()) |
| N = IntEnum('M', []) |
| P = Enum('P', [42]) |
| Q = Enum('Q', [('a', 42, 0)]) |
| R = IntEnum('R', [[0, 42]]) |
| S = Enum('S', {1: 1}) |
| T = Enum('T', keyword='a b') |
| U = Enum('U', *['a']) |
| V = Enum('U', **{'a': 1}) |
| W = Enum('W', 'a b') |
| W.c |
| [typing fixtures/typing-medium.pyi] |
| [out] |
| main:2: error: Too few arguments for Enum() |
| main:3: error: Enum() expects a string, tuple, list or dict literal as the second argument |
| main:4: error: Too many arguments for Enum() |
| main:5: error: Enum() expects a string, tuple, list or dict literal as the second argument |
| main:5: error: Name 'foo' is not defined |
| main:7: error: Enum() expects a string, tuple, list or dict literal as the second argument |
| main:8: error: Too few arguments for IntEnum() |
| main:9: error: IntEnum() expects a string, tuple, list or dict literal as the second argument |
| 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 |
| 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_python2-skip] |
| # 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') |
| Gu = Enum(u'Gu', {u'a': 1}) |
| Gb = Enum(b'Gb', {b'a': 1}) |
| Hu = Enum(u'Hu', [u'a']) |
| Hb = Enum(b'Hb', [b'a']) |
| 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 'builtins.int' |
| reveal_type(A3.x._value_) # N: Revealed type is 'builtins.int' |
| |
| 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 'builtins.int' |
| reveal_type(B3.x._value_) # N: Revealed type is 'builtins.int' |
| |
| # 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 'builtins.int' |
| reveal_type(C3.x._value_) # N: Revealed type is 'builtins.int' |
| |
| 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 'builtins.int' |
| reveal_type(D3.x._value_) # N: Revealed type is 'builtins.int' |
| |
| # 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 'builtins.int' |
| reveal_type(E3.x._value_) # N: Revealed type is 'builtins.int' |
| |
| |
| # 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 'builtins.int' |
| [out2] |
| main:2: note: Revealed type is 'builtins.str' |
| |
| [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 |
| |
| 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 |
| |
| 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 |
| |
| 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 |
| [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]' |
| 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]' |
| |
| 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) |
| 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) |
| |
| if y is z: |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(z) # N: Revealed type is 'Literal[__main__.Foo.A]?' |
| accepts_foo_a(z) |
| else: |
| reveal_type(y) # No output: this branch is unreachable |
| reveal_type(z) # No output: this branch is unreachable |
| if z is y: |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(z) # N: Revealed type is 'Literal[__main__.Foo.A]?' |
| accepts_foo_a(z) |
| else: |
| reveal_type(y) # No output: this branch is unreachable |
| reveal_type(z) # No output: this branch is unreachable |
| [builtins fixtures/bool.pyi] |
| |
| [case testEnumReachabilityNoNarrowingForUnionMessiness] |
| from enum import Enum |
| from typing_extensions import Literal |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| C = 3 |
| |
| x: Foo |
| y: Literal[Foo.A, Foo.B] |
| z: Literal[Foo.B, Foo.C] |
| |
| # For the sake of simplicity, no narrowing is done when the narrower type is a Union. |
| if x is y: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is 'Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]' |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is 'Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]' |
| |
| if y is z: |
| reveal_type(y) # N: Revealed type is 'Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]' |
| reveal_type(z) # N: Revealed type is 'Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]' |
| else: |
| reveal_type(y) # N: Revealed type is 'Union[Literal[__main__.Foo.A], Literal[__main__.Foo.B]]' |
| reveal_type(z) # N: Revealed type is 'Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testEnumReachabilityWithNone] |
| # flags: --strict-optional |
| from enum import Enum |
| from typing import Optional |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| C = 3 |
| |
| x: Optional[Foo] |
| if x: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[__main__.Foo, None]' |
| |
| if x is not None: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| else: |
| reveal_type(x) # N: Revealed type is 'None' |
| |
| if x is Foo.A: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C], None]' |
| [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]' |
| |
| 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]]' |
| |
| 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]]' |
| |
| [builtins fixtures/bool.pyi] |
| |
| [case testEnumReachabilityPEP484ExampleWithFinal] |
| # flags: --strict-optional |
| from typing import Union |
| from typing_extensions import Final |
| from enum import Enum |
| |
| class Empty(Enum): |
| token = 0 |
| _empty: Final = Empty.token |
| |
| def func(x: Union[int, None, Empty] = _empty) -> int: |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ |
| # E: Unsupported left operand type for + ("Empty") \ |
| # N: Left operand is of type "Union[int, None, Empty]" |
| if x is _empty: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Empty.token]' |
| return 0 |
| elif x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| return 1 |
| else: # At this point typechecker knows that x can only have type int |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| return x + 2 |
| [builtins fixtures/primitives.pyi] |
| |
| [case testEnumReachabilityPEP484ExampleWithMultipleValues] |
| from typing import Union |
| from enum import Enum |
| |
| class Reason(Enum): |
| timeout = 1 |
| error = 2 |
| |
| def process(response: Union[str, Reason] = '') -> str: |
| if response is Reason.timeout: |
| reveal_type(response) # N: Revealed type is 'Literal[__main__.Reason.timeout]' |
| return 'TIMEOUT' |
| elif response is Reason.error: |
| reveal_type(response) # N: Revealed type is 'Literal[__main__.Reason.error]' |
| return 'ERROR' |
| else: |
| # response can be only str, all other possible values exhausted |
| reveal_type(response) # N: Revealed type is 'builtins.str' |
| return 'PROCESSED: ' + response |
| [builtins fixtures/primitives.pyi] |
| |
| |
| [case testEnumReachabilityPEP484ExampleSingleton] |
| # flags: --strict-optional |
| from typing import Union |
| from typing_extensions import Final |
| from enum import Enum |
| |
| class Empty(Enum): |
| token = 0 |
| _empty = Empty.token |
| |
| def func(x: Union[int, None, Empty] = _empty) -> int: |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ |
| # E: Unsupported left operand type for + ("Empty") \ |
| # N: Left operand is of type "Union[int, None, Empty]" |
| if x is _empty: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Empty.token]' |
| return 0 |
| elif x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| return 1 |
| else: # At this point typechecker knows that x can only have type int |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| return x + 2 |
| [builtins fixtures/primitives.pyi] |
| |
| [case testEnumReachabilityPEP484ExampleSingletonWithMethod] |
| # flags: --strict-optional |
| from typing import Union |
| from typing_extensions import Final |
| from enum import Enum |
| |
| class Empty(Enum): |
| token = lambda x: x |
| |
| def f(self) -> int: |
| return 1 |
| |
| _empty = Empty.token |
| |
| def func(x: Union[int, None, Empty] = _empty) -> int: |
| boom = x + 42 # E: Unsupported left operand type for + ("None") \ |
| # E: Unsupported left operand type for + ("Empty") \ |
| # N: Left operand is of type "Union[int, None, Empty]" |
| if x is _empty: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Empty.token]' |
| return 0 |
| elif x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| return 1 |
| else: # At this point typechecker knows that x can only have type int |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| return x + 2 |
| [builtins fixtures/primitives.pyi] |
| |
| [case testAssignEnumAsAttribute] |
| from enum import Enum |
| |
| class A: |
| def __init__(self) -> None: |
| self.b = Enum("x", [("foo", "bar")]) # E: Enum type as attribute is not supported |
| |
| reveal_type(A().b) # N: Revealed type is 'Any' |
| |
| [case testEnumReachabilityWithChaining] |
| from enum import Enum |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| |
| x: Foo |
| y: Foo |
| |
| # We can't narrow anything in the else cases -- what if |
| # x is Foo.A and y is Foo.B or vice versa, for example? |
| if x is y is Foo.A: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| elif x is y is Foo.B: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| |
| if x is Foo.A is y: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| elif x is Foo.B is y: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| |
| if Foo.A is x is y: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| elif Foo.B is x is y: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| |
| [builtins fixtures/primitives.pyi] |
| |
| [case testEnumReachabilityWithChainingDisjoint] |
| # flags: --warn-unreachable |
| from enum import Enum |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| |
| # Used to divide up a chained comparison into multiple identity groups |
| def __lt__(self, other: object) -> bool: return True |
| |
| x: Foo |
| y: Foo |
| |
| # No conflict |
| if x is Foo.A < y is Foo.B: |
| reveal_type(x) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(y) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| else: |
| # Note: we can't narrow in this case. What if both x and y |
| # are Foo.A, for example? |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(y) # N: Revealed type is '__main__.Foo' |
| |
| # The standard output when we end up inferring two disjoint facts about the same expr |
| if x is Foo.A and x is Foo.B: |
| reveal_type(x) # E: Statement is unreachable |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| |
| # ..and we get the same result if we have two disjoint groups within the same comp expr |
| if x is Foo.A < x is Foo.B: |
| reveal_type(x) # E: Statement is unreachable |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| [builtins fixtures/primitives.pyi] |
| |
| [case testEnumReachabilityWithChainingDirectConflict] |
| # flags: --warn-unreachable |
| from enum import Enum |
| from typing_extensions import Literal, Final |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| C = 3 |
| |
| x: Foo |
| if x is Foo.A is Foo.B: |
| reveal_type(x) # E: Statement is unreachable |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| |
| literal_a: Literal[Foo.A] |
| literal_b: Literal[Foo.B] |
| if x is literal_a is literal_b: |
| reveal_type(x) # E: Statement is unreachable |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| |
| final_a: Final = Foo.A |
| final_b: Final = Foo.B |
| if x is final_a is final_b: |
| reveal_type(x) # E: Statement is unreachable |
| else: |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| reveal_type(x) # N: Revealed type is '__main__.Foo' |
| |
| [builtins fixtures/primitives.pyi] |
| |
| [case testEnumReachabilityWithChainingBigDisjoints] |
| # flags: --warn-unreachable |
| from enum import Enum |
| from typing_extensions import Literal, Final |
| |
| class Foo(Enum): |
| A = 1 |
| B = 2 |
| C = 3 |
| |
| def __lt__(self, other: object) -> bool: return True |
| |
| x0: Foo |
| x1: Foo |
| x2: Foo |
| x3: Foo |
| x4: Foo |
| x5: Foo |
| |
| if x0 is x1 is Foo.A is x2 < x3 is Foo.B is x4 is x5: |
| reveal_type(x0) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(x1) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| reveal_type(x2) # N: Revealed type is 'Literal[__main__.Foo.A]' |
| |
| reveal_type(x3) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| reveal_type(x4) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| reveal_type(x5) # N: Revealed type is 'Literal[__main__.Foo.B]' |
| else: |
| # We unfortunately can't narrow away anything. For example, |
| # what if x0 == Foo.A and x1 == Foo.B or vice versa? |
| reveal_type(x0) # N: Revealed type is '__main__.Foo' |
| reveal_type(x1) # N: Revealed type is '__main__.Foo' |
| reveal_type(x2) # N: Revealed type is '__main__.Foo' |
| |
| reveal_type(x3) # N: Revealed type is '__main__.Foo' |
| reveal_type(x4) # N: Revealed type is '__main__.Foo' |
| reveal_type(x5) # N: Revealed type is '__main__.Foo' |
| [builtins fixtures/primitives.pyi] |
| |
| [case testPrivateAttributeNotAsEnumMembers] |
| import enum |
| |
| class Comparator(enum.Enum): |
| LessThan = "<" |
| LessThanOrEqualTo = "<=" |
| EqualTo = "==" |
| NotEqualTo = "!=" |
| GreaterThanOrEqualTo = ">=" |
| GreaterThan = ">" |
| |
| __foo__ = { |
| LessThan: 1, |
| LessThanOrEqualTo: 2, |
| EqualTo: 3, |
| NotEqualTo: 4, |
| GreaterThanOrEqualTo: 5, |
| GreaterThan: 6, |
| } |
| |
| def foo(self) -> int: |
| return Comparator.__foo__[self.value] |
| |
| reveal_type(Comparator.__foo__) # N: Revealed type is 'builtins.dict[builtins.str, builtins.int]' |
| [builtins fixtures/dict.pyi] |