| -- Methods |
| -- ------- |
| |
| |
| [case testMethodCall] |
| |
| a = None # type: A |
| b = None # type: B |
| |
| a.foo(B()) # Fail |
| a.bar(B(), A()) # Fail |
| |
| a.foo(A()) |
| b.bar(B(), A()) |
| |
| class A: |
| def foo(self, x: 'A') -> None: pass |
| class B: |
| def bar(self, x: 'B', y: A) -> None: pass |
| [out] |
| main:5: error: Argument 1 to "foo" of "A" has incompatible type "B"; expected "A" |
| main:6: error: "A" has no attribute "bar" |
| |
| [case testMethodCallWithSubtype] |
| |
| a = None # type: A |
| a.foo(A()) |
| a.foo(B()) |
| a.bar(A()) # Fail |
| a.bar(B()) |
| |
| class A: |
| def foo(self, x: 'A') -> None: pass |
| def bar(self, x: 'B') -> None: pass |
| class B(A): pass |
| [out] |
| main:5: error: Argument 1 to "bar" of "A" has incompatible type "A"; expected "B" |
| |
| [case testInheritingMethod] |
| |
| a = None # type: B |
| a.foo(A()) # Fail |
| a.foo(B()) |
| |
| class A: |
| def foo(self, x: 'B') -> None: pass |
| class B(A): pass |
| [targets __main__, __main__, __main__.A.foo] |
| [out] |
| main:3: error: Argument 1 to "foo" of "A" has incompatible type "A"; expected "B" |
| |
| [case testMethodCallWithInvalidNumberOfArguments] |
| |
| a = None # type: A |
| a.foo() # Fail |
| a.foo(object(), A()) # Fail |
| |
| class A: |
| def foo(self, x: 'A') -> None: pass |
| [out] |
| main:3: error: Missing positional argument "x" in call to "foo" of "A" |
| main:4: error: Too many arguments for "foo" of "A" |
| main:4: error: Argument 1 to "foo" of "A" has incompatible type "object"; expected "A" |
| |
| [case testMethodBody] |
| import typing |
| class A: |
| def f(self) -> None: |
| a = object() # type: A # Fail |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "object", variable has type "A") |
| |
| [case testMethodArguments] |
| import typing |
| class A: |
| def f(self, a: 'A', b: 'B') -> None: |
| if int(): |
| a = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| b = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a = A() |
| b = B() |
| a = a |
| a = b # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| class B: pass |
| [out] |
| |
| [case testReturnFromMethod] |
| import typing |
| class A: |
| def f(self) -> 'A': |
| return B() # Fail |
| return A() |
| class B: pass |
| [out] |
| main:4: error: Incompatible return value type (got "B", expected "A") |
| |
| [case testSelfArgument] |
| import typing |
| class A: |
| def f(self) -> None: |
| o = self # type: B # Fail |
| self.g() # Fail |
| a = self # type: A |
| self.f() |
| class B: pass |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| main:5: error: "A" has no attribute "g" |
| |
| [case testAssignToMethodViaInstance] |
| import typing |
| class A: |
| def f(self): pass |
| A().f = None # E: Cannot assign to a method |
| |
| |
| [case testOverrideAttributeWithMethod] |
| # This was crashing: |
| # https://github.com/python/mypy/issues/10134 |
| from typing import Protocol |
| |
| class Base: |
| __hash__ = None |
| |
| class Derived(Base): |
| def __hash__(self) -> int: # E: Signature of "__hash__" incompatible with supertype "Base" |
| pass |
| |
| # Correct: |
| |
| class CallableProtocol(Protocol): |
| def __call__(self, arg: int) -> int: |
| pass |
| |
| class CorrectBase: |
| attr: CallableProtocol |
| |
| class CorrectDerived(CorrectBase): |
| def attr(self, arg: int) -> int: |
| pass |
| |
| [case testOverrideMethodWithAttribute] |
| # The reverse should not crash as well: |
| from typing import Callable |
| |
| class Base: |
| def __hash__(self) -> int: |
| pass |
| |
| class Derived(Base): |
| __hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]") |
| |
| |
| [case testOverridePartialAttributeWithMethod] |
| # This was crashing: https://github.com/python/mypy/issues/11686. |
| class Base: |
| def __init__(self, arg: int): |
| self.partial_type = [] # E: Need type annotation for "partial_type" (hint: "partial_type: List[<type>] = ...") |
| self.force_deferral = [] |
| |
| # Force inference of the `force_deferral` attribute in `__init__` to be |
| # deferred to a later pass by providing a definition in another context, |
| # which means `partial_type` remains only partially inferred. |
| force_deferral = [] # E: Need type annotation for "force_deferral" (hint: "force_deferral: List[<type>] = ...") |
| |
| |
| class Derived(Base): |
| def partial_type(self) -> int: # E: Signature of "partial_type" incompatible with supertype "Base" |
| ... |
| |
| |
| -- Attributes |
| -- ---------- |
| |
| |
| [case testReferToInvalidAttribute] |
| |
| class A: |
| def __init__(self) -> None: |
| self.x = object() |
| a: A |
| a.y # E: "A" has no attribute "y" |
| a.y = object() # E: "A" has no attribute "y" |
| a.x |
| a.x = object() |
| |
| [case testReferToInvalidAttributeUnannotatedInit] |
| class A: |
| def __init__(self): |
| self.x = object() |
| |
| a: A |
| a.y # E: "A" has no attribute "y" |
| a.y = object() # E: "A" has no attribute "y" |
| a.x |
| a.x = object() |
| |
| [case testArgumentTypeInference] |
| |
| class A: |
| def __init__(self, aa: 'A', bb: 'B') -> None: |
| self.a = aa |
| self.b = bb |
| class B: pass |
| a = None # type: A |
| b = None # type: B |
| a.a = b # Fail |
| a.b = a # Fail |
| b.a # Fail |
| a.a = a |
| a.b = b |
| [out] |
| main:9: error: Incompatible types in assignment (expression has type "B", variable has type "A") |
| main:10: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| main:11: error: "B" has no attribute "a" |
| |
| [case testExplicitAttributeInBody] |
| |
| a = None # type: A |
| a.x = object() # Fail |
| a.x = A() |
| class A: |
| x = None # type: A |
| [out] |
| main:3: error: Incompatible types in assignment (expression has type "object", variable has type "A") |
| |
| [case testAttributeDefinedInNonInitMethod] |
| import typing |
| class A: |
| def f(self) -> None: |
| self.x = 1 |
| self.y = '' |
| self.x = 1 |
| a = A() |
| a.x = 1 |
| a.y = '' |
| a.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| a.z = 0 # E: "A" has no attribute "z" |
| |
| [case testInheritanceAndAttributeAssignment] |
| import typing |
| class A: |
| def f(self) -> None: |
| self.x = 0 |
| class B(A): |
| def f(self) -> None: |
| self.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| [targets __main__, __main__.A.f, __main__.B.f] |
| |
| [case testAssignmentToAttributeInMultipleMethods] |
| import typing |
| class A: |
| def f(self) -> None: |
| self.x = 0 |
| def g(self) -> None: |
| self.x = '' # Fail |
| def __init__(self) -> None: |
| self.x = '' # Fail |
| [out] |
| main:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") |
| main:8: error: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testClassNamesDefinedOnSelUsedInClassBody] |
| class A(object): |
| def f(self): |
| self.attr = 1 |
| attr = 0 |
| |
| class B(object): |
| attr = 0 |
| def f(self): |
| self.attr = 1 |
| |
| class C(object): |
| attr = 0 |
| def f(self): |
| self.attr = 1 |
| attr = 0 |
| |
| class D(object): |
| def g(self): |
| self.attr = 1 |
| attr = 0 |
| def f(self): |
| self.attr = 1 |
| [out] |
| |
| [case testClassNamesDefinedOnSelUsedInClassBodyReveal] |
| |
| class A(object): |
| def f(self) -> None: |
| self.attr = 1 |
| attr # E: Name "attr" is not defined |
| |
| class B(object): |
| attr = 0 |
| def f(self) -> None: |
| reveal_type(self.attr) # N: Revealed type is "builtins.int" |
| [out] |
| |
| |
| -- Method overriding |
| -- ----------------- |
| |
| |
| [case testMethodOverridingWithIdenticalSignature] |
| import typing |
| class A: |
| def f(self, x: 'A') -> None: pass |
| def g(self, x: 'B' , y: object) -> 'A': pass |
| def h(self) -> None: pass |
| class B(A): |
| def f(self, x: A) -> None: pass |
| def g(self, x: 'B' , y: object) -> A: pass |
| def h(self) -> None: pass |
| [out] |
| |
| [case testMethodOverridingWithCovariantType] |
| import typing |
| class A: |
| def f(self, x: 'A', y: 'B') -> 'A': pass |
| def g(self, x: 'A', y: 'B') -> 'A': pass |
| class B(A): |
| def f(self, x: A, y: 'B') -> 'B': pass |
| def g(self, x: A, y: A) -> 'A': pass |
| [out] |
| |
| [case testMethodOverridingWithIncompatibleTypes] |
| import typing |
| class A: |
| def f(self, x: 'A', y: 'B') -> 'A': pass |
| def g(self, x: 'A', y: 'B') -> 'A': pass |
| def h(self, x: 'A', y: 'B') -> 'A': pass |
| class B(A): |
| def f(self, x: 'B', y: 'B') -> A: pass # Fail |
| def g(self, x: A, y: A) -> A: pass |
| def h(self, x: A, y: 'B') -> object: pass # Fail |
| [out] |
| main:7: error: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "A" |
| main:7: note: This violates the Liskov substitution principle |
| main:7: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| main:9: error: Return type "object" of "h" incompatible with return type "A" in supertype "A" |
| |
| [case testEqMethodsOverridingWithNonObjects] |
| class A: |
| def __eq__(self, other: A) -> bool: pass # Fail |
| [builtins fixtures/attr.pyi] |
| [out] |
| main:2: error: Argument 1 of "__eq__" is incompatible with supertype "object"; supertype defines the argument type as "object" |
| main:2: note: This violates the Liskov substitution principle |
| main:2: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| main:2: note: It is recommended for "__eq__" to work with arbitrary objects, for example: |
| main:2: note: def __eq__(self, other: object) -> bool: |
| main:2: note: if not isinstance(other, A): |
| main:2: note: return NotImplemented |
| main:2: note: return <logic to compare two A instances> |
| |
| [case testMethodOverridingWithIncompatibleArgumentCount] |
| import typing |
| class A: |
| def f(self, x: 'A') -> None: pass |
| def g(self, x: 'A', y: 'B') -> 'A': pass |
| class B(A): |
| def f(self, x: A, y: A) -> None: pass # Fail |
| def g(self, x: A) -> A: pass # Fail |
| [out] |
| main:6: error: Signature of "f" incompatible with supertype "A" |
| main:6: note: Superclass: |
| main:6: note: def f(self, x: A) -> None |
| main:6: note: Subclass: |
| main:6: note: def f(self, x: A, y: A) -> None |
| main:7: error: Signature of "g" incompatible with supertype "A" |
| main:7: note: Superclass: |
| main:7: note: def g(self, x: A, y: B) -> A |
| main:7: note: Subclass: |
| main:7: note: def g(self, x: A) -> A |
| |
| [case testMethodOverridingAcrossDeepInheritanceHierarchy1] |
| import typing |
| class A: |
| def f(self, x: 'B') -> None: pass |
| class B(A): pass |
| class C(B): # with gap in implementations |
| def f(self, x: 'C') -> None: # Fail |
| pass |
| [out] |
| main:6: error: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "B" |
| main:6: note: This violates the Liskov substitution principle |
| main:6: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| |
| [case testMethodOverridingAcrossDeepInheritanceHierarchy2] |
| import typing |
| class A: |
| def f(self) -> 'B': pass |
| class B(A): |
| def f(self) -> 'C': pass |
| class C(B): # with multiple implementations |
| def f(self) -> B: # Fail |
| pass |
| [out] |
| main:7: error: Return type "B" of "f" incompatible with return type "C" in supertype "B" |
| |
| [case testMethodOverridingWithVoidReturnValue] |
| import typing |
| class A: |
| def f(self) -> None: pass |
| def g(self) -> 'A': pass |
| class B(A): |
| def f(self) -> A: pass # Fail |
| def g(self) -> None: pass |
| [out] |
| main:6: error: Return type "A" of "f" incompatible with return type "None" in supertype "A" |
| |
| [case testOverride__new__WithDifferentSignature] |
| class A: |
| def __new__(cls, x: int) -> A: |
| pass |
| |
| class B(A): |
| def __new__(cls) -> B: |
| pass |
| |
| [case testOverride__new__AndCallObject] |
| from typing import TypeVar, Generic |
| |
| class A: |
| def __new__(cls, x: int) -> 'A': |
| return object.__new__(cls) |
| |
| T = TypeVar('T') |
| class B(Generic[T]): |
| def __new__(cls, foo: T) -> 'B[T]': |
| x = object.__new__(cls) |
| # object.__new__ doesn't have a great type :( |
| reveal_type(x) # N: Revealed type is "Any" |
| return x |
| |
| [builtins fixtures/__new__.pyi] |
| |
| [case testInnerFunctionNotOverriding] |
| class A: |
| def f(self) -> int: pass |
| |
| class B(A): |
| def g(self) -> None: |
| def f(self) -> str: pass |
| |
| [case testOverride__init_subclass__WithDifferentSignature] |
| class A: |
| def __init_subclass__(cls, x: int) -> None: pass |
| class B(A): # E: Missing positional argument "x" in call to "__init_subclass__" of "A" |
| def __init_subclass__(cls) -> None: pass |
| |
| [case testOverrideWithDecorator] |
| from typing import Callable |
| |
| def int_to_none(f: Callable[..., int]) -> Callable[..., None]: ... |
| def str_to_int(f: Callable[..., str]) -> Callable[..., int]: ... |
| |
| class A: |
| def f(self) -> None: pass |
| def g(self) -> str: pass |
| def h(self) -> None: pass |
| |
| class B(A): |
| @int_to_none |
| def f(self) -> int: pass |
| @str_to_int |
| def g(self) -> str: pass # Fail |
| @int_to_none |
| @str_to_int |
| def h(self) -> str: pass |
| [out] |
| main:15: error: Signature of "g" incompatible with supertype "A" |
| main:15: note: Superclass: |
| main:15: note: def g(self) -> str |
| main:15: note: Subclass: |
| main:15: note: def g(*Any, **Any) -> int |
| |
| [case testOverrideDecorated] |
| from typing import Callable |
| |
| def str_to_int(f: Callable[..., str]) -> Callable[..., int]: ... |
| |
| class A: |
| @str_to_int |
| def f(self) -> str: pass |
| @str_to_int |
| def g(self) -> str: pass |
| @str_to_int |
| def h(self) -> str: pass |
| |
| class B(A): |
| def f(self) -> int: pass |
| def g(self) -> str: pass # Fail |
| @str_to_int |
| def h(self) -> str: pass |
| [out] |
| main:15: error: Signature of "g" incompatible with supertype "A" |
| main:15: note: Superclass: |
| main:15: note: def g(*Any, **Any) -> int |
| main:15: note: Subclass: |
| main:15: note: def g(self) -> str |
| |
| [case testOverrideWithDecoratorReturningAny] |
| def dec(f): pass |
| |
| class A: |
| def f(self) -> str: pass |
| |
| class B(A): |
| @dec |
| def f(self) -> int: pass |
| |
| [case testOverrideWithDecoratorReturningInstance] |
| def dec(f) -> str: pass |
| |
| class A: |
| def f(self) -> str: pass |
| @dec |
| def g(self) -> int: pass |
| @dec |
| def h(self) -> int: pass |
| |
| class B(A): |
| @dec |
| def f(self) -> int: pass # E: Signature of "f" incompatible with supertype "A" |
| def g(self) -> int: pass # E: Signature of "g" incompatible with supertype "A" |
| @dec |
| def h(self) -> str: pass |
| |
| [case testOverrideStaticMethodWithStaticMethod] |
| class A: |
| @staticmethod |
| def f(x: int, y: str) -> None: pass |
| @staticmethod |
| def g(x: int, y: str) -> None: pass |
| |
| class B(A): |
| @staticmethod |
| def f(x: int, y: str) -> None: pass |
| @staticmethod |
| def g(x: str, y: str) -> None: pass # E: Argument 1 of "g" is incompatible with supertype "A"; supertype defines the argument type as "int" \ |
| # N: This violates the Liskov substitution principle \ |
| # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testOverrideClassMethodWithClassMethod] |
| class A: |
| @classmethod |
| def f(cls, x: int, y: str) -> None: pass |
| @classmethod |
| def g(cls, x: int, y: str) -> None: pass |
| |
| class B(A): |
| @classmethod |
| def f(cls, x: int, y: str) -> None: pass |
| @classmethod |
| def g(cls, x: str, y: str) -> None: pass # E: Argument 1 of "g" is incompatible with supertype "A"; supertype defines the argument type as "int" \ |
| # N: This violates the Liskov substitution principle \ |
| # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testOverrideClassMethodWithStaticMethod] |
| class A: |
| @classmethod |
| def f(cls, x: int) -> None: pass |
| @classmethod |
| def g(cls, x: int) -> int: pass |
| @classmethod |
| def h(cls) -> int: pass |
| |
| class B(A): |
| @staticmethod |
| def f(x: int) -> None: pass |
| @staticmethod |
| def g(x: str) -> int: pass # E: Argument 1 of "g" is incompatible with supertype "A"; supertype defines the argument type as "int" \ |
| # N: This violates the Liskov substitution principle \ |
| # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| @staticmethod |
| def h() -> int: pass |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testOverrideStaticMethodWithClassMethod] |
| class A: |
| @staticmethod |
| def f(x: int) -> None: pass |
| @staticmethod |
| def g(x: str) -> int: pass |
| @staticmethod |
| def h() -> int: pass |
| |
| class B(A): |
| @classmethod |
| def f(cls, x: int) -> None: pass |
| @classmethod |
| def g(cls, x: int) -> int: pass # E: Argument 1 of "g" is incompatible with supertype "A"; supertype defines the argument type as "str" \ |
| # N: This violates the Liskov substitution principle \ |
| # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| @classmethod |
| def h(cls) -> int: pass |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testAllowCovarianceInReadOnlyAttributes] |
| from typing import Callable, TypeVar |
| |
| T = TypeVar('T') |
| |
| class X: |
| pass |
| |
| |
| class Y(X): |
| pass |
| |
| def dec(f: Callable[..., T]) -> T: pass |
| |
| class A: |
| @dec |
| def f(self) -> X: pass |
| |
| class B(A): |
| @dec |
| def f(self) -> Y: pass |
| |
| |
| -- Constructors |
| -- ------------ |
| |
| |
| [case testTrivialConstructor] |
| import typing |
| a = A() # type: A |
| b = A() # type: B # Fail |
| class A: |
| def __init__(self) -> None: pass |
| class B: pass |
| [out] |
| main:3: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testConstructor] |
| import typing |
| a = A(B()) # type: A |
| aa = A(object()) # type: A # Fail |
| b = A(B()) # type: B # Fail |
| class A: |
| def __init__(self, x: 'B') -> None: pass |
| class B: pass |
| [out] |
| main:3: error: Argument 1 to "A" has incompatible type "object"; expected "B" |
| main:4: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testConstructorWithTwoArguments] |
| import typing |
| a = A(C(), B()) # type: A # Fail |
| |
| class A: |
| def __init__(self, x: 'B', y: 'C') -> None: pass |
| class B: pass |
| class C(B): pass |
| [out] |
| main:2: error: Argument 2 to "A" has incompatible type "B"; expected "C" |
| |
| [case testInheritedConstructor] |
| import typing |
| b = B(C()) # type: B |
| a = B(D()) # type: A # Fail |
| class A: |
| def __init__(self, x: 'C') -> None: pass |
| class B(A): pass |
| class C: pass |
| class D: pass |
| [out] |
| main:3: error: Argument 1 to "B" has incompatible type "D"; expected "C" |
| |
| [case testOverridingWithIncompatibleConstructor] |
| import typing |
| A() # Fail |
| B(C()) # Fail |
| A(C()) |
| B() |
| class A: |
| def __init__(self, x: 'C') -> None: pass |
| class B(A): |
| def __init__(self) -> None: pass |
| class C: pass |
| [out] |
| main:2: error: Missing positional argument "x" in call to "A" |
| main:3: error: Too many arguments for "B" |
| |
| [case testConstructorWithReturnValueType] |
| import typing |
| class A: |
| def __init__(self) -> 'A': pass |
| [out] |
| main:3: error: The return type of "__init__" must be None |
| |
| [case testConstructorWithImplicitReturnValueType] |
| import typing |
| class A: |
| def __init__(self, x: int): pass |
| [out] |
| |
| [case testDecoratedConstructorWithImplicitReturnValueType] |
| import typing |
| from typing import Callable |
| |
| def deco(fn: Callable) -> Callable: |
| return fn |
| |
| class A: |
| @deco |
| def __init__(self, x: int): pass |
| [out] |
| |
| [case testOverloadedConstructorWithImplicitReturnValueType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class Foo: |
| @overload |
| def __init__(self, a: int): |
| pass |
| |
| @overload |
| def __init__(self, a: str): |
| pass |
| |
| [case testConstructorWithAnyReturnValueType] |
| import typing |
| from typing import Any |
| class A: |
| def __init__(self) -> Any: pass # E: The return type of "__init__" must be None |
| |
| [case testDecoratedConstructorWithAnyReturnValueType] |
| import typing |
| from typing import Callable, Any |
| |
| def deco(fn: Callable) -> Callable: |
| return fn |
| |
| class A: |
| @deco |
| def __init__(self) -> Any: pass # E: The return type of "__init__" must be None |
| |
| [case testOverloadedConstructorWithAnyReturnValueType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class Foo: |
| @overload |
| def __init__(self, a: int) -> Any: # E: The return type of "__init__" must be None |
| pass |
| |
| @overload |
| def __init__(self, a: str) -> Any: # E: The return type of "__init__" must be None |
| pass |
| |
| [case testInitSubclassWithReturnValueType] |
| import typing |
| class A: |
| def __init_subclass__(cls) -> 'A': pass |
| [out] |
| main:3: error: The return type of "__init_subclass__" must be None |
| |
| [case testInitSubclassWithImplicitReturnValueType] |
| import typing |
| class A: |
| def __init_subclass__(cls, x: int=1): pass |
| [out] |
| |
| [case testDecoratedInitSubclassWithImplicitReturnValueType] |
| import typing |
| from typing import Callable |
| |
| def deco(fn: Callable) -> Callable: |
| return fn |
| |
| class A: |
| @deco |
| def __init_subclass__(cls, x: int=1): pass |
| [out] |
| |
| [case testOverloadedInitSubclassWithImplicitReturnValueType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class Foo: |
| @overload |
| def __init_subclass__(cls, a: int): |
| pass |
| |
| @overload |
| def __init_subclass__(cls, a: str): |
| pass |
| |
| [case testInitSubclassWithAnyReturnValueType] |
| import typing |
| from typing import Any |
| class A: |
| def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None |
| |
| [case testDecoratedInitSubclassWithAnyReturnValueType] |
| import typing |
| from typing import Callable, Any |
| |
| def deco(fn: Callable) -> Callable: |
| return fn |
| |
| class A: |
| @deco |
| def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None |
| [out] |
| |
| [case testOverloadedInitSubclassWithAnyReturnValueType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class Foo: |
| @overload |
| def __init_subclass__(cls, a: int) -> Any: # E: The return type of "__init_subclass__" must be None |
| pass |
| |
| @overload |
| def __init_subclass__(cls, a: str) -> Any: # E: The return type of "__init_subclass__" must be None |
| pass |
| |
| [case testGlobalFunctionInitWithReturnType] |
| import typing |
| a = __init__() # type: A |
| b = __init__() # type: B # Fail |
| def __init__() -> 'A': pass |
| class A: pass |
| class B: pass |
| [out] |
| main:3: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testAccessingInit] |
| from typing import Any, cast |
| class A: |
| def __init__(self, a: 'A') -> None: pass |
| a = None # type: A |
| a.__init__(a) # E: Accessing "__init__" on an instance is unsound, since instance.__init__ could be from an incompatible subclass |
| (cast(Any, a)).__init__(a) |
| |
| [case testDeepInheritanceHierarchy] |
| import typing |
| d = C() # type: D # E: Incompatible types in assignment (expression has type "C", variable has type "D") |
| if int(): |
| d = B() # E: Incompatible types in assignment (expression has type "B", variable has type "D") |
| if int(): |
| d = A() # E: Incompatible types in assignment (expression has type "A", variable has type "D") |
| if int(): |
| d = D2() # E: Incompatible types in assignment (expression has type "D2", variable has type "D") |
| a = D() # type: A |
| if int(): |
| a = D2() |
| b = D() # type: B |
| if int(): |
| b = D2() |
| |
| class A: pass |
| class B(A): pass |
| class C(B): pass |
| class D(C): pass |
| class D2(C): pass |
| |
| |
| -- Attribute access in class body |
| -- ------------------------------ |
| |
| |
| [case testDataAttributeRefInClassBody] |
| import typing |
| class B: pass |
| class A: |
| x = B() |
| y = x |
| b = x # type: B |
| if int(): |
| b = x |
| c = x # type: A # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| if int(): |
| c = b # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| [out] |
| |
| [case testMethodRefInClassBody] |
| from typing import Callable |
| class B: pass |
| class A: |
| def f(self) -> None: pass |
| g = f |
| h = f # type: Callable[[A], None] |
| if int(): |
| h = f |
| g = h |
| ff = f # type: Callable[[B], None] # E: Incompatible types in assignment (expression has type "Callable[[A], None]", variable has type "Callable[[B], None]") |
| if int(): |
| g = ff # E: Incompatible types in assignment (expression has type "Callable[[B], None]", variable has type "Callable[[A], None]") |
| [out] |
| |
| |
| -- Arbitrary statements in class body |
| -- ---------------------------------- |
| |
| |
| [case testStatementsInClassBody] |
| import typing |
| class B: pass |
| class A: |
| for x in [A()]: |
| y = x |
| if int(): |
| y = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| if int(): |
| x = A() |
| if int(): |
| y = A() |
| if int(): |
| x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| [builtins fixtures/for.pyi] |
| [out] |
| |
| |
| -- Class attributes |
| -- ---------------- |
| |
| |
| [case testAccessMethodViaClass] |
| import typing |
| class A: |
| def f(self) -> None: pass |
| A.f(A()) |
| A.f(object()) # E: Argument 1 to "f" of "A" has incompatible type "object"; expected "A" |
| A.f() # E: Missing positional argument "self" in call to "f" of "A" |
| A.f(None, None) # E: Too many arguments for "f" of "A" |
| |
| [case testAccessAttributeViaClass] |
| import typing |
| class B: pass |
| class A: |
| x = None # type: A |
| a = A.x # type: A |
| b = A.x # type: B # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testAccessingUndefinedAttributeViaClass] |
| import typing |
| class A: pass |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testAccessingUndefinedAttributeViaClassWithOverloadedInit] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| @overload |
| def __init__(self): pass |
| @overload |
| def __init__(self, x): pass |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testAccessMethodOfClassWithOverloadedInit] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class A: |
| @overload |
| def __init__(self) -> None: pass |
| @overload |
| def __init__(self, x: Any) -> None: pass |
| def f(self) -> None: pass |
| A.f(A()) |
| A.f() # E: Missing positional argument "self" in call to "f" of "A" |
| |
| [case testAssignmentToClassDataAttribute] |
| import typing |
| class B: pass |
| class A: |
| x = None # type: B |
| A.x = B() |
| A.x = object() # E: Incompatible types in assignment (expression has type "object", variable has type "B") |
| |
| [case testAssignmentToInferredClassDataAttribute] |
| import typing |
| class B: pass |
| class A: |
| x = B() |
| A.x = B() |
| A.x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testInitMethodUnbound] |
| |
| class B: pass |
| class A: |
| def __init__(self, b: B) -> None: pass |
| a = None # type: A |
| b = None # type: B |
| A.__init__(a, b) |
| A.__init__(b, b) # E: Argument 1 to "__init__" of "A" has incompatible type "B"; expected "A" |
| A.__init__(a, a) # E: Argument 2 to "__init__" of "A" has incompatible type "A"; expected "B" |
| |
| [case testAssignToMethodViaClass] |
| import typing |
| class A: |
| def f(self): pass |
| A.f = None # E: Cannot assign to a method |
| |
| [case testAssignToNestedClassViaClass] |
| import typing |
| class A: |
| class B: pass |
| A.B = None # E: Cannot assign to a type |
| [targets __main__] |
| |
| [case testAccessingClassAttributeWithTypeInferenceIssue] |
| x = C.x # E: Cannot determine type of "x" |
| def f() -> int: return 1 |
| class C: |
| x = f() |
| [builtins fixtures/list.pyi] |
| |
| [case testAccessingClassAttributeWithTypeInferenceIssue2] |
| class C: |
| x = [] |
| x = C.x |
| [builtins fixtures/list.pyi] |
| [out] |
| main:2: error: Need type annotation for "x" (hint: "x: List[<type>] = ...") |
| |
| [case testAccessingGenericClassAttribute] |
| from typing import Generic, TypeVar |
| T = TypeVar('T') |
| class A(Generic[T]): |
| x = None # type: T |
| A.x # E: Access to generic instance variables via class is ambiguous |
| A[int].x # E: Access to generic instance variables via class is ambiguous |
| [targets __main__] |
| |
| [case testAccessingNestedGenericClassAttribute] |
| from typing import Generic, List, TypeVar, Union |
| T = TypeVar('T') |
| U = TypeVar('U') |
| class A(Generic[T, U]): |
| x = None # type: Union[T, List[U]] |
| A.x # E: Access to generic instance variables via class is ambiguous |
| A[int, int].x # E: Access to generic instance variables via class is ambiguous |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Nested classes |
| -- -------------- |
| |
| |
| [case testClassWithinFunction] |
| def f() -> None: |
| class A: |
| def g(self) -> None: pass |
| a = None # type: A |
| a.g() |
| a.g(a) # E: Too many arguments for "g" of "A" |
| [targets __main__, __main__.f] |
| |
| [case testConstructNestedClass] |
| import typing |
| class A: |
| class B: pass |
| b = B() |
| if int(): |
| b = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| if int(): |
| b = B(b) # E: Too many arguments for "B" |
| [out] |
| |
| [case testConstructNestedClassWithCustomInit] |
| import typing |
| class A: |
| def f(self) -> None: |
| class B: |
| def __init__(self, a: 'A') -> None: pass |
| b = B(A()) |
| if int(): |
| b = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = B() # E: Missing positional argument "a" in call to "B" |
| [out] |
| |
| [case testDeclareVariableWithNestedClassType] |
| |
| def f() -> None: |
| class A: pass |
| a = None # type: A |
| if int(): |
| a = A() |
| a = object() # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| [out] |
| |
| [case testExternalReferenceToClassWithinClass] |
| class A: |
| class B: pass |
| b = None # type: A.B |
| if int(): |
| b = A.B() |
| if int(): |
| b = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| if int(): |
| b = A.B(b) # E: Too many arguments for "B" |
| |
| [case testAliasNestedClass] |
| class Outer: |
| class Inner: |
| def make_int(self) -> int: return 1 |
| reveal_type(Inner().make_int) # N: Revealed type is "def () -> builtins.int" |
| some_int = Inner().make_int() |
| |
| reveal_type(Outer.Inner.make_int) # N: Revealed type is "def (self: __main__.Outer.Inner) -> builtins.int" |
| reveal_type(Outer().some_int) # N: Revealed type is "builtins.int" |
| Bar = Outer.Inner |
| reveal_type(Bar.make_int) # N: Revealed type is "def (self: __main__.Outer.Inner) -> builtins.int" |
| x = Bar() # type: Bar |
| def produce() -> Bar: |
| reveal_type(Bar().make_int) # N: Revealed type is "def () -> builtins.int" |
| return Bar() |
| |
| [case testInnerClassPropertyAccess] |
| class Foo: |
| class Meta: |
| name = 'Bar' |
| meta = Meta |
| |
| reveal_type(Foo.Meta) # N: Revealed type is "def () -> __main__.Foo.Meta" |
| reveal_type(Foo.meta) # N: Revealed type is "def () -> __main__.Foo.Meta" |
| reveal_type(Foo.Meta.name) # N: Revealed type is "builtins.str" |
| reveal_type(Foo.meta.name) # N: Revealed type is "builtins.str" |
| reveal_type(Foo().Meta) # N: Revealed type is "def () -> __main__.Foo.Meta" |
| reveal_type(Foo().meta) # N: Revealed type is "def () -> __main__.Foo.Meta" |
| reveal_type(Foo().meta.name) # N: Revealed type is "builtins.str" |
| reveal_type(Foo().Meta.name) # N: Revealed type is "builtins.str" |
| |
| -- Declaring attribute type in method |
| -- ---------------------------------- |
| |
| |
| [case testDeclareAttributeTypeInInit] |
| |
| class A: |
| def __init__(self): |
| self.x = None # type: int |
| a = None # type: A |
| a.x = 1 |
| a.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testAccessAttributeDeclaredInInitBeforeDeclaration] |
| |
| a = None # type: A |
| a.x = 1 |
| a.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| class A: |
| def __init__(self): |
| self.x = None # type: int |
| |
| |
| -- Special cases |
| -- ------------- |
| |
| |
| [case testMultipleClassDefinition] |
| import typing |
| A() |
| class A: pass |
| class A: pass |
| [out] |
| main:4: error: Name "A" already defined on line 3 |
| |
| [case testDocstringInClass] |
| import typing |
| class A: |
| """Foo""" |
| class B: |
| 'x' |
| y = B() |
| [builtins fixtures/primitives.pyi] |
| |
| [case testErrorMessageInFunctionNestedWithinMethod] |
| import typing |
| class A: |
| def f(self) -> None: |
| def g() -> None: |
| "" + 1 # E: Unsupported operand types for + ("str" and "int") |
| "" + 1 # E: Unsupported operand types for + ("str" and "int") |
| [builtins fixtures/primitives.pyi] |
| |
| -- Static methods |
| -- -------------- |
| |
| |
| [case testSimpleStaticMethod] |
| import typing |
| class A: |
| @staticmethod |
| def f(x: int) -> None: pass |
| A.f(1) |
| A().f(1) |
| A.f('') # E: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" |
| A().f('') # E: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" |
| [builtins fixtures/staticmethod.pyi] |
| |
| [case testBuiltinStaticMethod] |
| import typing |
| int.from_bytes(b'', '') |
| int.from_bytes('', '') # E: Argument 1 to "from_bytes" of "int" has incompatible type "str"; expected "bytes" |
| [builtins fixtures/staticmethod.pyi] |
| |
| [case testAssignStaticMethodOnInstance] |
| import typing |
| class A: |
| @staticmethod |
| def f(x: int) -> None: pass |
| A().f = A.f # E: Cannot assign to a method |
| [builtins fixtures/staticmethod.pyi] |
| |
| |
| -- Class methods |
| -- ------------- |
| |
| |
| [case testSimpleClassMethod] |
| import typing |
| class A: |
| @classmethod |
| def f(cls, x: int) -> None: pass |
| A.f(1) |
| A().f(1) |
| A.f('') # E: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" |
| A().f('') # E: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" |
| [builtins fixtures/classmethod.pyi] |
| [targets __main__, __main__.A.f] |
| |
| [case testBuiltinClassMethod] |
| import typing |
| int.from_bytes(b'', '') |
| int.from_bytes('', '') # E: Argument 1 to "from_bytes" of "int" has incompatible type "str"; expected "bytes" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testAssignClassMethodOnClass] |
| import typing |
| class A: |
| @classmethod |
| def f(cls, x: int) -> None: pass |
| A.f = A.f # E: Cannot assign to a method |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testAssignClassMethodOnInstance] |
| import typing |
| class A: |
| @classmethod |
| def f(cls, x: int) -> None: pass |
| A().f = A.f # E: Cannot assign to a method |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodCalledInClassMethod] |
| import typing |
| class C: |
| @classmethod |
| def foo(cls) -> None: pass |
| @classmethod |
| def bar(cls) -> None: |
| cls() |
| cls(1) # E: Too many arguments for "C" |
| cls.bar() |
| cls.bar(1) # E: Too many arguments for "bar" of "C" |
| cls.bozo() # E: "Type[C]" has no attribute "bozo" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testClassMethodCalledOnClass] |
| import typing |
| class C: |
| @classmethod |
| def foo(cls) -> None: pass |
| C.foo() |
| C.foo(1) # E: Too many arguments for "foo" of "C" |
| C.bozo() # E: "Type[C]" has no attribute "bozo" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodCalledOnInstance] |
| import typing |
| class C: |
| @classmethod |
| def foo(cls) -> None: pass |
| C().foo() |
| C().foo(1) # E: Too many arguments for "foo" of "C" |
| C.bozo() # E: "Type[C]" has no attribute "bozo" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodMayCallAbstractMethod] |
| from abc import abstractmethod |
| import typing |
| class C: |
| @classmethod |
| def foo(cls) -> None: |
| cls().bar() |
| @abstractmethod |
| def bar(self) -> None: |
| pass |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodSubclassing] |
| class A: |
| @classmethod |
| def f(cls) -> None: pass |
| |
| def g(self) -> None: pass |
| |
| class B(A): |
| def f(self) -> None: pass # Fail |
| |
| @classmethod |
| def g(cls) -> None: pass |
| |
| class C(A): |
| @staticmethod |
| def f() -> None: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| main:8: error: Signature of "f" incompatible with supertype "A" |
| main:8: note: Superclass: |
| main:8: note: @classmethod |
| main:8: note: def f(cls) -> None |
| main:8: note: Subclass: |
| main:8: note: def f(self) -> None |
| |
| -- Properties |
| -- ---------- |
| |
| |
| [case testAccessingReadOnlyProperty] |
| import typing |
| class A: |
| @property |
| def f(self) -> str: pass |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "builtins.str" |
| [builtins fixtures/property.pyi] |
| |
| [case testAssigningToReadOnlyProperty] |
| import typing |
| class A: |
| @property |
| def f(self) -> str: pass |
| A().f = '' # E: Property "f" defined in "A" is read-only |
| [builtins fixtures/property.pyi] |
| |
| [case testAssigningToInheritedReadOnlyProperty] |
| class A: |
| @property |
| def f(self) -> str: pass |
| class B(A): pass |
| class C(A): |
| @property |
| def f(self) -> str: pass |
| |
| A().f = '' # E: Property "f" defined in "A" is read-only |
| B().f = '' # E: Property "f" defined in "A" is read-only |
| C().f = '' # E: Property "f" defined in "C" is read-only |
| [builtins fixtures/property.pyi] |
| |
| [case testPropertyGetterBody] |
| import typing |
| class A: |
| @property |
| def f(self) -> str: |
| self.x = 1 |
| self.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| return '' |
| [builtins fixtures/property.pyi] |
| [out] |
| |
| [case testDynamicallyTypedProperty] |
| import typing |
| class A: |
| @property |
| def f(self): pass |
| a = A() |
| a.f.xx |
| a.f = '' # E: Property "f" defined in "A" is read-only |
| [builtins fixtures/property.pyi] |
| |
| [case testPropertyWithSetter] |
| import typing |
| class A: |
| @property |
| def f(self) -> int: |
| return 1 |
| @f.setter |
| def f(self, x: int) -> None: |
| pass |
| a = A() |
| a.f = a.f |
| a.f.x # E: "int" has no attribute "x" |
| a.f = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| a.f = 1 |
| reveal_type(a.f) # N: Revealed type is "builtins.int" |
| [builtins fixtures/property.pyi] |
| |
| [case testPropertyWithDeleterButNoSetter] |
| import typing |
| class A: |
| @property |
| def f(self) -> int: |
| return 1 |
| @f.deleter |
| def f(self, x) -> None: |
| pass |
| a = A() |
| a.f = a.f # E: Property "f" defined in "A" is read-only |
| a.f.x # E: "int" has no attribute "x" |
| [builtins fixtures/property.pyi] |
| |
| -- Descriptors |
| -- ----------- |
| |
| |
| [case testAccessingNonDataDescriptor] |
| from typing import Any |
| class D: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| class A: |
| f = D() |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "builtins.str" |
| |
| [case testSettingNonDataDescriptor] |
| from typing import Any |
| class D: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| class A: |
| f = D() |
| a = A() |
| a.f = 'foo' |
| a.f = D() # E: Incompatible types in assignment (expression has type "D", variable has type "str") |
| |
| [case testSettingDataDescriptor] |
| from typing import Any |
| class D: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| def __set__(self, inst: Any, value: str) -> None: pass |
| class A: |
| f = D() |
| a = A() |
| a.f = '' |
| a.f = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [case testSettingDescriptorWithOverloadedDunderSet1] |
| from typing import Any, overload, Union |
| class D: |
| @overload |
| def __set__(self, inst: Any, value: str) -> None: pass |
| @overload |
| def __set__(self, inst: Any, value: int) -> None: pass |
| def __set__(self, inst: Any, value: Union[str, int]) -> None: pass |
| class A: |
| f = D() |
| a = A() |
| a.f = '' |
| a.f = 1 |
| a.f = 1.5 # E |
| [out] |
| main:13: error: No overload variant of "__set__" of "D" matches argument types "A", "float" |
| main:13: note: Possible overload variants: |
| main:13: note: def __set__(self, inst: Any, value: str) -> None |
| main:13: note: def __set__(self, inst: Any, value: int) -> None |
| |
| [case testSettingDescriptorWithOverloadedDunderSet2] |
| from typing import overload, Union |
| class D: |
| @overload |
| def __set__(self, inst: A, value: str) -> None: pass |
| @overload |
| def __set__(self, inst: B, value: int) -> None: pass |
| def __set__(self, inst: Union[A, B], value: Union[str, int]) -> None: pass |
| class A: |
| f = D() |
| class B: |
| f = D() |
| a = A() |
| b = B() |
| a.f = '' |
| b.f = 1 |
| a.f = 1 # E |
| b.f = '' # E |
| [out] |
| main:16: error: No overload variant of "__set__" of "D" matches argument types "A", "int" |
| main:16: note: Possible overload variants: |
| main:16: note: def __set__(self, inst: A, value: str) -> None |
| main:16: note: def __set__(self, inst: B, value: int) -> None |
| main:17: error: No overload variant of "__set__" of "D" matches argument types "B", "str" |
| main:17: note: Possible overload variants: |
| main:17: note: def __set__(self, inst: A, value: str) -> None |
| main:17: note: def __set__(self, inst: B, value: int) -> None |
| |
| [case testReadingDescriptorWithoutDunderGet] |
| from typing import Union, Any |
| class D: |
| def __set__(self, inst: Any, value: str) -> None: pass |
| class A: |
| f = D() |
| def __init__(self): self.f = 's' |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "__main__.D" |
| |
| [case testAccessingDescriptorFromClass] |
| # flags: --strict-optional |
| from d import D, Base |
| class A(Base): |
| f = D() |
| reveal_type(A.f) # N: Revealed type is "d.D" |
| reveal_type(A().f) # N: Revealed type is "builtins.str" |
| [file d.pyi] |
| from typing import TypeVar, Type, Generic, overload |
| class Base: pass |
| class D: |
| def __init__(self) -> None: pass |
| @overload |
| def __get__(self, inst: None, own: Type[Base]) -> D: pass |
| @overload |
| def __get__(self, inst: Base, own: Type[Base]) -> str: pass |
| [builtins fixtures/bool.pyi] |
| |
| [case testAccessingDescriptorFromClassWrongBase] |
| # flags: --strict-optional |
| from d import D, Base |
| class A: |
| f = D() |
| reveal_type(A.f) |
| reveal_type(A().f) |
| [file d.pyi] |
| from typing import TypeVar, Type, Generic, overload |
| class Base: pass |
| class D: |
| def __init__(self) -> None: pass |
| @overload |
| def __get__(self, inst: None, own: Type[Base]) -> D: pass |
| @overload |
| def __get__(self, inst: Base, own: Type[Base]) -> str: pass |
| [builtins fixtures/bool.pyi] |
| [out] |
| main:5: error: Argument 2 to "__get__" of "D" has incompatible type "Type[A]"; expected "Type[Base]" |
| main:5: note: Revealed type is "d.D" |
| main:6: error: No overload variant of "__get__" of "D" matches argument types "A", "Type[A]" |
| main:6: note: Possible overload variants: |
| main:6: note: def __get__(self, inst: None, own: Type[Base]) -> D |
| main:6: note: def __get__(self, inst: Base, own: Type[Base]) -> str |
| main:6: note: Revealed type is "Any" |
| |
| [case testAccessingGenericNonDataDescriptor] |
| from typing import TypeVar, Type, Generic, Any |
| V = TypeVar('V') |
| class D(Generic[V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: Any, own: Type) -> V: return self.v |
| class A: |
| f = D(10) |
| g = D('10') |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "builtins.int" |
| reveal_type(a.g) # N: Revealed type is "builtins.str" |
| |
| [case testSettingGenericDataDescriptor] |
| from typing import TypeVar, Type, Generic, Any |
| V = TypeVar('V') |
| class D(Generic[V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: Any, own: Type) -> V: return self.v |
| def __set__(self, inst: Any, v: V) -> None: pass |
| class A: |
| f = D(10) |
| g = D('10') |
| a = A() |
| a.f = 1 |
| a.f = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| a.g = '' |
| a.g = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [case testAccessingGenericDescriptorFromClass] |
| # flags: --strict-optional |
| from d import D |
| class A: |
| f = D(10) # type: D[A, int] |
| g = D('10') # type: D[A, str] |
| reveal_type(A.f) # N: Revealed type is "d.D[__main__.A, builtins.int]" |
| reveal_type(A.g) # N: Revealed type is "d.D[__main__.A, builtins.str]" |
| reveal_type(A().f) # N: Revealed type is "builtins.int" |
| reveal_type(A().g) # N: Revealed type is "builtins.str" |
| [file d.pyi] |
| from typing import TypeVar, Type, Generic, overload |
| T = TypeVar('T') |
| V = TypeVar('V') |
| class D(Generic[T, V]): |
| def __init__(self, v: V) -> None: pass |
| @overload |
| def __get__(self, inst: None, own: Type[T]) -> 'D[T, V]': pass |
| @overload |
| def __get__(self, inst: T, own: Type[T]) -> V: pass |
| [builtins fixtures/bool.pyi] |
| |
| [case testAccessingGenericDescriptorFromInferredClass] |
| # flags: --strict-optional |
| from typing import Type |
| from d import D |
| class A: |
| f = D(10) # type: D[A, int] |
| g = D('10') # type: D[A, str] |
| def f(some_class: Type[A]): |
| reveal_type(some_class.f) |
| reveal_type(some_class.g) |
| [file d.pyi] |
| from typing import TypeVar, Type, Generic, overload |
| T = TypeVar('T') |
| V = TypeVar('V') |
| class D(Generic[T, V]): |
| def __init__(self, v: V) -> None: pass |
| @overload |
| def __get__(self, inst: None, own: Type[T]) -> 'D[T, V]': pass |
| @overload |
| def __get__(self, inst: T, own: Type[T]) -> V: pass |
| [builtins fixtures/bool.pyi] |
| [out] |
| main:8: note: Revealed type is "d.D[__main__.A, builtins.int]" |
| main:9: note: Revealed type is "d.D[__main__.A, builtins.str]" |
| |
| [case testAccessingGenericDescriptorFromClassBadOverload] |
| # flags: --strict-optional |
| from d import D |
| class A: |
| f = D(10) # type: D[A, int] |
| reveal_type(A.f) |
| [file d.pyi] |
| from typing import TypeVar, Type, Generic, overload |
| T = TypeVar('T') |
| V = TypeVar('V') |
| class D(Generic[T, V]): |
| def __init__(self, v: V) -> None: pass |
| @overload |
| def __get__(self, inst: None, own: None) -> 'D[T, V]': pass |
| @overload |
| def __get__(self, inst: T, own: Type[T]) -> V: pass |
| [builtins fixtures/bool.pyi] |
| [out] |
| main:5: error: No overload variant of "__get__" of "D" matches argument types "None", "Type[A]" |
| main:5: note: Possible overload variants: |
| main:5: note: def __get__(self, inst: None, own: None) -> D[A, int] |
| main:5: note: def __get__(self, inst: A, own: Type[A]) -> int |
| main:5: note: Revealed type is "Any" |
| |
| [case testAccessingNonDataDescriptorSubclass] |
| from typing import Any |
| class C: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| class D(C): pass |
| class A: |
| f = D() |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "builtins.str" |
| |
| [case testSettingDataDescriptorSubclass] |
| from typing import Any |
| class C: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| def __set__(self, inst: Any, v: str) -> None: pass |
| class D(C): pass |
| class A: |
| f = D() |
| a = A() |
| a.f = '' |
| a.f = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [case testReadingDescriptorSubclassWithoutDunderGet] |
| from typing import Union, Any |
| class C: |
| def __set__(self, inst: Any, v: str) -> None: pass |
| class D(C): pass |
| class A: |
| f = D() |
| def __init__(self): self.f = 's' |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "__main__.D" |
| |
| [case testAccessingGenericNonDataDescriptorSubclass] |
| from typing import TypeVar, Type, Generic, Any |
| V = TypeVar('V') |
| class C(Generic[V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: Any, own: Type) -> V: return self.v |
| class D(C[V], Generic[V]): pass |
| class A: |
| f = D(10) |
| g = D('10') |
| a = A() |
| reveal_type(a.f) # N: Revealed type is "builtins.int" |
| reveal_type(a.g) # N: Revealed type is "builtins.str" |
| |
| [case testSettingGenericDataDescriptorSubclass] |
| from typing import TypeVar, Type, Generic |
| T = TypeVar('T') |
| V = TypeVar('V') |
| class C(Generic[T, V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: T, own: Type[T]) -> V: return self.v |
| def __set__(self, inst: T, v: V) -> None: pass |
| class D(C[T, V], Generic[T, V]): pass |
| class A: |
| f = D(10) # type: D[A, int] |
| g = D('10') # type: D[A, str] |
| a = A() |
| a.f = 1 |
| a.f = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| a.g = '' |
| a.g = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [case testSetDescriptorOnClass] |
| from typing import TypeVar, Type, Generic |
| T = TypeVar('T') |
| V = TypeVar('V') |
| class D(Generic[T, V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: T, own: Type[T]) -> V: return self.v |
| def __set__(self, inst: T, v: V) -> None: pass |
| class A: |
| f = D(10) # type: D[A, int] |
| A.f = D(20) |
| A.f = D('some string') # E: Argument 1 to "D" has incompatible type "str"; expected "int" |
| |
| [case testSetDescriptorOnInferredClass] |
| from typing import TypeVar, Type, Generic, Any |
| V = TypeVar('V') |
| class D(Generic[V]): |
| def __init__(self, v: V) -> None: self.v = v |
| def __get__(self, inst: Any, own: Type) -> V: return self.v |
| def __set__(self, inst: Any, v: V) -> None: pass |
| class A: |
| f = D(10) |
| def f(some_class: Type[A]): |
| A.f = D(20) |
| A.f = D('some string') |
| [out] |
| main:11: error: Argument 1 to "D" has incompatible type "str"; expected "int" |
| |
| [case testDescriptorUncallableDunderSet] |
| class D: |
| __set__ = 's' |
| class A: |
| f = D() |
| A().f = 'x' # E: __main__.D.__set__ is not callable |
| |
| [case testDescriptorDunderSetTooFewArgs] |
| class D: |
| def __set__(self, inst): pass |
| class A: |
| f = D() |
| A().f = 'x' # E: Too many arguments for "__set__" |
| |
| [case testDescriptorDunderSetTooManyArgs] |
| class D: |
| def __set__(self, inst, v, other): pass |
| class A: |
| f = D() |
| A().f = 'x' # E: Too few arguments for "__set__" |
| |
| [case testDescriptorDunderSetWrongArgTypes] |
| class D: |
| def __set__(self, inst: str, v:str) -> None: pass |
| class A: |
| f = D() |
| A().f = 'x' # E: Argument 1 to "__set__" of "D" has incompatible type "A"; expected "str" |
| |
| [case testDescriptorUncallableDunderGet] |
| class D: |
| __get__ = 's' |
| class A: |
| f = D() |
| A().f # E: __main__.D.__get__ is not callable |
| |
| [case testDescriptorDunderGetTooFewArgs] |
| class D: |
| def __get__(self, inst): pass |
| class A: |
| f = D() |
| A().f # E: Too many arguments for "__get__" |
| |
| [case testDescriptorDunderGetTooManyArgs] |
| class D: |
| def __get__(self, inst, own, other): pass |
| class A: |
| f = D() |
| A().f = 'x' # E: Too few arguments for "__get__" |
| |
| [case testDescriptorDunderGetWrongArgTypeForInstance] |
| from typing import Any |
| class D: |
| def __get__(self, inst: str, own: Any) -> Any: pass |
| class A: |
| f = D() |
| A().f # E: Argument 1 to "__get__" of "D" has incompatible type "A"; expected "str" |
| |
| [case testDescriptorDunderGetWrongArgTypeForOwner] |
| from typing import Any |
| class D: |
| def __get__(self, inst: Any, own: str) -> Any: pass |
| class A: |
| f = D() |
| A().f # E: Argument 2 to "__get__" of "D" has incompatible type "Type[A]"; expected "str" |
| |
| [case testDescriptorGetSetDifferentTypes] |
| from typing import Any |
| class D: |
| def __get__(self, inst: Any, own: Any) -> str: return 's' |
| def __set__(self, inst: Any, v: int) -> None: pass |
| class A: |
| f = D() |
| a = A() |
| a.f = 1 |
| reveal_type(a.f) # N: Revealed type is "builtins.str" |
| |
| [case testDescriptorGetUnion] |
| from typing import Any, Union |
| class String: |
| def __get__(self, inst: Any, owner: Any) -> str: |
| return '' |
| |
| class A: |
| attr: str |
| |
| class B: |
| attr = String() |
| |
| def foo(x: Union[A, B]) -> None: |
| reveal_type(x.attr) # N: Revealed type is "builtins.str" |
| |
| -- _promote decorators |
| -- ------------------- |
| |
| |
| [case testSimpleDucktypeDecorator] |
| from typing import _promote |
| class A: pass |
| @_promote(A) |
| class B: pass |
| a = None # type: A |
| b = None # type: B |
| if int(): |
| b = a # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a = b |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testDucktypeTransitivityDecorator] |
| from typing import _promote |
| class A: pass |
| @_promote(A) |
| class B: pass |
| @_promote(B) |
| class C: pass |
| a = None # type: A |
| c = None # type: C |
| if int(): |
| c = a # E: Incompatible types in assignment (expression has type "A", variable has type "C") |
| a = c |
| [typing fixtures/typing-medium.pyi] |
| |
| |
| -- Hard coded type promotions |
| -- -------------------------- |
| |
| [case testHardCodedTypePromotions] |
| import typing |
| def f(x: float) -> None: pass |
| def g(x: complex) -> None: pass |
| f(1) |
| g(1) |
| g(1.1) |
| [builtins fixtures/complex.pyi] |
| |
| |
| -- Operator methods |
| -- ---------------- |
| |
| |
| [case testOperatorMethodOverrideIntroducingOverloading] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| def __add__(self, x: int) -> int: pass |
| class B(A): |
| @overload # Fail |
| def __add__(self, x: int) -> int: pass |
| @overload |
| def __add__(self, x: str) -> str: pass |
| [out] |
| tmp/foo.pyi:5: error: Signature of "__add__" incompatible with supertype "A" |
| tmp/foo.pyi:5: note: Superclass: |
| tmp/foo.pyi:5: note: def __add__(self, int) -> int |
| tmp/foo.pyi:5: note: Subclass: |
| tmp/foo.pyi:5: note: @overload |
| tmp/foo.pyi:5: note: def __add__(self, int) -> int |
| tmp/foo.pyi:5: note: @overload |
| tmp/foo.pyi:5: note: def __add__(self, str) -> str |
| tmp/foo.pyi:5: note: Overloaded operator methods cannot have wider argument types in overrides |
| |
| [case testOperatorMethodOverrideWideningArgumentType] |
| import typing |
| class A: |
| def __add__(self, x: int) -> int: pass |
| class B(A): |
| def __add__(self, x: object) -> int: pass |
| [out] |
| |
| [case testOperatorMethodOverrideNarrowingReturnType] |
| import typing |
| class A: |
| def __add__(self, x: int) -> 'A': pass |
| class B(A): |
| def __add__(self, x: int) -> 'B': pass |
| |
| [case testOperatorMethodOverrideWithDynamicallyTyped] |
| import typing |
| class A: |
| def __add__(self, x: int) -> 'A': pass |
| class B(A): |
| def __add__(self, x): pass |
| |
| [case testOperatorMethodAgainstSameType] |
| class A: |
| def __add__(self, x: int) -> 'A': |
| if isinstance(x, int): |
| return A() |
| else: |
| return NotImplemented |
| |
| def __radd__(self, x: 'A') -> 'A': |
| if isinstance(x, A): |
| return A() |
| else: |
| return NotImplemented |
| |
| class B(A): pass |
| |
| # Note: This is a runtime error. If we run x.__add__(y) |
| # where x and y are *not* the same type, Python will not try |
| # calling __radd__. |
| A() + A() # E: Unsupported operand types for + ("A" and "A") |
| |
| # Here, Python *will* call __radd__(...) |
| reveal_type(B() + A()) # N: Revealed type is "__main__.A" |
| reveal_type(A() + B()) # N: Revealed type is "__main__.A" |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testBinaryOpeartorMethodPositionalArgumentsOnly] |
| class A: |
| def __add__(self, other: int) -> int: pass |
| def __iadd__(self, other: int) -> int: pass |
| def __radd__(self, other: int) -> int: pass |
| |
| reveal_type(A.__add__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" |
| reveal_type(A.__iadd__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" |
| reveal_type(A.__radd__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" |
| |
| [case testOperatorMethodOverrideWithIdenticalOverloadedType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| @overload |
| def __add__(self, x: int) -> 'A': pass |
| @overload |
| def __add__(self, x: str) -> 'A': pass |
| class B(A): |
| @overload |
| def __add__(self, x: int) -> 'A': pass |
| @overload |
| def __add__(self, x: str) -> 'A': pass |
| |
| [case testOverloadedOperatorMethodOverrideWithDynamicallyTypedMethod] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class A: |
| @overload |
| def __add__(self, x: int) -> 'A': pass |
| @overload |
| def __add__(self, x: str) -> 'A': pass |
| class B(A): |
| def __add__(self, x): pass |
| class C(A): |
| def __add__(self, x: Any) -> A: pass |
| |
| [case testOverloadedOperatorMethodOverrideWithNewItem] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class A: |
| @overload |
| def __add__(self, x: int) -> 'A': pass |
| @overload |
| def __add__(self, x: str) -> 'A': pass |
| class B(A): |
| @overload # Fail |
| def __add__(self, x: int) -> A: pass |
| @overload |
| def __add__(self, x: str) -> A: pass |
| @overload |
| def __add__(self, x: type) -> A: pass |
| [out] |
| tmp/foo.pyi:8: error: Signature of "__add__" incompatible with supertype "A" |
| tmp/foo.pyi:8: note: Superclass: |
| tmp/foo.pyi:8: note: @overload |
| tmp/foo.pyi:8: note: def __add__(self, int) -> A |
| tmp/foo.pyi:8: note: @overload |
| tmp/foo.pyi:8: note: def __add__(self, str) -> A |
| tmp/foo.pyi:8: note: Subclass: |
| tmp/foo.pyi:8: note: @overload |
| tmp/foo.pyi:8: note: def __add__(self, int) -> A |
| tmp/foo.pyi:8: note: @overload |
| tmp/foo.pyi:8: note: def __add__(self, str) -> A |
| tmp/foo.pyi:8: note: @overload |
| tmp/foo.pyi:8: note: def __add__(self, type) -> A |
| tmp/foo.pyi:8: note: Overloaded operator methods cannot have wider argument types in overrides |
| |
| [case testOverloadedOperatorMethodOverrideWithSwitchedItemOrder] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class A: |
| @overload |
| def __add__(self, x: 'B') -> 'B': pass |
| @overload |
| def __add__(self, x: 'A') -> 'A': pass |
| class B(A): |
| @overload |
| def __add__(self, x: 'A') -> 'A': pass |
| @overload |
| def __add__(self, x: 'B') -> 'B': pass |
| class C(A): |
| @overload |
| def __add__(self, x: 'B') -> 'B': pass |
| @overload |
| def __add__(self, x: 'A') -> 'A': pass |
| [out] |
| tmp/foo.pyi:8: error: Signature of "__add__" incompatible with supertype "A" |
| tmp/foo.pyi:8: note: Overload variants must be defined in the same order as they are in "A" |
| tmp/foo.pyi:11: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader |
| |
| [case testReverseOperatorMethodArgumentType] |
| from typing import Any |
| class A: pass |
| class B: |
| def __radd__(self, x: A) -> int: pass # Error |
| class C: |
| def __radd__(self, x: A) -> Any: pass |
| class D: |
| def __radd__(self, x: A) -> object: pass |
| [out] |
| |
| [case testReverseOperatorMethodArgumentType2] |
| from typing import Any, Tuple, Callable |
| class A: |
| def __radd__(self, x: Tuple[int, str]) -> int: pass |
| class B: |
| def __radd__(self, x: Callable[[], int]) -> int: pass |
| class C: |
| def __radd__(self, x: Any) -> int: pass |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testReverseOperatorMethodInvalid] |
| from foo import * |
| [file foo.pyi] |
| class A: ... |
| class B: |
| def __rmul__(self) -> A: ... |
| class C: |
| def __radd__(self, other, oops) -> int: ... |
| [out] |
| tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]" |
| tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]" |
| |
| [case testReverseOperatorOrderingCase1] |
| class A: |
| def __radd__(self, other: 'A') -> int: ... |
| |
| # Note: Python only tries calling __add__ and never __radd__, even though it's present |
| A() + A() # E: Unsupported left operand type for + ("A") |
| |
| [case testReverseOperatorOrderingCase2] |
| class A: |
| def __lt__(self, other: object) -> bool: ... |
| |
| # Not all operators have the above shortcut though. |
| reveal_type(A() > A()) # N: Revealed type is "builtins.bool" |
| reveal_type(A() < A()) # N: Revealed type is "builtins.bool" |
| [builtins fixtures/bool.pyi] |
| |
| [case testReverseOperatorOrderingCase3] |
| class A: |
| def __add__(self, other: B) -> int: ... |
| |
| class B: |
| def __radd__(self, other: A) -> str: ... # E: Signatures of "__radd__" of "B" and "__add__" of "A" are unsafely overlapping |
| |
| # Normally, we try calling __add__ before __radd__ |
| reveal_type(A() + B()) # N: Revealed type is "builtins.int" |
| |
| [case testReverseOperatorOrderingCase4] |
| class A: |
| def __add__(self, other: B) -> int: ... |
| |
| class B(A): |
| def __radd__(self, other: A) -> str: ... # E: Signatures of "__radd__" of "B" and "__add__" of "A" are unsafely overlapping |
| |
| # However, if B is a subtype of A, we try calling __radd__ first. |
| reveal_type(A() + B()) # N: Revealed type is "builtins.str" |
| |
| [case testReverseOperatorOrderingCase5] |
| # Note: these two methods are not unsafely overlapping because __radd__ is |
| # never called -- see case 1. |
| class A: |
| def __add__(self, other: B) -> int: ... |
| def __radd__(self, other: A) -> str: ... |
| |
| class B(A): pass |
| |
| # ...but only if B specifically defines a new __radd__. |
| reveal_type(A() + B()) # N: Revealed type is "builtins.int" |
| |
| [case testReverseOperatorOrderingCase6] |
| class A: |
| def __add__(self, other: B) -> int: ... |
| def __radd__(self, other: A) -> str: ... |
| |
| class B(A): |
| # Although A.__radd__ can never be called, B.__radd__ *can* be -- so the |
| # unsafe overlap check kicks in here. |
| def __radd__(self, other: A) -> str: ... # E: Signatures of "__radd__" of "B" and "__add__" of "A" are unsafely overlapping |
| |
| reveal_type(A() + B()) # N: Revealed type is "builtins.str" |
| |
| [case testReverseOperatorOrderingCase7] |
| class A: |
| def __add__(self, other: B) -> int: ... |
| def __radd__(self, other: A) -> str: ... |
| |
| class B(A): |
| def __radd__(self, other: A) -> str: ... # E: Signatures of "__radd__" of "B" and "__add__" of "A" are unsafely overlapping |
| |
| class C(B): pass |
| |
| # A refinement made by a parent also counts |
| reveal_type(A() + C()) # N: Revealed type is "builtins.str" |
| |
| [case testReverseOperatorWithOverloads1] |
| from typing import overload |
| |
| class A: |
| def __add__(self, other: C) -> int: ... |
| |
| class B: |
| def __add__(self, other: C) -> int: ... |
| |
| class C: |
| @overload |
| def __radd__(self, other: A) -> str: ... # E: Signatures of "__radd__" of "C" and "__add__" of "A" are unsafely overlapping |
| @overload |
| def __radd__(self, other: B) -> str: ... # E: Signatures of "__radd__" of "C" and "__add__" of "B" are unsafely overlapping |
| def __radd__(self, other): pass |
| |
| reveal_type(A() + C()) # N: Revealed type is "builtins.int" |
| reveal_type(B() + C()) # N: Revealed type is "builtins.int" |
| |
| [case testReverseOperatorWithOverloads2] |
| from typing import overload, Union |
| |
| class Num1: |
| def __add__(self, other: Num1) -> Num1: ... |
| def __radd__(self, other: Num1) -> Num1: ... |
| |
| class Num2(Num1): |
| @overload |
| def __add__(self, other: Num2) -> Num2: ... |
| @overload |
| def __add__(self, other: Num1) -> Num2: ... |
| def __add__(self, other): pass |
| |
| @overload |
| def __radd__(self, other: Num2) -> Num2: ... |
| @overload |
| def __radd__(self, other: Num1) -> Num2: ... |
| def __radd__(self, other): pass |
| |
| class Num3(Num1): |
| def __add__(self, other: Union[Num1, Num3]) -> Num3: ... |
| def __radd__(self, other: Union[Num1, Num3]) -> Num3: ... |
| |
| reveal_type(Num1() + Num2()) # N: Revealed type is "__main__.Num2" |
| reveal_type(Num2() + Num1()) # N: Revealed type is "__main__.Num2" |
| |
| reveal_type(Num1() + Num3()) # N: Revealed type is "__main__.Num3" |
| reveal_type(Num3() + Num1()) # N: Revealed type is "__main__.Num3" |
| |
| reveal_type(Num2() + Num3()) # N: Revealed type is "__main__.Num2" |
| reveal_type(Num3() + Num2()) # N: Revealed type is "__main__.Num3" |
| |
| [case testDivReverseOperator] |
| # No error: __div__ has no special meaning in Python 3 |
| class A1: |
| def __div__(self, x: B1) -> int: ... |
| class B1: |
| def __rdiv__(self, x: A1) -> str: ... |
| |
| class A2: |
| def __truediv__(self, x: B2) -> int: ... |
| class B2: |
| def __rtruediv__(self, x: A2) -> str: ... # E: Signatures of "__rtruediv__" of "B2" and "__truediv__" of "A2" are unsafely overlapping |
| |
| A1() / B1() # E: Unsupported left operand type for / ("A1") |
| reveal_type(A2() / B2()) # N: Revealed type is "builtins.int" |
| |
| [case testReverseOperatorMethodForwardIsAny] |
| from typing import Any |
| def deco(f: Any) -> Any: return f |
| class C: |
| @deco |
| def __add__(self, other: C) -> C: return C() |
| def __radd__(self, other: C) -> C: return C() |
| [out] |
| |
| [case testReverseOperatorMethodForwardIsAny2] |
| from typing import Any |
| def deco(f: Any) -> Any: return f |
| class C: |
| __add__ = None # type: Any |
| def __radd__(self, other: C) -> C: return C() |
| [out] |
| |
| [case testReverseOperatorMethodForwardIsAny3] |
| from typing import Any |
| def deco(f: Any) -> Any: return f |
| class C: |
| __add__ = 42 |
| def __radd__(self, other: C) -> C: return C() |
| [out] |
| main:5: error: Forward operator "__add__" is not callable |
| |
| [case testOverloadedReverseOperatorMethodArgumentType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload, Any |
| class A: |
| @overload |
| def __radd__(self, x: 'A') -> str: pass |
| @overload |
| def __radd__(self, x: 'A') -> Any: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader |
| [out] |
| |
| [case testReverseOperatorMethodArgumentTypeAndOverloadedMethod] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| @overload |
| def __add__(self, x: int) -> int: pass |
| @overload |
| def __add__(self, x: str) -> int: pass |
| def __radd__(self, x: 'A') -> str: pass |
| |
| [case testReverseOperatorStar] |
| class B: |
| def __radd__(*self) -> int: pass |
| def __rsub__(*self: 'B') -> int: pass |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReverseOperatorTypeVar1] |
| from typing import TypeVar, Any |
| T = TypeVar("T", bound='Real') |
| class Real: |
| def __add__(self, other: Any) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "T" are unsafely overlapping |
| |
| # Note: When doing A + B and if B is a subtype of A, we will always call B.__radd__(A) first |
| # and only try A.__add__(B) second if necessary. |
| reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" |
| |
| # Note: When doing A + A, we only ever call A.__add__(A), never A.__radd__(A). |
| reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" |
| |
| [case testReverseOperatorTypeVar2a] |
| from typing import TypeVar |
| T = TypeVar("T", bound='Real') |
| class Real: |
| def __add__(self, other: Fraction) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "T" are unsafely overlapping |
| |
| reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" |
| reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" |
| |
| |
| [case testReverseOperatorTypeVar2b] |
| from typing import TypeVar |
| T = TypeVar("T", Real, Fraction) |
| class Real: |
| def __add__(self, other: Fraction) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "Real" are unsafely overlapping |
| |
| reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" |
| reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" |
| |
| [case testReverseOperatorTypeVar3] |
| from typing import TypeVar, Any |
| T = TypeVar("T", bound='Real') |
| class Real: |
| def __add__(self, other: FractionChild) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "T" are unsafely overlapping |
| class FractionChild(Fraction): pass |
| |
| reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" |
| reveal_type(FractionChild() + Fraction()) # N: Revealed type is "__main__.FractionChild" |
| reveal_type(FractionChild() + FractionChild()) # N: Revealed type is "builtins.str" |
| |
| # Runtime error: we try calling __add__, it doesn't match, and we don't try __radd__ since |
| # the LHS and the RHS are not the same. |
| Fraction() + Fraction() # E: Unsupported operand types for + ("Fraction" and "Fraction") |
| |
| [case testReverseOperatorTypeType] |
| from typing import TypeVar, Type |
| class Real(type): |
| def __add__(self, other: FractionChild) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: Type['A']) -> Real: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "Type[A]" are unsafely overlapping |
| class FractionChild(Fraction): pass |
| |
| class A(metaclass=Real): pass |
| |
| [case testOperatorDoubleUnionIntFloat] |
| from typing import Union |
| |
| a: Union[int, float] |
| b: int |
| c: float |
| |
| reveal_type(a + a) # N: Revealed type is "builtins.float" |
| reveal_type(a + b) # N: Revealed type is "builtins.float" |
| reveal_type(b + a) # N: Revealed type is "builtins.float" |
| reveal_type(a + c) # N: Revealed type is "builtins.float" |
| reveal_type(c + a) # N: Revealed type is "builtins.float" |
| [builtins fixtures/ops.pyi] |
| |
| [case testOperatorDoubleUnionStandardSubtyping] |
| from typing import Union |
| |
| class Parent: |
| def __add__(self, x: Parent) -> Parent: pass |
| def __radd__(self, x: Parent) -> Parent: pass |
| |
| class Child(Parent): |
| def __add__(self, x: Parent) -> Child: pass |
| def __radd__(self, x: Parent) -> Child: pass |
| |
| a: Union[Parent, Child] |
| b: Parent |
| c: Child |
| |
| reveal_type(a + a) # N: Revealed type is "__main__.Parent" |
| reveal_type(a + b) # N: Revealed type is "__main__.Parent" |
| reveal_type(b + a) # N: Revealed type is "__main__.Parent" |
| reveal_type(a + c) # N: Revealed type is "__main__.Child" |
| reveal_type(c + a) # N: Revealed type is "__main__.Child" |
| |
| [case testOperatorDoubleUnionNoRelationship1] |
| from typing import Union |
| |
| class Foo: |
| def __add__(self, x: Foo) -> Foo: pass |
| def __radd__(self, x: Foo) -> Foo: pass |
| |
| class Bar: |
| def __add__(self, x: Bar) -> Bar: pass |
| def __radd__(self, x: Bar) -> Bar: pass |
| |
| a: Union[Foo, Bar] |
| b: Foo |
| c: Bar |
| |
| a + a # E: Unsupported operand types for + ("Foo" and "Bar") \ |
| # E: Unsupported operand types for + ("Bar" and "Foo") \ |
| # N: Both left and right operands are unions |
| |
| a + b # E: Unsupported operand types for + ("Bar" and "Foo") \ |
| # N: Left operand is of type "Union[Foo, Bar]" |
| |
| b + a # E: Unsupported operand types for + ("Foo" and "Bar") \ |
| # N: Right operand is of type "Union[Foo, Bar]" |
| |
| a + c # E: Unsupported operand types for + ("Foo" and "Bar") \ |
| # N: Left operand is of type "Union[Foo, Bar]" |
| |
| c + a # E: Unsupported operand types for + ("Bar" and "Foo") \ |
| # N: Right operand is of type "Union[Foo, Bar]" |
| |
| [case testOperatorDoubleUnionNoRelationship2] |
| from typing import Union |
| |
| class Foo: |
| def __add__(self, x: Foo) -> Foo: pass |
| def __radd__(self, x: Foo) -> Foo: pass |
| |
| class Bar: |
| def __add__(self, x: Union[Foo, Bar]) -> Bar: pass |
| def __radd__(self, x: Union[Foo, Bar]) -> Bar: pass |
| |
| a: Union[Foo, Bar] |
| b: Foo |
| c: Bar |
| |
| reveal_type(a + a) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" |
| reveal_type(a + b) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" |
| reveal_type(b + a) # N: Revealed type is "Union[__main__.Foo, __main__.Bar]" |
| reveal_type(a + c) # N: Revealed type is "__main__.Bar" |
| reveal_type(c + a) # N: Revealed type is "__main__.Bar" |
| |
| [case testOperatorDoubleUnionNaiveAdd] |
| from typing import Union |
| |
| class A: pass |
| class B: pass |
| class C: |
| def __radd__(self, x: A) -> int: pass |
| class D: |
| def __radd__(self, x: B) -> str: pass |
| |
| x: Union[A, B] |
| y: Union[C, D] |
| |
| x + y # E: Unsupported operand types for + ("A" and "D") \ |
| # E: Unsupported operand types for + ("B" and "C") \ |
| # N: Both left and right operands are unions |
| |
| [case testOperatorDoubleUnionInterwovenUnionAdd] |
| from typing import Union |
| |
| class Out1: pass |
| class Out2: pass |
| class Out3: pass |
| class Out4: pass |
| |
| class A: |
| def __add__(self, x: D) -> Out1: pass |
| class B: |
| def __add__(self, x: C) -> Out2: pass |
| class C: |
| def __radd__(self, x: A) -> Out3: pass |
| class D: |
| def __radd__(self, x: B) -> Out4: pass |
| |
| x: Union[A, B] |
| y: Union[C, D] |
| |
| reveal_type(x + y) # N: Revealed type is "Union[__main__.Out3, __main__.Out1, __main__.Out2, __main__.Out4]" |
| reveal_type(A() + y) # N: Revealed type is "Union[__main__.Out3, __main__.Out1]" |
| reveal_type(B() + y) # N: Revealed type is "Union[__main__.Out2, __main__.Out4]" |
| reveal_type(x + C()) # N: Revealed type is "Union[__main__.Out3, __main__.Out2]" |
| reveal_type(x + D()) # N: Revealed type is "Union[__main__.Out1, __main__.Out4]" |
| |
| [case testOperatorDoubleUnionDivision] |
| from typing import Union |
| def f(a): |
| # type: (Union[int, float]) -> None |
| a /= 1.1 |
| b = a / 1.1 |
| reveal_type(b) # N: Revealed type is "builtins.float" |
| [builtins fixtures/ops.pyi] |
| |
| [case testOperatorWithInference] |
| from typing import TypeVar, Iterable, Union |
| |
| T = TypeVar('T') |
| def sum(x: Iterable[T]) -> Union[T, int]: ... |
| |
| def len(x: Iterable[T]) -> int: ... |
| |
| x = [1.1, 2.2, 3.3] |
| reveal_type(sum(x)) # N: Revealed type is "builtins.float" |
| reveal_type(sum(x) / len(x)) # N: Revealed type is "builtins.float" |
| [builtins fixtures/floatdict.pyi] |
| |
| [case testOperatorWithEmptyListAndSum] |
| from typing import TypeVar, Iterable, Union, overload |
| |
| T = TypeVar('T') |
| S = TypeVar('S') |
| @overload |
| def sum(x: Iterable[T]) -> Union[T, int]: ... |
| @overload |
| def sum(x: Iterable[T], default: S) -> Union[T, S]: ... |
| def sum(*args): pass |
| |
| x = ["a", "b", "c"] |
| reveal_type(x + sum([x, x, x], [])) # N: Revealed type is "builtins.list[builtins.str]" |
| [builtins fixtures/floatdict.pyi] |
| |
| [case testAbstractReverseOperatorMethod] |
| import typing |
| from abc import abstractmethod |
| class A: |
| @abstractmethod |
| def __lt__(self, x: 'A') -> int: pass |
| class B: |
| @abstractmethod |
| def __lt__(self, x: 'B') -> int: pass |
| @abstractmethod |
| def __gt__(self, x: 'B') -> int: pass |
| [out] |
| |
| [case testOperatorMethodsAndOverloadingSpecialCase] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| @overload |
| def __add__(self, x: 'A') -> int: pass |
| @overload |
| def __add__(self, x: str) -> int: pass |
| class B: |
| def __radd__(self, x: 'A') -> str: pass |
| [out] |
| |
| [case testUnsafeOverlappingWithOperatorMethodsAndOverloading2] |
| from foo import A, B |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| def __add__(self, x: 'A') -> int: pass |
| class B: |
| @overload |
| def __radd__(self, x: 'X') -> str: pass # Error |
| @overload |
| def __radd__(self, x: A) -> str: pass # Error |
| class X: |
| def __add__(self, x: B) -> int: pass |
| [out] |
| tmp/foo.pyi:6: error: Signatures of "__radd__" of "B" and "__add__" of "X" are unsafely overlapping |
| |
| [case testUnsafeOverlappingWithLineNo] |
| from typing import TypeVar |
| class Real: |
| def __add__(self, other) -> str: ... |
| class Fraction(Real): |
| def __radd__(self, other: Real) -> Real: ... |
| [out] |
| main:5: error: Signatures of "__radd__" of "Fraction" and "__add__" of "Real" are unsafely overlapping |
| |
| [case testOverlappingNormalAndInplaceOperatorMethod] |
| import typing |
| class A: |
| # Incompatible (potential trouble with __radd__) |
| def __add__(self, x: 'A') -> int: pass |
| def __iadd__(self, x: 'B') -> int: pass |
| class B: |
| # Safe |
| def __add__(self, x: 'C') -> int: pass |
| def __iadd__(self, x: A) -> int: pass |
| class C(A): pass |
| [out] |
| main:5: error: Signatures of "__iadd__" and "__add__" are incompatible |
| |
| [case testOverloadedNormalAndInplaceOperatorMethod] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class A: |
| @overload |
| def __add__(self, x: int) -> int: pass |
| @overload |
| def __add__(self, x: str) -> int: pass |
| @overload # Error |
| def __iadd__(self, x: int) -> int: pass |
| @overload |
| def __iadd__(self, x: object) -> int: pass |
| class B: |
| @overload |
| def __add__(self, x: int) -> int: pass |
| @overload |
| def __add__(self, x: str) -> str: pass |
| @overload |
| def __iadd__(self, x: int) -> int: pass |
| @overload |
| def __iadd__(self, x: str) -> str: pass |
| [out] |
| tmp/foo.pyi:7: error: Signatures of "__iadd__" and "__add__" are incompatible |
| |
| [case testIntroducingInplaceOperatorInSubclass] |
| import typing |
| class A: |
| def __add__(self, x: 'A') -> 'B': pass |
| class B(A): |
| # __iadd__ effectively partially overrides __add__ |
| def __iadd__(self, x: 'A') -> 'A': pass # Error |
| class C(A): |
| def __iadd__(self, x: int) -> 'B': pass # Error |
| class D(A): |
| def __iadd__(self, x: 'A') -> 'B': pass |
| [out] |
| main:6: error: Return type "A" of "__iadd__" incompatible with return type "B" in "__add__" of supertype "A" |
| main:8: error: Argument 1 of "__iadd__" is incompatible with "__add__" of supertype "A"; supertype defines the argument type as "A" |
| main:8: note: This violates the Liskov substitution principle |
| main:8: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides |
| main:8: error: Signatures of "__iadd__" and "__add__" are incompatible |
| |
| [case testGetattribute] |
| |
| a, b = None, None # type: A, B |
| class A: |
| def __getattribute__(self, x: str) -> A: |
| return A() |
| class B: pass |
| |
| a = a.foo |
| b = a.bar |
| [builtins fixtures/tuple.pyi] |
| [out] |
| main:9: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testDecoratedGetAttribute] |
| from typing import Callable, TypeVar |
| |
| T = TypeVar('T', bound=Callable) |
| |
| def decorator(f: T) -> T: |
| return f |
| |
| def bad(f: Callable) -> Callable[..., int]: |
| return f |
| |
| class A: |
| @decorator |
| def __getattribute__(self, x: str) -> A: |
| return A() |
| class B: |
| @bad # We test that type will be taken from decorated type, not node itself |
| def __getattribute__(self, x: str) -> A: |
| return A() |
| |
| a: A |
| b: B |
| |
| a1: A = a.foo |
| b1: B = a.bar # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a2: A = b.baz # E: Incompatible types in assignment (expression has type "int", variable has type "A") |
| b2: B = b.roo # E: Incompatible types in assignment (expression has type "int", variable has type "B") |
| [builtins fixtures/tuple.pyi] |
| |
| [case testGetattributeSignature] |
| class A: |
| def __getattribute__(self, x: str) -> A: pass |
| class B: |
| def __getattribute__(self, x: A) -> B: pass |
| class C: |
| def __getattribute__(self, x: str, y: str) -> C: pass |
| class D: |
| def __getattribute__(self, x: str) -> None: pass |
| [out] |
| main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattribute__" |
| main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattribute__" |
| |
| [case testGetattr] |
| |
| a, b = None, None # type: A, B |
| class A: |
| def __getattr__(self, x: str) -> A: |
| return A() |
| class B: pass |
| |
| a = a.foo |
| b = a.bar |
| [builtins fixtures/tuple.pyi] |
| [out] |
| main:9: error: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| [case testDecoratedGetattr] |
| from typing import Callable, TypeVar |
| |
| T = TypeVar('T', bound=Callable) |
| |
| def decorator(f: T) -> T: |
| return f |
| |
| def bad(f: Callable) -> Callable[..., int]: |
| return f |
| |
| class A: |
| @decorator |
| def __getattr__(self, x: str) -> A: |
| return A() |
| class B: |
| @bad # We test that type will be taken from decorated type, not node itself |
| def __getattr__(self, x: str) -> A: |
| return A() |
| |
| a: A |
| b: B |
| |
| a1: A = a.foo |
| b1: B = a.bar # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a2: A = b.baz # E: Incompatible types in assignment (expression has type "int", variable has type "A") |
| b2: B = b.roo # E: Incompatible types in assignment (expression has type "int", variable has type "B") |
| [builtins fixtures/tuple.pyi] |
| |
| [case testGetattrWithGetitem] |
| class A: |
| def __getattr__(self, x: str) -> 'A': |
| return A() |
| |
| a = A() |
| a[0] # E: Value of type "A" is not indexable |
| |
| [case testGetattrWithCall] |
| class A: |
| def __getattr__(self, x: str) -> 'A': |
| return A() |
| |
| a = A() |
| a.y() # E: "A" not callable |
| |
| [case testGetattrWithCallable] |
| from typing import Callable, Any |
| |
| class C: |
| def __getattr__(self, attr: str) -> C: ... |
| |
| def do(cd: Callable[..., Any]) -> None: ... |
| |
| do(C()) # E: Argument 1 to "do" has incompatible type "C"; expected "Callable[..., Any]" |
| |
| [case testGetattrWithCallableTypeVar] |
| from typing import Callable, Any, TypeVar |
| |
| class C: |
| def __getattr__(self, attr: str) -> C: ... |
| |
| T = TypeVar('T', bound=Callable[..., Any]) |
| |
| def do(cd: T) -> T: ... |
| |
| do(C()) # E: Value of type variable "T" of "do" cannot be "C" |
| |
| [case testNestedGetattr] |
| def foo() -> object: |
| def __getattr__() -> None: # no error because not in a class |
| pass |
| return __getattr__ |
| |
| class X: |
| def foo(self) -> object: |
| def __getattr__() -> None: # no error because not directly inside a class |
| pass |
| return __getattr__ |
| |
| [case testGetattrSignature] |
| class A: |
| def __getattr__(self, x: str) -> A: pass |
| class B: |
| def __getattr__(self, x: A) -> B: pass |
| class C: |
| def __getattr__(self, x: str, y: str) -> C: pass |
| class D: |
| def __getattr__(self, x: str) -> None: pass |
| [out] |
| main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattr__" |
| main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattr__" |
| |
| [case testSetattr] |
| from typing import Union, Any |
| class A: |
| def __setattr__(self, name: str, value: Any) -> None: ... |
| |
| a = A() |
| a.test = 'hello' |
| |
| class B: |
| def __setattr__(self, name: str, value: Union[int, str]) -> None: ... |
| |
| b = B() |
| b.both = 1 |
| b.work = '2' |
| |
| class C: |
| def __setattr__(self, name: str, value: str) -> None: ... |
| |
| c = C() |
| c.fail = 4 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| class D: |
| __setattr__ = 'hello' # E: Invalid signature "str" for "__setattr__" |
| |
| d = D() |
| d.crash = 4 # E: "D" has no attribute "crash" |
| |
| class Ex: |
| def __setattr__(self, name: str, value: int) -> None:... |
| test = '42' # type: str |
| e = Ex() |
| e.test = 'hello' |
| e.t = 4 |
| |
| class Super: |
| def __setattr__(self, name: str, value: int) -> None: ... |
| |
| class Sub(Super): |
| ... |
| s = Sub() |
| s.success = 4 |
| s.fail = 'fail' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testDecoratedSetattr] |
| from typing import Any, Callable, TypeVar |
| |
| T = TypeVar('T', bound=Callable) |
| |
| def decorator(f: T) -> T: |
| return f |
| |
| def bad(f: Callable) -> Callable[[Any, str, int], None]: |
| return f |
| |
| class A: |
| @decorator |
| def __setattr__(self, k: str, v: str) -> None: |
| pass |
| class B: |
| @bad # We test that type will be taken from decorated type, not node itself |
| def __setattr__(self, k: str, v: str) -> None: |
| pass |
| |
| a: A |
| a.foo = 'a' |
| a.bar = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| b: B |
| b.good = 1 |
| b.bad = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSetattrSignature] |
| from typing import Any |
| |
| class Test: |
| def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "Callable[[], None]" for "__setattr__" |
| t = Test() |
| t.crash = 'test' # E: "Test" has no attribute "crash" |
| |
| class A: |
| def __setattr__(self): ... # E: Invalid signature "Callable[[A], Any]" for "__setattr__" |
| a = A() |
| a.test = 4 # E: "A" has no attribute "test" |
| |
| class B: |
| def __setattr__(self, name, value: int): ... |
| b = B() |
| b.integer = 5 |
| |
| class C: |
| def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "Callable[[C, int, int], None]" for "__setattr__" |
| c = C() |
| c.check = 13 |
| |
| class X: |
| __setattr__ = ... # type: Any |
| |
| [case testGetattrAndSetattr] |
| from typing import Any |
| class A: |
| def __setattr__(self, name: str, value: Any) -> None: ... |
| def __getattr__(self, name: str) -> Any: ... |
| a = A() |
| a.test = 4 |
| t = a.test |
| |
| class B: |
| def __setattr__(self, name: str, value: int) -> None: ... |
| def __getattr__(self, name: str) -> str: ... |
| integer = 0 |
| b = B() |
| b.at = '3' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| if int(): |
| integer = b.at # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testSetattrKeywordArg] |
| from typing import Any |
| |
| class C: |
| def __setattr__(self, key: str, value: Any, p: bool = False) -> None: ... |
| |
| c: C |
| c.__setattr__("x", 42, p=True) |
| |
| -- CallableType objects |
| -- ---------------- |
| |
| |
| [case testCallableObject] |
| import typing |
| a = A() |
| b = B() |
| |
| a() # E: Missing positional argument "x" in call to "__call__" of "A" |
| a(a, a) # E: Too many arguments for "__call__" of "A" |
| if int(): |
| a = a(a) |
| if int(): |
| a = a(b) # E: Argument 1 to "__call__" of "A" has incompatible type "B"; expected "A" |
| if int(): |
| b = a(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| class A: |
| def __call__(self, x: A) -> A: |
| pass |
| class B: pass |
| |
| |
| -- __new__ |
| -- -------- |
| |
| |
| [case testConstructInstanceWith__new__] |
| class C: |
| def __new__(cls, foo: int = None) -> 'C': |
| obj = object.__new__(cls) |
| return obj |
| |
| x = C(foo=12) |
| x.a # E: "C" has no attribute "a" |
| C(foo='') # E: Argument "foo" to "C" has incompatible type "str"; expected "Optional[int]" |
| [builtins fixtures/__new__.pyi] |
| |
| [case testConstructInstanceWithDynamicallyTyped__new__] |
| class C: |
| def __new__(cls, foo): # N: "C" defined here |
| obj = object.__new__(cls) |
| return obj |
| |
| x = C(foo=12) |
| x = C(foo='x') |
| x.a # E: "C" has no attribute "a" |
| C(bar='') # E: Unexpected keyword argument "bar" for "C" |
| [builtins fixtures/__new__.pyi] |
| |
| [case testClassWith__new__AndCompatibilityWithType] |
| class C: |
| def __new__(cls, foo: int = None) -> 'C': |
| obj = object.__new__(cls) |
| return obj |
| def f(x: type) -> None: pass |
| def g(x: int) -> None: pass |
| f(C) |
| g(C) # E: Argument 1 to "g" has incompatible type "Type[C]"; expected "int" |
| [builtins fixtures/__new__.pyi] |
| |
| [case testClassWith__new__AndCompatibilityWithType2] |
| class C: |
| def __new__(cls, foo): |
| obj = object.__new__(cls) |
| return obj |
| def f(x: type) -> None: pass |
| def g(x: int) -> None: pass |
| f(C) |
| g(C) # E: Argument 1 to "g" has incompatible type "Type[C]"; expected "int" |
| [builtins fixtures/__new__.pyi] |
| |
| [case testGenericClassWith__new__] |
| from typing import TypeVar, Generic |
| T = TypeVar('T') |
| class C(Generic[T]): |
| def __new__(cls, foo: T) -> 'C[T]': |
| obj = object.__new__(cls) |
| return obj |
| def set(self, x: T) -> None: pass |
| c = C('') |
| c.set('') |
| c.set(1) # E: Argument 1 to "set" of "C" has incompatible type "int"; expected "str" |
| [builtins fixtures/__new__.pyi] |
| |
| [case testOverloaded__new__] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| class C: |
| @overload |
| def __new__(cls, foo: int) -> 'C': |
| obj = object.__new__(cls) |
| return obj |
| @overload |
| def __new__(cls, x: str, y: str) -> 'C': |
| obj = object.__new__(cls) |
| return obj |
| c = C(1) |
| c.a # E: "C" has no attribute "a" |
| C('', '') |
| C('') # E: No overload variant of "C" matches argument type "str" \ |
| # N: Possible overload variants: \ |
| # N: def __new__(cls, foo: int) -> C \ |
| # N: def __new__(cls, x: str, y: str) -> C |
| [builtins fixtures/__new__.pyi] |
| |
| |
| -- Special cases |
| -- ------------- |
| |
| |
| [case testSubclassInt] |
| import typing |
| class A(int): pass |
| n = 0 |
| if int(): |
| n = A() |
| a = A() |
| if int(): |
| a = 0 # E: Incompatible types in assignment (expression has type "int", variable has type "A") |
| |
| [case testForwardReferenceToNestedClass] |
| def f(o: 'B.C') -> None: |
| o.f('') # E: Argument 1 to "f" of "C" has incompatible type "str"; expected "int" |
| |
| class B: |
| class C: |
| def f(self, x: int) -> None: pass |
| [out] |
| |
| [case testForwardReferenceToNestedClassDeep] |
| def f(o: 'B.C.D') -> None: |
| o.f('') # E: Argument 1 to "f" of "D" has incompatible type "str"; expected "int" |
| |
| class B: |
| class C: |
| class D: |
| def f(self, x: int) -> None: pass |
| [out] |
| |
| [case testForwardReferenceToNestedClassWithinClass] |
| class B: |
| def f(self, o: 'C.D') -> None: |
| o.f('') # E: Argument 1 to "f" of "D" has incompatible type "str"; expected "int" |
| |
| class C: |
| class D: |
| def f(self, x: int) -> None: pass |
| [out] |
| |
| [case testClassVsInstanceDisambiguation] |
| class A: pass |
| def f(x: A) -> None: pass |
| f(A) # E: Argument 1 to "f" has incompatible type "Type[A]"; expected "A" |
| [out] |
| |
| -- TODO |
| -- attribute inherited from superclass; assign in __init__ |
| -- refer to attribute before type has been inferred (the initialization in |
| -- __init__ has not been analyzed) |
| |
| [case testAnyBaseClassUnconstrainedConstructor] |
| from typing import Any |
| B = None # type: Any |
| class C(B): pass |
| C(0) |
| C(arg=0) |
| [out] |
| |
| [case testErrorMapToSupertype] |
| import typing |
| class X(Nope): pass # E: Name "Nope" is not defined |
| a, b = X() # Used to crash here (#2244) |
| |
| |
| -- Class-valued attributes |
| -- ----------------------- |
| |
| [case testClassValuedAttributesBasics] |
| class A: ... |
| class B: |
| a = A |
| bad = lambda: 42 |
| |
| B().bad() # E: Attribute function "bad" with type "Callable[[], int]" does not accept self argument |
| reveal_type(B.a) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(B().a) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(B().a()) # N: Revealed type is "__main__.A" |
| |
| class C: |
| a = A |
| def __init__(self) -> None: |
| self.aa = self.a() |
| |
| reveal_type(C().aa) # N: Revealed type is "__main__.A" |
| [out] |
| |
| [case testClassValuedAttributesGeneric] |
| from typing import Generic, TypeVar, Type |
| T = TypeVar('T') |
| |
| class A(Generic[T]): |
| def __init__(self, x: T) -> None: |
| self.x = x |
| class B(Generic[T]): |
| a: Type[A[T]] = A |
| |
| reveal_type(B[int]().a) # N: Revealed type is "Type[__main__.A[builtins.int]]" |
| B[int]().a('hi') # E: Argument 1 to "A" has incompatible type "str"; expected "int" |
| |
| class C(Generic[T]): |
| a = A |
| def __init__(self) -> None: |
| self.aa = self.a(42) |
| |
| reveal_type(C().aa) # N: Revealed type is "__main__.A[builtins.int]" |
| [out] |
| |
| [case testClassValuedAttributesAlias] |
| from typing import Generic, TypeVar |
| T = TypeVar('T') |
| S = TypeVar('S') |
| |
| class A(Generic[T, S]): ... |
| |
| SameA = A[T, T] |
| |
| class B: |
| a_any = SameA |
| a_int = SameA[int] |
| |
| reveal_type(B().a_any) # N: Revealed type is "def () -> __main__.A[Any, Any]" |
| reveal_type(B().a_int()) # N: Revealed type is "__main__.A[builtins.int, builtins.int]" |
| |
| class C: |
| a_int = SameA[int] |
| def __init__(self) -> None: |
| self.aa = self.a_int() |
| |
| reveal_type(C().aa) # N: Revealed type is "__main__.A[builtins.int, builtins.int]" |
| [out] |
| |
| |
| -- Type[C] |
| -- ------- |
| |
| |
| [case testTypeUsingTypeCBasic] |
| from typing import Type |
| class User: pass |
| class ProUser(User): pass |
| def new_user(user_class: Type[User]) -> User: |
| return user_class() |
| reveal_type(new_user(User)) # N: Revealed type is "__main__.User" |
| reveal_type(new_user(ProUser)) # N: Revealed type is "__main__.User" |
| [out] |
| |
| [case testTypeUsingTypeCDefaultInit] |
| from typing import Type |
| class B: |
| pass |
| def f(A: Type[B]) -> None: |
| A(0) # E: Too many arguments for "B" |
| A() |
| [out] |
| |
| [case testTypeUsingTypeCInitWithArg] |
| from typing import Type |
| class B: |
| def __init__(self, a: int) -> None: pass |
| def f(A: Type[B]) -> None: |
| A(0) |
| A() # E: Missing positional argument "a" in call to "B" |
| [out] |
| |
| [case testTypeUsingTypeCTypeVar] |
| from typing import Type, TypeVar |
| class User: pass |
| class ProUser(User): pass |
| U = TypeVar('U', bound=User) |
| def new_user(user_class: Type[U]) -> U: |
| user = user_class() |
| reveal_type(user) |
| return user |
| pro_user = new_user(ProUser) |
| reveal_type(pro_user) |
| [out] |
| main:7: note: Revealed type is "U`-1" |
| main:10: note: Revealed type is "__main__.ProUser" |
| |
| [case testTypeUsingTypeCTypeVarDefaultInit] |
| from typing import Type, TypeVar |
| class B: |
| pass |
| T = TypeVar('T', bound=B) |
| def f(A: Type[T]) -> None: |
| A() |
| A(0) # E: Too many arguments for "B" |
| [out] |
| |
| [case testTypeUsingTypeCTypeVarWithInit] |
| from typing import Type, TypeVar |
| class B: |
| def __init__(self, a: int) -> None: pass |
| T = TypeVar('T', bound=B) |
| def f(A: Type[T]) -> None: |
| A() # E: Missing positional argument "a" in call to "B" |
| A(0) |
| [out] |
| |
| [case testTypeUsingTypeCTwoTypeVars] |
| from typing import Type, TypeVar |
| class User: pass |
| class ProUser(User): pass |
| class WizUser(ProUser): pass |
| U = TypeVar('U', bound=User) |
| def new_user(u_c: Type[U]) -> U: pass |
| P = TypeVar('P', bound=ProUser) |
| def new_pro(pro_c: Type[P]) -> P: |
| return new_user(pro_c) |
| wiz = new_pro(WizUser) |
| reveal_type(wiz) |
| def error(u_c: Type[U]) -> P: # Error here, see below |
| return new_pro(u_c) # Error here, see below |
| [out] |
| main:11: note: Revealed type is "__main__.WizUser" |
| main:12: error: A function returning TypeVar should receive at least one argument containing the same Typevar |
| main:12: note: Consider using the upper bound "ProUser" instead |
| main:13: error: Value of type variable "P" of "new_pro" cannot be "U" |
| main:13: error: Incompatible return value type (got "U", expected "P") |
| |
| [case testTypeUsingTypeCCovariance] |
| from typing import Type, TypeVar |
| class User: pass |
| class ProUser(User): pass |
| def new_user(user_class: Type[User]) -> User: |
| return user_class() |
| def new_pro_user(user_class: Type[ProUser]): |
| new_user(user_class) |
| [out] |
| |
| [case testAllowCovariantArgsInConstructor] |
| from typing import Generic, TypeVar |
| |
| T_co = TypeVar('T_co', covariant=True) |
| |
| class C(Generic[T_co]): |
| def __init__(self, x: T_co) -> None: # This should be allowed |
| self.x = x |
| def meth(self) -> None: |
| reveal_type(self.x) # N: Revealed type is "T_co`1" |
| |
| reveal_type(C(1).x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/property.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCErrorCovariance] |
| from typing import Type, TypeVar |
| class User: pass |
| def new_user(user_class: Type[User]): |
| return user_class() |
| def foo(arg: Type[int]): |
| new_user(arg) # E: Argument 1 to "new_user" has incompatible type "Type[int]"; expected "Type[User]" |
| [out] |
| |
| [case testTypeUsingTypeCUnionOverload] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, Union, overload |
| class X: |
| @overload |
| def __init__(self) -> None: pass |
| @overload |
| def __init__(self, a: int) -> None: pass |
| class Y: |
| def __init__(self) -> None: pass |
| def bar(o: Type[Union[X, Y]]): pass |
| bar(X) |
| bar(Y) |
| [out] |
| |
| [case testTypeUsingTypeCTypeAny] |
| from typing import Type, Any |
| def foo(arg: Type[Any]): |
| x = arg() |
| x = arg(0) |
| x = arg('', ()) |
| reveal_type(x) # N: Revealed type is "Any" |
| x.foo |
| class X: pass |
| foo(X) |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCTypeAnyMember] |
| from typing import Type, Any |
| def foo(arg: Type[Any]): |
| x = arg.member_name |
| arg.new_member_name = 42 |
| # Member access is ok and types as Any |
| reveal_type(x) # N: Revealed type is "Any" |
| # But Type[Any] is distinct from Any |
| y: int = arg # E: Incompatible types in assignment (expression has type "Type[Any]", variable has type "int") |
| [out] |
| |
| [case testTypeUsingTypeCTypeAnyMemberFallback] |
| from typing import Type, Any |
| def foo(arg: Type[Any]): |
| reveal_type(arg.__str__) # N: Revealed type is "def () -> builtins.str" |
| reveal_type(arg.mro()) # N: Revealed type is "builtins.list[builtins.type[Any]]" |
| [builtins fixtures/type.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCTypeNoArg] |
| from typing import Type |
| def foo(arg: Type): |
| x = arg() |
| reveal_type(x) # N: Revealed type is "Any" |
| class X: pass |
| foo(X) |
| [out] |
| |
| [case testTypeUsingTypeCBuiltinType] |
| from typing import Type |
| def foo(arg: type): pass |
| class X: pass |
| def bar(arg: Type[X]): |
| foo(arg) |
| foo(X) |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCClassMethod] |
| from typing import Type |
| class User: |
| @classmethod |
| def foo(cls) -> int: pass |
| def bar(self) -> int: pass |
| def process(cls: Type[User]): |
| reveal_type(cls.foo()) # N: Revealed type is "builtins.int" |
| obj = cls() |
| reveal_type(cls.bar(obj)) # N: Revealed type is "builtins.int" |
| cls.mro() # Defined in class type |
| cls.error # E: "Type[User]" has no attribute "error" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCClassMethodUnion] |
| from typing import Type, Union |
| class User: |
| @classmethod |
| def foo(cls) -> int: pass |
| def bar(self) -> int: pass |
| class ProUser(User): pass |
| class BasicUser(User): pass |
| def process(cls: Type[Union[BasicUser, ProUser]]): |
| cls.foo() |
| obj = cls() |
| cls.bar(obj) |
| cls.mro() # Defined in class type |
| cls.error # E: Item "type" of "Union[Type[BasicUser], Type[ProUser]]" has no attribute "error" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCClassMethodFromTypeVar] |
| from typing import Type, TypeVar |
| class User: |
| @classmethod |
| def foo(cls) -> int: pass |
| def bar(self) -> int: pass |
| U = TypeVar('U', bound=User) |
| def process(cls: Type[U]): |
| reveal_type(cls.foo()) # N: Revealed type is "builtins.int" |
| obj = cls() |
| reveal_type(cls.bar(obj)) # N: Revealed type is "builtins.int" |
| cls.mro() # Defined in class type |
| cls.error # E: "Type[U]" has no attribute "error" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCClassMethodFromTypeVarUnionBound] |
| # Ideally this would work, but not worth the effort; just don't crash |
| from typing import Type, TypeVar, Union |
| class User: |
| @classmethod |
| def foo(cls) -> int: pass |
| def bar(self) -> int: pass |
| class ProUser(User): pass |
| class BasicUser(User): pass |
| U = TypeVar('U', bound=Union[ProUser, BasicUser]) |
| def process(cls: Type[U]): |
| cls.foo() # E: "Type[U]" has no attribute "foo" |
| obj = cls() |
| cls.bar(obj) # E: "Type[U]" has no attribute "bar" |
| cls.mro() # Defined in class type |
| cls.error # E: "Type[U]" has no attribute "error" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeUsingTypeCErrorUnsupportedType] |
| from typing import Type, Tuple |
| def foo(arg: Type[Tuple[int]]): |
| arg() # E: Cannot instantiate type "Type[Tuple[int]]" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testTypeUsingTypeCOverloadedClass] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, TypeVar, overload |
| class User: |
| @overload |
| def __init__(self) -> None: pass |
| @overload |
| def __init__(self, arg: int) -> None: pass |
| @classmethod |
| def foo(cls) -> None: pass |
| U = TypeVar('U', bound=User) |
| def new(uc: Type[U]) -> U: |
| uc.foo() |
| u = uc() |
| u.foo() |
| if 1: |
| u = uc(0) |
| u.foo() |
| u = uc('') # Error |
| u.foo(0) # Error |
| return uc() |
| u = new(User) |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| tmp/foo.pyi:17: error: No overload variant of "User" matches argument type "str" |
| tmp/foo.pyi:17: note: Possible overload variants: |
| tmp/foo.pyi:17: note: def __init__(self) -> U |
| tmp/foo.pyi:17: note: def __init__(self, arg: int) -> U |
| tmp/foo.pyi:18: error: Too many arguments for "foo" of "User" |
| |
| [case testTypeUsingTypeCInUpperBound] |
| from typing import TypeVar, Type |
| class B: pass |
| T = TypeVar('T', bound=Type[B]) |
| def f(a: T): pass |
| [out] |
| |
| [case testTypeUsingTypeCTuple] |
| from typing import Type, Tuple |
| def f(a: Type[Tuple[int, int]]): |
| a() # E: Cannot instantiate type "Type[Tuple[int, int]]" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testTypeUsingTypeCNamedTuple] |
| from typing import Type, NamedTuple |
| N = NamedTuple('N', [('x', int), ('y', int)]) |
| def f(a: Type[N]): |
| a() |
| [builtins fixtures/list.pyi] |
| [out] |
| main:4: error: Missing positional arguments "x", "y" in call to "N" |
| |
| [case testTypeUsingTypeCJoin] |
| from typing import Type |
| class B: pass |
| class C(B): pass |
| class D(B): pass |
| def foo(c: Type[C], d: Type[D]) -> None: |
| x = [c, d] |
| reveal_type(x) |
| |
| [builtins fixtures/list.pyi] |
| [out] |
| main:7: note: Revealed type is "builtins.list[Type[__main__.B]]" |
| |
| [case testTypeEquivalentTypeAny] |
| from typing import Type, Any |
| |
| a = None # type: Type[Any] |
| b = a # type: type |
| |
| x = None # type: type |
| y = x # type: Type[Any] |
| |
| class C: ... |
| |
| p = None # type: type |
| q = p # type: Type[C] |
| |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testTypeEquivalentTypeAny2] |
| from typing import Type, Any, TypeVar, Generic |
| |
| class C: ... |
| x = None # type: type |
| y = None # type: Type[Any] |
| z = None # type: Type[C] |
| |
| lst = [x, y, z] |
| reveal_type(lst) # N: Revealed type is "builtins.list[builtins.type]" |
| |
| T1 = TypeVar('T1', bound=type) |
| T2 = TypeVar('T2', bound=Type[Any]) |
| class C1(Generic[T1]): ... |
| class C2(Generic[T2]): ... |
| |
| C1[Type[Any]], C2[type] # both these should not fail |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testTypeEquivalentTypeAnyEdgeCase] |
| class C: |
| pass |
| |
| class M(type): |
| def __init__(cls, x) -> None: |
| type.__init__(cls, x) |
| |
| class Mbad(type): |
| def __init__(cls, x) -> None: |
| type.__init__(C(), x) # E: Argument 1 to "__init__" of "type" has incompatible type "C"; expected "type" |
| [builtins fixtures/primitives.pyi] |
| [out] |
| |
| [case testTypeMatchesOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload, Any |
| |
| class User: pass |
| UserType = User # type: Type[User] |
| |
| @overload |
| def f(a: int) -> Any: pass |
| @overload |
| def f(a: object) -> int: pass |
| |
| reveal_type(f(User)) # N: Revealed type is "builtins.int" |
| reveal_type(f(UserType)) # N: Revealed type is "builtins.int" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeMatchesGeneralTypeInOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| UserType = User # type: Type[User] |
| |
| @overload |
| def f(a: type) -> int: |
| return 1 |
| @overload |
| def f(a: int) -> str: |
| return "a" |
| |
| reveal_type(f(User)) # N: Revealed type is "builtins.int" |
| reveal_type(f(UserType)) # N: Revealed type is "builtins.int" |
| reveal_type(f(1)) # N: Revealed type is "builtins.str" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeMatchesSpecificTypeInOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| UserType = User # type: Type[User] |
| |
| @overload |
| def f(a: User) -> User: |
| return User() |
| @overload |
| def f(a: Type[User]) -> int: |
| return 1 |
| @overload |
| def f(a: int) -> str: |
| return "a" |
| |
| reveal_type(f(User)) # N: Revealed type is "builtins.int" |
| reveal_type(f(UserType)) # N: Revealed type is "builtins.int" |
| reveal_type(f(User())) # N: Revealed type is "foo.User" |
| reveal_type(f(1)) # N: Revealed type is "builtins.str" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testMixingTypeTypeInOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: User) -> Type[User]: |
| return User |
| @overload |
| def f(a: Type[User]) -> User: |
| return a() |
| @overload |
| def f(a: int) -> Type[User]: |
| return User |
| @overload |
| def f(a: str) -> User: |
| return User() |
| |
| reveal_type(f(User())) # N: Revealed type is "Type[foo.User]" |
| reveal_type(f(User)) # N: Revealed type is "foo.User" |
| reveal_type(f(3)) # N: Revealed type is "Type[foo.User]" |
| reveal_type(f("hi")) # N: Revealed type is "foo.User" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testGeneralTypeMatchesSpecificTypeInOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, Any, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: Type[User]) -> None: pass |
| @overload |
| def f(a: int) -> None: pass |
| |
| def mock_1() -> type: return User |
| def mock_2() -> Type[Any]: return User |
| |
| f(User) |
| f(mock_1()) |
| f(mock_2()) |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testNonTypeDoesNotMatchOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: Type[User]) -> None: pass |
| @overload |
| def f(a: type) -> None: pass |
| |
| f(3) # E: No overload variant of "f" matches argument type "int" \ |
| # N: Possible overload variants: \ |
| # N: def f(a: Type[User]) -> None \ |
| # N: def f(a: type) -> None |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testInstancesDoNotMatchTypeInOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: Type[User]) -> None: pass |
| @overload |
| def f(a: int) -> None: pass |
| |
| f(User) |
| f(User()) # E: No overload variant of "f" matches argument type "User" \ |
| # N: Possible overload variants: \ |
| # N: def f(a: Type[User]) -> None \ |
| # N: def f(a: int) -> None |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeCovarianceWithOverloadedFunctions] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class A: pass |
| class B(A): pass |
| class C(B): pass |
| AType = A # type: Type[A] |
| BType = B # type: Type[B] |
| CType = C # type: Type[C] |
| |
| @overload |
| def f(a: Type[B]) -> None: pass |
| @overload |
| def f(a: int) -> None: pass |
| |
| f(A) # E: Argument 1 to "f" has incompatible type "Type[A]"; expected "Type[B]" |
| f(B) |
| f(C) |
| f(AType) # E: Argument 1 to "f" has incompatible type "Type[A]"; expected "Type[B]" |
| f(BType) |
| f(CType) |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| |
| [case testOverloadedCovariantTypesFail] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class A: pass |
| class B(A): pass |
| |
| @overload |
| def f(a: Type[B]) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types |
| @overload |
| def f(a: Type[A]) -> str: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testDistinctOverloadedCovariantTypesSucceed] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class A: pass |
| class AChild(A): pass |
| class B: pass |
| class BChild(B): pass |
| |
| @overload |
| def f(a: Type[A]) -> int: pass |
| @overload |
| def f(a: Type[B]) -> str: pass |
| @overload |
| def f(a: A) -> A: pass |
| @overload |
| def f(a: B) -> B: pass |
| |
| reveal_type(f(A)) # N: Revealed type is "builtins.int" |
| reveal_type(f(AChild)) # N: Revealed type is "builtins.int" |
| reveal_type(f(B)) # N: Revealed type is "builtins.str" |
| reveal_type(f(BChild)) # N: Revealed type is "builtins.str" |
| |
| reveal_type(f(A())) # N: Revealed type is "foo.A" |
| reveal_type(f(AChild())) # N: Revealed type is "foo.A" |
| reveal_type(f(B())) # N: Revealed type is "foo.B" |
| reveal_type(f(BChild())) # N: Revealed type is "foo.B" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testSubtypeWithMoreOverloadsThanSupertypeSucceeds] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| |
| |
| class X: pass |
| class Y: pass |
| class Z: pass |
| |
| |
| class A: |
| @overload |
| def f(self, x: X) -> X: pass |
| @overload |
| def f(self, y: Y) -> Y: pass |
| |
| class B(A): |
| @overload |
| def f(self, x: X) -> X: pass |
| @overload |
| def f(self, y: Y) -> Y: pass |
| @overload |
| def f(self, z: Z) -> Z: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testSubtypeOverloadCoveringMultipleSupertypeOverloadsSucceeds] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| |
| |
| class A: pass |
| class B(A): pass |
| class C(A): pass |
| class D: pass |
| |
| |
| class Super: |
| @overload |
| def foo(self, a: B) -> C: pass |
| @overload |
| def foo(self, a: C) -> A: pass |
| @overload |
| def foo(self, a: D) -> D: pass |
| |
| class Sub(Super): |
| @overload |
| def foo(self, a: A) -> C: pass |
| @overload |
| def foo(self, a: D) -> D: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testSubtypeOverloadWithOverlappingArgumentsButWrongReturnType] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| |
| |
| class A: pass |
| class B(A): pass |
| class C: pass |
| |
| |
| class Super: |
| @overload |
| def foo(self, a: A) -> A: pass |
| @overload |
| def foo(self, a: C) -> C: pass |
| |
| class Sub(Super): |
| @overload # Fail |
| def foo(self, a: A) -> A: pass |
| @overload |
| def foo(self, a: B) -> C: pass # Fail |
| @overload |
| def foo(self, a: C) -> C: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| tmp/foo.pyi:16: error: Signature of "foo" incompatible with supertype "Super" |
| tmp/foo.pyi:16: note: Superclass: |
| tmp/foo.pyi:16: note: @overload |
| tmp/foo.pyi:16: note: def foo(self, a: A) -> A |
| tmp/foo.pyi:16: note: @overload |
| tmp/foo.pyi:16: note: def foo(self, a: C) -> C |
| tmp/foo.pyi:16: note: Subclass: |
| tmp/foo.pyi:16: note: @overload |
| tmp/foo.pyi:16: note: def foo(self, a: A) -> A |
| tmp/foo.pyi:16: note: @overload |
| tmp/foo.pyi:16: note: def foo(self, a: B) -> C |
| tmp/foo.pyi:16: note: @overload |
| tmp/foo.pyi:16: note: def foo(self, a: C) -> C |
| tmp/foo.pyi:19: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader |
| |
| [case testTypeTypeOverlapsWithObjectAndType] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: Type[User]) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types |
| @overload |
| def f(a: object) -> str: pass |
| |
| @overload |
| def g(a: Type[User]) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types |
| @overload |
| def g(a: type) -> str: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeOverlapsWithObject] |
| from foo import * |
| [file foo.pyi] |
| from typing import Type, overload |
| |
| class User: pass |
| |
| @overload |
| def f(a: type) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types |
| @overload |
| def f(a: object) -> str: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeConstructorReturnsTypeType] |
| class User: |
| @classmethod |
| def test_class_method(cls) -> int: pass |
| @staticmethod |
| def test_static_method() -> str: pass |
| def test_instance_method(self) -> None: pass |
| |
| u = User() |
| |
| reveal_type(type(u)) # N: Revealed type is "Type[__main__.User]" |
| reveal_type(type(u).test_class_method()) # N: Revealed type is "builtins.int" |
| reveal_type(type(u).test_static_method()) # N: Revealed type is "builtins.str" |
| type(u).test_instance_method() # E: Missing positional argument "self" in call to "test_instance_method" of "User" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testObfuscatedTypeConstructorReturnsTypeType] |
| from typing import TypeVar |
| class User: pass |
| |
| f1 = type |
| |
| A = TypeVar('A') |
| def f2(func: A) -> A: |
| return func |
| |
| u = User() |
| |
| reveal_type(f1(u)) # N: Revealed type is "Type[__main__.User]" |
| reveal_type(f2(type)(u)) # N: Revealed type is "Type[__main__.User]" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testTypeConstructorLookalikeFails] |
| class User: pass |
| |
| def fake1(a: object) -> type: |
| return User |
| def fake2(a: int) -> type: |
| return User |
| |
| reveal_type(type(User())) # N: Revealed type is "Type[__main__.User]" |
| reveal_type(fake1(User())) # N: Revealed type is "builtins.type" |
| reveal_type(fake2(3)) # N: Revealed type is "builtins.type" |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testOtherTypeConstructorsSucceed] |
| def foo(self) -> int: return self.attr |
| |
| User = type('User', (object,), {'foo': foo, 'attr': 3}) |
| reveal_type(User) # N: Revealed type is "builtins.type" |
| [builtins fixtures/args.pyi] |
| [out] |
| |
| [case testTypeTypeComparisonWorks] |
| class User: pass |
| |
| User == User |
| User == type(User()) |
| type(User()) == User |
| type(User()) == type(User()) |
| |
| User != User |
| User != type(User()) |
| type(User()) != User |
| type(User()) != type(User()) |
| |
| int == int |
| int == type(3) |
| type(3) == int |
| type(3) == type(3) |
| |
| int != int |
| int != type(3) |
| type(3) != int |
| type(3) != type(3) |
| |
| User is User |
| User is type(User) |
| type(User) is User |
| type(User) is type(User) |
| |
| int is int |
| int is type(3) |
| type(3) is int |
| type(3) is type(3) |
| |
| int.__eq__(int) |
| int.__eq__(3, 4) |
| [builtins fixtures/args.pyi] |
| [out] |
| main:33: error: Too few arguments for "__eq__" of "int" |
| main:33: error: Unsupported operand types for == ("int" and "Type[int]") |
| |
| [case testMroSetAfterError] |
| class C(str, str): |
| foo = 0 |
| bar = foo |
| [out] |
| main:1: error: Duplicate base class "str" |
| |
| [case testCannotDetermineMro] |
| class A: pass |
| class B(A): pass |
| class C(B): pass |
| class D(A, B): pass # E: Cannot determine consistent method resolution order (MRO) for "D" |
| class E(C, D): pass |
| |
| [case testInconsistentMroLocalRef] |
| class A: pass |
| class B(object, A): # E: Cannot determine consistent method resolution order (MRO) for "B" |
| def readlines(self): pass |
| __iter__ = readlines |
| |
| [case testDynamicMetaclass] |
| class C(metaclass=int()): # E: Dynamic metaclass not supported for "C" |
| pass |
| |
| [case testDynamicMetaclassCrash] |
| class C(metaclass=int().x): # E: Dynamic metaclass not supported for "C" |
| pass |
| |
| [case testVariableSubclass] |
| class A: |
| a = 1 # type: int |
| class B(A): |
| a = 1 |
| [out] |
| |
| [case testVariableSubclassAssignMismatch] |
| class A: |
| a = 1 # type: int |
| class B(A): |
| a = "a" |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testVariableSubclassAssignment] |
| class A: |
| a = None # type: int |
| class B(A): |
| def __init__(self) -> None: |
| self.a = "a" |
| [out] |
| main:5: error: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testVariableSubclassTypeOverwrite] |
| class A: |
| a = None # type: int |
| class B(A): |
| a = None # type: str |
| class C(B): |
| a = "a" |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testVariableSubclassTypeOverwriteImplicit] |
| class A: |
| a = 1 |
| class B(A): |
| a = None # type: str |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testVariableSuperUsage] |
| class A: |
| a = [] # type: list |
| class B(A): |
| a = [1, 2] |
| class C(B): |
| a = B.a + [3] |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testClassAllBases] |
| from typing import Union |
| class A: |
| a = None # type: Union[int, str] |
| class B(A): |
| a = 1 |
| class C(B): |
| a = "str" |
| class D(A): |
| a = "str" |
| [out] |
| main:7: error: Incompatible types in assignment (expression has type "str", base class "B" defined the type as "int") |
| |
| [case testVariableTypeVar] |
| from typing import TypeVar, Generic |
| T = TypeVar('T') |
| class A(Generic[T]): |
| a = None # type: T |
| class B(A[int]): |
| a = 1 |
| |
| [case testVariableTypeVarInvalid] |
| from typing import TypeVar, Generic |
| T = TypeVar('T') |
| class A(Generic[T]): |
| a = None # type: T |
| class B(A[int]): |
| a = "abc" |
| [out] |
| main:6: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testVariableTypeVarIndirectly] |
| from typing import TypeVar, Generic |
| T = TypeVar('T') |
| class A(Generic[T]): |
| a = None # type: T |
| class B(A[int]): |
| pass |
| class C(B): |
| a = "a" |
| [out] |
| main:8: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testVariableTypeVarList] |
| from typing import List, TypeVar, Generic |
| T = TypeVar('T') |
| class A(Generic[T]): |
| a = None # type: List[T] |
| b = None # type: List[T] |
| class B(A[int]): |
| a = [1] |
| b = [''] |
| [builtins fixtures/list.pyi] |
| [out] |
| main:8: error: List item 0 has incompatible type "str"; expected "int" |
| |
| [case testVariableMethod] |
| class A: |
| def a(self) -> None: pass |
| b = 1 |
| class B(A): |
| a = 1 |
| def b(self) -> None: pass |
| [out] |
| main:5: error: Incompatible types in assignment (expression has type "int", base class "A" defined the type as "Callable[[A], None]") |
| main:6: error: Signature of "b" incompatible with supertype "A" |
| |
| [case testVariableProperty] |
| class A: |
| @property |
| def a(self) -> bool: pass |
| class B(A): |
| a = None # type: bool |
| class C(A): |
| a = True |
| class D(A): |
| a = 1 |
| [builtins fixtures/property.pyi] |
| [out] |
| main:9: error: Incompatible types in assignment (expression has type "int", base class "A" defined the type as "bool") |
| |
| [case testVariableOverwriteAny] |
| from typing import Any |
| class A: |
| a = 1 |
| class B(A): |
| a = 'x' # type: Any |
| [out] |
| |
| [case testInstanceMethodOverwrite] |
| class B(): |
| def n(self, a: int) -> None: pass |
| class C(B): |
| def m(self, a: int) -> None: pass |
| n = m |
| [out] |
| |
| [case testInstanceMethodOverwriteError] |
| class B(): |
| def n(self, a: int) -> None: pass |
| class C(B): |
| def m(self, a: str) -> None: pass |
| n = m |
| [out] |
| main:5: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "B" defined the type as "Callable[[int], None]") |
| |
| [case testInstanceMethodOverwriteTypevar] |
| from typing import Generic, TypeVar |
| T = TypeVar("T") |
| class B(Generic[T]): |
| def n(self, a: T) -> None: pass |
| class C(B[int]): |
| def m(self, a: int) -> None: pass |
| n = m |
| |
| [case testInstanceMethodOverwriteTwice] |
| class I: |
| def foo(self) -> None: pass |
| class A(I): |
| def foo(self) -> None: pass |
| class B(A): |
| def bar(self) -> None: pass |
| foo = bar |
| class C(B): |
| def bar(self) -> None: pass |
| foo = bar |
| |
| [case testClassMethodOverwrite] |
| class B(): |
| @classmethod |
| def n(self, a: int) -> None: pass |
| class C(B): |
| @classmethod |
| def m(self, a: int) -> None: pass |
| n = m |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testClassMethodOverwriteError] |
| class B(): |
| @classmethod |
| def n(self, a: int) -> None: pass |
| class C(B): |
| @classmethod |
| def m(self, a: str) -> None: pass |
| n = m |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| main:7: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "B" defined the type as "Callable[[int], None]") |
| |
| [case testClassSpec] |
| from typing import Callable |
| class A(): |
| b = None # type: Callable[[A, int], int] |
| class B(A): |
| def c(self, a: int) -> int: pass |
| b = c |
| |
| [case testClassSpecError] |
| from typing import Callable |
| class A(): |
| b = None # type: Callable[[A, int], int] |
| class B(A): |
| def c(self, a: str) -> int: pass |
| b = c |
| [out] |
| main:6: error: Incompatible types in assignment (expression has type "Callable[[str], int]", base class "A" defined the type as "Callable[[int], int]") |
| |
| [case testClassStaticMethod] |
| class A(): |
| @staticmethod |
| def a(a: int) -> None: pass |
| class B(A): |
| @staticmethod |
| def b(a: str) -> None: pass |
| a = b |
| [builtins fixtures/staticmethod.pyi] |
| [out] |
| main:7: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "A" defined the type as "Callable[[int], None]") |
| |
| [case testClassStaticMethodIndirect] |
| class A(): |
| @staticmethod |
| def a(a: int) -> None: pass |
| c = a |
| class B(A): |
| @staticmethod |
| def b(a: str) -> None: pass |
| c = b |
| [builtins fixtures/staticmethod.pyi] |
| [out] |
| main:8: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "A" defined the type as "Callable[[int], None]") |
| |
| [case testClassStaticMethodSubclassing] |
| class A: |
| @staticmethod |
| def a() -> None: pass |
| |
| def b(self) -> None: pass |
| |
| @staticmethod |
| def c() -> None: pass |
| |
| class B(A): |
| def a(self) -> None: pass # Fail |
| |
| @classmethod |
| def b(cls) -> None: pass |
| |
| @staticmethod |
| def c() -> None: pass |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| main:11: error: Signature of "a" incompatible with supertype "A" |
| main:11: note: Superclass: |
| main:11: note: @staticmethod |
| main:11: note: def a() -> None |
| main:11: note: Subclass: |
| main:11: note: def a(self) -> None |
| |
| [case testTempNode] |
| class A(): |
| def a(self) -> None: pass |
| class B(A): |
| def b(self) -> None: pass |
| a = c = b |
| |
| [case testListObject] |
| from typing import List |
| class A: |
| x = [] # type: List[object] |
| class B(A): |
| x = [1] |
| [builtins fixtures/list.pyi] |
| |
| [case testClassMemberObject] |
| class A: |
| x = object() |
| class B(A): |
| x = 1 |
| class C(B): |
| x = '' |
| [out] |
| main:6: error: Incompatible types in assignment (expression has type "str", base class "B" defined the type as "int") |
| |
| [case testSlots] |
| class A: |
| __slots__ = ("a") |
| class B(A): |
| __slots__ = ("a", "b") |
| [builtins fixtures/tuple.pyi] |
| |
| [case testClassOrderOfError] |
| class A: |
| x = 1 |
| class B(A): |
| x = "a" |
| class C(B): |
| x = object() |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| main:6: error: Incompatible types in assignment (expression has type "object", base class "B" defined the type as "str") |
| |
| [case testClassOneErrorPerLine] |
| class A: |
| x = 1 |
| class B(A): |
| x = "" |
| x = 1.0 |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| main:5: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int") |
| |
| [case testClassIgnoreType_RedefinedAttributeAndGrandparentAttributeTypesNotIgnored] |
| class A: |
| x = 0 |
| class B(A): |
| x = '' # type: ignore |
| class C(B): |
| x = '' |
| [out] |
| |
| [case testClassIgnoreType_RedefinedAttributeTypeIgnoredInChildren] |
| class A: |
| x = 0 |
| class B(A): |
| x = '' # type: ignore |
| class C(B): |
| x = '' # type: ignore |
| [out] |
| |
| [case testInvalidMetaclassStructure] |
| class X(type): pass |
| class Y(type): pass |
| class A(metaclass=X): pass |
| class B(A, metaclass=Y): pass # E: Inconsistent metaclass structure for "B" |
| |
| [case testMetaclassNoTypeReveal] |
| class M: |
| x = 0 # type: int |
| |
| class A(metaclass=M): pass # E: Metaclasses not inheriting from "type" are not supported |
| |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testMetaclassTypeReveal] |
| from typing import Type |
| class M(type): |
| x = 0 # type: int |
| |
| class A(metaclass=M): pass |
| |
| def f(TA: Type[A]): |
| reveal_type(TA) # N: Revealed type is "Type[__main__.A]" |
| reveal_type(TA.x) # N: Revealed type is "builtins.int" |
| |
| [case testSubclassMetaclass] |
| class M1(type): |
| x = 0 |
| class M2(M1): pass |
| class C(metaclass=M2): |
| pass |
| reveal_type(C.x) # N: Revealed type is "builtins.int" |
| |
| [case testMetaclassSubclass] |
| from typing import Type |
| class M(type): |
| x = 0 # type: int |
| |
| class A(metaclass=M): pass |
| class B(A): pass |
| |
| def f(TB: Type[B]): |
| reveal_type(TB) # N: Revealed type is "Type[__main__.B]" |
| reveal_type(TB.x) # N: Revealed type is "builtins.int" |
| |
| [case testMetaclassIterable] |
| from typing import Iterable, Iterator |
| |
| class ImplicitMeta(type): |
| def __iter__(self) -> Iterator[int]: yield 1 |
| |
| class Implicit(metaclass=ImplicitMeta): pass |
| |
| for _ in Implicit: pass |
| reveal_type(list(Implicit)) # N: Revealed type is "builtins.list[builtins.int]" |
| |
| class ExplicitMeta(type, Iterable[int]): |
| def __iter__(self) -> Iterator[int]: yield 1 |
| |
| class Explicit(metaclass=ExplicitMeta): pass |
| for _ in Explicit: pass |
| reveal_type(list(Explicit)) # N: Revealed type is "builtins.list[builtins.int]" |
| |
| [builtins fixtures/list.pyi] |
| |
| [case testMetaclassTuple] |
| from typing import Tuple |
| |
| class M(Tuple[int]): pass |
| class C(metaclass=M): pass # E: Invalid metaclass "M" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testMetaclassOperatorBeforeReversed] |
| class X: |
| def __radd__(self, x: int) -> int: ... |
| |
| class Meta(type): |
| def __add__(cls, x: X) -> str: ... |
| |
| class Concrete(metaclass=Meta): |
| pass |
| |
| reveal_type(Concrete + X()) # N: Revealed type is "builtins.str" |
| Concrete + "hello" # E: Unsupported operand types for + ("Type[Concrete]" and "str") |
| |
| [case testMetaclassOperatorTypeVar] |
| from typing import Type, TypeVar |
| |
| class MetaClass(type): |
| def __mul__(cls, other: int) -> str: |
| return "" |
| |
| class Test(metaclass=MetaClass): |
| pass |
| |
| S = TypeVar("S", bound=Test) |
| |
| def f(x: Type[Test]) -> str: |
| return x * 0 |
| def g(x: Type[S]) -> str: |
| return reveal_type(x * 0) # N: Revealed type is "builtins.str" |
| |
| [case testMetaclassGetitem] |
| class M(type): |
| def __getitem__(self, key) -> int: return 1 |
| |
| class A(metaclass=M): pass |
| |
| reveal_type(A[M]) # N: Revealed type is "builtins.int" |
| |
| [case testMetaclassSelfType] |
| from typing import TypeVar, Type |
| |
| class M(type): pass |
| T = TypeVar('T') |
| |
| class M1(M): |
| def foo(cls: Type[T]) -> T: ... |
| |
| class A(metaclass=M1): pass |
| reveal_type(A.foo()) # N: Revealed type is "__main__.A" |
| |
| [case testMetaclassAndSkippedImport] |
| # flags: --ignore-missing-imports |
| from missing import M |
| class A(metaclass=M): |
| y = 0 |
| reveal_type(A.y) # N: Revealed type is "builtins.int" |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testAnyMetaclass] |
| from typing import Any |
| M = None # type: Any |
| class A(metaclass=M): |
| y = 0 |
| reveal_type(A.y) # N: Revealed type is "builtins.int" |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testValidTypeAliasAsMetaclass] |
| from typing_extensions import TypeAlias |
| |
| Explicit: TypeAlias = type |
| Implicit = type |
| |
| class E(metaclass=Explicit): ... |
| class I(metaclass=Implicit): ... |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testValidTypeAliasOfTypeAliasAsMetaclass] |
| from typing_extensions import TypeAlias |
| |
| Explicit: TypeAlias = type |
| Implicit = type |
| |
| A1: TypeAlias = Explicit |
| A2 = Explicit |
| A3: TypeAlias = Implicit |
| A4 = Implicit |
| |
| class C1(metaclass=A1): ... |
| class C2(metaclass=A2): ... |
| class C3(metaclass=A3): ... |
| class C4(metaclass=A4): ... |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testTypeAliasWithArgsAsMetaclass] |
| from typing import Generic, TypeVar |
| from typing_extensions import TypeAlias |
| |
| T = TypeVar('T') |
| class Meta(Generic[T]): ... |
| |
| Explicit: TypeAlias = Meta[T] |
| Implicit = Meta[T] |
| |
| class E(metaclass=Explicit): ... # E: Invalid metaclass "Explicit" |
| class I(metaclass=Implicit): ... # E: Invalid metaclass "Implicit" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testTypeAliasNonTypeAsMetaclass] |
| from typing_extensions import TypeAlias |
| |
| Explicit: TypeAlias = int |
| Implicit = int |
| |
| class E(metaclass=Explicit): ... # E: Metaclasses not inheriting from "type" are not supported |
| class I(metaclass=Implicit): ... # E: Metaclasses not inheriting from "type" are not supported |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testInvalidVariableAsMetaclass] |
| from typing import Any |
| M = 0 # type: int |
| MM = 0 |
| class A(metaclass=M): # E: Invalid metaclass "M" |
| y = 0 |
| class B(metaclass=MM): # E: Invalid metaclass "MM" |
| y = 0 |
| reveal_type(A.y) # N: Revealed type is "builtins.int" |
| A.x # E: "Type[A]" has no attribute "x" |
| |
| [case testAnyAsBaseOfMetaclass] |
| from typing import Any, Type |
| M = None # type: Any |
| class MM(M): pass |
| |
| class A(metaclass=MM): |
| y = 0 |
| @classmethod |
| def f(cls) -> None: pass |
| def g(self) -> None: pass |
| |
| def h(a: Type[A], b: Type[object]) -> None: |
| h(a, a) |
| h(b, a) # E: Argument 1 to "h" has incompatible type "Type[object]"; expected "Type[A]" |
| a.f(1) # E: Too many arguments for "f" of "A" |
| reveal_type(a.y) # N: Revealed type is "builtins.int" |
| |
| x = A # type: MM |
| reveal_type(A.y) # N: Revealed type is "builtins.int" |
| reveal_type(A.x) # N: Revealed type is "Any" |
| A.f(1) # E: Too many arguments for "f" of "A" |
| A().g(1) # E: Too many arguments for "g" of "A" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testMetaclassTypeCallable] |
| class M(type): |
| x = 5 |
| |
| class A(metaclass=M): pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| |
| [case testMetaclassStrictSupertypeOfTypeWithClassmethods] |
| from typing import Type, TypeVar |
| TA = TypeVar('TA', bound='A') |
| TTA = TypeVar('TTA', bound='Type[A]') |
| TM = TypeVar('TM', bound='M') |
| |
| class M(type): |
| def g1(cls: 'Type[A]') -> A: pass # E: The erased type of self "Type[__main__.A]" is not a supertype of its class "__main__.M" |
| def g2(cls: Type[TA]) -> TA: pass # E: The erased type of self "Type[__main__.A]" is not a supertype of its class "__main__.M" |
| def g3(cls: TTA) -> TTA: pass # E: The erased type of self "Type[__main__.A]" is not a supertype of its class "__main__.M" |
| def g4(cls: TM) -> TM: pass |
| m: M |
| |
| class A(metaclass=M): |
| def foo(self): pass |
| |
| reveal_type(A.g1) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(A.g2) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(A.g3) # N: Revealed type is "def () -> def () -> __main__.A" |
| reveal_type(A.g4) # N: Revealed type is "def () -> def () -> __main__.A" |
| |
| class B(metaclass=M): |
| def foo(self): pass |
| |
| B.g1 # E: Invalid self argument "Type[B]" to attribute function "g1" with type "Callable[[Type[A]], A]" |
| B.g2 # E: Invalid self argument "Type[B]" to attribute function "g2" with type "Callable[[Type[TA]], TA]" |
| B.g3 # E: Invalid self argument "Type[B]" to attribute function "g3" with type "Callable[[TTA], TTA]" |
| reveal_type(B.g4) # N: Revealed type is "def () -> def () -> __main__.B" |
| |
| # 4 examples of unsoundness - instantiation, classmethod, staticmethod and ClassVar: |
| |
| ta: Type[A] = m # E: Incompatible types in assignment (expression has type "M", variable has type "Type[A]") |
| a: A = ta() |
| reveal_type(ta.g1) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(ta.g2) # N: Revealed type is "def () -> __main__.A" |
| reveal_type(ta.g3) # N: Revealed type is "def () -> Type[__main__.A]" |
| reveal_type(ta.g4) # N: Revealed type is "def () -> Type[__main__.A]" |
| |
| x: M = ta |
| x.g1 # E: Invalid self argument "M" to attribute function "g1" with type "Callable[[Type[A]], A]" |
| x.g2 # E: Invalid self argument "M" to attribute function "g2" with type "Callable[[Type[TA]], TA]" |
| x.g3 # E: Invalid self argument "M" to attribute function "g3" with type "Callable[[TTA], TTA]" |
| reveal_type(x.g4) # N: Revealed type is "def () -> __main__.M" |
| |
| def r(ta: Type[TA], tta: TTA) -> None: |
| x: M = ta |
| y: M = tta |
| |
| class Class(metaclass=M): |
| @classmethod |
| def f1(cls: Type[Class]) -> None: pass |
| @classmethod |
| def f2(cls: M) -> None: pass |
| cl: Type[Class] = m # E: Incompatible types in assignment (expression has type "M", variable has type "Type[Class]") |
| reveal_type(cl.f1) # N: Revealed type is "def ()" |
| reveal_type(cl.f2) # N: Revealed type is "def ()" |
| x1: M = cl |
| |
| class Static(metaclass=M): |
| @staticmethod |
| def f() -> None: pass |
| s: Type[Static] = m # E: Incompatible types in assignment (expression has type "M", variable has type "Type[Static]") |
| reveal_type(s.f) # N: Revealed type is "def ()" |
| x2: M = s |
| |
| from typing import ClassVar |
| class Cvar(metaclass=M): |
| x = 1 # type: ClassVar[int] |
| cv: Type[Cvar] = m # E: Incompatible types in assignment (expression has type "M", variable has type "Type[Cvar]") |
| cv.x |
| x3: M = cv |
| |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testMetaclassOverloadResolution] |
| from typing import Type, overload |
| class A: pass |
| |
| class EM(type): pass |
| class E(metaclass=EM): pass |
| |
| class EM1(type): pass |
| class E1(metaclass=EM1): pass |
| |
| @overload |
| def f(x: EM) -> int: ... |
| @overload |
| def f(x: EM1) -> A: ... |
| @overload |
| def f(x: str) -> str: ... |
| def f(x: object) -> object: return '' |
| |
| e: EM |
| reveal_type(f(e)) # N: Revealed type is "builtins.int" |
| |
| et: Type[E] |
| reveal_type(f(et)) # N: Revealed type is "builtins.int" |
| |
| e1: EM1 |
| reveal_type(f(e1)) # N: Revealed type is "__main__.A" |
| |
| e1t: Type[E1] |
| reveal_type(f(e1t)) # N: Revealed type is "__main__.A" |
| |
| reveal_type(f('')) # N: Revealed type is "builtins.str" |
| |
| [case testTypeCErasesGenericsFromC] |
| from typing import Generic, Type, TypeVar |
| |
| K = TypeVar('K') |
| V = TypeVar('V') |
| class ExampleDict(Generic[K, V]): ... |
| |
| D = TypeVar('D') |
| def mkdict(dict_type: Type[D]) -> D: ... |
| reveal_type(mkdict(ExampleDict)) # N: Revealed type is "__main__.ExampleDict[Any, Any]" |
| |
| [case testTupleForwardBase] |
| from m import a |
| a[0]() # E: "int" not callable |
| |
| [file m.py] |
| from typing import Tuple |
| a = None # type: A |
| class A(Tuple[int, str]): pass |
| [builtins fixtures/tuple.pyi] |
| |
| -- Synthetic types crashes |
| -- ----------------------- |
| |
| [case testCrashOnSelfRecursiveNamedTupleVar] |
| |
| from typing import NamedTuple |
| |
| N = NamedTuple('N', [('x', N)]) # E: Cannot resolve name "N" (possible cyclic definition) |
| n: N |
| reveal_type(n) # N: Revealed type is "Tuple[Any, fallback=__main__.N]" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testCrashOnSelfRecursiveTypedDictVar] |
| from mypy_extensions import TypedDict |
| |
| A = TypedDict('A', {'a': 'A'}) # type: ignore |
| a: A |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testCrashInJoinOfSelfRecursiveNamedTuples] |
| |
| from typing import NamedTuple |
| |
| class N(NamedTuple): |
| x: N # type: ignore |
| class M(NamedTuple): |
| x: M # type: ignore |
| |
| n: N |
| m: M |
| lst = [n, m] |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testCorrectJoinOfSelfRecursiveTypedDicts] |
| |
| from mypy_extensions import TypedDict |
| |
| class N(TypedDict): |
| x: N # E: Cannot resolve name "N" (possible cyclic definition) |
| class M(TypedDict): |
| x: M # E: Cannot resolve name "M" (possible cyclic definition) |
| |
| n: N |
| m: M |
| lst = [n, m] |
| reveal_type(lst[0]['x']) # N: Revealed type is "Any" |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testCrashInForwardRefToNamedTupleWithIsinstance] |
| from typing import Dict, NamedTuple |
| |
| NameDict = Dict[str, 'NameInfo'] |
| class NameInfo(NamedTuple): |
| ast: bool |
| |
| def parse_ast(name_dict: NameDict) -> None: |
| if isinstance(name_dict[''], int): |
| pass |
| reveal_type(name_dict['test']) # N: Revealed type is "Tuple[builtins.bool, fallback=__main__.NameInfo]" |
| [builtins fixtures/isinstancelist.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testCrashInForwardRefToTypedDictWithIsinstance] |
| from mypy_extensions import TypedDict |
| from typing import Dict |
| |
| NameDict = Dict[str, 'NameInfo'] |
| class NameInfo(TypedDict): |
| ast: bool |
| |
| def parse_ast(name_dict: NameDict) -> None: |
| if isinstance(name_dict[''], int): |
| pass |
| reveal_type(name_dict['']['ast']) # N: Revealed type is "builtins.bool" |
| [builtins fixtures/isinstancelist.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testCorrectIsinstanceInForwardRefToNewType] |
| from typing import Dict, NewType |
| |
| NameDict = Dict[str, 'NameInfo'] |
| class Base: |
| ast: bool |
| NameInfo = NewType('NameInfo', Base) |
| |
| def parse_ast(name_dict: NameDict) -> None: |
| if isinstance(name_dict[''], int): |
| pass |
| x = name_dict[''] |
| reveal_type(x) # N: Revealed type is "__main__.NameInfo" |
| if int(): |
| x = NameInfo(Base()) # OK |
| x = Base() # E: Incompatible types in assignment (expression has type "Base", variable has type "NameInfo") |
| [builtins fixtures/isinstancelist.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testNoCrashForwardRefToBrokenDoubleNewType] |
| from typing import Any, Dict, List, NewType |
| |
| Foo = NewType('NotFoo', int) # E: String argument 1 "NotFoo" to NewType(...) does not match variable name "Foo" |
| Foos = NewType('Foos', List[Foo]) # type: ignore |
| |
| def frob(foos: Dict[Any, Foos]) -> None: |
| foo = foos.get(1) |
| dict(foo) |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testNoCrashForwardRefToBrokenDoubleNewTypeClass] |
| from typing import Any, Dict, List, NewType |
| |
| Foo = NewType('NotFoo', int) # type: ignore |
| Foos = NewType('Foos', List[Foo]) # type: ignore |
| |
| x: C |
| class C: |
| def frob(self, foos: Dict[Any, Foos]) -> None: |
| foo = foos.get(1) |
| dict(foo) |
| |
| reveal_type(x.frob) # N: Revealed type is "def (foos: builtins.dict[Any, __main__.Foos])" |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testNewTypeFromForwardNamedTuple] |
| from typing import NewType, NamedTuple, Tuple |
| |
| NT = NewType('NT', N) |
| class N(NamedTuple): |
| x: int |
| |
| x: NT = N(1) # E: Incompatible types in assignment (expression has type "N", variable has type "NT") |
| x = NT(N(1)) |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testNewTypeFromForwardTypedDict] |
| |
| from typing import NewType, Tuple |
| from mypy_extensions import TypedDict |
| |
| NT = NewType('NT', N) # E: Argument 2 to NewType(...) must be subclassable (got "N") |
| class N(TypedDict): |
| x: int |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCorrectAttributeInForwardRefToNamedTuple] |
| from typing import NamedTuple |
| proc: Process |
| reveal_type(proc.state) # N: Revealed type is "builtins.int" |
| |
| def get_state(proc: 'Process') -> int: |
| return proc.state |
| class Process(NamedTuple): |
| state: int |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCorrectItemTypeInForwardRefToTypedDict] |
| from mypy_extensions import TypedDict |
| proc: Process |
| reveal_type(proc['state']) # N: Revealed type is "builtins.int" |
| |
| def get_state(proc: 'Process') -> int: |
| return proc['state'] |
| class Process(TypedDict): |
| state: int |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testCorrectDoubleForwardNamedTuple] |
| from typing import NamedTuple |
| |
| x: A |
| class A(NamedTuple): |
| one: 'B' |
| other: int |
| class B(NamedTuple): |
| attr: str |
| y: A |
| y = x |
| reveal_type(x.one.attr) # N: Revealed type is "builtins.str" |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCrashOnDoubleForwardTypedDict] |
| from mypy_extensions import TypedDict |
| |
| x: A |
| class A(TypedDict): |
| one: 'B' |
| other: int |
| class B(TypedDict): |
| attr: str |
| |
| reveal_type(x['one']['attr']) # N: Revealed type is "builtins.str" |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testCrashOnForwardUnionOfNamedTuples] |
| from typing import Union, NamedTuple |
| |
| Node = Union['Foo', 'Bar'] |
| class Foo(NamedTuple): |
| x: int |
| class Bar(NamedTuple): |
| x: int |
| |
| def foo(node: Node) -> int: |
| x = node |
| reveal_type(node) # N: Revealed type is "Union[Tuple[builtins.int, fallback=__main__.Foo], Tuple[builtins.int, fallback=__main__.Bar]]" |
| return x.x |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCrashOnForwardUnionOfTypedDicts] |
| from mypy_extensions import TypedDict |
| from typing import Union |
| |
| NodeType = Union['Foo', 'Bar'] |
| class Foo(TypedDict): |
| x: int |
| class Bar(TypedDict): |
| x: int |
| |
| def foo(node: NodeType) -> int: |
| x = node |
| return x['x'] |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testSupportForwardUnionOfNewTypes] |
| from typing import Union, NewType |
| x: Node |
| reveal_type(x.x) # N: Revealed type is "builtins.int" |
| |
| class A: |
| x: int |
| class B: |
| x: int |
| |
| Node = Union['Foo', 'Bar'] |
| Foo = NewType('Foo', A) |
| Bar = NewType('Bar', B) |
| |
| def foo(node: Node) -> Node: |
| x = node |
| return Foo(A()) |
| [out] |
| |
| [case testForwardReferencesInNewTypeMRORecomputed] |
| from typing import NewType |
| x: Foo |
| Foo = NewType('Foo', B) |
| class A: |
| x: int |
| class B(A): |
| pass |
| |
| reveal_type(x.x) # N: Revealed type is "builtins.int" |
| [out] |
| |
| [case testCrashOnComplexNamedTupleUnionProperty] |
| from typing import NamedTuple, Union |
| |
| x: AOrB |
| AOrB = Union['A', 'B'] |
| class A(NamedTuple): |
| x: int |
| |
| class B(object): |
| def __init__(self, a: AOrB) -> None: |
| self.a = a |
| @property |
| def x(self) -> int: |
| return self.a.x |
| |
| reveal_type(x.x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/property.pyi] |
| [out] |
| |
| [case testCorrectIsinstanceWithForwardUnion] |
| from typing import Union, NamedTuple |
| |
| ForwardUnion = Union['TP', int] |
| class TP(NamedTuple('TP', [('x', int)])): pass |
| |
| def f(x: ForwardUnion) -> None: |
| reveal_type(x) # N: Revealed type is "Union[Tuple[builtins.int, fallback=__main__.TP], builtins.int]" |
| if isinstance(x, TP): |
| reveal_type(x) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.TP]" |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testCrashInvalidArgsSyntheticClassSyntax] |
| from typing import List, NamedTuple |
| from mypy_extensions import TypedDict |
| class TD(TypedDict): |
| x: List[int, str] # E: "list" expects 1 type argument, but 2 given |
| class NM(NamedTuple): |
| x: List[int, str] # E: "list" expects 1 type argument, but 2 given |
| |
| # These two should never crash, reveals are in the next test |
| TD({'x': []}) |
| NM(x=[]) |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCrashInvalidArgsSyntheticClassSyntaxReveals] |
| from typing import List, NamedTuple |
| from mypy_extensions import TypedDict |
| class TD(TypedDict): |
| x: List[int, str] # E: "list" expects 1 type argument, but 2 given |
| class NM(NamedTuple): |
| x: List[int, str] # E: "list" expects 1 type argument, but 2 given |
| |
| x: TD |
| x1 = TD({'x': []}) |
| y: NM |
| y1 = NM(x=[]) |
| reveal_type(x) # N: Revealed type is "TypedDict('__main__.TD', {'x': builtins.list[Any]})" |
| reveal_type(x1) # N: Revealed type is "TypedDict('__main__.TD', {'x': builtins.list[Any]})" |
| reveal_type(y) # N: Revealed type is "Tuple[builtins.list[Any], fallback=__main__.NM]" |
| reveal_type(y1) # N: Revealed type is "Tuple[builtins.list[Any], fallback=__main__.NM]" |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCrashInvalidArgsSyntheticFunctionSyntax] |
| from typing import List, NewType, NamedTuple |
| from mypy_extensions import TypedDict |
| TD = TypedDict('TD', {'x': List[int, str]}) # E: "list" expects 1 type argument, but 2 given |
| NM = NamedTuple('NM', [('x', List[int, str])]) # E: "list" expects 1 type argument, but 2 given |
| NT = NewType('NT', List[int, str]) # E: "list" expects 1 type argument, but 2 given |
| |
| # These three should not crash |
| TD({'x': []}) |
| NM(x=[]) |
| NT([]) |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCrashForwardSyntheticClassSyntax] |
| from typing import NamedTuple |
| from mypy_extensions import TypedDict |
| class A1(NamedTuple): |
| b: 'B' |
| x: int |
| class A2(TypedDict): |
| b: 'B' |
| x: int |
| class B: |
| pass |
| x: A1 |
| y: A2 |
| reveal_type(x.b) # N: Revealed type is "__main__.B" |
| reveal_type(y['b']) # N: Revealed type is "__main__.B" |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCrashForwardSyntheticFunctionSyntax] |
| from typing import NamedTuple |
| from mypy_extensions import TypedDict |
| A1 = NamedTuple('A1', [('b', 'B'), ('x', int)]) |
| A2 = TypedDict('A2', {'b': 'B', 'x': int}) |
| class B: |
| pass |
| x: A1 |
| y: A2 |
| reveal_type(x.b) # N: Revealed type is "__main__.B" |
| reveal_type(y['b']) # N: Revealed type is "__main__.B" |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| -- Special support for six |
| -- ----------------------- |
| |
| [case testSixMetaclass] |
| import six |
| class M(type): |
| x = 5 |
| class A(six.with_metaclass(M)): pass |
| @six.add_metaclass(M) |
| class B: pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(B).x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFromSixMetaclass] |
| from six import with_metaclass, add_metaclass |
| class M(type): |
| x = 5 |
| class A(with_metaclass(M)): pass |
| @add_metaclass(M) |
| class B: pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(B).x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSixMetaclassImportFrom] |
| import six |
| from metadefs import M |
| class A(six.with_metaclass(M)): pass |
| @six.add_metaclass(M) |
| class B: pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(B).x) # N: Revealed type is "builtins.int" |
| [file metadefs.py] |
| class M(type): |
| x = 5 |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSixMetaclassImport] |
| import six |
| import metadefs |
| class A(six.with_metaclass(metadefs.M)): pass |
| @six.add_metaclass(metadefs.M) |
| class B: pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(B).x) # N: Revealed type is "builtins.int" |
| [file metadefs.py] |
| class M(type): |
| x = 5 |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSixMetaclassAndBase] |
| from typing import Iterable, Iterator |
| import six |
| class M(type, Iterable[int]): |
| x = 5 |
| def __iter__(self) -> Iterator[int]: ... |
| class A: |
| def foo(self): pass |
| class B: |
| def bar(self): pass |
| class C1(six.with_metaclass(M, A)): pass |
| @six.add_metaclass(M) |
| class D1(A): pass |
| class C2(six.with_metaclass(M, A, B)): pass |
| @six.add_metaclass(M) |
| class D2(A, B): pass |
| reveal_type(type(C1).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(D1).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(C2).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(D2).x) # N: Revealed type is "builtins.int" |
| C1().foo() |
| D1().foo() |
| C1().bar() # E: "C1" has no attribute "bar" |
| D1().bar() # E: "D1" has no attribute "bar" |
| for x in C1: reveal_type(x) # N: Revealed type is "builtins.int" |
| for x in C2: reveal_type(x) # N: Revealed type is "builtins.int" |
| C2().foo() |
| D2().foo() |
| C2().bar() |
| D2().bar() |
| C2().baz() # E: "C2" has no attribute "baz" |
| D2().baz() # E: "D2" has no attribute "baz" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSixMetaclassGenerics] |
| from typing import Generic, GenericMeta, TypeVar |
| import six |
| class DestroyableMeta(type): |
| pass |
| class Destroyable(six.with_metaclass(DestroyableMeta)): |
| pass |
| T_co = TypeVar('T_co', bound='Destroyable', covariant=True) |
| class ArcMeta(GenericMeta, DestroyableMeta): |
| pass |
| class Arc(six.with_metaclass(ArcMeta, Generic[T_co], Destroyable)): |
| pass |
| @six.add_metaclass(ArcMeta) |
| class Arc1(Generic[T_co], Destroyable): |
| pass |
| class MyDestr(Destroyable): |
| pass |
| reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr]" |
| reveal_type(Arc1[MyDestr]()) # N: Revealed type is "__main__.Arc1[__main__.MyDestr]" |
| [builtins fixtures/bool.pyi] |
| [typing fixtures/typing-full.pyi] |
| |
| [case testSixMetaclassErrors] |
| |
| import six |
| class M(type): pass |
| class A(object): pass |
| def f() -> type: return M |
| class C1(six.with_metaclass(M), object): pass # E: Unsupported dynamic base class "six.with_metaclass" |
| class C2(C1, six.with_metaclass(M)): pass # E: Unsupported dynamic base class "six.with_metaclass" |
| class C3(six.with_metaclass(A)): pass # E: Metaclasses not inheriting from "type" are not supported |
| @six.add_metaclass(A) # E: Metaclasses not inheriting from "type" are not supported \ |
| # E: Argument 1 to "add_metaclass" has incompatible type "Type[A]"; expected "Type[type]" |
| |
| class D3(A): pass |
| class C4(six.with_metaclass(M), metaclass=M): pass # E: Multiple metaclass definitions |
| @six.add_metaclass(M) |
| class D4(metaclass=M): pass # E: Multiple metaclass definitions |
| class C5(six.with_metaclass(f())): pass # E: Dynamic metaclass not supported for "C5" |
| @six.add_metaclass(f()) # E: Dynamic metaclass not supported for "D5" |
| class D5: pass |
| |
| @six.add_metaclass(M) |
| class CD(six.with_metaclass(M)): pass # E: Multiple metaclass definitions |
| |
| class M1(type): pass |
| class Q1(metaclass=M1): pass |
| @six.add_metaclass(M) |
| class CQA(Q1): pass # E: Inconsistent metaclass structure for "CQA" |
| class CQW(six.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSixMetaclassAny] |
| import t # type: ignore |
| import six |
| class E(metaclass=t.M): pass |
| class F(six.with_metaclass(t.M)): pass |
| @six.add_metaclass(t.M) |
| class G: pass |
| [builtins fixtures/tuple.pyi] |
| |
| -- Special support for future.utils |
| -- -------------------------------- |
| |
| [case testFutureMetaclass] |
| import future.utils |
| class M(type): |
| x = 5 |
| class A(future.utils.with_metaclass(M)): pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFromFutureMetaclass] |
| from future.utils import with_metaclass |
| class M(type): |
| x = 5 |
| class A(with_metaclass(M)): pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFutureMetaclassImportFrom] |
| import future.utils |
| from metadefs import M |
| class A(future.utils.with_metaclass(M)): pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| [file metadefs.py] |
| class M(type): |
| x = 5 |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFutureMetaclassImport] |
| import future.utils |
| import metadefs |
| class A(future.utils.with_metaclass(metadefs.M)): pass |
| reveal_type(type(A).x) # N: Revealed type is "builtins.int" |
| [file metadefs.py] |
| class M(type): |
| x = 5 |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFutureMetaclassAndBase] |
| from typing import Iterable, Iterator |
| import future.utils |
| class M(type, Iterable[int]): |
| x = 5 |
| def __iter__(self) -> Iterator[int]: ... |
| class A: |
| def foo(self): pass |
| class B: |
| def bar(self): pass |
| class C1(future.utils.with_metaclass(M, A)): pass |
| class C2(future.utils.with_metaclass(M, A, B)): pass |
| reveal_type(type(C1).x) # N: Revealed type is "builtins.int" |
| reveal_type(type(C2).x) # N: Revealed type is "builtins.int" |
| C1().foo() |
| C1().bar() # E: "C1" has no attribute "bar" |
| for x in C1: reveal_type(x) # N: Revealed type is "builtins.int" |
| for x in C2: reveal_type(x) # N: Revealed type is "builtins.int" |
| C2().foo() |
| C2().bar() |
| C2().baz() # E: "C2" has no attribute "baz" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFutureMetaclassGenerics] |
| from typing import Generic, GenericMeta, TypeVar |
| import future.utils |
| class DestroyableMeta(type): |
| pass |
| class Destroyable(future.utils.with_metaclass(DestroyableMeta)): |
| pass |
| T_co = TypeVar('T_co', bound='Destroyable', covariant=True) |
| class ArcMeta(GenericMeta, DestroyableMeta): |
| pass |
| class Arc(future.utils.with_metaclass(ArcMeta, Generic[T_co], Destroyable)): |
| pass |
| class MyDestr(Destroyable): |
| pass |
| reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr]" |
| [builtins fixtures/bool.pyi] |
| [typing fixtures/typing-full.pyi] |
| |
| [case testFutureMetaclassErrors] |
| import future.utils |
| class M(type): pass |
| class A(object): pass |
| def f() -> type: return M |
| class C1(future.utils.with_metaclass(M), object): pass # E: Unsupported dynamic base class "future.utils.with_metaclass" |
| class C2(C1, future.utils.with_metaclass(M)): pass # E: Unsupported dynamic base class "future.utils.with_metaclass" |
| class C3(future.utils.with_metaclass(A)): pass # E: Metaclasses not inheriting from "type" are not supported |
| class C4(future.utils.with_metaclass(M), metaclass=M): pass # E: Multiple metaclass definitions |
| class C5(future.utils.with_metaclass(f())): pass # E: Dynamic metaclass not supported for "C5" |
| |
| class M1(type): pass |
| class Q1(metaclass=M1): pass |
| class CQW(future.utils.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testFutureMetaclassAny] |
| import t # type: ignore |
| import future.utils |
| class E(metaclass=t.M): pass |
| class F(future.utils.with_metaclass(t.M)): pass |
| |
| -- Misc |
| -- ---- |
| [builtins fixtures/tuple.pyi] |
| |
| [case testCorrectEnclosingClassPushedInDeferred] |
| class C: |
| def __getattr__(self, attr: str) -> int: |
| x: F |
| return x.f |
| |
| class F: |
| def __init__(self, f: int) -> None: |
| self.f = f |
| [out] |
| |
| [case testCorrectEnclosingClassPushedInDeferred2] |
| from typing import TypeVar |
| T = TypeVar('T', bound=C) |
| class C: |
| def m(self: T) -> T: |
| class Inner: |
| x: F |
| f = x.f |
| return self |
| |
| class F: |
| def __init__(self, f: int) -> None: |
| self.f = f |
| [out] |
| |
| [case testCorrectEnclosingClassPushedInDeferred3] |
| class A: |
| def f(self) -> None: |
| def g(x: int) -> int: |
| return y |
| |
| y = int() |
| [out] |
| |
| [case testMetaclassMemberAccessViaType] |
| from typing import Type |
| class M(type): |
| def m(cls, x: int) -> int: |
| pass |
| |
| class C(metaclass=M): |
| pass |
| x = C |
| y: Type[C] = C |
| |
| reveal_type(type(C).m) # N: Revealed type is "def (cls: __main__.M, x: builtins.int) -> builtins.int" |
| reveal_type(type(x).m) # N: Revealed type is "def (cls: __main__.M, x: builtins.int) -> builtins.int" |
| reveal_type(type(y).m) # N: Revealed type is "def (cls: __main__.M, x: builtins.int) -> builtins.int" |
| [out] |
| |
| [case testMetaclassMemberAccessViaType2] |
| from typing import Any, Type |
| class M(type): |
| def m(cls, x: int) -> int: |
| pass |
| B: Any |
| class C(B, metaclass=M): |
| pass |
| |
| x: Type[C] |
| reveal_type(x.m) # N: Revealed type is "def (x: builtins.int) -> builtins.int" |
| reveal_type(x.whatever) # N: Revealed type is "Any" |
| [out] |
| |
| [case testMetaclassMemberAccessViaType3] |
| from typing import Any, Type, TypeVar |
| T = TypeVar('T') |
| class C(Any): |
| def bar(self: T) -> Type[T]: pass |
| def foo(self) -> None: |
| reveal_type(self.bar()) # N: Revealed type is "Type[__main__.C]" |
| reveal_type(self.bar().__name__) # N: Revealed type is "builtins.str" |
| [builtins fixtures/type.pyi] |
| [out] |
| |
| [case testClassDecoratorIsTypeChecked] |
| from typing import Callable, Type |
| def decorate(x: int) -> Callable[[type], type]: # N: "decorate" defined here |
| ... |
| def decorate_forward_ref() -> Callable[[Type[A]], Type[A]]: |
| ... |
| @decorate(y=17) # E: Unexpected keyword argument "y" for "decorate" |
| @decorate() # E: Missing positional argument "x" in call to "decorate" |
| @decorate(22, 25) # E: Too many arguments for "decorate" |
| @decorate_forward_ref() |
| @decorate(11) |
| class A: pass |
| |
| @decorate # E: Argument 1 to "decorate" has incompatible type "Type[A2]"; expected "int" |
| class A2: pass |
| |
| [case testClassDecoratorIncorrect] |
| def not_a_class_decorator(x: int) -> int: ... |
| @not_a_class_decorator(7) |
| class A3: pass # E: "int" not callable |
| |
| not_a_function = 17 |
| @not_a_function() # E: "int" not callable |
| class B: pass |
| |
| @not_a_function |
| class B2: pass # E: "int" not callable |
| |
| b = object() |
| @b.nothing # E: "object" has no attribute "nothing" |
| class C: pass |
| |
| @undefined # E: Name "undefined" is not defined |
| class D: pass |
| |
| [case testSlotsCompatibility] |
| class A: |
| __slots__ = () |
| class B(A): |
| __slots__ = ('a', 'b') |
| class C: |
| __slots__ = ('x',) |
| class D(B, C): |
| __slots__ = ('aa', 'bb', 'cc') |
| [builtins fixtures/tuple.pyi] |
| |
| [case testRevealLocalsOnClassVars] |
| class C1(object): |
| t = 'a' |
| y = 3.0 |
| class Inner(object): pass |
| reveal_locals() |
| |
| [out] |
| main:5: note: Revealed local types are: |
| main:5: note: t: builtins.str |
| main:5: note: y: builtins.float |
| |
| [case testAbstractClasses] |
| import a |
| import b |
| |
| [file a.pyi] |
| from abc import ABCMeta, abstractmethod |
| from typing import Protocol |
| |
| class A: # OK, has @abstractmethod |
| @abstractmethod |
| def f(self) -> None: |
| pass |
| |
| class B(A): # E: Class a.B has abstract attributes "f" # N: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass |
| pass |
| |
| class C(A, metaclass=ABCMeta): # OK, has ABCMeta as a metaclass |
| pass |
| |
| class D(A): # OK, implements the abstract method |
| def f(self) -> None: |
| pass |
| |
| class E(Protocol): # OK, is a protocol |
| @abstractmethod |
| def f(self) -> None: |
| pass |
| |
| class F(E, Protocol): # OK, is a protocol |
| pass |
| |
| [file b.py] |
| # All of these are OK because this is not a stub file. |
| from abc import ABCMeta, abstractmethod |
| from typing import Protocol |
| |
| class A: |
| @abstractmethod |
| def f(self) -> None: |
| pass |
| |
| class B(A): |
| pass |
| |
| class C(A, metaclass=ABCMeta): |
| pass |
| |
| class D(A): |
| def f(self) -> None: |
| pass |
| |
| class E(Protocol): |
| @abstractmethod |
| def f(self) -> None: |
| pass |
| |
| class F(E, Protocol): |
| pass |
| |
| [case testClassMethodOverride] |
| from typing import Callable, Any |
| |
| def deco(f: Callable[..., Any]) -> Callable[..., Any]: ... |
| |
| class B: |
| @classmethod |
| def meth(cls, x: int) -> int: ... |
| |
| class C(B): |
| @classmethod |
| @deco |
| def meth(cls, x: int) -> int: ... |
| [builtins fixtures/classmethod.pyi] |
| [out] |
| |
| [case testGetAttrImportAnnotation] |
| import a |
| x: a.A |
| y: a.A.B.C |
| reveal_type(x) # N: Revealed type is "Any" |
| reveal_type(y) # N: Revealed type is "Any" |
| [file a.pyi] |
| from typing import Any |
| def __getattr__(attr: str) -> Any: ... |
| [builtins fixtures/module.pyi] |
| [out] |
| |
| [case testGetAttrImportBaseClass] |
| import a |
| class B(a.A): ... |
| [file a.pyi] |
| from typing import Any |
| def __getattr__(attr: str) -> Any: ... |
| [builtins fixtures/module.pyi] |
| [out] |
| |
| [case testGetAttrDescriptor] |
| from typing import TypeVar, Generic, Any |
| |
| T = TypeVar('T') |
| class C(Generic[T]): |
| normal: T |
| def __getattr__(self, attr: str) -> T: ... |
| |
| class Descr: |
| def __get__(self, inst: Any, owner: Any) -> int: ... |
| |
| class D(C[Descr]): |
| other: Descr |
| |
| d: D |
| reveal_type(d.normal) # N: Revealed type is "builtins.int" |
| reveal_type(d.dynamic) # N: Revealed type is "__main__.Descr" |
| reveal_type(D.other) # N: Revealed type is "builtins.int" |
| D.dynamic # E: "Type[D]" has no attribute "dynamic" |
| [out] |
| |
| [case testSelfDescriptorAssign] |
| from typing import Any |
| |
| class Descr: |
| def __get__(self, inst: Any, owner: Any) -> int: ... |
| |
| class C: |
| def __init__(self, x: Descr) -> None: |
| self.x = x |
| |
| c = C(Descr()) |
| reveal_type(c.x) # N: Revealed type is "__main__.Descr" |
| [out] |
| |
| [case testForwardInstanceWithWrongArgCount] |
| from typing import TypeVar, Generic |
| |
| T = TypeVar('T') |
| class G(Generic[T]): ... |
| |
| A = G |
| x: A[B[int, int]] # E: "G" expects 1 type argument, but 2 given |
| B = G |
| [out] |
| |
| [case testForwardInstanceWithNoArgs] |
| from typing import TypeVar, Generic |
| |
| T = TypeVar('T') |
| class G(Generic[T]): ... |
| |
| A = G |
| x: A[B] |
| reveal_type(x) # N: Revealed type is "__main__.G[__main__.G[Any]]" |
| B = G |
| [out] |
| |
| [case testForwardInstanceWithBound] |
| # flags: --show-column-numbers |
| from typing import TypeVar, Generic |
| |
| T = TypeVar('T', bound=str) |
| class G(Generic[T]): ... |
| |
| A = G |
| x: A[B[int]] # E |
| B = G |
| [out] |
| main:8:4: error: Type argument "G[int]" of "G" must be a subtype of "str" |
| main:8:6: error: Type argument "int" of "G" must be a subtype of "str" |
| |
| [case testExtremeForwardReferencing] |
| from typing import TypeVar, Generic |
| |
| T = TypeVar('T', covariant=True) |
| class B(Generic[T]): ... |
| |
| y: A |
| z: A[int] |
| x = [y, z] |
| reveal_type(x) # N: Revealed type is "builtins.list[__main__.B[Any]]" |
| |
| A = B |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testNoneAnyFallback] |
| from typing import Any |
| dynamic: Any |
| class C(dynamic): pass |
| x: None = C() # E: Incompatible types in assignment (expression has type "C", variable has type "None") |
| [out] |
| |
| [case testNoneAnyFallbackDescriptor] |
| from typing import Any |
| from d import Descr |
| |
| dynamic: Any |
| class C(dynamic): |
| id = Descr(int) |
| name = Descr(str) |
| |
| c: C |
| reveal_type(c.id) # N: Revealed type is "builtins.int" |
| reveal_type(C.name) # N: Revealed type is "d.Descr[builtins.str]" |
| |
| [file d.pyi] |
| from typing import Any, overload, Generic, TypeVar, Type |
| |
| T = TypeVar('T') |
| class Descr(Generic[T]): |
| def __init__(self, tp: Type[T]) -> None: ... |
| @overload |
| def __get__(self, inst: None, owner: Any) -> Descr[T]: ... |
| @overload |
| def __get__(self, inst: object, owner: Any) -> T: ... |
| [out] |
| |
| [case testClassCustomPropertyWorks] |
| from typing import TypeVar, Generic, Callable, Any |
| |
| V = TypeVar('V') |
| |
| class classproperty(Generic[V]): |
| def __init__(self, getter: Callable[[Any], V]) -> None: |
| self.getter = getter |
| def __get__(self, instance: Any, owner: Any) -> V: |
| return self.getter(owner) |
| |
| class C: |
| @classproperty |
| def foo(cls) -> int: |
| return 42 |
| |
| reveal_type(C.foo) # N: Revealed type is "builtins.int" |
| reveal_type(C().foo) # N: Revealed type is "builtins.int" |
| [out] |
| |
| [case testMultipleInheritanceCycle] |
| import b |
| [file a.py] |
| from b import B |
| class A: ... |
| class C(A, B): ... |
| class D(C): ... |
| class Other: ... |
| [file b.py] |
| from a import Other |
| class B: ... |
| [out] |
| |
| [case testMultipleInheritanceCycle2] |
| import b |
| [file a.py] |
| from b import B |
| class A: ... |
| class C(A, B): ... |
| class D(C): ... |
| class Other: ... |
| a: A |
| b: B |
| c: C |
| d: D |
| d = A() # E: Incompatible types in assignment (expression has type "A", variable has type "D") |
| if int(): |
| d = B() # E: Incompatible types in assignment (expression has type "B", variable has type "D") |
| if int(): |
| d = C() # E: Incompatible types in assignment (expression has type "C", variable has type "D") |
| a = D() |
| b = D() |
| c = D() |
| [file b.py] |
| from a import Other |
| class B: ... |
| [out] |
| |
| [case testAllowPropertyAndInit1] |
| class C: |
| def __init__(self, x: int) -> None: |
| self.x = x |
| @property |
| def x(self) -> int: pass |
| @x.setter |
| def x(self, x: int) -> None: pass |
| [builtins fixtures/property.pyi] |
| [out] |
| |
| [case testAllowPropertyAndInit2] |
| class C: |
| @property |
| def x(self) -> int: pass |
| @x.setter |
| def x(self, x: int) -> None: pass |
| def __init__(self, x: int) -> None: |
| self.x = x |
| [builtins fixtures/property.pyi] |
| |
| [case testAllowPropertyAndInit3] |
| class C: |
| def __init__(self, x: int) -> None: |
| self.x = x # type: ignore |
| @property # Should be no error here |
| def x(self) -> int: pass |
| [builtins fixtures/property.pyi] |
| [out] |
| |
| [case testClassMethodBeforeInit1] |
| class Foo: |
| @classmethod |
| def bar(cls) -> Foo: |
| return cls("bar") |
| |
| def __init__(self, baz: str) -> None: |
| self.baz = baz |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodBeforeInit2] |
| class Foo: |
| @classmethod |
| def bar(cls) -> Foo: |
| return cls(Bar()) |
| |
| def __init__(self, baz: 'Bar') -> None: |
| self.baz = baz |
| |
| class Bar: pass |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testClassMethodBeforeInit3] |
| from typing import overload |
| class Foo: |
| @classmethod |
| @overload |
| def bar(cls, x: int) -> Foo: ... |
| @classmethod |
| @overload |
| def bar(cls, x: str) -> Foo: ... |
| @classmethod |
| def bar(cls, x: object) -> Foo: |
| return cls(x) |
| |
| def __init__(self, baz: object) -> None: |
| self.baz = baz |
| |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testNewAndInit1] |
| class A: |
| def __init__(self, x: int) -> None: |
| pass |
| |
| class B(A): |
| def __new__(cls) -> B: |
| pass |
| |
| B() |
| |
| [case testNewAndInit2] |
| from typing import Any |
| |
| class A: |
| def __new__(cls, *args: Any) -> 'A': |
| ... |
| |
| class B(A): |
| def __init__(self, x: int) -> None: |
| pass |
| |
| reveal_type(B) # N: Revealed type is "def (x: builtins.int) -> __main__.B" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testNewAndInit3] |
| from typing import Any |
| |
| class A: |
| def __new__(cls, *args: Any) -> 'A': |
| ... |
| def __init__(self, x: int) -> None: |
| pass |
| |
| reveal_type(A) # N: Revealed type is "def (x: builtins.int) -> __main__.A" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testCyclicDecorator] |
| import b |
| [file a.py] |
| import b |
| import c |
| |
| class A(b.B): |
| @c.deco |
| def meth(self) -> int: ... |
| [file b.py] |
| import a |
| import c |
| |
| class B: |
| @c.deco |
| def meth(self) -> int: ... |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicOverload] |
| import b |
| [file a.pyi] |
| import b |
| from typing import overload |
| |
| class A(b.B): |
| @overload |
| def meth(self, x: int) -> int: ... |
| @overload |
| def meth(self, x: str) -> str: ... |
| [file b.pyi] |
| import a |
| from typing import overload |
| |
| class B: |
| @overload |
| def meth(self, x: int) -> int: ... |
| @overload |
| def meth(self, x: str) -> str: ... |
| [out] |
| |
| [case testCyclicOverloadDeferred] |
| import b |
| [file a.py] |
| import b |
| from typing import overload, Union |
| |
| class A(b.B): |
| @overload |
| def meth(self, x: int) -> int: ... |
| @overload |
| def meth(self, x: str) -> str: ... |
| def meth(self, x) -> Union[int, str]: |
| reveal_type(other.x) # N: Revealed type is "builtins.int" |
| return 0 |
| |
| other: Other |
| class Other: |
| def __init__(self) -> None: |
| self.x = f() |
| def f() -> int: ... |
| [file b.py] |
| import a |
| from typing import overload |
| |
| class B: |
| @overload |
| def meth(self, x: int) -> int: ... |
| @overload |
| def meth(self, x: str) -> str: ... |
| def meth(self, x): |
| pass |
| [out] |
| |
| [case testCyclicOverrideAny] |
| import a |
| [file b.py] |
| import a |
| class Sub(a.Base): |
| def x(self) -> int: pass |
| |
| [file a.py] |
| import b |
| class Base: |
| def __init__(self): |
| self.x = 1 |
| [out] |
| |
| [case testCyclicOverrideChecked] |
| import a |
| [file b.py] |
| import a |
| class Sub(a.Base): |
| def x(self) -> int: pass # E: Signature of "x" incompatible with supertype "Base" |
| |
| [file a.py] |
| import b |
| class Base: |
| def __init__(self) -> None: |
| self.x = 1 |
| [out] |
| |
| [case testCyclicOverrideCheckedDecorator] |
| import a |
| [file b.py] |
| import a |
| import c |
| class Sub(a.Base): |
| @c.deco |
| def x(self) -> int: pass # E: Signature of "x" incompatible with supertype "Base" |
| |
| [file a.py] |
| import b |
| import c |
| class Base: |
| def __init__(self) -> None: |
| self.x = 1 |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicOverrideCheckedDecoratorDeferred] |
| import a |
| [file b.py] |
| import a |
| import c |
| class Sub(a.Base): |
| @c.deco |
| def x(self) -> int: pass # E: Signature of "x" incompatible with supertype "Base" |
| |
| [file a.py] |
| import b |
| import c |
| class Base: |
| def __init__(self) -> None: |
| self.x = f() |
| |
| def f() -> int: ... |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicOverrideAnyDecoratorDeferred] |
| import a |
| [file b.py] |
| import a |
| import c |
| class Sub(a.Base): |
| @c.deco |
| def x(self) -> int: pass |
| |
| [file a.py] |
| from b import Sub |
| import c |
| class Base: |
| def __init__(self) -> None: |
| self.x = f() |
| |
| def f() -> int: ... |
| [file c.py] |
| from typing import Any, Callable |
| def deco(f: Callable[..., Any]) -> Any: ... |
| [out] |
| |
| [case testCyclicDecoratorDoubleDeferred] |
| import b |
| [file a.py] |
| import b |
| import c |
| |
| class A(b.B): |
| @c.deco |
| def meth(self) -> int: |
| reveal_type(other.x) # N: Revealed type is "builtins.int" |
| return 0 |
| |
| other: Other |
| class Other: |
| def __init__(self) -> None: |
| self.x = f() |
| def f() -> int: ... |
| [file b.py] |
| from a import A |
| import c |
| |
| class B: |
| @c.deco |
| def meth(self) -> int: |
| pass |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicDecoratorSuper] |
| import b |
| [file a.py] |
| import b |
| import c |
| |
| class A(b.B): |
| @c.deco |
| def meth(self) -> int: |
| y = super().meth() |
| reveal_type(y) # N: Revealed type is "Tuple[builtins.int, builtins.int]" |
| return 0 |
| [file b.py] |
| from a import A |
| import c |
| |
| class B: |
| @c.deco |
| def meth(self) -> int: |
| pass |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicDecoratorBothDeferred] |
| import b |
| [file a.py] |
| import b |
| import c |
| |
| class A(b.B): |
| @c.deco |
| def meth(self) -> int: |
| pass |
| [file b.py] |
| from a import A |
| import c |
| |
| class B: |
| @c.deco |
| def meth(self) -> int: |
| reveal_type(other.x) # N: Revealed type is "builtins.int" |
| return 0 |
| |
| other: Other |
| class Other: |
| def __init__(self) -> None: |
| self.x = f() |
| def f() -> int: ... |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testCyclicDecoratorSuperDeferred] |
| import b |
| [file a.py] |
| import b |
| import c |
| |
| class A(b.B): |
| @c.deco |
| def meth(self) -> int: |
| y = super().meth() |
| reveal_type(y) # N: Revealed type is "Tuple[builtins.int, builtins.int]" |
| reveal_type(other.x) # N: Revealed type is "builtins.int" |
| return 0 |
| |
| other: Other |
| class Other: |
| def __init__(self) -> None: |
| self.x = f() |
| def f() -> int: ... |
| [file b.py] |
| from a import A |
| import c |
| |
| class B: |
| @c.deco |
| def meth(self) -> int: |
| pass |
| [file c.py] |
| from typing import TypeVar, Tuple, Callable |
| T = TypeVar('T') |
| def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testOptionalDescriptorsBinder] |
| # flags: --strict-optional |
| from typing import Type, TypeVar, Optional |
| T = TypeVar('T') |
| |
| class IntDescr: |
| def __get__(self, obj: T, typ: Type[T]) -> Optional[int]: ... |
| def __set__(self, obj: T, value: Optional[int]) -> None: ... |
| |
| class C: |
| spec = IntDescr() |
| |
| def meth_spec(self) -> None: |
| if self.spec is None: |
| self.spec = 0 |
| reveal_type(self.spec) # N: Revealed type is "builtins.int" |
| [builtins fixtures/bool.pyi] |
| |
| [case testUnionDescriptorsBinder] |
| from typing import Type, TypeVar, Union |
| T = TypeVar('T') |
| |
| class A: ... |
| class B: ... |
| |
| class UnionDescr: |
| def __get__(self, obj: T, typ: Type[T]) -> Union[A, B]: ... |
| def __set__(self, obj: T, value: Union[A, B]) -> None: ... |
| |
| class C: |
| spec = UnionDescr() |
| |
| def meth_spec(self) -> None: |
| self.spec = A() |
| reveal_type(self.spec) # N: Revealed type is "__main__.A" |
| [builtins fixtures/bool.pyi] |
| |
| [case testSubclassDescriptorsBinder] |
| from typing import Type, TypeVar, Optional |
| T = TypeVar('T') |
| |
| class A: ... |
| class B(A): ... |
| |
| class SubDescr: |
| def __get__(self, obj: T, typ: Type[T]) -> A: ... |
| def __set__(self, obj: T, value: A) -> None: ... |
| |
| class C: |
| spec = SubDescr() |
| |
| def meth_spec(self) -> None: |
| self.spec = B() |
| reveal_type(self.spec) # N: Revealed type is "__main__.B" |
| [builtins fixtures/bool.pyi] |
| |
| [case testDecoratedDunderGet] |
| from typing import Any, Callable, TypeVar, Type |
| |
| F = TypeVar('F', bound=Callable) |
| T = TypeVar('T') |
| |
| def decorator(f: F) -> F: |
| return f |
| |
| def change(f: Callable) -> Callable[..., int]: |
| pass |
| |
| def untyped(f): |
| return f |
| |
| class A: ... |
| |
| class Descr1: |
| @decorator |
| def __get__(self, obj: T, typ: Type[T]) -> A: ... |
| class Descr2: |
| @change |
| def __get__(self, obj: T, typ: Type[T]) -> A: ... |
| class Descr3: |
| @untyped |
| def __get__(self, obj: T, typ: Type[T]) -> A: ... |
| |
| class C: |
| spec1 = Descr1() |
| spec2 = Descr2() |
| spec3 = Descr3() |
| |
| c: C |
| reveal_type(c.spec1) # N: Revealed type is "__main__.A" |
| reveal_type(c.spec2) # N: Revealed type is "builtins.int" |
| reveal_type(c.spec3) # N: Revealed type is "Any" |
| [builtins fixtures/bool.pyi] |
| |
| [case testDecoratedDunderSet] |
| from typing import Any, Callable, TypeVar, Type |
| |
| F = TypeVar('F', bound=Callable) |
| T = TypeVar('T') |
| |
| def decorator(f: F) -> F: |
| return f |
| |
| def change(f: Callable) -> Callable[[Any, Any, int], None]: |
| pass |
| |
| def untyped(f): |
| return f |
| |
| class A: ... |
| |
| class Descr1: |
| @decorator |
| def __set__(self, obj: T, value: A) -> None: ... |
| class Descr2: |
| @change |
| def __set__(self, obj: T, value: A) -> None: ... |
| class Descr3: |
| @untyped |
| def __set__(self, obj: T, value: A) -> None: ... |
| |
| class C: |
| spec1 = Descr1() |
| spec2 = Descr2() |
| spec3 = Descr3() |
| |
| c: C |
| c.spec1 = A() |
| c.spec1 = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "A") |
| c.spec2 = A() # E: Incompatible types in assignment (expression has type "A", variable has type "int") |
| c.spec2 = 1 |
| c.spec3 = A() |
| c.spec3 = 1 |
| [builtins fixtures/bool.pyi] |
| |
| [case testClassLevelImport] |
| # flags: --ignore-missing-imports |
| class Test: |
| import a |
| def __init__(self) -> None: |
| some_module = self.a |
| [out] |
| |
| [case testIsInstanceTypeVsMetaclass] |
| from typing import Type |
| class Meta(type): |
| pass |
| class Thing(metaclass=Meta): |
| pass |
| |
| def foo(x: Type[Thing]) -> Type[Thing]: |
| assert isinstance(x, Meta) |
| return x |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceTypeVsUnionOfType] |
| from typing import Type, Union |
| |
| class AA: pass |
| class AB: pass |
| |
| class M: pass |
| |
| class A(M, AA): pass |
| class B(M, AB): pass |
| |
| AOrB = Union[A, B] |
| |
| class T(object): |
| def __init__(self, typ: Type[AOrB] = A) -> None: |
| assert isinstance(typ, type(M)) |
| self.typ: Type[AOrB] = typ |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceTypeIsSubclass] |
| from typing import Union, Type |
| |
| class C: ... |
| |
| x: Union[C, Type[C]] |
| |
| if isinstance(x, type) and issubclass(x, C): |
| reveal_type(x) # N: Revealed type is "Type[__main__.C]" |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceTypeByAssert] |
| class A: |
| x = 42 |
| |
| i: type = A |
| assert issubclass(i, A) |
| reveal_type(i.x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceTypeTypeVar] |
| from typing import Type, TypeVar, Generic |
| |
| class Base: ... |
| class Sub(Base): ... |
| |
| T = TypeVar('T', bound=Base) |
| |
| class C(Generic[T]): |
| def meth(self, cls: Type[T]) -> None: |
| if not issubclass(cls, Sub): |
| return |
| reveal_type(cls) # N: Revealed type is "Type[__main__.Sub]" |
| def other(self, cls: Type[T]) -> None: |
| if not issubclass(cls, Sub): |
| return |
| reveal_type(cls) # N: Revealed type is "Type[__main__.Sub]" |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceTypeSubclass] |
| # flags: --strict-optional |
| from typing import Type, Optional |
| class Base: ... |
| class One(Base): |
| x: int |
| class Other(Base): |
| x: int |
| |
| def test() -> None: |
| x: Optional[Type[Base]] |
| if int(): |
| x = One |
| elif int(): |
| x = Other |
| else: |
| return |
| reveal_type(x) # N: Revealed type is "Union[def () -> __main__.One, def () -> __main__.Other]" |
| reveal_type(x.x) # N: Revealed type is "builtins.int" |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testMemberRedefinition] |
| class C: |
| def __init__(self) -> None: |
| self.foo = 12 |
| self.foo: int = 12 # E: Attribute "foo" already defined on line 3 |
| |
| [case testMemberRedefinitionDefinedInClass] |
| class C: |
| foo = 12 |
| def __init__(self) -> None: |
| self.foo: int = 12 # E: Attribute "foo" already defined on line 2 |
| |
| [case testAbstractInit] |
| from abc import abstractmethod, ABCMeta |
| class A(metaclass=ABCMeta): |
| @abstractmethod |
| def __init__(self, a: int) -> None: |
| pass |
| class B(A): |
| pass |
| class C(B): |
| def __init__(self, a: int) -> None: |
| self.c = a |
| a = A(1) # E: Cannot instantiate abstract class "A" with abstract attribute "__init__" |
| A.c # E: "Type[A]" has no attribute "c" |
| b = B(2) # E: Cannot instantiate abstract class "B" with abstract attribute "__init__" |
| B.c # E: "Type[B]" has no attribute "c" |
| c = C(3) |
| c.c |
| C.c |
| |
| [case testDecoratedConstructors] |
| from typing import TypeVar, Callable, Any |
| |
| F = TypeVar('F', bound=Callable[..., Any]) |
| |
| def dec(f: F) -> F: ... |
| |
| class A: |
| @dec |
| def __init__(self, x: int) -> None: ... |
| |
| class B: |
| @dec |
| def __new__(cls, x: int) -> B: ... |
| |
| reveal_type(A) # N: Revealed type is "def (x: builtins.int) -> __main__.A" |
| reveal_type(B) # N: Revealed type is "def (x: builtins.int) -> __main__.B" |
| |
| [case testDecoratedConstructorsBad] |
| from typing import Callable, Any |
| |
| def dec(f: Callable[[Any, int], Any]) -> int: ... |
| |
| class A: |
| @dec # E: Unsupported decorated constructor type |
| def __init__(self, x: int) -> None: ... |
| |
| class B: |
| @dec # E: Unsupported decorated constructor type |
| def __new__(cls, x: int) -> B: ... |
| |
| [case testIgnorePrivateAttributesTypeCheck] |
| class B: |
| __foo_: int |
| class C(B): |
| __foo_: str |
| [out] |
| |
| [case testIgnorePrivateMethodsTypeCheck] |
| class B: |
| def __foo_(self) -> int: ... |
| class C(B): |
| def __foo_(self) -> str: ... |
| [out] |
| |
| [case testCheckForPrivateMethodsWhenPublicCheck] |
| class B: |
| __foo__: int |
| class C(B): |
| __foo__: str |
| [out] |
| main:4: error: Incompatible types in assignment (expression has type "str", base class "B" defined the type as "int") |
| |
| [case testIgnorePrivateMethodsTypeCheck2] |
| class A: |
| def __foo_(self) -> int: ... |
| class B: |
| def __foo_(self) -> str: ... |
| |
| class C(A, B): pass |
| [out] |
| |
| [case testAttributeDefOrder1] |
| import a |
| |
| [file a.py] |
| from b import C |
| |
| class D(C): |
| def g(self) -> None: |
| self.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| def f(self) -> None: |
| reveal_type(self.x) # N: Revealed type is "builtins.int" |
| |
| |
| [file b.py] |
| import a |
| |
| class C: |
| def __init__(self) -> None: |
| self.x = 0 |
| |
| [targets b, a, b.C.__init__, a.D.g, a.D.f, __main__] |
| |
| [case testAttributeDefOrder2] |
| class D(C): |
| def g(self) -> None: |
| self.x = '' |
| |
| def f(self) -> None: |
| # https://github.com/python/mypy/issues/7162 |
| reveal_type(self.x) # N: Revealed type is "builtins.str" |
| |
| |
| class C: |
| def __init__(self) -> None: |
| self.x = 0 |
| |
| class E(C): |
| def g(self) -> None: |
| self.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| def f(self) -> None: |
| reveal_type(self.x) # N: Revealed type is "builtins.int" |
| |
| [targets __main__, __main__, __main__.D.g, __main__.D.f, __main__.C.__init__, __main__.E.g, __main__.E.f] |
| |
| [case testNewReturnType1] |
| class A: |
| def __new__(cls) -> B: |
| pass |
| |
| class B(A): pass |
| |
| reveal_type(A()) # N: Revealed type is "__main__.B" |
| reveal_type(B()) # N: Revealed type is "__main__.B" |
| |
| [case testNewReturnType2] |
| from typing import Any |
| |
| # make sure that __new__ method that return Any are ignored when |
| # determining the return type |
| class A: |
| def __new__(cls): |
| pass |
| |
| class B: |
| def __new__(cls) -> Any: |
| pass |
| |
| reveal_type(A()) # N: Revealed type is "__main__.A" |
| reveal_type(B()) # N: Revealed type is "__main__.B" |
| |
| [case testNewReturnType3] |
| |
| # Check for invalid __new__ typing |
| |
| class A: |
| def __new__(cls) -> int: # E: Incompatible return type for "__new__" (returns "int", but must return a subtype of "A") |
| pass |
| |
| reveal_type(A()) # N: Revealed type is "__main__.A" |
| |
| [case testNewReturnType4] |
| from typing import TypeVar, Type |
| |
| # Check for __new__ using type vars |
| |
| TX = TypeVar('TX', bound='X') |
| class X: |
| def __new__(lol: Type[TX], x: int) -> TX: |
| pass |
| class Y(X): pass |
| |
| reveal_type(X(20)) # N: Revealed type is "__main__.X" |
| reveal_type(Y(20)) # N: Revealed type is "__main__.Y" |
| |
| [case testNewReturnType5] |
| from typing import Any, TypeVar, Generic, overload |
| |
| T = TypeVar('T') |
| class O(Generic[T]): |
| @overload |
| def __new__(cls) -> O[int]: |
| pass |
| @overload |
| def __new__(cls, x: int) -> O[str]: |
| pass |
| def __new__(cls, x: int = 0) -> O[Any]: |
| pass |
| |
| reveal_type(O()) # N: Revealed type is "__main__.O[builtins.int]" |
| reveal_type(O(10)) # N: Revealed type is "__main__.O[builtins.str]" |
| |
| [case testNewReturnType6] |
| from typing import Tuple, Optional |
| |
| # Check for some cases that aren't allowed |
| |
| class X: |
| def __new__(cls) -> Optional[Y]: # E: "__new__" must return a class instance (got "Optional[Y]") |
| pass |
| class Y: |
| def __new__(cls) -> Optional[int]: # E: "__new__" must return a class instance (got "Optional[int]") |
| pass |
| |
| |
| [case testNewReturnType7] |
| from typing import NamedTuple |
| |
| # ... test __new__ returning tuple type |
| class A: |
| def __new__(cls) -> 'B': |
| pass |
| |
| N = NamedTuple('N', [('x', int)]) |
| class B(A, N): pass |
| |
| reveal_type(A()) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.B]" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testNewReturnType8] |
| from typing import TypeVar, Any |
| |
| # test type var from a different argument |
| TX = TypeVar('TX', bound='X') |
| class X: |
| def __new__(cls, x: TX) -> TX: # E: "__new__" must return a class instance (got "TX") |
| pass |
| |
| [case testNewReturnType9] |
| class A: |
| def __new__(cls) -> A: |
| pass |
| |
| class B(A): |
| pass |
| |
| reveal_type(B()) # N: Revealed type is "__main__.B" |
| |
| [case testNewReturnType10] |
| # https://github.com/python/mypy/issues/11398 |
| from typing import Type |
| |
| class MyMetaClass(type): |
| def __new__(cls, name, bases, attrs) -> Type['MyClass']: |
| pass |
| |
| class MyClass(metaclass=MyMetaClass): |
| pass |
| |
| [case testNewReturnType11] |
| # https://github.com/python/mypy/issues/11398 |
| class MyMetaClass(type): |
| def __new__(cls, name, bases, attrs) -> type: |
| pass |
| |
| class MyClass(metaclass=MyMetaClass): |
| pass |
| |
| [case testNewReturnType12] |
| # https://github.com/python/mypy/issues/11398 |
| from typing import Type |
| |
| class MyMetaClass(type): |
| def __new__(cls, name, bases, attrs) -> int: # E: Incompatible return type for "__new__" (returns "int", but must return a subtype of "type") |
| pass |
| |
| class MyClass(metaclass=MyMetaClass): |
| pass |
| |
| [case testGenericOverride] |
| from typing import Generic, TypeVar, Any |
| |
| T = TypeVar('T') |
| |
| class B(Generic[T]): |
| x: T |
| |
| class C(B): |
| def __init__(self) -> None: |
| self.x: Any |
| |
| [case testGenericOverridePreciseInvalid] |
| from typing import Generic, TypeVar, Any |
| |
| T = TypeVar('T') |
| |
| class B(Generic[T]): |
| x: T |
| |
| class C(B[str]): |
| def __init__(self) -> None: |
| self.x: int # E: Incompatible types in assignment (expression has type "int", base class "B" defined the type as "str") |
| |
| [case testGenericOverridePreciseValid] |
| from typing import Generic, TypeVar |
| |
| T = TypeVar('T') |
| |
| class B(Generic[T]): |
| x: T |
| |
| class C(B[float]): |
| def __init__(self) -> None: |
| self.x: int # We currently allow covariant overriding. |
| |
| [case testGenericOverrideGeneric] |
| from typing import Generic, TypeVar, List |
| |
| T = TypeVar('T') |
| |
| class B(Generic[T]): |
| x: T |
| |
| class C(B[T]): |
| def __init__(self) -> None: |
| self.x: List[T] # E: Incompatible types in assignment (expression has type "List[T]", base class "B" defined the type as "T") |
| [builtins fixtures/list.pyi] |
| |
| [case testGenericOverrideGenericChained] |
| from typing import Generic, TypeVar, Tuple |
| |
| T = TypeVar('T') |
| S = TypeVar('S') |
| |
| class A(Generic[T]): |
| x: T |
| |
| class B(A[Tuple[T, S]]): ... |
| |
| class C(B[int, T]): |
| def __init__(self) -> None: |
| # TODO: error message could be better. |
| self.x: Tuple[str, T] # E: Incompatible types in assignment (expression has type "Tuple[str, T]", base class "A" defined the type as "Tuple[int, T]") |
| [builtins fixtures/tuple.pyi] |
| |
| [case testInitSubclassWrongType] |
| class Base: |
| default_name: str |
| |
| def __init_subclass__(cls, default_name: str): |
| super().__init_subclass__() |
| cls.default_name = default_name |
| return |
| |
| class Child(Base, default_name=5): # E: Argument "default_name" to "__init_subclass__" of "Base" has incompatible type "int"; expected "str" |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassTooFewArgs] |
| class Base: |
| default_name: str |
| |
| def __init_subclass__(cls, default_name: str, **kwargs): |
| super().__init_subclass__() |
| cls.default_name = default_name |
| return |
| |
| class Child(Base): # E: Missing positional argument "default_name" in call to "__init_subclass__" of "Base" |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassTooFewArgs2] |
| class Base: |
| default_name: str |
| |
| def __init_subclass__(cls, default_name: str, thing: int): |
| super().__init_subclass__() |
| cls.default_name = default_name |
| return |
| # TODO implement this, so that no error is raised? |
| d = {"default_name": "abc", "thing": 0} |
| class Child(Base, **d): # E: Missing positional arguments "default_name", "thing" in call to "__init_subclass__" of "Base" |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassOK] |
| class Base: |
| default_name: str |
| thing: int |
| |
| def __init_subclass__(cls, default_name: str, thing:int, **kwargs): |
| super().__init_subclass__() |
| cls.default_name = default_name |
| return |
| |
| class Child(Base, thing=5, default_name=""): |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassWithMetaclassOK] |
| class Base: |
| thing: int |
| |
| def __init_subclass__(cls, thing: int): |
| cls.thing = thing |
| |
| class Child(Base, metaclass=type, thing=0): |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassWithCustomMetaclassOK] |
| class M(type): ... |
| class Child(metaclass=M, thing=0): |
| pass |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testTooManyArgsForObject] |
| class A(thing=5): |
| pass |
| [out] |
| main:1: error: Unexpected keyword argument "thing" for "__init_subclass__" of "object" |
| tmp/builtins.pyi:5: note: "__init_subclass__" of "object" defined here |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassWithImports] |
| from init_subclass.a import Base |
| class Child(Base, thing=5): # E: Missing positional argument "default_name" in call to "__init_subclass__" of "Base" |
| pass |
| [file init_subclass/a.py] |
| class Base: |
| default_name: str |
| thing: int |
| |
| def __init_subclass__(cls, default_name: str, thing:int, **kwargs): |
| pass |
| [file init_subclass/__init__.py] |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassWithImportsOK] |
| from init_subclass.a import MidBase |
| class Main(MidBase, test=True): pass |
| [file init_subclass/a.py] |
| class Base: |
| def __init_subclass__(cls, **kwargs) -> None: pass |
| class MidBase(Base): pass |
| [file init_subclass/__init__.py] |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassUnannotated] |
| class A: |
| def __init_subclass__(cls, *args, **kwargs): |
| super().__init_subclass__(*args, **kwargs) |
| |
| class B(A): |
| pass |
| |
| reveal_type(A.__init_subclass__) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> Any" |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testInitSubclassUnannotatedMulti] |
| from typing import ClassVar, List, Type |
| |
| class A: |
| registered_classes: ClassVar[List[Type[A]]] = [] |
| def __init_subclass__(cls, *args, register=True, **kwargs): |
| if register: |
| cls.registered_classes.append(cls) |
| super().__init_subclass__(*args, **kwargs) |
| |
| class B(A): ... |
| class C(A, register=False): ... |
| class D(C): ... |
| [builtins fixtures/object_with_init_subclass.pyi] |
| |
| [case testClassMethodUnannotated] |
| class C: |
| def __new__(cls): ... |
| @classmethod |
| def meth(cls): ... |
| |
| reveal_type(C.meth) # N: Revealed type is "def () -> Any" |
| reveal_type(C.__new__) # N: Revealed type is "def (cls: Type[__main__.C]) -> Any" |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testOverrideGenericSelfClassMethod] |
| from typing import Generic, TypeVar, Type, List |
| |
| T = TypeVar('T', bound=A) |
| |
| class A: |
| @classmethod |
| def meth(cls: Type[T]) -> List[T]: ... |
| |
| class B(A): |
| @classmethod |
| def meth(cls: Type[T]) -> List[T]: ... |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testCheckUntypedDefsSelf1] |
| # flags: --check-untyped-defs |
| |
| from typing import Generic, TypeVar |
| T = TypeVar('T') |
| |
| class Desc: |
| def __get__(self, x, y): |
| # type: (...) -> bool |
| pass |
| |
| class Foo: |
| y = Desc() |
| |
| def __init__(self): |
| self.x = 0 |
| |
| def foo(self): |
| reveal_type(self.x) # N: Revealed type is "builtins.int" |
| reveal_type(self.y) # N: Revealed type is "builtins.bool" |
| self.bar() |
| self.baz() # E: "Foo" has no attribute "baz" |
| |
| @classmethod |
| def bar(cls): |
| cls.baz() # E: "Type[Foo]" has no attribute "baz" |
| |
| class C(Generic[T]): |
| x: T |
| def meth(self): |
| self.x + 1 # E: Unsupported left operand type for + ("T") |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testCheckUntypedDefsSelf2] |
| # flags: --check-untyped-defs |
| |
| class Foo: |
| def __init__(self): |
| self.x = None |
| self.y = [] |
| |
| reveal_type(Foo().x) # N: Revealed type is "Union[Any, None]" |
| reveal_type(Foo().y) # N: Revealed type is "builtins.list[Any]" |
| [builtins fixtures/list.pyi] |
| |
| [case testCheckUntypedDefsSelf3] |
| # flags: --check-untyped-defs |
| |
| class Foo: |
| def bad(): # E: Method must have at least one argument |
| self.x = 0 # E: Name "self" is not defined |
| |
| [case testTypeAfterAttributeAccessWithDisallowAnyExpr] |
| # flags: --disallow-any-expr |
| |
| def access_before_declaration(self) -> None: |
| obj = Foo('bar') |
| obj.value |
| x = 1 |
| |
| reveal_type(x) # N: Revealed type is "builtins.int" |
| x = x + 1 |
| |
| class Foo: |
| def __init__(self, value: str) -> None: |
| self.value = value |
| |
| def access_after_declaration(self) -> None: |
| obj = Foo('bar') |
| obj.value |
| x = 1 |
| |
| reveal_type(x) # N: Revealed type is "builtins.int" |
| x = x + 1 |
| |
| [case testIsSubClassNarrowDownTypesOfTypeVariables] |
| from typing import Type, TypeVar, Generic |
| |
| class Base: |
| field: int = 42 |
| |
| TypeT = TypeVar("TypeT", bound=type) |
| |
| TypeT1 = TypeVar("TypeT1", bound=Type[Base]) |
| |
| class C1: |
| def method(self, other: type) -> int: |
| if issubclass(other, Base): |
| reveal_type(other) # N: Revealed type is "Type[__main__.Base]" |
| return other.field |
| return 0 |
| |
| class C2(Generic[TypeT]): |
| def method(self, other: TypeT) -> int: |
| if issubclass(other, Base): |
| reveal_type(other) # N: Revealed type is "Type[__main__.Base]" |
| return other.field |
| return 0 |
| |
| class C3(Generic[TypeT1]): |
| def method(self, other: TypeT1) -> int: |
| if issubclass(other, Base): |
| reveal_type(other) # N: Revealed type is "TypeT1`1" |
| return other.field |
| return 0 |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testPropertyWithExtraMethod] |
| def dec(f): |
| return f |
| |
| class A: |
| @property |
| def x(self): ... |
| @x.setter |
| def x(self, value) -> None: ... |
| def x(self) -> None: ... # E: Unexpected definition for property "x" |
| |
| @property |
| def y(self) -> int: ... |
| @y.setter |
| def y(self, value: int) -> None: ... |
| @dec # E: Only supported top decorator is @y.setter |
| def y(self) -> None: ... |
| |
| reveal_type(A().y) # N: Revealed type is "builtins.int" |
| [builtins fixtures/property.pyi] |
| |
| [case testEnclosingScopeLambdaNoCrash] |
| class C: |
| x = lambda x: x.y.g() |
| |
| [case testEnclosingScopeLambdaNoCrashExplicit] |
| from typing import Callable |
| class C: |
| x: Callable[[C], int] = lambda x: x.y.g() # E: "C" has no attribute "y" |
| |
| [case testOpWithInheritedFromAny] |
| from typing import Any |
| C: Any |
| class D(C): |
| pass |
| |
| class D1(C): |
| def __add__(self, rhs: float) -> D1: |
| return self |
| |
| reveal_type(0.5 + C) # N: Revealed type is "Any" |
| |
| reveal_type(0.5 + D()) # N: Revealed type is "Any" |
| reveal_type(D() + 0.5) # N: Revealed type is "Any" |
| reveal_type("str" + D()) # N: Revealed type is "builtins.str" |
| reveal_type(D() + "str") # N: Revealed type is "Any" |
| |
| |
| reveal_type(0.5 + D1()) # N: Revealed type is "Any" |
| reveal_type(D1() + 0.5) # N: Revealed type is "__main__.D1" |
| [builtins fixtures/primitives.pyi] |
| |
| [case testRefMethodWithDecorator] |
| from typing import Type, final |
| |
| class A: |
| pass |
| |
| class B: |
| @staticmethod |
| def A() -> Type[A]: ... |
| @staticmethod |
| def B() -> Type[A]: # E: Function "__main__.B.A" is not valid as a type \ |
| # N: Perhaps you need "Callable[...]" or a callback protocol? |
| return A |
| |
| class C: |
| @final |
| @staticmethod |
| def A() -> Type[A]: |
| return A |
| |
| [builtins fixtures/staticmethod.pyi] |
| |
| [case testRefMethodWithOverloadDecorator] |
| from typing import Type, overload |
| |
| class A: |
| pass |
| |
| class B: |
| @classmethod |
| @overload |
| def A(cls, x: int) -> Type[A]: ... |
| @classmethod |
| @overload |
| def A(cls, x: str) -> Type[A]: ... |
| @classmethod |
| def A(cls, x: object) -> Type[A]: ... |
| def B(cls, x: int) -> Type[A]: ... # E: Function "__main__.B.A" is not valid as a type \ |
| # N: Perhaps you need "Callable[...]" or a callback protocol? |
| |
| [builtins fixtures/classmethod.pyi] |
| |
| [case testFinalClassWithAbstractAttributes] |
| from abc import abstractmethod, ABCMeta |
| from typing import final |
| |
| @final |
| class A(metaclass=ABCMeta): # E: Final class __main__.A has abstract attributes "bar", "foo" |
| @abstractmethod |
| def foo(self): |
| pass |
| |
| @property |
| @abstractmethod |
| def bar(self): |
| pass |
| |
| [builtins fixtures/property.pyi] |
| |
| [case testFinalClassWithoutABCMeta] |
| from abc import abstractmethod |
| from typing import final |
| |
| @final |
| class A(): # E: Final class __main__.A has abstract attributes "bar", "foo" |
| @abstractmethod |
| def foo(self): |
| pass |
| |
| @property |
| @abstractmethod |
| def bar(self): |
| pass |
| |
| [builtins fixtures/property.pyi] |
| |
| [case testFinalClassInheritedAbstractAttributes] |
| from abc import abstractmethod, ABCMeta |
| from typing import final |
| |
| class A(metaclass=ABCMeta): |
| @abstractmethod |
| def foo(self): |
| pass |
| |
| @final |
| class B(A): # E: Final class __main__.B has abstract attributes "foo" |
| pass |
| |
| [case testUndefinedBaseclassInNestedClass] |
| class C: |
| class C1(XX): pass # E: Name "XX" is not defined |
| |
| [case testArgsKwargsInheritance] |
| from typing import Any |
| |
| class A(object): |
| def f(self, *args: Any, **kwargs: Any) -> int: ... |
| |
| class B(A): |
| def f(self, x: int) -> int: ... |
| [builtins fixtures/dict.pyi] |
| |
| [case testClassScopeImports] |
| class Foo: |
| from mod import plain_function # E: Unsupported class scoped import |
| from mod import plain_var |
| |
| reveal_type(Foo.plain_function) # N: Revealed type is "Any" |
| reveal_type(Foo().plain_function) # N: Revealed type is "Any" |
| |
| reveal_type(Foo.plain_var) # N: Revealed type is "builtins.int" |
| reveal_type(Foo().plain_var) # N: Revealed type is "builtins.int" |
| |
| [file mod.py] |
| def plain_function(x: int, y: int) -> int: ... |
| plain_var: int |
| |
| [case testClassScopeImportModule] |
| class Foo: |
| import mod |
| |
| reveal_type(Foo.mod) # N: Revealed type is "builtins.object" |
| reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" |
| [file mod.py] |
| foo: int |
| |
| [case testClassScopeImportAlias] |
| class Foo: |
| from mod import function # E: Unsupported class scoped import |
| foo = function |
| |
| from mod import var1 |
| bar = var1 |
| |
| from mod import var2 |
| baz = var2 |
| |
| from mod import var3 |
| qux = var3 |
| |
| reveal_type(Foo.foo) # N: Revealed type is "Any" |
| reveal_type(Foo.function) # N: Revealed type is "Any" |
| |
| reveal_type(Foo.bar) # N: Revealed type is "builtins.int" |
| reveal_type(Foo.var1) # N: Revealed type is "builtins.int" |
| |
| reveal_type(Foo.baz) # N: Revealed type is "mod.C" |
| reveal_type(Foo.var2) # N: Revealed type is "mod.C" |
| |
| reveal_type(Foo.qux) # N: Revealed type is "builtins.int" |
| reveal_type(Foo.var3) # N: Revealed type is "builtins.int" |
| |
| [file mod.py] |
| def function(x: int, y: int) -> int: ... |
| var1: int |
| |
| class C: ... |
| var2: C |
| |
| A = int |
| var3: A |
| |
| |
| [case testClassScopeImportModuleStar] |
| class Foo: |
| from mod import * # E: Unsupported class scoped import |
| |
| reveal_type(Foo.foo) # N: Revealed type is "builtins.int" |
| reveal_type(Foo.bar) # N: Revealed type is "Any" |
| reveal_type(Foo.baz) # E: "Type[Foo]" has no attribute "baz" \ |
| # N: Revealed type is "Any" |
| |
| [file mod.py] |
| foo: int |
| def bar(x: int) -> int: ... |
| |
| [case testClassScopeImportFunctionNested] |
| class Foo: |
| class Bar: |
| from mod import baz # E: Unsupported class scoped import |
| |
| reveal_type(Foo.Bar.baz) # N: Revealed type is "Any" |
| reveal_type(Foo.Bar().baz) # N: Revealed type is "Any" |
| |
| [file mod.py] |
| def baz(x: int) -> int: ... |
| |
| [case testClassScopeImportUndefined] |
| class Foo: |
| from unknown import foo # E: Cannot find implementation or library stub for module named "unknown" \ |
| # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports |
| |
| reveal_type(Foo.foo) # N: Revealed type is "Any" |
| reveal_type(Foo().foo) # N: Revealed type is "Any" |
| |
| [case testClassScopeImportWithFollowImports] |
| # flags: --follow-imports=skip |
| class Foo: |
| from mod import foo |
| |
| reveal_type(Foo().foo) # N: Revealed type is "Any" |
| [file mod.py] |
| def foo(x: int, y: int) -> int: ... |
| |
| [case testClassScopeImportVarious] |
| class Foo: |
| from mod1 import foo # E: Unsupported class scoped import |
| from mod2 import foo |
| |
| from mod1 import meth1 # E: Unsupported class scoped import |
| def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined on line 5 |
| |
| def meth2(self, a: str) -> str: ... |
| from mod1 import meth2 # E: Unsupported class scoped import \ |
| # E: Name "meth2" already defined on line 8 |
| |
| class Bar: |
| from mod1 import foo # E: Unsupported class scoped import |
| |
| import mod1 |
| reveal_type(Foo.foo) # N: Revealed type is "Any" |
| reveal_type(Bar.foo) # N: Revealed type is "Any" |
| reveal_type(mod1.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" |
| |
| [file mod1.py] |
| def foo(x: int, y: int) -> int: ... |
| def meth1(x: int) -> int: ... |
| def meth2(x: int) -> int: ... |
| [file mod2.py] |
| def foo(z: str) -> int: ... |
| |
| |
| [case testClassScopeImportWithError] |
| class Foo: |
| from mod import meth1 # E: Unsupported class scoped import |
| from mod import meth2 # E: Unsupported class scoped import |
| from mod import T |
| |
| reveal_type(Foo.T) # E: Type variable "Foo.T" cannot be used as an expression \ |
| # N: Revealed type is "Any" |
| |
| [file mod.pyi] |
| from typing import Any, TypeVar, overload |
| |
| @overload |
| def meth1(self: Any, y: int) -> int: ... |
| @overload |
| def meth1(self: Any, y: str) -> str: ... |
| |
| T = TypeVar("T") |
| def meth2(self: Any, y: T) -> T: ... |
| |
| [case testClassScopeImportWithWrapperAndError] |
| class Foo: |
| from mod import foo # E: Unsupported class scoped import |
| |
| [file mod.py] |
| from typing import Any, Callable, TypeVar |
| |
| FuncT = TypeVar("FuncT", bound=Callable[..., Any]) |
| def identity_wrapper(func: FuncT) -> FuncT: |
| return func |
| |
| @identity_wrapper |
| def foo(self: Any) -> str: |
| return "" |
| |
| [case testParentClassWithTypeAliasAndSubclassWithMethod] |
| from typing import Any, Callable, TypeVar |
| |
| class Parent: |
| foo = Callable[..., int] |
| class bar: |
| pass |
| import typing as baz |
| foobar = TypeVar("foobar") |
| |
| class Child(Parent): |
| def foo(self, val: int) -> int: # E: Signature of "foo" incompatible with supertype "Parent" |
| return val |
| def bar(self, val: str) -> str: # E: Signature of "bar" incompatible with supertype "Parent" |
| return val |
| def baz(self, val: float) -> float: # E: Signature of "baz" incompatible with supertype "Parent" |
| return val |
| def foobar(self) -> bool: # E: Signature of "foobar" incompatible with supertype "Parent" |
| return False |
| |
| x: Parent.foo = lambda: 5 |
| y: Parent.bar = Parent.bar() |
| z: Parent.baz.Any = 1 |
| child = Child() |
| a: int = child.foo(1) |
| b: str = child.bar("abc") |
| c: float = child.baz(3.4) |
| d: bool = child.foobar() |
| |
| [case testGenericTupleTypeCreation] |
| from typing import Generic, Tuple, TypeVar |
| |
| T = TypeVar("T") |
| S = TypeVar("S") |
| class C(Tuple[T, S]): |
| def __init__(self, x: T, y: S) -> None: ... |
| def foo(self, arg: T) -> S: ... |
| |
| cis: C[int, str] |
| reveal_type(cis) # N: Revealed type is "Tuple[builtins.int, builtins.str, fallback=__main__.C[builtins.int, builtins.str]]" |
| cii = C(0, 1) |
| reveal_type(cii) # N: Revealed type is "Tuple[builtins.int, builtins.int, fallback=__main__.C[builtins.int, builtins.int]]" |
| reveal_type(cis.foo) # N: Revealed type is "def (arg: builtins.int) -> builtins.str" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testGenericTupleTypeSubclassing] |
| from typing import Generic, Tuple, TypeVar, List |
| |
| T = TypeVar("T") |
| class C(Tuple[T, T]): ... |
| class D(C[List[T]]): ... |
| |
| di: D[int] |
| reveal_type(di) # N: Revealed type is "Tuple[builtins.list[builtins.int], builtins.list[builtins.int], fallback=__main__.D[builtins.int]]" |
| [builtins fixtures/tuple.pyi] |