| -- Test cases for simple expressions. | |
| -- | |
| -- See also: | |
| -- * check-functions.test contains test cases for calls. | |
| -- * check-varargs.test contains test cases for *args. | |
| -- * check-dynamic.test contains test cases related to 'Any' type. | |
| -- * check-generics.test contains test cases for generic values. | |
| -- None expression | |
| -- --------------- | |
| [case testNoneAsRvalue] | |
| import typing | |
| a: A | |
| class A: pass | |
| [out] | |
| [case testNoneAsArgument] | |
| # flags: --no-strict-optional | |
| import typing | |
| def f(x: 'A', y: 'B') -> None: pass | |
| f(None, None) | |
| class A: pass | |
| class B(A): pass | |
| [out] | |
| -- Simple expressions | |
| -- ------------------ | |
| [case testIntLiteral] | |
| a = 0 | |
| b: A | |
| if int(): | |
| b = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "A") | |
| if int(): | |
| a = 1 | |
| class A: | |
| pass | |
| [case testStrLiteral] | |
| a = '' | |
| b: A | |
| if int(): | |
| b = 'x' # E: Incompatible types in assignment (expression has type "str", variable has type "A") | |
| if int(): | |
| a = 'x' | |
| if int(): | |
| a = r"x" | |
| if int(): | |
| a = """foo""" | |
| class A: | |
| pass | |
| [case testFloatLiteral] | |
| a = 0.0 | |
| b: A | |
| if str(): | |
| b = 1.1 # E: Incompatible types in assignment (expression has type "float", variable has type "A") | |
| if str(): | |
| a = 1.1 | |
| class A: | |
| pass | |
| [builtins fixtures/dict.pyi] | |
| [case testComplexLiteral] | |
| a = 0.0j | |
| b: A | |
| if str(): | |
| b = 1.1j # E: Incompatible types in assignment (expression has type "complex", variable has type "A") | |
| if str(): | |
| a = 1.1j | |
| class A: | |
| pass | |
| [builtins fixtures/dict.pyi] | |
| [case testBytesLiteral] | |
| b: bytes | |
| a: A | |
| if str(): | |
| b = b'foo' | |
| if str(): | |
| b = br"foo" | |
| if str(): | |
| b = b'''foo''' | |
| if str(): | |
| a = b'foo' # E: Incompatible types in assignment (expression has type "bytes", variable has type "A") | |
| class A: pass | |
| [builtins fixtures/dict.pyi] | |
| [case testUnicodeLiteralInPython3] | |
| s: str | |
| if int(): | |
| s = u'foo' | |
| b: bytes | |
| if int(): | |
| b = u'foo' # E: Incompatible types in assignment (expression has type "str", variable has type "bytes") | |
| [builtins fixtures/primitives.pyi] | |
| -- Binary operators | |
| -- ---------------- | |
| [case testAdd] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a + c # E: Unsupported operand types for + ("A" and "C") | |
| if int(): | |
| a = a + b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b + a # E: Unsupported left operand type for + ("B") | |
| if int(): | |
| c = a + b | |
| class A: | |
| def __add__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testSub] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a - c # E: Unsupported operand types for - ("A" and "C") | |
| if int(): | |
| a = a - b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b - a # E: Unsupported left operand type for - ("B") | |
| if int(): | |
| c = a - b | |
| class A: | |
| def __sub__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testMul] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a * c # E: Unsupported operand types for * ("A" and "C") | |
| if int(): | |
| a = a * b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b * a # E: Unsupported left operand type for * ("B") | |
| if int(): | |
| c = a * b | |
| class A: | |
| def __mul__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testMatMul] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a @ c # E: Unsupported operand types for @ ("A" and "C") | |
| if int(): | |
| a = a @ b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b @ a # E: Unsupported left operand type for @ ("B") | |
| if int(): | |
| c = a @ b | |
| class A: | |
| def __matmul__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testDiv] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a / c # E: Unsupported operand types for / ("A" and "C") | |
| a = a / b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b / a # E: Unsupported left operand type for / ("B") | |
| if int(): | |
| c = a / b | |
| class A: | |
| def __truediv__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testIntDiv] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a // c # E: Unsupported operand types for // ("A" and "C") | |
| a = a // b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b // a # E: Unsupported left operand type for // ("B") | |
| if int(): | |
| c = a // b | |
| class A: | |
| def __floordiv__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testMod] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a % c # E: Unsupported operand types for % ("A" and "C") | |
| if int(): | |
| a = a % b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b % a # E: Unsupported left operand type for % ("B") | |
| if int(): | |
| c = a % b | |
| class A: | |
| def __mod__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testPow] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a ** c # E: Unsupported operand types for ** ("A" and "C") | |
| if int(): | |
| a = a ** b # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b ** a # E: Unsupported left operand type for ** ("B") | |
| if int(): | |
| c = a ** b | |
| class A: | |
| def __pow__(self, x: 'B') -> 'C': | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testMiscBinaryOperators] | |
| a: A | |
| b: B | |
| b = a & a # Fail | |
| b = a | b # Fail | |
| b = a ^ a # Fail | |
| b = a << b # Fail | |
| b = a >> a # Fail | |
| b = a & b | |
| b = a | a | |
| b = a ^ b | |
| b = a << a | |
| b = a >> b | |
| class A: | |
| def __and__(self, x: 'B') -> 'B': pass | |
| def __or__(self, x: 'A') -> 'B': pass | |
| def __xor__(self, x: 'B') -> 'B': pass | |
| def __lshift__(self, x: 'A') -> 'B': pass | |
| def __rshift__(self, x: 'B') -> 'B': pass | |
| class B: pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| main:3: error: Unsupported operand types for & ("A" and "A") | |
| main:4: error: Unsupported operand types for | ("A" and "B") | |
| main:5: error: Unsupported operand types for ^ ("A" and "A") | |
| main:6: error: Unsupported operand types for << ("A" and "B") | |
| main:7: error: Unsupported operand types for >> ("A" and "A") | |
| [case testBooleanAndOr] | |
| a: A | |
| b: bool | |
| if int(): | |
| b = b and b | |
| if int(): | |
| b = b or b | |
| if int(): | |
| b = b and a # E: Incompatible types in assignment (expression has type "Literal[False] | A", variable has type "bool") | |
| if int(): | |
| b = a and b # E: Incompatible types in assignment (expression has type "A | bool", variable has type "bool") | |
| if int(): | |
| b = b or a # E: Incompatible types in assignment (expression has type "Literal[True] | A", variable has type "bool") | |
| if int(): | |
| b = a or b # E: Incompatible types in assignment (expression has type "A | bool", variable has type "bool") | |
| class A: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testRestrictedTypeAnd] | |
| b: bool | |
| i: str | |
| j = not b and i | |
| if j: | |
| reveal_type(j) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/bool.pyi] | |
| [case testRestrictedTypeOr] | |
| b: bool | |
| i: str | |
| j = b or i | |
| if not j: | |
| reveal_type(j) # N: Revealed type is "Literal['']" | |
| [builtins fixtures/bool.pyi] | |
| [case testAndOr] | |
| s = "" | |
| b = bool() | |
| reveal_type(s and b or b) # N: Revealed type is "builtins.bool" | |
| [builtins fixtures/bool.pyi] | |
| [case testRestrictedBoolAndOrWithGenerics] | |
| from typing import List | |
| def f(a: List[str], b: bool) -> bool: | |
| x = a and b | |
| y: bool | |
| return reveal_type(x or y) # N: Revealed type is "builtins.bool" | |
| [builtins fixtures/list.pyi] | |
| [case testNonBooleanOr] | |
| c: C | |
| d: D | |
| b: bool | |
| if int(): | |
| c = c or c | |
| if int(): | |
| c = c or d | |
| if int(): | |
| c = d or c | |
| if int(): | |
| b = c or c # E: Incompatible types in assignment (expression has type "C", variable has type "bool") | |
| if int(): | |
| d = c or d # E: Incompatible types in assignment (expression has type "C", variable has type "D") | |
| if int(): | |
| d = d or c # E: Incompatible types in assignment (expression has type "C", variable has type "D") | |
| class C: pass | |
| class D(C): pass | |
| [builtins fixtures/bool.pyi] | |
| [case testInOperator] | |
| from typing import Iterator, Iterable, Any | |
| a: A | |
| b: B | |
| c: bool | |
| d: D | |
| e: Any | |
| if int(): | |
| c = c in a # E: Unsupported operand types for in ("bool" and "A") | |
| if int(): | |
| a = b in a # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| c = a in b # E: Unsupported right operand type for in ("B") | |
| if int(): | |
| c = b in d # E: Unsupported operand types for in ("B" and "D") | |
| if int(): | |
| c = b in a | |
| if int(): | |
| c = a in d | |
| if int(): | |
| c = e in d | |
| if int(): | |
| c = a in e | |
| class A: | |
| def __contains__(self, x: 'B') -> bool: pass | |
| class B: pass | |
| class D(Iterable[A]): | |
| def __iter__(self) -> Iterator[A]: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testNotInOperator] | |
| from typing import Iterator, Iterable, Any | |
| a: A | |
| b: B | |
| c: bool | |
| d: D | |
| e: Any | |
| if int(): | |
| c = c not in a # E: Unsupported operand types for in ("bool" and "A") | |
| if int(): | |
| a = b not in a # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| c = a not in b # E: Unsupported right operand type for in ("B") | |
| if int(): | |
| c = b not in d # E: Unsupported operand types for in ("B" and "D") | |
| if int(): | |
| c = b not in a | |
| if int(): | |
| c = a not in d | |
| if int(): | |
| c = e in d | |
| if int(): | |
| c = a in e | |
| class A: | |
| def __contains__(self, x: 'B') -> bool: pass | |
| class B: pass | |
| class D(Iterable[A]): | |
| def __iter__(self) -> Iterator[A]: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testNonBooleanContainsReturnValue] | |
| a: A | |
| b: bool | |
| c: str | |
| if int(): | |
| b = a not in a | |
| if int(): | |
| b = a in a | |
| if int(): | |
| c = a not in a # E: Incompatible types in assignment (expression has type "bool", variable has type "str") | |
| if int(): | |
| c = a in a # E: Incompatible types in assignment (expression has type "bool", variable has type "str") | |
| class A: | |
| def __contains__(self, x: 'A') -> str: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testInWithInvalidArgs] | |
| a = 1 in ([1] + ['x']) # E: List item 0 has incompatible type "str"; expected "int" | |
| [builtins fixtures/list.pyi] | |
| [case testEq] | |
| a: A | |
| b: bool | |
| if int(): | |
| a = a == b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| a = a != b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| b = a == b | |
| if int(): | |
| b = a != b | |
| class A: | |
| def __eq__(self, o: object) -> bool: pass | |
| def __ne__(self, o: object) -> bool: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testLtAndGt] | |
| a: A | |
| b: B | |
| bo: bool | |
| if int(): | |
| a = a < b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| a = a > b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| bo = a < b | |
| if int(): | |
| bo = a > b | |
| class A: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| class B: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| [builtins fixtures/bool.pyi] | |
| [case cmpIgnoredPy3] | |
| a: A | |
| b: B | |
| bo: bool | |
| bo = a <= b # E: Unsupported left operand type for <= ("A") | |
| class A: | |
| def __cmp__(self, o: 'B') -> bool: pass | |
| class B: | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testLeAndGe] | |
| a: A | |
| b: B | |
| bo: bool | |
| if int(): | |
| a = a <= b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| a = a >= b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| bo = a <= b | |
| if int(): | |
| bo = a >= b | |
| class A: | |
| def __le__(self, o: 'B') -> bool: pass | |
| def __ge__(self, o: 'B') -> bool: pass | |
| class B: | |
| def __le__(self, o: 'B') -> bool: pass | |
| def __ge__(self, o: 'B') -> bool: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testChainedComp] | |
| a: A | |
| b: B | |
| bo: bool | |
| a < a < b < b # Fail | |
| a < b < b < b | |
| a < a > a < b # Fail | |
| class A: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| class B: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| [builtins fixtures/bool.pyi] | |
| [out] | |
| main:4: error: Unsupported operand types for < ("A" and "A") | |
| main:6: error: Unsupported operand types for < ("A" and "A") | |
| main:6: error: Unsupported operand types for > ("A" and "A") | |
| [case testChainedCompBoolRes] | |
| a: A | |
| b: B | |
| bo: bool | |
| if int(): | |
| bo = a < b < b | |
| if int(): | |
| a = a < b < b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| class A: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| class B: | |
| def __lt__(self, o: 'B') -> bool: pass | |
| def __gt__(self, o: 'B') -> bool: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testChainedCompResTyp] | |
| x: X | |
| y: Y | |
| a: A | |
| b: B | |
| p: P | |
| bo: bool | |
| if int(): | |
| b = y == y == y | |
| if int(): | |
| bo = y == y == y # E: Incompatible types in assignment (expression has type "B", variable has type "bool") | |
| if int(): | |
| a = x < y | |
| if int(): | |
| a = x < y == y # E: Incompatible types in assignment (expression has type "P", variable has type "A") | |
| if int(): | |
| p = x < y == y | |
| class P: | |
| pass | |
| class A(P): | |
| pass | |
| class B(P): | |
| pass | |
| class X: | |
| def __lt__(self, o: 'Y') -> A: pass | |
| def __gt__(self, o: 'Y') -> A: pass | |
| class Y: | |
| def __lt__(self, o: 'Y') -> A: pass | |
| def __gt__(self, o: 'Y') -> A: pass | |
| def __eq__(self, o: 'Y') -> B: pass # type: ignore | |
| [builtins fixtures/bool.pyi] | |
| [case testIs] | |
| a: A | |
| b: bool | |
| if int(): | |
| a = a is b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| b = a is b | |
| if int(): | |
| b = b is a | |
| if int(): | |
| b = a is None | |
| class A: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testIsNot] | |
| a: A | |
| b: bool | |
| if int(): | |
| a = a is not b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| b = a is not b | |
| if int(): | |
| b = b is not a | |
| if int(): | |
| b = a is not None | |
| class A: pass | |
| [builtins fixtures/bool.pyi] | |
| [case testIsRightOperand] | |
| 1 is 1() | |
| [builtins fixtures/bool.pyi] | |
| [out] | |
| main:2: error: "int" not callable | |
| [case testReverseBinaryOperator] | |
| class A: | |
| def __add__(self, x: int) -> int: pass | |
| class B: | |
| def __radd__(self, x: A) -> str: pass | |
| s: str | |
| n: int | |
| if int(): | |
| n = A() + 1 | |
| if int(): | |
| s = A() + B() | |
| if int(): | |
| n = A() + B() # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testReverseBinaryOperator2] | |
| class A: | |
| def __add__(self, x: 'A') -> object: pass | |
| class B: | |
| def __radd__(self, x: A) -> str: pass | |
| s: str | |
| n: int | |
| if int(): | |
| s = A() + B() | |
| n = A() + B() # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testReverseBinaryOperator3] | |
| class N: | |
| def __add__(self, x: 'N') -> object: pass | |
| class A: | |
| def __add__(self, x: N) -> int: pass | |
| class B: | |
| def __radd__(self, x: N) -> str: pass | |
| s: str | |
| s = A() + B() # E: Unsupported operand types for + ("A" and "B") | |
| [case testReverseBinaryOperator4] | |
| from typing import assert_type, Never | |
| class Size(tuple[int, ...]): | |
| def __add__(self, other: tuple[int, ...], /) -> "Size": return Size() # type: ignore[override] | |
| def __radd__(self, other: tuple[int, ...], /) -> "Size": return Size() | |
| size: Size = Size([3, 4]) | |
| tup0: tuple[()] = () | |
| tup1: tuple[int] = (1,) | |
| tup2: tuple[int, int] = (1, 2) | |
| tupN: tuple[int, ...] = (1, 2, 3) | |
| tupX: tuple[Never, ...] = () | |
| assert_type(tup0 + size, Size) | |
| assert_type(tup1 + size, Size) | |
| assert_type(tup2 + size, Size) | |
| assert_type(tupN + size, Size) | |
| assert_type(tupX + size, Size) | |
| [builtins fixtures/tuple-typeshed.pyi] | |
| [case testBinaryOperatorWithAnyRightOperand] | |
| from typing import Any, cast | |
| class A: pass | |
| A() + cast(Any, 1) | |
| [case testReverseComparisonOperator] | |
| class C: | |
| def __gt__(self, x: 'A') -> object: pass | |
| class A: | |
| def __lt__(self, x: C) -> int: pass # E: Signatures of "__lt__" of "A" and "__gt__" of "C" are unsafely overlapping | |
| class B: | |
| def __gt__(self, x: A) -> str: pass | |
| s: str | |
| n: int | |
| if int(): | |
| n = A() < C() | |
| s = A() < B() | |
| if int(): | |
| n = A() < B() # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| s = object() < B() # E: Unsupported operand types for > ("B" and "object") | |
| [case testReversibleComparisonWithExtraArgument] | |
| class C: | |
| def __lt__(self, o: object, x: str = "") -> int: ... | |
| [case testErrorContextAndBinaryOperators] | |
| import typing | |
| class A: | |
| def __getitem__(self, i: str) -> int: pass | |
| def f() -> None: | |
| A()[1] # Error | |
| class B: | |
| A()[1] # Error | |
| A()[1] # Error | |
| [out] | |
| main:5: error: Invalid index type "int" for "A"; expected type "str" | |
| main:7: error: Invalid index type "int" for "A"; expected type "str" | |
| main:8: error: Invalid index type "int" for "A"; expected type "str" | |
| [case testErrorContextAndBinaryOperators2] | |
| import m | |
| [file m.py] | |
| import typing | |
| class A: | |
| def __getitem__(self, i: str) -> int: pass | |
| def f() -> None: | |
| A()[1] # Error | |
| class B: | |
| A()[1] # Error | |
| A()[1] # Error | |
| [out] | |
| tmp/m.py:5: error: Invalid index type "int" for "A"; expected type "str" | |
| tmp/m.py:7: error: Invalid index type "int" for "A"; expected type "str" | |
| tmp/m.py:8: error: Invalid index type "int" for "A"; expected type "str" | |
| [case testDivmod] | |
| # flags: --disable-error-code=used-before-def | |
| from typing import Tuple, Union, SupportsInt | |
| _Decimal = Union[Decimal, int] | |
| class Decimal(SupportsInt): | |
| def __init__(self, int) -> None: ... | |
| def __divmod__(self, other: _Decimal) -> Tuple[Decimal, Decimal]: ... | |
| def __rdivmod__(self, other: _Decimal) -> Tuple[Decimal, Decimal]: ... | |
| i = 8 | |
| f = 8.0 | |
| d = Decimal(8) | |
| reveal_type(divmod(i, i)) # N: Revealed type is "tuple[builtins.int, builtins.int]" | |
| reveal_type(divmod(f, i)) # N: Revealed type is "tuple[builtins.float, builtins.float]" | |
| reveal_type(divmod(d, i)) # N: Revealed type is "tuple[__main__.Decimal, __main__.Decimal]" | |
| reveal_type(divmod(i, f)) # N: Revealed type is "tuple[builtins.float, builtins.float]" | |
| reveal_type(divmod(f, f)) # N: Revealed type is "tuple[builtins.float, builtins.float]" | |
| divmod(d, f) # E: Unsupported operand types for divmod ("Decimal" and "float") | |
| reveal_type(divmod(i, d)) # N: Revealed type is "tuple[__main__.Decimal, __main__.Decimal]" | |
| divmod(f, d) # E: Unsupported operand types for divmod ("float" and "Decimal") | |
| reveal_type(divmod(d, d)) # N: Revealed type is "tuple[__main__.Decimal, __main__.Decimal]" | |
| # Now some bad calls | |
| divmod() # E: "divmod" expects 2 arguments \ | |
| # E: Missing positional arguments "_x", "_y" in call to "divmod" | |
| divmod(7) # E: "divmod" expects 2 arguments \ | |
| # E: Missing positional argument "_y" in call to "divmod" | |
| divmod(7, 8, 9) # E: "divmod" expects 2 arguments \ | |
| # E: Too many arguments for "divmod" | |
| divmod(_x=7, _y=9) # E: "divmod" must be called with 2 positional arguments | |
| divmod('foo', 'foo') # E: Unsupported left operand type for divmod ("str") | |
| divmod(i, 'foo') # E: Unsupported operand types for divmod ("int" and "str") | |
| divmod(f, 'foo') # E: Unsupported operand types for divmod ("float" and "str") | |
| divmod(d, 'foo') # E: Unsupported operand types for divmod ("Decimal" and "str") | |
| divmod('foo', i) # E: Unsupported operand types for divmod ("str" and "int") | |
| divmod('foo', f) # E: Unsupported operand types for divmod ("str" and "float") | |
| divmod('foo', d) # E: Unsupported operand types for divmod ("str" and "Decimal") | |
| [builtins fixtures/divmod.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| -- Unary operators | |
| -- --------------- | |
| [case testUnaryMinus] | |
| a: A | |
| b: B | |
| if int(): | |
| a = -a # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| b = -b # E: Unsupported operand type for unary - ("B") | |
| if int(): | |
| b = -a | |
| class A: | |
| def __neg__(self) -> 'B': | |
| pass | |
| class B: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnaryPlus] | |
| a: A | |
| b: B | |
| if int(): | |
| a = +a # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| b = +b # E: Unsupported operand type for unary + ("B") | |
| if int(): | |
| b = +a | |
| class A: | |
| def __pos__(self) -> 'B': | |
| pass | |
| class B: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnaryNot] | |
| a: A | |
| b: bool | |
| if int(): | |
| a = not b # E: Incompatible types in assignment (expression has type "bool", variable has type "A") | |
| if int(): | |
| b = not a | |
| if int(): | |
| b = not b | |
| class A: | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testUnaryBitwiseNeg] | |
| a: A | |
| b: B | |
| if int(): | |
| a = ~a # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| b = ~b # E: Unsupported operand type for ~ ("B") | |
| if int(): | |
| b = ~a | |
| class A: | |
| def __invert__(self) -> 'B': | |
| pass | |
| class B: | |
| pass | |
| -- Indexing | |
| -- -------- | |
| [builtins fixtures/tuple.pyi] | |
| [case testIndexing] | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| c = a[c] # E: Invalid index type "C" for "A"; expected type "B" | |
| if int(): | |
| a = a[b] # E: Incompatible types in assignment (expression has type "C", variable has type "A") | |
| if int(): | |
| c = b[a] # E: Value of type "B" is not indexable | |
| if int(): | |
| c = a[b] | |
| class A: | |
| def __getitem__(self, x: 'B') -> 'C': | |
| pass | |
| class B: pass | |
| class C: pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testIndexingAsLvalue] | |
| a: A | |
| b: B | |
| c: C | |
| a[c] = c # Fail | |
| a[b] = a # Fail | |
| b[a] = c # Fail | |
| a[b] = c | |
| class A: | |
| def __setitem__(self, x: 'B', y: 'C') -> None: | |
| pass | |
| class B: | |
| pass | |
| class C: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| main:4: error: Invalid index type "C" for "A"; expected type "B" | |
| main:5: error: Incompatible types in assignment (expression has type "A", target has type "C") | |
| main:6: error: Unsupported target for indexed assignment ("B") | |
| [case testOverloadedIndexing] | |
| from foo import * | |
| [file foo.pyi] | |
| from typing import overload | |
| a: A | |
| b: B | |
| c: C | |
| a[b] | |
| a[c] | |
| a[1] # E: No overload variant of "__getitem__" of "A" matches argument type "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def __getitem__(self, B, /) -> int \ | |
| # N: def __getitem__(self, C, /) -> str | |
| i: int | |
| s: str | |
| if int(): | |
| i = a[b] | |
| if int(): | |
| s = a[b] # E: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| if int(): | |
| i = a[c] # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| if int(): | |
| s = a[c] | |
| class A: | |
| @overload | |
| def __getitem__(self, x: 'B') -> int: | |
| pass | |
| @overload | |
| def __getitem__(self, x: 'C') -> str: | |
| pass | |
| class B: pass | |
| class C: pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| -- Cast expression | |
| -- --------------- | |
| [case testCastExpressions] | |
| from typing import cast, Any | |
| class A: pass | |
| class B: pass | |
| class C(A): pass | |
| a: A | |
| b: B | |
| c: C | |
| if int(): | |
| a = cast(A, a()) # E: "A" not callable | |
| if int(): | |
| a = cast(Any, a()) # E: "A" not callable | |
| b = cast(A, a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") | |
| if int(): | |
| a = cast(A, b) | |
| if int(): | |
| a = cast(A, a) | |
| c = cast(C, a) | |
| if int(): | |
| a = cast(A, c) | |
| if int(): | |
| a = cast(Any, b) | |
| b = cast(Any, a) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testAnyCast] | |
| from typing import cast, Any | |
| a: A | |
| b: B | |
| a = cast(Any, a()) # Fail | |
| a = cast(Any, b) | |
| b = cast(Any, a) | |
| class A: pass | |
| class B: pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| main:4: error: "A" not callable | |
| -- assert_type() | |
| [case testAssertType] | |
| from typing import assert_type, Any, Literal | |
| a: int = 1 | |
| returned = assert_type(a, int) | |
| reveal_type(returned) # N: Revealed type is "builtins.int" | |
| assert_type(a, str) # E: Expression is of type "int", not "str" | |
| assert_type(a, Any) # E: Expression is of type "int", not "Any" | |
| assert_type(a, Literal[1]) # E: Expression is of type "int", not "Literal[1]" | |
| assert_type(42, Literal[42]) | |
| assert_type(42, int) # E: Expression is of type "Literal[42]", not "int" | |
| [builtins fixtures/tuple.pyi] | |
| [case testAssertTypeGeneric] | |
| from typing import assert_type, Literal, TypeVar, Generic | |
| T = TypeVar("T") | |
| def f(x: T) -> T: return x | |
| assert_type(f(1), int) | |
| class Gen(Generic[T]): | |
| def __new__(cls, obj: T) -> Gen[T]: ... | |
| assert_type(Gen(1), Gen[int]) | |
| # With type context, it infers Gen[Literal[1]] instead. | |
| y: Gen[Literal[1]] = assert_type(Gen(1), Gen[Literal[1]]) | |
| [builtins fixtures/tuple.pyi] | |
| [case testAssertTypeUncheckedFunction] | |
| from typing import Literal, assert_type | |
| def f(): | |
| x = 42 | |
| assert_type(x, Literal[42]) | |
| [out] | |
| main:4: error: Expression is of type "Any", not "Literal[42]" | |
| main:4: note: "assert_type" expects everything to be "Any" in unchecked functions | |
| [builtins fixtures/tuple.pyi] | |
| [case testAssertTypeUncheckedFunctionWithUntypedCheck] | |
| # flags: --check-untyped-defs | |
| from typing import Literal, assert_type | |
| def f(): | |
| x = 42 | |
| assert_type(x, Literal[42]) | |
| [out] | |
| main:5: error: Expression is of type "int", not "Literal[42]" | |
| [builtins fixtures/tuple.pyi] | |
| [case testAssertTypeNoPromoteUnion] | |
| from typing import Union, assert_type | |
| Scalar = Union[int, bool, bytes, bytearray] | |
| def reduce_it(s: Scalar) -> Scalar: | |
| return s | |
| assert_type(reduce_it(True), Scalar) | |
| [builtins fixtures/tuple.pyi] | |
| [case testAssertTypeWithDeferredNodes] | |
| from typing import Callable, TypeVar, assert_type | |
| T = TypeVar("T") | |
| def dec(f: Callable[[], T]) -> Callable[[], T]: | |
| return f | |
| def func() -> None: | |
| some = _inner_func() | |
| assert_type(some, int) | |
| @dec | |
| def _inner_func() -> int: | |
| return 1 | |
| [builtins fixtures/tuple.pyi] | |
| -- None return type | |
| -- ---------------- | |
| [case testNoneReturnTypeBasics] | |
| def f() -> None: | |
| pass | |
| class A: | |
| def g(self, x: object) -> None: | |
| pass | |
| def __call__(self) -> None: | |
| pass | |
| a: A | |
| o: object | |
| if int(): | |
| a = f() # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Incompatible types in assignment (expression has type "None", variable has type "A") | |
| if int(): | |
| o = a() # E: Function does not return a value (it only ever returns None) | |
| if int(): | |
| o = A().g(a) # E: "g" of "A" does not return a value (it only ever returns None) | |
| if int(): | |
| o = A.g(a, a) # E: "g" of "A" does not return a value (it only ever returns None) | |
| A().g(f()) # E: "f" does not return a value (it only ever returns None) | |
| x: A = f() # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Incompatible types in assignment (expression has type "None", variable has type "A") | |
| f() | |
| A().g(a) | |
| [builtins fixtures/tuple.pyi] | |
| [case testNoneReturnTypeWithStatements] | |
| import typing | |
| def f() -> None: pass | |
| if f(): # E: "f" does not return a value (it only ever returns None) | |
| pass | |
| elif f(): # E: "f" does not return a value (it only ever returns None) | |
| pass | |
| while f(): # E: "f" does not return a value (it only ever returns None) | |
| pass | |
| def g() -> object: | |
| return f() # E: "f" does not return a value (it only ever returns None) | |
| raise f() # E: Exception must be derived from BaseException \ | |
| # E: "f" does not return a value (it only ever returns None) | |
| [builtins fixtures/exception.pyi] | |
| [case testNoneReturnTypeWithExpressions] | |
| from typing import cast | |
| def f() -> None: pass | |
| class A: | |
| def __add__(self, x: 'A') -> 'A': pass | |
| a: A | |
| [f()] # E: "f" does not return a value (it only ever returns None) | |
| f() + a # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Unsupported left operand type for + ("None") | |
| a + f() # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Unsupported operand types for + ("A" and "None") | |
| f() == a # E: "f" does not return a value (it only ever returns None) | |
| a != f() # E: Unsupported left operand type for != ("A") \ | |
| # E: "f" does not return a value (it only ever returns None) | |
| cast(A, f()) | |
| f().foo # E: "f" does not return a value (it only ever returns None) \ | |
| # E: "None" has no attribute "foo" | |
| [builtins fixtures/list.pyi] | |
| [case testNoneReturnTypeWithExpressions2] | |
| import typing | |
| def f() -> None: pass | |
| class A: | |
| def __add__(self, x: 'A') -> 'A': | |
| pass | |
| a: A | |
| b: bool | |
| f() in a # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Unsupported right operand type for in ("A") | |
| a < f() # E: Unsupported left operand type for < ("A") \ | |
| # E: "f" does not return a value (it only ever returns None) | |
| f() <= a # E: "f" does not return a value (it only ever returns None) \ | |
| # E: Unsupported left operand type for <= ("None") | |
| a in f() # E: Unsupported right operand type for in ("None") \ | |
| # E: "f" does not return a value (it only ever returns None) | |
| -f() # E: Unsupported operand type for unary - ("None") \ | |
| # E: "f" does not return a value (it only ever returns None) | |
| not f() # E: "f" does not return a value (it only ever returns None) | |
| f() and b # E: "f" does not return a value (it only ever returns None) | |
| b or f() # E: "f" does not return a value (it only ever returns None) | |
| [builtins fixtures/bool.pyi] | |
| -- Slicing | |
| -- ------- | |
| [case testGetSlice] | |
| a: A | |
| b: B | |
| if int(): | |
| a = a[1:2] # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| a = a[1:] # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| a = a[:2] # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| a = a[:] # E: Incompatible types in assignment (expression has type "B", variable has type "A") | |
| if int(): | |
| b = a[1:2] | |
| if int(): | |
| b = a[1:] | |
| if int(): | |
| b = a[:2] | |
| if int(): | |
| b = a[:] | |
| class A: | |
| def __getitem__(self, s: slice) -> 'B': pass | |
| class B: pass | |
| [builtins fixtures/slice.pyi] | |
| [case testSlicingWithInvalidBase] | |
| a: A | |
| a[1:2] # E: Invalid index type "slice[int, int, None]" for "A"; expected type "int" | |
| a[:] # E: Invalid index type "slice[None, None, None]" for "A"; expected type "int" | |
| class A: | |
| def __getitem__(self, n: int) -> 'A': pass | |
| [builtins fixtures/slice.pyi] | |
| [case testSlicingWithNonindexable] | |
| o: object | |
| o[1:2] # E: Value of type "object" is not indexable | |
| o[:] # E: Value of type "object" is not indexable | |
| [builtins fixtures/slice.pyi] | |
| [case testNonIntSliceBounds] | |
| from typing import Any | |
| a: Any | |
| o: object | |
| a[o:1] | |
| a[1:o] | |
| a[o:] | |
| a[:o] | |
| [builtins fixtures/slice.pyi] | |
| [case testSliceSupportsIndex] | |
| import typing_extensions | |
| class Index: | |
| def __init__(self, value: int) -> None: | |
| self.value = value | |
| def __index__(self) -> int: | |
| return self.value | |
| c = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
| reveal_type(c[Index(0):Index(5)]) # N: Revealed type is "builtins.list[builtins.int]" | |
| [file typing_extensions.pyi] | |
| from typing import Protocol | |
| class SupportsIndex(Protocol): | |
| def __index__(self) -> int: ... | |
| [builtins fixtures/slice.pyi] | |
| [case testSliceWithPerFileStrictOptional] | |
| # flags: --no-strict-optional | |
| # mypy: strict-optional | |
| "x"[1:] | |
| [file builtins.py] | |
| from typing import Generic, TypeVar | |
| _StartT = TypeVar("_StartT", covariant=True) | |
| _StopT = TypeVar("_StopT", covariant=True, default=_StartT) | |
| _StepT = TypeVar("_StepT", covariant=True, default=_StartT | _StopT) | |
| class object: | |
| def __init__(self) -> None: pass | |
| class type: pass | |
| class tuple(Generic[_StartT]): pass | |
| class function: pass | |
| class int: pass | |
| class str: | |
| def __getitem__(self, index: slice[int | None]) -> str: pass | |
| class slice(Generic[_StartT, _StopT, _StepT]): pass | |
| class dict: pass | |
| [case testNoneSliceBounds] | |
| from typing import Any | |
| a: Any | |
| a[None:1] | |
| a[1:None] | |
| a[None:] | |
| a[:None] | |
| [builtins fixtures/slice.pyi] | |
| [case testNoneSliceBoundsWithStrictOptional] | |
| from typing import Any | |
| a: Any | |
| a[None:1] | |
| a[1:None] | |
| a[None:] | |
| a[:None] | |
| [builtins fixtures/slice.pyi] | |
| -- Lambdas | |
| -- ------- | |
| [case testTrivialLambda] | |
| from typing import Callable | |
| f = lambda: 1 # type: Callable[[], int] | |
| if int(): | |
| f = lambda: ''.x # E: "str" has no attribute "x" | |
| if int(): | |
| f = lambda: '' \ | |
| # E: Incompatible types in assignment (expression has type "Callable[[], str]", variable has type "Callable[[], int]") \ | |
| # E: Incompatible return value type (got "str", expected "int") | |
| [case testVoidLambda] | |
| import typing | |
| def void() -> None: | |
| pass | |
| x = lambda: void() # type: typing.Callable[[], None] | |
| [case testNoCrashOnLambdaGenerator] | |
| # flags: --no-strict-optional | |
| from typing import Iterator, Callable | |
| # These should not crash | |
| lambda: (yield) | |
| gen: Callable[[], Iterator[str]] | |
| gen = (lambda: (yield 1)) # E: Incompatible types in "yield" (actual type "int", expected type "str") | |
| def fun(cb: Callable[[], Iterator[str]]) -> None: | |
| pass | |
| fun(lambda: (yield from [1])) # E: Incompatible types in "yield from" (actual type "int", expected type "str") | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testLambdaAndReachability] | |
| def f() -> None: | |
| aa = [] | |
| y = lambda x: 1 | |
| aa.append(1) | |
| 1() # E: "int" not callable | |
| [builtins fixtures/list.pyi] | |
| -- List comprehensions | |
| -- ------------------- | |
| [case testSimpleListComprehension] | |
| from typing import List | |
| a: List[A] | |
| a = [x for x in a] | |
| b = [x for x in a] # type: List[B] # E: List comprehension has incompatible type List[A]; expected List[B] | |
| class A: pass | |
| class B: pass | |
| [builtins fixtures/for.pyi] | |
| [case testSimpleListComprehensionNestedTuples] | |
| from typing import List, Tuple | |
| l: List[Tuple[A, Tuple[A, B]]] | |
| a = [a2 for a1, (a2, b1) in l] # type: List[A] | |
| b = [a2 for a1, (a2, b1) in l] # type: List[B] # E: List comprehension has incompatible type List[A]; expected List[B] | |
| class A: pass | |
| class B: pass | |
| [builtins fixtures/for.pyi] | |
| [case testSimpleListComprehensionNestedTuples2] | |
| from typing import List, Tuple | |
| l: List[Tuple[int, Tuple[int, str]]] | |
| a = [f(d) for d, (i, s) in l] | |
| b = [f(s) for d, (i, s) in l] # E: Argument 1 to "f" has incompatible type "str"; expected "int" | |
| def f(x: int): pass | |
| [builtins fixtures/for.pyi] | |
| [case testListComprehensionWithNonDirectMapping] | |
| from typing import List | |
| a: List[A] | |
| b: List[B] | |
| if int(): | |
| b = [f(x) for x in a] | |
| if int(): | |
| a = [f(x) for x in a] # E: List comprehension has incompatible type List[B]; expected List[A] | |
| ([f(x) for x in b]) # E: Argument 1 to "f" has incompatible type "B"; expected "A" | |
| class A: pass | |
| class B: pass | |
| def f(a: A) -> B: pass | |
| [builtins fixtures/for.pyi] | |
| [case testErrorInListComprehensionCondition] | |
| from typing import List | |
| a: List[A] | |
| a = [x for x in a if x()] # E: "A" not callable | |
| class A: pass | |
| [builtins fixtures/for.pyi] | |
| [case testTypeInferenceOfListComprehension] | |
| from typing import List | |
| a: List[A] | |
| o = [x for x in a] # type: List[object] | |
| class A: pass | |
| [builtins fixtures/for.pyi] | |
| [case testSimpleListComprehensionInClassBody] | |
| from typing import List | |
| class A: | |
| a: List[A] | |
| a = [x for x in a] | |
| b = [x for x in a] # type: List[B] # E: List comprehension has incompatible type List[A]; expected List[B] | |
| class B: pass | |
| [builtins fixtures/for.pyi] | |
| [out] | |
| -- Set comprehension | |
| -- ----------------- | |
| [case testSimpleSetComprehension] | |
| from typing import Set | |
| a: Set[A] | |
| a = {x for x in a} | |
| b = {x for x in a} # type: Set[B] # E: Set comprehension has incompatible type Set[A]; expected Set[B] | |
| class A: pass | |
| class B: pass | |
| [builtins fixtures/set.pyi] | |
| -- Dictionary comprehension | |
| -- ------------------------ | |
| [case testSimpleDictionaryComprehension] | |
| from typing import Dict, List, Tuple | |
| abd: Dict[A, B] | |
| abl: List[Tuple[A, B]] | |
| abd = {a: b for a, b in abl} | |
| x = {a: b for a, b in abl} # type: Dict[B, A] | |
| y = {a: b for a, b in abl} # type: A | |
| class A: pass | |
| class B: pass | |
| [builtins fixtures/dict.pyi] | |
| [out] | |
| main:5: error: Key expression in dictionary comprehension has incompatible type "A"; expected type "B" | |
| main:5: error: Value expression in dictionary comprehension has incompatible type "B"; expected type "A" | |
| main:6: error: Incompatible types in assignment (expression has type "dict[A, B]", variable has type "A") | |
| [case testDictionaryComprehensionWithNonDirectMapping] | |
| from typing import Dict, List, Tuple | |
| abd: Dict[A, B] | |
| abl: List[Tuple[A, B]] | |
| abd = {a: f(b) for a, b in abl} | |
| class A: pass | |
| class B: pass | |
| class C: pass | |
| def f(b: A) -> C: pass | |
| [builtins fixtures/dict.pyi] | |
| [out] | |
| main:4: error: Value expression in dictionary comprehension has incompatible type "C"; expected type "B" | |
| main:4: error: Argument 1 to "f" has incompatible type "B"; expected "A" | |
| -- Generator expressions | |
| -- --------------------- | |
| [case testSimpleGeneratorExpression] | |
| from typing import Iterator | |
| # The implementation is mostly identical to list comprehensions, so only a few | |
| # test cases is ok. | |
| a: Iterator[int] | |
| if int(): | |
| a = (x for x in a) | |
| b: Iterator[str] | |
| if int(): | |
| b = (x for x in a) # E: Generator has incompatible item type "int"; expected "str" | |
| [builtins fixtures/for.pyi] | |
| [case testGeneratorIncompatibleErrorMessage] | |
| from typing import Callable, Iterator, List | |
| a = [] # type: List[Callable[[], str]] | |
| b: Iterator[Callable[[], int]] | |
| if int(): | |
| b = (x for x in a) # E: Generator has incompatible item type "Callable[[], str]"; expected "Callable[[], int]" | |
| [builtins fixtures/list.pyi] | |
| [case testGeneratorNoSpuriousError] | |
| from typing import Iterable, overload | |
| @overload | |
| def take_iterable(iterable: Iterable[bool], /) -> None: ... | |
| @overload | |
| def take_iterable(iterable: Iterable[int], /) -> None: ... | |
| def take_iterable(iterable): pass | |
| take_iterable(1 for _ in []) | |
| take_iterable(reveal_type(1 for _ in [])) # N: Revealed type is "typing.Generator[builtins.int, None, None]" | |
| # NOTE: Type is revealed for every overload tried | |
| # TODO: Overload shouldn't fail if expression contains an error that shouldn't affect the inferred type. | |
| take_iterable(reveal_type(1 if (-"") else 1 for _ in [])) # N: Revealed type is "typing.Generator[builtins.int, None, None]" \ | |
| # E: Generator has incompatible item type "int"; expected "bool" \ | |
| # N: Revealed type is "typing.Generator[builtins.bool, None, None]" \ | |
| # E: Unsupported operand type for unary - ("str") | |
| [builtins fixtures/for.pyi] | |
| -- Conditional expressions | |
| -- ----------------------- | |
| [case testSimpleConditionalExpression] | |
| import typing | |
| y = '' | |
| x = 1 if y else 2 | |
| if int(): | |
| x = 3 | |
| if int(): | |
| x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testConditionalExpressionWithEmptyCondition] | |
| import typing | |
| def f() -> None: pass | |
| x = 1 if f() else 2 # E: "f" does not return a value (it only ever returns None) | |
| [case testConditionalExpressionWithSubtyping] | |
| import typing | |
| class A: pass | |
| class B(A): pass | |
| x = B() if bool() else A() | |
| if int(): | |
| x = A() | |
| if int(): | |
| x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "A") | |
| y = A() if bool() else B() | |
| if int(): | |
| y = A() | |
| if int(): | |
| y = '' # E: Incompatible types in assignment (expression has type "str", variable has type "A") | |
| [builtins fixtures/bool.pyi] | |
| [case testConditionalExpressionAndTypeContext] | |
| import typing | |
| x = [1] if bool() else [] | |
| if int(): | |
| x = [1] | |
| if int(): | |
| x = ['x'] # E: List item 0 has incompatible type "str"; expected "int" | |
| [builtins fixtures/list.pyi] | |
| [case testConditionalExpressionUnion] | |
| from typing import Union | |
| reveal_type(1 if bool() else 2) # N: Revealed type is "Literal[1]? | Literal[2]?" | |
| reveal_type(1 if bool() else '') # N: Revealed type is "Literal[1]? | Literal['']?" | |
| x: Union[int, str] = reveal_type(1 if bool() else '') # N: Revealed type is "Literal[1]? | Literal['']?" | |
| class A: | |
| pass | |
| class B(A): | |
| pass | |
| class C: | |
| pass | |
| class D(A): | |
| pass | |
| a = A() | |
| b = B() | |
| c = C() | |
| d = D() | |
| reveal_type(a if bool() else b) # N: Revealed type is "__main__.A" | |
| reveal_type(b if bool() else c) # N: Revealed type is "__main__.B | __main__.C" | |
| reveal_type(c if bool() else b) # N: Revealed type is "__main__.C | __main__.B" | |
| reveal_type(c if bool() else a) # N: Revealed type is "__main__.C | __main__.A" | |
| reveal_type(d if bool() else b) # N: Revealed type is "__main__.D | __main__.B" | |
| [builtins fixtures/bool.pyi] | |
| [case testConditionalExpressionUnionWithAny] | |
| from typing import Union, Any | |
| a: Any | |
| x: Union[int, str] = reveal_type(a if int() else 1) # N: Revealed type is "Any | Literal[1]?" | |
| reveal_type(a if int() else 1) # N: Revealed type is "Any | Literal[1]?" | |
| [case testConditionalExpressionStatementNoReturn] | |
| from typing import List, Union | |
| x = [] | |
| y = "" | |
| x.append(y) if bool() else x.append(y) | |
| z = x.append(y) if bool() else x.append(y) # E: "append" of "list" does not return a value (it only ever returns None) | |
| [builtins fixtures/list.pyi] | |
| [case testConditionalExpressionWithUnreachableBranches] | |
| from typing import TypeVar | |
| T = TypeVar("T", int, str) | |
| def foo(x: T) -> T: | |
| return x + 1 if isinstance(x, int) else x + "a" | |
| [builtins fixtures/isinstancelist.pyi] | |
| -- Special cases | |
| -- ------------- | |
| [case testOperationsWithNonInstanceTypes] | |
| from typing import cast | |
| class A: | |
| def __add__(self, a: 'A') -> 'A': pass | |
| def f() -> None: | |
| pass | |
| a: A | |
| None + a # E: Unsupported left operand type for + ("None") | |
| f + a # E: Unsupported left operand type for + ("Callable[[], None]") | |
| a + f # E: Unsupported operand types for + ("A" and "Callable[[], None]") | |
| cast(A, f) | |
| [case testOperatorMethodWithInvalidArgCount] | |
| a: A | |
| a + a # Fail | |
| class A: | |
| def __add__(self) -> 'A': | |
| pass | |
| [out] | |
| main:3: error: Too many arguments for "__add__" of "A" | |
| [case testOperatorMethodAsVar] | |
| from typing import Any | |
| class A: | |
| def __init__(self, _add: Any) -> None: | |
| self.__add__ = _add | |
| a: A | |
| a + a | |
| [out] | |
| [case testOperatorMethodAsVar2] | |
| class A: | |
| def f(self, x: int) -> str: pass | |
| __add__ = f | |
| s: str | |
| s = A() + 1 | |
| A() + (A() + 1) | |
| [out] | |
| main:7: error: Argument 1 has incompatible type "str"; expected "int" | |
| [case testIndexedLvalueWithSubtypes] | |
| a: A | |
| b: B | |
| c: C | |
| a[c] = c | |
| a[b] = c | |
| a[c] = b | |
| class A: | |
| def __setitem__(self, x: 'B', y: 'B') -> None: | |
| pass | |
| class B: | |
| pass | |
| class C(B): | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| -- Ellipsis | |
| -- -------- | |
| [case testEllipsis] | |
| a: A | |
| if str(): | |
| a = ... # E: Incompatible types in assignment (expression has type "EllipsisType", variable has type "A") | |
| b = ... | |
| c = ... | |
| if str(): | |
| b = c | |
| ....__class__ | |
| ....a # E: "EllipsisType" has no attribute "a" | |
| class A: pass | |
| [builtins fixtures/dict-full.pyi] | |
| -- Yield expression | |
| -- ---------------- | |
| [case testYieldExpression] | |
| def f(x: int) -> None: | |
| x = yield f('') | |
| x = 1 | |
| [builtins fixtures/for.pyi] | |
| [out] | |
| main:1: error: The return type of a generator function should be "Generator" or one of its supertypes | |
| main:2: error: "f" does not return a value (it only ever returns None) | |
| main:2: error: Argument 1 to "f" has incompatible type "str"; expected "int" | |
| [case testYieldExpressionWithNone] | |
| from typing import Iterator | |
| def f(x: int) -> Iterator[None]: | |
| (yield) | |
| [builtins fixtures/for.pyi] | |
| [out] | |
| -- Yield from expression | |
| -- ---------------- | |
| [case testYieldFromIteratorHasNoValue] | |
| from typing import Iterator | |
| def f() -> Iterator[int]: | |
| yield 5 | |
| def g() -> Iterator[int]: | |
| a = yield from f() # E: Function does not return a value (it only ever returns None) | |
| [case testYieldFromGeneratorHasValue] | |
| from typing import Iterator, Generator | |
| def f() -> Generator[int, None, str]: | |
| yield 5 | |
| return "ham" | |
| def g() -> Iterator[int]: | |
| a = "string" | |
| a = yield from f() | |
| [out] | |
| [case testYieldFromTupleExpression] | |
| from typing import Generator | |
| def g() -> Generator[int, None, None]: | |
| x = yield from () # E: Function does not return a value (it only ever returns None) | |
| x = yield from (0, 1, 2) # E: Function does not return a value (it only ever returns None) | |
| x = yield from (0, "ERROR") # E: Incompatible types in "yield from" (actual type "int | str", expected type "int") \ | |
| # E: Function does not return a value (it only ever returns None) | |
| x = yield from ("ERROR",) # E: Incompatible types in "yield from" (actual type "str", expected type "int") \ | |
| # E: Function does not return a value (it only ever returns None) | |
| [builtins fixtures/tuple.pyi] | |
| -- dict(...) | |
| -- --------- | |
| -- Note that the stub used in unit tests does not have all overload | |
| -- variants, but it should not matter. | |
| [case testDictWithKeywordArgsOnly] | |
| from typing import Dict, Any | |
| d1 = dict(a=1, b=2) # type: Dict[str, int] | |
| d2 = dict(a=1, b='') # type: Dict[str, int] # E: Dict entry 1 has incompatible type "str": "str"; expected "str": "int" | |
| d3 = dict(a=1) # type: Dict[int, int] # E: Dict entry 0 has incompatible type "str": "int"; expected "int": "int" | |
| d4 = dict(a=1, b=1) | |
| d4.xyz # E: "dict[str, int]" has no attribute "xyz" | |
| d5 = dict(a=1, b='') # type: Dict[str, Any] | |
| [builtins fixtures/dict.pyi] | |
| [case testDictWithoutKeywordArgs] | |
| from typing import Dict | |
| d = dict() # E: Need type annotation for "d" (hint: "d: dict[<type>, <type>] = ...") | |
| d2 = dict() # type: Dict[int, str] | |
| dict(undefined) # E: Name "undefined" is not defined | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromList] | |
| from typing import Dict | |
| d = dict([(1, 'x'), (2, 'y')]) | |
| d() # E: "dict[int, str]" not callable | |
| d2 = dict([(1, 'x')]) # type: Dict[str, str] # E: List item 0 has incompatible type "tuple[int, str]"; expected "tuple[str, str]" | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromIterableAndKeywordArg] | |
| from typing import Dict | |
| it = [('x', 1)] | |
| d = dict(it, x=1) | |
| d() # E: "dict[str, int]" not callable | |
| d2 = dict(it, x='') | |
| d2() # E: "dict[str, object]" not callable | |
| d3 = dict(it, x='') # type: Dict[str, int] # E: Argument "x" to "dict" has incompatible type "str"; expected "int" | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromIterableAndKeywordArg2] | |
| it = [(1, 'x')] | |
| dict(it, x='y') # E: Keyword argument only valid with "str" key type in call to "dict" | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromIterableAndKeywordArg3] | |
| d = dict([], x=1) | |
| d() # E: "dict[str, int]" not callable | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromIterableAndStarStarArgs] | |
| from typing import Dict | |
| it = [('x', 1)] | |
| kw = {'x': 1} | |
| d = dict(it, **kw) | |
| d() # E: "dict[str, int]" not callable | |
| kw2 = {'x': ''} | |
| d2 = dict(it, **kw2) | |
| d2() # E: "dict[str, object]" not callable | |
| d3 = dict(it, **kw2) # type: Dict[str, int] # E: Argument 2 to "dict" has incompatible type "**dict[str, str]"; expected "int" | |
| [builtins fixtures/dict.pyi] | |
| [case testDictFromIterableAndStarStarArgs2] | |
| it = [(1, 'x')] | |
| kw = {'x': 'y'} | |
| d = dict(it, **kw) # E: Keyword argument only valid with "str" key type in call to "dict" | |
| d() # E: "dict[int, str]" not callable | |
| [builtins fixtures/dict.pyi] | |
| [case testUserDefinedClassNamedDict] | |
| from typing import Generic, TypeVar | |
| T = TypeVar('T') | |
| S = TypeVar('S') | |
| class dict(Generic[T, S]): | |
| def __init__(self, x: T, **kwargs: T) -> None: pass | |
| dict(1, y=1) | |
| [builtins fixtures/dict.pyi] | |
| [case testSpecialSignatureForSubclassOfDict] | |
| from typing import TypeVar, Dict, Generic | |
| T = TypeVar('T') | |
| S = TypeVar('S') | |
| class D1(dict): pass # Implicit base class Dict[Any, Any] | |
| D1([(1, 2)], x=1) | |
| class D2(Dict[T, S], Generic[T, S]): pass | |
| da = D2([('x', 2)], x=1) | |
| da() # E: "D2[str, int]" not callable | |
| D2([(1, 2)], x=1) # E: Keyword argument only valid with "str" key type in call to "dict" | |
| db = D2(x=1) | |
| db() # E: "D2[str, int]" not callable | |
| [builtins fixtures/dict.pyi] | |
| [case testSpecialSignatureForSubclassOfDict2] | |
| from typing import TypeVar, Dict, Generic | |
| T = TypeVar('T') | |
| class D(Dict[str, T], Generic[T]): pass | |
| D([('x', 1)], x=1) | |
| [builtins fixtures/dict.pyi] | |
| [case testOverridingSpecialSignatureInSubclassOfDict] | |
| from typing import TypeVar, Dict, Generic | |
| T = TypeVar('T') | |
| S = TypeVar('S') | |
| class D(Dict[T, S], Generic[T, S]): | |
| def __init__(self, x: S, y: T) -> None: pass | |
| d = D(1, y='') | |
| d() # E: "D[str, int]" not callable | |
| [builtins fixtures/dict.pyi] | |
| [case testRevealType] | |
| reveal_type(1) # N: Revealed type is "Literal[1]?" | |
| [case testRevealLocals] | |
| x = 1 | |
| y = 2 | |
| z = x + y | |
| reveal_locals() | |
| [out] | |
| main:4: note: Revealed local types are: | |
| main:4: note: x: builtins.int | |
| main:4: note: y: builtins.int | |
| main:4: note: z: builtins.int | |
| [case testUndefinedRevealType] | |
| reveal_type(x) | |
| [out] | |
| main:1: error: Name "x" is not defined | |
| main:1: note: Revealed type is "Any" | |
| [case testUserDefinedRevealType] | |
| def reveal_type(x: int) -> None: pass | |
| reveal_type("foo") # E: Argument 1 to "reveal_type" has incompatible type "str"; expected "int" | |
| [case testTypingRevealType] | |
| from typing import reveal_type | |
| from typing import reveal_type as show_me_the_type | |
| reveal_type(1) # N: Revealed type is "Literal[1]?" | |
| show_me_the_type(1) # N: Revealed type is "Literal[1]?" | |
| [case testTypingExtensionsRevealType] | |
| from typing_extensions import reveal_type | |
| from typing_extensions import reveal_type as show_me_the_type | |
| reveal_type(1) # N: Revealed type is "Literal[1]?" | |
| show_me_the_type(1) # N: Revealed type is "Literal[1]?" | |
| [builtins fixtures/tuple.pyi] | |
| [case testRevealTypeVar] | |
| reveal_type = 1 | |
| 1 + "foo" # E: Unsupported operand types for + ("int" and "str") | |
| [case testRevealForward] | |
| def f() -> None: | |
| reveal_type(x) | |
| x = 1 + int() | |
| [out] | |
| main:2: note: Revealed type is "builtins.int" | |
| [case testRevealUncheckedFunction] | |
| def f(): | |
| x = 42 | |
| reveal_type(x) | |
| [out] | |
| main:3: note: Revealed type is "Any" | |
| main:3: note: 'reveal_type' always outputs 'Any' in unchecked functions | |
| [case testRevealCheckUntypedDefs] | |
| # flags: --check-untyped-defs | |
| def f(): | |
| x = 42 | |
| reveal_type(x) | |
| [out] | |
| main:4: note: Revealed type is "builtins.int" | |
| [case testRevealTypedDef] | |
| def f() -> None: | |
| x = 42 | |
| reveal_type(x) | |
| [out] | |
| main:3: note: Revealed type is "builtins.int" | |
| [case testLambdaTypedContext] | |
| def f() -> None: | |
| lambda: 'a'.missing() # E: "str" has no attribute "missing" | |
| [case testLambdaUnypedContext] | |
| def f(): | |
| lambda: 'a'.missing() | |
| [case testLambdaCheckUnypedContext] | |
| # flags: --check-untyped-defs | |
| def f(): | |
| lambda: 'a'.missing() # E: "str" has no attribute "missing" | |
| [case testEqNone] | |
| None == None | |
| [builtins fixtures/ops.pyi] | |
| [case testLtNone] | |
| None < None # E: Unsupported left operand type for < ("None") | |
| [builtins fixtures/ops.pyi] | |
| [case testDictWithStarExpr] | |
| b = {'z': 26, *a} # E: Starred expression cannot be used here \ | |
| # E: Expected `:`, found `}` | |
| [builtins fixtures/dict.pyi] | |
| [case testDictWithStarStarExpr] | |
| from typing import Dict, Iterable | |
| class Thing: | |
| def keys(self) -> Iterable[str]: | |
| ... | |
| def __getitem__(self, key: str) -> int: | |
| ... | |
| a = {'a': 1} | |
| b = {'z': 26, **a} | |
| c = {**b} | |
| d = {**a, **b, 'c': 3} | |
| e = {1: 'a', **a} # E: Cannot infer value of type parameter "KT" of <dict> \ | |
| # N: Try assigning the literal to a variable annotated as dict[<key>, <val>] | |
| f = {**b} # type: Dict[int, int] # E: Unpacked dict entry 0 has incompatible type "dict[str, int]"; expected "SupportsKeysAndGetItem[int, int]" | |
| g = {**Thing()} | |
| h = {**a, **Thing()} | |
| i = {**Thing()} # type: Dict[int, int] # E: Unpacked dict entry 0 has incompatible type "Thing"; expected "SupportsKeysAndGetItem[int, int]" \ | |
| # N: Following member(s) of "Thing" have conflicts: \ | |
| # N: Expected: \ | |
| # N: def __getitem__(self, int, /) -> int \ | |
| # N: Got: \ | |
| # N: def __getitem__(self, str, /) -> int \ | |
| # N: Expected: \ | |
| # N: def keys(self) -> Iterable[int] \ | |
| # N: Got: \ | |
| # N: def keys(self) -> Iterable[str] | |
| j = {1: 'a', **Thing()} # E: Cannot infer value of type parameter "KT" of <dict> \ | |
| # N: Try assigning the literal to a variable annotated as dict[<key>, <val>] | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testDictIncompatibleTypeErrorMessage] | |
| from typing import Dict, Callable | |
| def things() -> int: | |
| return 42 | |
| stuff: Dict[int, Callable[[], str]] = { | |
| 1: things # E: Dict entry 0 has incompatible type "int": "Callable[[], int]"; expected "int": "Callable[[], str]" | |
| } | |
| [builtins fixtures/dict.pyi] | |
| [case testDictIncompatibleKeyVerbosity] | |
| from typing import Dict | |
| import mod | |
| class A: ... | |
| class B(A): ... | |
| d: Dict[A, B] = {A(): mod.B()} # E: Dict entry 0 has incompatible type "A": "mod.B"; expected "A": "__main__.B" | |
| [file mod.py] | |
| class B: ... | |
| [builtins fixtures/dict.pyi] | |
| [case testDictIncompatibleValueVerbosity] | |
| from typing import Dict | |
| import mod | |
| class A: ... | |
| class B(A): ... | |
| d: Dict[B, A] = {mod.B(): A()} # E: Dict entry 0 has incompatible type "mod.B": "A"; expected "__main__.B": "A" | |
| [file mod.py] | |
| class B: ... | |
| [builtins fixtures/dict.pyi] | |
| [case testTypeAnnotationNeededMultipleAssignment] | |
| x, y = [], [] # E: Need type annotation for "x" (hint: "x: list[<type>] = ...") \ | |
| # E: Need type annotation for "y" (hint: "y: list[<type>] = ...") | |
| [builtins fixtures/list.pyi] | |
| [case testStrictEqualityEq] | |
| # flags: --strict-equality | |
| class A: ... | |
| class B: ... | |
| class C(B): ... | |
| A() == B() # E: Non-overlapping equality check (left operand type: "A", right operand type: "B") | |
| B() == C() | |
| C() == B() | |
| A() != B() # E: Non-overlapping equality check (left operand type: "A", right operand type: "B") | |
| B() != C() | |
| C() != B() | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityIs] | |
| # flags: --strict-equality | |
| class A: ... | |
| class B: ... | |
| class C(B): ... | |
| A() is B() # E: Non-overlapping identity check (left operand type: "A", right operand type: "B") | |
| B() is C() | |
| C() is B() | |
| A() is not B() # E: Non-overlapping identity check (left operand type: "A", right operand type: "B") | |
| B() is not C() | |
| C() is not B() | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityContains] | |
| # flags: --strict-equality | |
| class A: ... | |
| class B: ... | |
| class C(B): ... | |
| A() in [B()] # E: Non-overlapping container check (element type: "A", container item type: "B") | |
| B() in [C()] | |
| C() in [B()] | |
| A() not in [B()] # E: Non-overlapping container check (element type: "A", container item type: "B") | |
| B() not in [C()] | |
| C() not in [B()] | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityUnions] | |
| # flags: --strict-equality | |
| from typing import Container, Union | |
| class A: ... | |
| class B: ... | |
| a: Union[int, str] | |
| b: Union[A, B] | |
| a == int() | |
| b == int() # E: Non-overlapping equality check (left operand type: "A | B", right operand type: "int") | |
| a is int() | |
| b is int() # E: Non-overlapping identity check (left operand type: "A | B", right operand type: "int") | |
| ca: Union[Container[int], Container[str]] | |
| cb: Union[Container[A], Container[B]] | |
| 42 in ca | |
| 42 in cb # E: Non-overlapping container check (element type: "int", container item type: "A | B") | |
| [builtins fixtures/bool.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityBytesSpecial] | |
| # flags: --strict-equality | |
| b'abc' in b'abcde' | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testStrictEqualityBytesSpecialUnion] | |
| # flags: --strict-equality | |
| from typing import Union | |
| x: Union[bytes, str] | |
| b'abc' in x | |
| x in b'abc' | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testStrictEqualityByteArraySpecial] | |
| # flags: --strict-equality | |
| b'abc' in bytearray(b'abcde') | |
| bytearray(b'abc') in b'abcde' # OK on Python 3 | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testStrictEqualityNoPromotePy3] | |
| # flags: --strict-equality | |
| 'a' == b'a' # E: Non-overlapping equality check (left operand type: "Literal['a']", right operand type: "Literal[b'a']") | |
| b'a' in 'abc' # E: Non-overlapping container check (element type: "bytes", container item type: "str") | |
| x: str | |
| y: bytes | |
| x != y # E: Non-overlapping equality check (left operand type: "str", right operand type: "bytes") | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityOkPromote] | |
| # flags: --strict-equality | |
| from typing import Container | |
| c: Container[int] | |
| 1 == 1.0 # OK | |
| 1.0 in c # OK | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityAny] | |
| # flags: --strict-equality | |
| from typing import Any, Container | |
| x: Any | |
| c: Container[str] | |
| x in c | |
| x == 42 | |
| x is 42 | |
| [builtins fixtures/bool.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityStrictOptional] | |
| # flags: --strict-equality | |
| x: str | |
| if x is not None: # OK even with strict-optional | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityNoStrictOptional] | |
| # flags: --strict-equality --no-strict-optional | |
| x: str | |
| if x is not None: # OK without strict-optional | |
| pass | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityEqNoOptionalOverlap] | |
| # flags: --strict-equality | |
| from typing import Optional | |
| x: Optional[str] | |
| y: Optional[int] | |
| if x == y: # E: Non-overlapping equality check (left operand type: "str | None", right operand type: "int | None") | |
| ... | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqCheckStrictEquality] | |
| # flags: --strict-equality | |
| class A: | |
| def __eq__(self, other: A) -> bool: # type: ignore | |
| ... | |
| class B: | |
| def __eq__(self, other: B) -> bool: # type: ignore | |
| ... | |
| # Don't report non-overlapping check if there is already and error. | |
| A() == B() # E: Unsupported operand types for == ("A" and "B") | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualitySequenceAndCustomEq] | |
| # flags: --strict-equality | |
| from typing import Tuple | |
| class C: pass | |
| class D: | |
| def __eq__(self, other): return True | |
| a = [C()] | |
| b = [D()] | |
| a == b | |
| b == a | |
| t1: Tuple[C, ...] | |
| t2: Tuple[D, ...] | |
| t1 == t2 | |
| t2 == t1 | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqCheckStrictEqualityOKInstance] | |
| # flags: --strict-equality | |
| class A: | |
| def __eq__(self, other: object) -> bool: | |
| ... | |
| class B: | |
| def __eq__(self, other: object) -> bool: | |
| ... | |
| A() == int() # OK | |
| int() != B() # OK | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqCheckStrictEqualityOKUnion] | |
| # flags: --strict-equality | |
| from typing import Union | |
| class A: | |
| def __eq__(self, other: object) -> bool: | |
| ... | |
| x: Union[A, str] | |
| x == int() | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqCheckStrictEqualityTuple] | |
| # flags: --strict-equality | |
| from typing import NamedTuple | |
| class Base(NamedTuple): | |
| attr: int | |
| class Custom(Base): | |
| def __eq__(self, other: object) -> bool: ... | |
| Base(int()) == int() # E: Non-overlapping equality check (left operand type: "Base", right operand type: "int") | |
| Base(int()) == tuple() | |
| Custom(int()) == int() | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqCheckStrictEqualityMeta] | |
| # flags: --strict-equality | |
| class CustomMeta(type): | |
| def __eq__(self, other: object) -> bool: ... | |
| class Normal: ... | |
| class Custom(metaclass=CustomMeta): ... | |
| Normal == int() # E: Non-overlapping equality check (left operand type: "type[Normal]", right operand type: "int") | |
| Normal == Normal | |
| Custom == int() | |
| n: type[Normal] = Normal | |
| c: type[Custom] = Custom | |
| n == int() # E: Non-overlapping equality check (left operand type: "type[Normal]", right operand type: "int") | |
| n == n | |
| c == int() | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomContainsCheckStrictEquality] | |
| # flags: --strict-equality | |
| class A: | |
| def __contains__(self, other: A) -> bool: | |
| ... | |
| # Don't report non-overlapping check if there is already and error. | |
| 42 in A() # E: Unsupported operand types for in ("int" and "A") | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityTypeVsCallable] | |
| # flags: --strict-equality | |
| from typing import Type, List | |
| class C: ... | |
| class D(C): ... | |
| class Bad: ... | |
| subclasses: List[Type[C]] | |
| object in subclasses | |
| D in subclasses | |
| Bad in subclasses # E: Non-overlapping container check (element type: "type[Bad]", container item type: "type[C]") | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityMetaclass] | |
| # flags: --strict-equality | |
| from typing import List, Type, Any | |
| class Meta(type): ... | |
| class OtherMeta(type): ... | |
| class A(metaclass=Meta): ... | |
| class B(metaclass=Meta): ... | |
| class C(metaclass=OtherMeta): ... | |
| o: Type[object] | |
| a: Type[Any] | |
| aa: type | |
| exp: List[Meta] | |
| A in exp | |
| B in exp | |
| C in exp # E: Non-overlapping container check (element type: "type[C]", container item type: "Meta") | |
| o in exp | |
| a in exp | |
| aa in exp | |
| a in [A, B] | |
| aa in [A, B] | |
| class AA: ... | |
| class BB: ... | |
| a in [AA, BB] | |
| aa in [AA, BB] | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testEmptyListOverlap] | |
| # mypy: strict-equality | |
| from typing import List | |
| x: List[int] | |
| x == [] | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testCustomEqDecoratedStrictEquality] | |
| # flags: --strict-equality | |
| from typing import TypeVar, Callable, Any | |
| F = TypeVar('F', bound=Callable[..., Any]) | |
| def deco(f: F) -> F: ... | |
| class Custom: | |
| @deco | |
| def __eq__(self, other: object) -> bool: ... | |
| Custom() == int() | |
| [builtins fixtures/bool.pyi] | |
| [case testCustomEqVarStrictEquality] | |
| # flags: --strict-equality | |
| class Custom: | |
| def compare(self, other: object) -> bool: ... | |
| __eq__ = compare | |
| Custom() == int() | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityDisabledWithTypeVarRestrictions] | |
| # flags: --strict-equality | |
| from typing import TypeVar | |
| T = TypeVar('T', str, int) | |
| def f(x: T) -> T: | |
| if x == int(): # OK | |
| ... | |
| return x | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityWithALiteral] | |
| # flags: --strict-equality | |
| from typing import Final, Literal | |
| def returns_a_or_b() -> Literal['a', 'b']: | |
| ... | |
| def returns_1_or_2() -> Literal[1, 2]: | |
| ... | |
| THREE: Final = 3 | |
| if returns_a_or_b() == 'c': # E: Non-overlapping equality check (left operand type: "Literal['a', 'b']", right operand type: "Literal['c']") | |
| ... | |
| if returns_1_or_2() is THREE: # E: Non-overlapping identity check (left operand type: "Literal[1, 2]", right operand type: "Literal[3]") | |
| ... | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityWithALiteralNewType] | |
| # flags: --strict-equality | |
| from typing import NewType | |
| UserId = NewType('UserId', int) | |
| FileId = NewType('FileId', str) | |
| u: UserId | |
| f: FileId | |
| if u == 0: # OK | |
| ... | |
| if f == 0: # E: Non-overlapping equality check (left operand type: "FileId", right operand type: "Literal[0]") | |
| ... | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityWithFixedLengthTupleInCheck] | |
| # flags: --strict-equality | |
| if 1 in ('x', 'y'): # E: Non-overlapping container check (element type: "int", container item type: "str") | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityWithAnySentinel] | |
| # flags: --strict-equality | |
| from __future__ import annotations | |
| from typing import Any, cast | |
| class A: ... | |
| class B: ... | |
| sentinel: Any = object() | |
| def f1(a: A = sentinel, b: B = sentinel): | |
| if a is sentinel and b is sentinel: | |
| raise | |
| def f2(a: A | None = sentinel, b: B | None = sentinel): | |
| if a is sentinel and b is sentinel: | |
| raise | |
| sentinel_strict = object() | |
| def f3(a: A = sentinel_strict, b: B = sentinel_strict): # E: Incompatible default for parameter "a" (default has type "object", parameter has type "A") \ | |
| # E: Incompatible default for parameter "b" (default has type "object", parameter has type "B") | |
| if a is sentinel_strict and b is sentinel_strict: # E: Non-overlapping identity check (left operand type: "B", right operand type: "A") | |
| raise | |
| def f4(a: A | None = sentinel_strict, b: B | None = sentinel_strict): # E: Incompatible default for parameter "a" (default has type "object", parameter has type "A | None") \ | |
| # E: Incompatible default for parameter "b" (default has type "object", parameter has type "B | None") | |
| if a is sentinel_strict and b is sentinel_strict: # E: Non-overlapping identity check (left operand type: "B | None", right operand type: "A | None") | |
| raise | |
| sentinel_inferred = cast(Any, object()) | |
| def f5(a: A = sentinel_inferred, b: B = sentinel_inferred): | |
| if a is sentinel_inferred and b is sentinel_inferred: # E: Non-overlapping identity check (left operand type: "B", right operand type: "A") | |
| raise | |
| def f6(a: A | None = sentinel_inferred, b: B | None = sentinel_inferred): | |
| if a is sentinel_inferred and b is sentinel_inferred: # E: Non-overlapping identity check (left operand type: "B | None", right operand type: "A | None") | |
| raise | |
| [builtins fixtures/bool.pyi] | |
| [case testOverlappingAnyTypeWithoutStrictOptional] | |
| # flags: --no-strict-optional --strict-equality | |
| from typing import Any, Optional | |
| x: Optional[Any] | |
| if x in (1, 2): | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testOverlappingClassCallables] | |
| # flags: --strict-equality | |
| from typing import Any, Callable, Type | |
| x: Type[int] | |
| y: Callable[[], Any] | |
| x == y | |
| y == x | |
| int == y | |
| y == int | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityAndEnumWithCustomEq] | |
| # flags: --strict-equality | |
| from enum import Enum | |
| class E1(Enum): | |
| X = 0 | |
| Y = 1 | |
| class E2(Enum): | |
| X = 0 | |
| Y = 1 | |
| def __eq__(self, other: object) -> bool: | |
| return bool() | |
| E1.X == E1.Y # E: Non-overlapping equality check (left operand type: "Literal[E1.X]", right operand type: "Literal[E1.Y]") | |
| E2.X == E2.Y | |
| [builtins fixtures/bool.pyi] | |
| [case testStrictEqualityWithBytesContains] | |
| # flags: --strict-equality | |
| data = b"xy" | |
| b"x" in data | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityWithDifferentMapTypes] | |
| # flags: --strict-equality | |
| from typing import Mapping | |
| class A(Mapping[int, str]): ... | |
| class B(Mapping[int, str]): ... | |
| a: A | |
| b: B | |
| assert a == b | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityWithRecursiveMapTypes] | |
| # flags: --strict-equality | |
| from typing import Dict | |
| R = Dict[str, R] | |
| a: R | |
| b: R | |
| assert a == b | |
| R2 = Dict[int, R2] | |
| c: R2 | |
| assert a == c # E: Non-overlapping equality check (left operand type: "dict[str, R]", right operand type: "dict[int, R2]") | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityWithRecursiveListTypes] | |
| # flags: --strict-equality | |
| from typing import List, Union | |
| R = List[Union[str, R]] | |
| a: R | |
| b: R | |
| assert a == b | |
| R2 = List[Union[int, R2]] | |
| c: R2 | |
| assert a == c | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStrictEqualityForNone] | |
| # flags: --strict-equality --strict-equality-for-none | |
| class A: ... | |
| def a1(x: A) -> None: | |
| assert x is None # E: Non-overlapping identity check (left operand type: "A", right operand type: "None") | |
| def a2(x: A) -> None: | |
| x is not None # E: Non-overlapping identity check (left operand type: "A", right operand type: "None") | |
| def a3(x: A) -> None: | |
| None == x # E: Non-overlapping equality check (left operand type: "None", right operand type: "A") | |
| def a4(x: list[A]) -> None: | |
| None in x # E: Non-overlapping container check (element type: "None", container item type: "A") | |
| class B: | |
| def __eq__(self, x: object) -> bool: ... | |
| def b1(x: B) -> None: | |
| assert x is None # E: Non-overlapping identity check (left operand type: "B", right operand type: "None") | |
| def b2(x: B) -> None: | |
| x is not None # E: Non-overlapping identity check (left operand type: "B", right operand type: "None") | |
| def b3(x: B) -> None: | |
| x == None | |
| def b4(x: list[B]) -> None: | |
| None in x | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testUnimportedHintAny] | |
| def f(x: Any) -> None: # E: Name "Any" is not defined \ | |
| # N: Did you forget to import it from "typing"? (Suggestion: "from typing import Any") | |
| pass | |
| [case testUnimportedHintAnyLower] | |
| def f(x: any) -> None: # E: Name "any" is not defined \ | |
| # N: Did you forget to import it from "typing"? (Suggestion: "from typing import Any") | |
| pass | |
| [case testUnimportedHintOptional] | |
| def f(x: Optional[str]) -> None: # E: Name "Optional" is not defined \ | |
| # N: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional") | |
| pass | |
| [case testAssertionLazilyWithIsNone] | |
| from typing import Optional, List | |
| li: Optional[List] = [] | |
| assert li is None, li[0] | |
| [builtins fixtures/list.pyi] | |
| [case testAssertionLazilyWithIsInstance] | |
| from typing import Optional, List | |
| li: Optional[List] = [] | |
| assert not isinstance(li,list), li[0] | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testAssertCurrentFrameIsNotUnreachable] | |
| def f() -> int: # E: Missing return statement | |
| x: int | |
| assert isinstance(x, int), '...' | |
| [builtins fixtures/isinstance.pyi] | |
| [case testTypeVarAsValue] | |
| from typing import TypeVar | |
| T = TypeVar("T") | |
| x: int | |
| x + T # E: Unsupported left operand type for + ("int") | |
| T() # E: "TypeVar" not callable | |
| [builtins fixtures/tuple.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [case testStringDisallowedUnpacking] | |
| d: dict[str, str] | |
| for a1, b1 in d: # E: Unpacking a string is disallowed | |
| reveal_type(a1) # N: Revealed type is "builtins.str" | |
| reveal_type(b1) # N: Revealed type is "builtins.str" | |
| s = "foo" | |
| a2, b2 = s # E: Unpacking a string is disallowed | |
| reveal_type(a2) # N: Revealed type is "builtins.str" | |
| reveal_type(b2) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/primitives.pyi] | |
| [case testStringLiteralUnpacking] | |
| from typing import Literal, Final | |
| def takes_literal(xy: Literal["xy"]): | |
| x, y = xy | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| x, y, z = xy # E: Unpacking a string is disallowed | |
| reveal_type(z) # N: Revealed type is "builtins.str" | |
| def last_known_value() -> None: | |
| xy: Final = "xy" | |
| x, y = xy | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| x, y, z = xy # E: Unpacking a string is disallowed | |
| reveal_type(z) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/primitives.pyi] | |
| [case testOverloadUnexpectedKeywordArgWithTypoSuggestion] | |
| from typing import overload, Union | |
| @overload | |
| def f(foobar: int) -> None: ... | |
| @overload | |
| def f(foobar: str) -> None: ... | |
| def f(foobar: Union[int, str]) -> None: pass | |
| f(fobar=1) # E: Unexpected keyword argument "fobar" for overloaded function "f"; did you mean "foobar"? | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadUnexpectedKeywordArgNoMatch] | |
| from typing import overload, Union | |
| @overload | |
| def f(foobar: int) -> None: ... | |
| @overload | |
| def f(foobar: str) -> None: ... | |
| def f(foobar: Union[int, str]) -> None: pass | |
| f(random=[1,2,3]) # E: Unexpected keyword argument "random" for overloaded function "f" \ | |
| # E: No overload variant of "f" matches argument type "list[int]" \ | |
| # N: Possible overload variants: \ | |
| # N: def f(foobar: int) -> None \ | |
| # N: def f(foobar: str) -> None | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadMultipleUnexpectedKeywordArgs] | |
| from typing import overload, Union | |
| @overload | |
| def f(foobar: int) -> None: ... | |
| @overload | |
| def f(foobar: str) -> None: ... | |
| def f(foobar: Union[int, str]) -> None: pass | |
| f(fobar=1, baz=2) # E: Unexpected keyword argument "fobar" for overloaded function "f"; did you mean "foobar"? \ | |
| # E: Unexpected keyword argument "baz" for overloaded function "f" | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadManyUnexpectedKeywordArgs] | |
| from typing import overload, Union | |
| @overload | |
| def f(foobar: int) -> None: ... | |
| @overload | |
| def f(foobar: str) -> None: ... | |
| def f(foobar: Union[int, str]) -> None: pass | |
| f(foobar=1, a=2, b=3, c=4, d=5, e=6) # E: Unexpected keyword arguments "a", "b", "c", "d", "e" for overloaded function "f" \ | |
| # E: No overload variant of "f" matches argument types "int", "int", "int", "int", "int", "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def f(foobar: int) -> None \ | |
| # N: def f(foobar: str) -> None | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadUnexpectedKeywordArgsWithTypeMismatch] | |
| from typing import overload, Union | |
| @overload | |
| def f(foobar: int) -> None: ... | |
| @overload | |
| def f(foobar: str) -> None: ... | |
| def f(foobar: Union[int, str]) -> None: pass | |
| f(fobar=1, other=[1,2,3]) # E: Unexpected keyword argument "fobar" for overloaded function "f"; did you mean "foobar"? \ | |
| # E: Unexpected keyword argument "other" for overloaded function "f" \ | |
| # E: No overload variant of "f" matches argument types "int", "list[int]" \ | |
| # N: Possible overload variants: \ | |
| # N: def f(foobar: int) -> None \ | |
| # N: def f(foobar: str) -> None | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadPositionalArgTypeMismatch] | |
| from typing import overload, Union | |
| @overload | |
| def g(x: int, y: int) -> int: ... | |
| @overload | |
| def g(x: str, y: str) -> str: ... | |
| def g(x: Union[int, str], y: Union[int, str]) -> Union[int, str]: | |
| return x | |
| g([1, 2], 3) # E: No overload variant of "g" matches argument types "list[int]", "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def g(x: int, y: int) -> int \ | |
| # N: def g(x: str, y: str) -> str | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadUnexpectedKeywordWithPositionalMismatch] | |
| from typing import overload, Union | |
| @overload | |
| def g(x: int, y: int) -> int: ... | |
| @overload | |
| def g(x: str, y: str) -> str: ... | |
| def g(x: Union[int, str], y: Union[int, str]) -> Union[int, str]: | |
| return x | |
| g([1, 2], z=3) # E: Unexpected keyword argument "z" for overloaded function "g" \ | |
| # E: No overload variant of "g" matches argument types "list[int]", "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def g(x: int, y: int) -> int \ | |
| # N: def g(x: str, y: str) -> str | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadNamedArgTypeMismatch] | |
| from typing import overload, Union | |
| @overload | |
| def g(x: int, y: int) -> int: ... | |
| @overload | |
| def g(x: str, y: str) -> str: ... | |
| def g(x: Union[int, str], y: Union[int, str]) -> Union[int, str]: | |
| return x | |
| g(x="hello", y=1) # E: No overload variant of "g" matches argument types "str", "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def g(x: int, y: int) -> int \ | |
| # N: def g(x: str, y: str) -> str | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadMixedArgsWithNonFirstKeywordTypo] | |
| from typing import overload, Union | |
| @overload | |
| def f(x: int, name: int, value: int) -> None: ... | |
| @overload | |
| def f(x: str, name: str, value: str) -> None: ... | |
| def f(x: Union[int, str], name: Union[int, str], value: Union[int, str]) -> None: pass | |
| f(1, name=2, valeu=3) # E: Unexpected keyword argument "valeu" for overloaded function "f"; did you mean "value"? \ | |
| # E: No overload variant of "f" matches argument types "int", "int", "int" \ | |
| # N: Possible overload variants: \ | |
| # N: def f(x: int, name: int, value: int) -> None \ | |
| # N: def f(x: str, name: str, value: str) -> None | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadTwoMisspelledKeywordsDifferentTargets] | |
| from typing import overload, Union | |
| @overload | |
| def f(name: int, value: int) -> None: ... | |
| @overload | |
| def f(name: str, value: str) -> None: ... | |
| def f(name: Union[int, str], value: Union[int, str]) -> None: pass | |
| f(nme=1, valeu=2) # E: Unexpected keyword argument "nme" for overloaded function "f"; did you mean "name"? \ | |
| # E: Unexpected keyword argument "valeu" for overloaded function "f"; did you mean "value"? | |
| [builtins fixtures/list.pyi] | |
| [case testOverloadMethodKeywordTypo] | |
| from typing import overload, Union | |
| class A: | |
| @overload | |
| def f(self, foobar: int) -> None: ... | |
| @overload | |
| def f(self, foobar: str) -> None: ... | |
| def f(self, foobar: Union[int, str]) -> None: pass | |
| A().f(fobar=1) # E: Unexpected keyword argument "fobar" for overloaded function "f" of "A"; did you mean "foobar"? | |
| [builtins fixtures/list.pyi] |