| [case testForcedAssignment] |
| x = 1 # type: object |
| y = 1 |
| y = x # E: Incompatible types in assignment (expression has type "object", variable has type "int") |
| x = 2 |
| y = x |
| [case testJoinAny] |
| from typing import List, Any |
| |
| x = None # type: List[Any] |
| |
| def foo() -> List[int]: pass |
| def bar() -> List[str]: pass |
| |
| if bool(): |
| x = foo() |
| else: |
| x = bar() |
| |
| x * 2 |
| [builtins fixtures/list.pyi] |
| |
| [case testGeneratorExpressionTypes] |
| |
| class A: y = 1 |
| x = [A()] |
| y = [x] |
| |
| z = [1,2] |
| z = [a.y for b in y for a in b] |
| |
| [builtins fixtures/list.pyi] |
| |
| [case testClassAttributeInitialization-skip] |
| class A: |
| x = None # type: int |
| def __init__(self) -> None: |
| self.y = None # type: int |
| z = self.x |
| w = self.y |
| [case testAssignmentSubtypes-skip] |
| from typing import Union |
| |
| def foo(x: Union[str, int]): |
| if isinstance(x, int): |
| x = 'a' |
| x + 'a' # Works in the current code |
| z = x # We probably want this to be of type str. |
| y = [x] # But what type should this be? |
| y[0] + 'a' # (1) Should this work? |
| y + [1] # (2) Or this? |
| z = 1 # Also, is this valid? |
| |
| x = None # type: int |
| y = [x] |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testFunctionDefaultArgs] |
| |
| class A: pass |
| class B(A): y = 1 |
| |
| x = A() |
| |
| def foo(x: A = B()): |
| x.y # E: "A" has no attribute "y" |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceFancyConditionals] |
| |
| class A: pass |
| class B(A): y = 1 |
| |
| x = A() |
| |
| if isinstance(x, B): |
| x.y |
| |
| while isinstance(x, B): |
| x.y |
| |
| while isinstance(x, B): |
| x.y |
| x = B() |
| |
| [builtins fixtures/isinstance.pyi] |
| |
| |
| [case testSubtypingWithAny] |
| |
| class A: y = 1 |
| class B(A): z = 1 |
| |
| def foo(): pass |
| |
| x = A() |
| x = B() |
| x.z |
| x = foo() |
| x.z # E: "A" has no attribute "z" |
| x.y |
| |
| [case testSingleMultiAssignment-skip] |
| |
| x = 'a' |
| (x, ) = ('a',) |
| |
| [case testUnionMultiAssignment] |
| from typing import Union |
| |
| x = None # type: Union[int, str] |
| x = 1 |
| x = 'a' |
| x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x = 1 |
| (x, y) = ('a', 1) |
| x + 1 # E: Unsupported operand types for + ("str" and "int") |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testUnionIfZigzag] |
| from typing import Union |
| |
| def f(x: Union[int, str]) -> None: |
| x = 1 |
| if x: |
| x = 'a' |
| x = 1 |
| x + 1 |
| [builtins fixtures/isinstancelist.pyi] |
| |
| |
| [case testTwoLoopsUnion] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| def bar() -> None: |
| x = foo() |
| if isinstance(x, int): |
| return |
| while bool(): |
| x + 'a' |
| while bool(): |
| x = foo() |
| if bool(): |
| return |
| x = 'a' |
| x + 'a' |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testComplicatedBlocks] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| def bar() -> None: |
| x = foo() |
| if isinstance(x, int): |
| return |
| while bool(): |
| x + 'a' |
| while bool(): |
| x = foo() |
| if bool(): |
| return |
| x = 'a' |
| x + 'a' |
| |
| x = foo() |
| if isinstance(x, int): |
| return |
| while bool(): |
| x + 'a' |
| while bool(): |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| x = foo() |
| if bool(): |
| continue |
| x = 'a' |
| x = 'a' |
| x + 'a' |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testUnionTryExcept] |
| |
| class A: y = A() |
| class B(A): z = 1 |
| |
| x = A() |
| x = B() |
| x.z |
| try: |
| x.z |
| x = A() |
| x = B() |
| x.z |
| except: |
| pass |
| x.z # E: "A" has no attribute "z" |
| |
| |
| [case testUnionTryExcept2] |
| |
| class A: y = A() |
| class B(A): z = 1 |
| |
| x = A() |
| try: |
| x.z # E: "A" has no attribute "z" |
| x = A() |
| x = B() |
| x.z |
| except: |
| x.z # E: "A" has no attribute "z" |
| x = B() |
| x.z |
| else: |
| x = B() |
| x.z |
| |
| [case testUnionTryExcept3] |
| class A: y = A() |
| class B(A): z = 1 |
| x = A() |
| x = B() |
| try: |
| raise BaseException() |
| x = A() |
| except: |
| pass |
| x.z |
| x = B() |
| try: |
| x = A() |
| raise BaseException() |
| except: |
| pass |
| x.z # E: "A" has no attribute "z" |
| x = B() |
| try: |
| pass |
| except: |
| x = A() |
| raise BaseException() |
| x.z |
| try: |
| x = A() |
| except: |
| pass |
| x.z # E: "A" has no attribute "z" |
| x = B() |
| try: |
| pass |
| except: |
| x = A() |
| x.z # E: "A" has no attribute "z" |
| [builtins fixtures/exception.pyi] |
| [case testUnionTryExcept4] |
| |
| class A: pass |
| class B(A): z = 1 |
| |
| x = A() |
| while bool(): |
| try: |
| x.z # E: "A" has no attribute "z" |
| x = A() |
| except: |
| x = B() |
| else: |
| x = B() |
| x.z |
| [builtins fixtures/exception.pyi] |
| [case testUnionTryFinally] |
| class A: pass |
| class B(A): b = 1 |
| |
| x = A() |
| x = B() |
| try: |
| x = A() |
| x.b # E: "A" has no attribute "b" |
| x = B() |
| finally: |
| x.b # E: "A" has no attribute "b" |
| x.b |
| [case testUnionTryFinally2] |
| class A: pass |
| class B(A): b = 1 |
| |
| x = A() |
| x = B() |
| try: |
| x = A() |
| x = B() |
| except: |
| pass |
| finally: |
| pass |
| x.b # E: "A" has no attribute "b" |
| [case testUnionTryFinally3] |
| class A: pass |
| class B(A): b = 1 |
| |
| x = A() |
| x = B() |
| try: |
| x = A() |
| x = B() |
| except: |
| pass |
| finally: |
| x = B() |
| x.b |
| [case testUnionTryFinally4] |
| class A: pass |
| class B(A): b = 1 |
| |
| while 2: |
| x = A() |
| x = B() |
| try: |
| x = A() |
| x = B() |
| except: |
| pass |
| finally: |
| x.b # E: "A" has no attribute "b" |
| if not isinstance(x, B): |
| break |
| x.b |
| [builtins fixtures/isinstancelist.pyi] |
| [case testUnionTryFinally5] |
| class A: pass |
| class B(A): b = 1 |
| |
| while 2: |
| x = A() |
| try: |
| x = A() |
| x = B() |
| finally: |
| x.b # E: "A" has no attribute "b" |
| break |
| x.b |
| x.b |
| [case testUnionTryFinally6] |
| class A: pass |
| class B(A): b = 1 |
| |
| def f() -> int: |
| x = B() # type: A |
| try: |
| x = B() |
| except: |
| x = A() |
| # An exception could occur here |
| x = B() |
| finally: |
| return x.b # E: "A" has no attribute "b" |
| [out] |
| [case testUnionListIsinstance] |
| |
| from typing import Union, List |
| |
| class A: y = A() |
| class B(A): z = C() |
| |
| class C: pass |
| class D(C): d = 1 |
| |
| |
| def f(x: Union[List[int], List[str], int]) -> None: |
| if isinstance(x, list): |
| a = x[0] |
| if isinstance(a, int): |
| a + 1 |
| a + 'x' # E: Unsupported operand types for + ("int" and "str") |
| |
| # type of a? |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| else: |
| x[0] # E: Value of type "int" is not indexable |
| x + 1 |
| x[0] # E: Value of type "Union[List[int], List[str], int]" is not indexable |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testUnionListIsinstance2] |
| |
| from typing import Union, List |
| class A: a = 1 |
| class B: pass |
| class C: pass |
| |
| def g(x: Union[A, B]) -> A: pass |
| def h(x: C) -> A: pass |
| |
| def f(x: Union[A, B, C]) -> None: |
| if isinstance(x, C): |
| x = h(x) |
| else: |
| x = g(x) |
| x.a |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testUnionStrictDefnBasic] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x = 1 |
| x = x + 1 |
| x = foo() |
| x = x + 1 # E: Unsupported operand types for + (likely involving Union) |
| if isinstance(x, str): |
| x = x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x = 1 |
| x = x + 1 |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testSubtypeRedefinitionBasic] |
| from typing import Union |
| |
| class A: pass |
| class B(A): y = 1 |
| |
| x = A() |
| x.y # E: "A" has no attribute "y" |
| x = B() |
| x.y # OK: x is known to be a B |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceBasic] |
| from typing import Union |
| |
| x = None # type: Union[int, str] |
| |
| if isinstance(x, str): |
| x = x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x = x + 'a' |
| else: |
| x = x + 'a' # E: Unsupported operand types for + ("int" and "str") |
| x = x + 1 |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceIndexing] |
| from typing import Union |
| |
| x = None # type: Union[int, str] |
| j = [x] |
| |
| if isinstance(j[0], str): |
| j[0] = j[0] + 'a' |
| j[0] = j[0] + 1 # E: Unsupported operand types for + ("str" and "int") |
| else: |
| j[0] = j[0] + 'a' # E: Unsupported operand types for + ("int" and "str") |
| j[0] = j[0] + 1 |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceSubClassMember] |
| from typing import Union |
| |
| class Animal: |
| pass |
| |
| class Dog(Animal): |
| paws = 4 # type: Union[int, str] |
| |
| def bark(self): pass |
| |
| class House: |
| pet = None # type: Animal |
| |
| h = House() |
| h.pet = Dog() |
| |
| while bool(): |
| if isinstance(h.pet, Dog): |
| if isinstance(h.pet.paws, str): |
| x = h.pet.paws + 'a' |
| y = h.pet.paws + 1 # E: Unsupported operand types for + (likely involving Union) |
| z = h.pet.paws + 'a' # E: Unsupported operand types for + (likely involving Union) |
| if isinstance(h.pet.paws, str): |
| x = h.pet.paws + 'a' |
| break |
| y = h.pet.paws + 1 |
| z = h.pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str") |
| [builtins fixtures/isinstancelist.pyi] |
| [case testIsInstanceSubClassReset] |
| class A: pass |
| class B(A): b=1 |
| |
| class C: |
| a = A() |
| |
| x = C() |
| x.a.b # E: "A" has no attribute "b" |
| if isinstance(x.a, B): |
| x.a.b |
| x = C() |
| x.a.b # E: "A" has no attribute "b" |
| [builtins fixtures/isinstance.pyi] |
| [case testIsinstanceTuple] |
| from typing import Union |
| |
| class A: |
| pass |
| |
| class B: |
| def method2(self, arg: int): |
| return 123 |
| |
| class C: |
| def method2(self, arg: int): |
| return 456 |
| |
| def method3(self, arg: str): |
| return 'abc' |
| |
| v = A() # type: Union[A, B, C] |
| |
| if isinstance(v, (B, C)): |
| v.method2(123) |
| v.method3('xyz') # E: Some element of union has no attribute "method3" |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testMemberAssignmentChanges-skip] |
| from typing import Union |
| |
| class Dog: |
| paws = 1 # type: Union[int, str] |
| |
| pet = Dog() |
| |
| pet.paws + 'a' # E: moo |
| pet.paws = 'a' |
| pet.paws + 'a' |
| pet.paws = 1 |
| pet.paws + 1 |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceSubClassMemberHard-skip] |
| from typing import Union |
| |
| class Animal: |
| pass |
| |
| class Dog(Animal): |
| paws = 4 # type: Union[int, str] |
| |
| def bark(self): pass |
| |
| class House: |
| pet = None # type: Animal |
| |
| h = House() |
| h.pet = Dog() |
| |
| if isinstance(h.pet, Dog): |
| if isinstance(h.pet.paws, str): |
| for i in [1]: |
| h.pet.paws + 'a' |
| if bool(): |
| break |
| h.pet.paws = 1 |
| h.pet.paws + 1 |
| |
| if isinstance(h.pet.paws, str): |
| h.pet.paws + 'a' |
| else: |
| h.pet.paws + 1 |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceReturn] |
| from typing import Union |
| |
| def foo() -> None: |
| x = 1 # type: Union[int, str] |
| if isinstance(x, int): |
| return |
| y = x + 'asdad' |
| |
| def bar() -> None: |
| x = 1 # type: Union[int, str] |
| if isinstance(x, int): |
| return |
| else: |
| pass |
| y = x + 'asdad' |
| |
| foo() |
| [builtins fixtures/isinstancelist.pyi] |
| [case testIsInstanceBadBreak] |
| from typing import Union |
| |
| def foo() -> None: |
| x = None # type: Union[int, str] |
| if isinstance(x, int): |
| for z in [1,2]: |
| break |
| else: |
| pass |
| y = x + 'asdad' # E: Unsupported operand types for + (likely involving Union) |
| |
| foo() |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| [case testIsInstanceThreeUnion] |
| from typing import Union, List |
| |
| x = None # type: Union[int, str, List[int]] |
| |
| while bool(): |
| if isinstance(x, int): |
| x + 1 |
| elif isinstance(x, str): |
| x + 'a' |
| else: |
| x + [1] |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| x + [1] # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| [case testIsInstanceThreeUnion2] |
| from typing import Union, List |
| |
| x = None # type: Union[int, str, List[int]] |
| |
| while bool(): |
| if isinstance(x, int): |
| x + 1 |
| break |
| elif isinstance(x, str): |
| x + 'a' |
| break |
| x + [1] |
| x + 'a' # E: Unsupported operand types for + ("list" and "str") |
| x + [1] # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsInstanceThreeUnion3] |
| from typing import Union, List |
| |
| while bool(): |
| x = None # type: Union[int, str, List[int]] |
| x = 1 |
| if isinstance(x, int): |
| x + 1 |
| break |
| elif isinstance(x, str): |
| x + 'a' |
| break |
| x + [1] # These lines aren't reached because x was an int |
| x + 'a' |
| x + [1] # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testRemovingTypeRepeatedly] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| for i in [1, 2]: |
| x = foo() |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| if isinstance(x, int): |
| break |
| x + 'a' |
| |
| x = foo() |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| if isinstance(x, int): |
| break |
| x + 'a' |
| |
| x = foo() |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| if isinstance(x, int): |
| break |
| x + 'a' |
| |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| |
| |
| [case testModifyRepeatedly] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| |
| x = 1 |
| x + 1 |
| x + 'a' # E: Unsupported operand types for + ("int" and "str") |
| |
| x = 'a' |
| x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x + 'a' |
| |
| x = foo() |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x + 'a' # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testModifyLoop] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 'a' |
| x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x = 1 |
| x + 1 |
| |
| while bool(): |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 'a' |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testModifyLoop2] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 'a' |
| x + 1 # E: Unsupported operand types for + ("str" and "int") |
| x = 1 |
| x + 1 |
| |
| for i in [1]: |
| x = 'a' |
| |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| |
| [case testModifyLoop3] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x = 1 |
| |
| while bool(): |
| x + 1 |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 1 |
| for y in [1]: |
| x + 1 |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testModifyLoopWhile4] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x = 1 |
| |
| while bool(): |
| x + 1 |
| if bool(): |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x = 'a' |
| x + 'a' |
| x = 1 |
| while bool(): |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| if bool(): |
| x = 'a' |
| continue |
| else: |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 'a' |
| x + 'a' |
| [builtins fixtures/isinstancelist.pyi] |
| [case testModifyLoopFor4] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x = 1 |
| |
| for y in [1]: |
| x + 1 |
| if bool(): |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x = 'a' |
| x + 'a' |
| x = 1 |
| for y in [1]: |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| if bool(): |
| x = 'a' |
| continue |
| else: |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 'a' |
| x + 'a' |
| [builtins fixtures/isinstancelist.pyi] |
| [case testModifyNestedLoop] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| x = 1 |
| |
| for y in [1]: |
| for z in [1]: |
| break |
| else: |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| x = 1 |
| while bool(): |
| while bool(): |
| break |
| else: |
| x = 'a' |
| break |
| else: |
| x + 1 |
| x + 1 # E: Unsupported operand types for + (likely involving Union) |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testModifyLoopLong] |
| from typing import Union |
| |
| class A: a = 1 |
| |
| def foo() -> Union[int, str, A]: pass |
| |
| def bar() -> None: |
| x = foo() |
| x + 1 # E: Unsupported left operand type for + (some union) |
| if isinstance(x, A): |
| x.a |
| else: |
| if isinstance(x, int): |
| x + 1 |
| x + 'a' # E: Unsupported operand types for + ("int" and "str") |
| else: |
| x + 'a' |
| x.a # E: "str" has no attribute "a" |
| x = A() |
| |
| if isinstance(x, str): |
| x + 'a' |
| else: |
| while bool(): |
| if isinstance(x, int): |
| x + 1 |
| else: |
| x.a |
| break |
| while bool(): |
| if isinstance(x, int): |
| x + 1 |
| else: |
| x.a |
| continue |
| |
| #for i in [1]: |
| while bool(): |
| if isinstance(x, int): |
| x + 1 |
| else: |
| x.a # E: Some element of union has no attribute "a" |
| x = 'a' |
| |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testWhileExitCondition1] |
| from typing import Union |
| x = 1 # type: Union[int, str] |
| while isinstance(x, int): |
| if bool(): |
| continue |
| x = 'a' |
| else: |
| reveal_type(x) # E: Revealed type is 'builtins.str' |
| reveal_type(x) # E: Revealed type is 'builtins.str' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testWhileExitCondition2] |
| from typing import Union |
| x = 1 # type: Union[int, str] |
| while isinstance(x, int): |
| if bool(): |
| break |
| x = 'a' |
| else: |
| reveal_type(x) # E: Revealed type is 'builtins.str' |
| reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testWhileLinkedList] |
| from typing import Union |
| LinkedList = Union['Cons', 'Nil'] |
| class Nil: pass |
| class Cons: |
| tail = None # type: LinkedList |
| def last(x: LinkedList) -> Nil: |
| while isinstance(x, Cons): |
| x = x.tail |
| return x |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testReturnAndFlow] |
| def foo() -> int: |
| return 1 and 2 |
| return 'a' |
| [case testCastIsinstance] |
| from typing import Union |
| |
| def foo() -> Union[int, str]: pass |
| |
| x = foo() |
| y = 1 # type: int |
| |
| if isinstance(x, str): |
| x = y |
| x + 1 |
| x + 'a' # E: Unsupported operand types for + ("int" and "str") |
| |
| [builtins fixtures/isinstancelist.pyi] |
| |
| |
| [case testUnreachableCode] |
| x = 1 # type: int |
| |
| while bool(): |
| x = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| break |
| x = 'a' # Note: no error because unreachable code |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testUnreachableCode2] |
| x = 1 |
| while bool(): |
| try: |
| pass |
| except: |
| continue |
| else: |
| continue |
| x + 'a' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testUnreachableWhileTrue] |
| def f(x: int) -> None: |
| while True: |
| if x: |
| return |
| 1() |
| [builtins fixtures/bool.pyi] |
| |
| [case testUnreachableAssertFalse] |
| def f() -> None: |
| assert False |
| 1() |
| [builtins fixtures/bool.pyi] |
| |
| [case testUnreachableAssertFalse2] |
| # flags: --fast-parser |
| def f() -> None: |
| # The old parser doesn't understand the syntax below |
| assert False, "hi" |
| 1() |
| [builtins fixtures/bool.pyi] |
| |
| [case testUnreachableReturnOrAssertFalse] |
| def f(x: int) -> int: |
| if x: |
| return x |
| else: |
| assert False |
| 1() |
| [builtins fixtures/bool.pyi] |
| |
| [case testUnreachableTryExcept] |
| def f() -> None: |
| try: |
| f() |
| return |
| except BaseException: |
| return |
| 1() |
| [builtins fixtures/exception.pyi] |
| |
| [case testUnreachableTryExceptElse] |
| def f() -> None: |
| try: |
| f() |
| except BaseException: |
| return |
| else: |
| return |
| 1() |
| [builtins fixtures/exception.pyi] |
| |
| [case testUnreachableTryReturnFinally1] |
| def f() -> None: |
| try: |
| return |
| finally: |
| pass |
| 1() |
| |
| [case testUnreachableTryReturnFinally2] |
| def f() -> None: |
| try: |
| pass |
| finally: |
| return |
| 1() |
| |
| [case testUnreachableTryReturnExceptRaise] |
| def f() -> None: |
| try: |
| return |
| except: |
| raise |
| 1() |
| |
| [case testUnreachableReturnLambda] |
| from typing import Callable |
| def g(t: Callable[[int], int]) -> int: pass |
| def f() -> int: |
| return g(lambda x: x) |
| 1() |
| |
| [case testIsinstanceAnd] |
| class A: |
| pass |
| |
| class B(A): |
| flag = 1 |
| |
| x = B() # type: A |
| |
| if isinstance(x, B) and 1: |
| x.flag |
| [builtins fixtures/isinstancelist.pyi] |
| [case testIsinstanceShortcircuit] |
| class A: |
| pass |
| |
| class B(A): |
| flag = 1 |
| |
| x = B() # type: A |
| |
| if isinstance(x, B) and x.flag: |
| pass |
| if isinstance(x, B) or x.flag: # E: "A" has no attribute "flag" |
| pass |
| if not isinstance(x, B) or x.flag: |
| pass |
| if not isinstance(x, B) and x.flag: # E: "A" has no attribute "flag" |
| pass |
| [builtins fixtures/isinstancelist.pyi] |
| [case testIsinstanceExpression] |
| class A: |
| pass |
| |
| class B(A): |
| flag = 1 |
| |
| x = B() # type: A |
| |
| x.flag if isinstance(x, B) else 0 |
| 0 if not isinstance(x, B) else x.flag |
| 0 if isinstance(x, B) else x.flag # E: "A" has no attribute "flag" |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsinstanceMultiAnd] |
| class A: |
| pass |
| |
| class B(A): |
| flag = 1 |
| |
| class C(A): |
| glaf = 1 |
| |
| x = B() # type: A |
| y = C() # type: A |
| |
| if isinstance(x, B) and isinstance(y, C): |
| x.flag += 1 |
| y.glaf += 1 |
| x() # E: "B" not callable |
| y() # E: "C" not callable |
| else: |
| x() # E: "A" not callable |
| y() # E: "A" not callable |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsinstanceMultiAndSpecialCase] |
| class A: |
| pass |
| |
| class B(A): |
| flag = 1 |
| |
| class C(A): |
| glaf = 1 |
| |
| x = B() # type: A |
| y = C() # type: A |
| |
| if isinstance(x, B) and isinstance(y, int): |
| 1() # type checking skipped |
| if isinstance(y, int) and isinstance(x, B): |
| 1() # type checking skipped |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testReturnWithCallExprAndIsinstance] |
| |
| from typing import Union |
| def f(x: Union[int, str]) -> None: |
| if not isinstance(x, int): |
| return foo() |
| x() # E: "int" not callable |
| def foo(): pass |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| |
| [case testIsinstanceOr1] |
| from typing import Optional |
| def f(a: bool, x: object) -> Optional[int]: |
| if a or not isinstance(x, int): |
| return None |
| reveal_type(x) # E: Revealed type is 'builtins.int' |
| return x |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceOr2] |
| from typing import Optional |
| def g(a: bool, x: object) -> Optional[int]: |
| if not isinstance(x, int) or a: |
| return None |
| reveal_type(x) # E: Revealed type is 'builtins.int' |
| return x |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceOr3] |
| from typing import Optional |
| def h(a: bool, x: object) -> Optional[int]: |
| if a or isinstance(x, int): |
| return None |
| return x # E: Incompatible return value type (got "object", expected "int") |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceWithOverlappingUnionType] |
| from typing import Union |
| def f(x: Union[float, int]) -> None: |
| if isinstance(x, float): |
| pass |
| if not isinstance(x, int): |
| f(x) |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testIsinstanceWithOverlappingUnionType2] |
| from typing import Union |
| class A: pass |
| class B(A): pass |
| def f(x: Union[A, B]) -> None: |
| if isinstance(x, A): |
| pass |
| if not isinstance(x, B): |
| f(x) |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testIsinstanceOfSuperclass] |
| class A: pass |
| class B(A): pass |
| x = B() |
| if isinstance(x, A): |
| reveal_type(x) # E: Revealed type is '__main__.B' |
| if not isinstance(x, A): |
| reveal_type(x) # unreachable |
| x = A() |
| reveal_type(x) # E: Revealed type is '__main__.B' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testIsinstanceOfNonoverlapping] |
| class A: pass |
| class B: pass |
| x = B() |
| if isinstance(x, A): |
| reveal_type(x) # unreachable |
| else: |
| reveal_type(x) # E: Revealed type is '__main__.B' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testAssertIsinstance] |
| def f(x: object): |
| assert isinstance(x, int) |
| y = 0 # type: int |
| y = x |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testUnionAssertIsinstance] |
| from typing import Union |
| def f(x: Union[str, int]): |
| assert isinstance(x, int) |
| y = 0 # type: int |
| y = x |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testAnyAssertIsinstance] |
| from typing import Any |
| def f(x: Any): |
| assert isinstance(x, int) # this should narrow x to type int |
| x + "foo" # E: Unsupported operand types for + ("int" and "str") |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceOfGenericClassRetainsParameters] |
| from typing import List, Union |
| def f(x: Union[List[int], str]) -> None: |
| if isinstance(x, list): |
| x[0]() |
| [builtins fixtures/isinstancelist.pyi] |
| [out] |
| main:4: error: "int" not callable |
| |
| [case testIsinstanceOrIsinstance] |
| class A: pass |
| class B(A): |
| flag = 1 |
| class C(A): |
| flag = 2 |
| x1 = A() |
| if isinstance(x1, B) or isinstance(x1, C): |
| reveal_type(x1) # E: Revealed type is 'Union[__main__.B, __main__.C]' |
| f = x1.flag # type: int |
| else: |
| reveal_type(x1) # E: Revealed type is '__main__.A' |
| f = 0 |
| x2 = A() |
| if isinstance(x2, A) or isinstance(x2, C): |
| reveal_type(x2) # E: Revealed type is '__main__.A' |
| f = x2.flag # E: "A" has no attribute "flag" |
| else: |
| # unreachable |
| 1() |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| [case testComprehensionIsInstance] |
| from typing import List, Union |
| a = [] # type: List[Union[int, str]] |
| l = [x for x in a if isinstance(x, int)] |
| g = (x for x in a if isinstance(x, int)) |
| d = {0: x for x in a if isinstance(x, int)} |
| reveal_type(l) # E: Revealed type is 'builtins.list[builtins.int*]' |
| reveal_type(g) # E: Revealed type is 'typing.Iterator[builtins.int*]' |
| reveal_type(d) # E: Revealed type is 'builtins.dict[builtins.int*, builtins.int*]' |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testIsinstanceInWrongOrderInBooleanOp] |
| class A: |
| m = 1 |
| def f(x: object) -> None: |
| if x.m and isinstance(x, A) or False: # E: "object" has no attribute "m" |
| pass |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceAndOr] |
| class A: |
| a = None # type: A |
| |
| def f(x: object) -> None: |
| b = isinstance(x, A) and x.a or A() |
| reveal_type(b) # E: Revealed type is '__main__.A' |
| [builtins fixtures/isinstance.pyi] |
| [out] |