blob: 361d4db78752e05e5c1e36af0059c8788954c96f [file] [log] [blame] [edit]
[case testForcedAssignment]
x = 1 # type: object
y = 1
def f(): x, y # Prevent independent redefinition
y = x # E: Incompatible types in assignment (expression has type "object", variable has type "int")
x = 2
y = x
[builtins fixtures/tuple.pyi]
[case testJoinAny]
from typing import List, Any
x: 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 testIsinstanceNestedTuple]
from typing import Union, List, Tuple, Dict
def f(x: Union[int, str, List]) -> None:
if isinstance(x, (str, (int,))):
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
x[1] # E: Value of type "Union[int, str]" is not indexable
else:
reveal_type(x) # N: Revealed type is "builtins.list[Any]"
x[1]
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
if isinstance(x, (str, (list,))):
reveal_type(x) # N: Revealed type is "Union[builtins.str, builtins.list[Any]]"
x[1]
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
[builtins fixtures/isinstancelist.pyi]
[case testClassAttributeInitialization]
class A:
x: int
def __init__(self) -> None:
self.y: int
z = self.x
w = self.y
[case testAssignmentSubtypes]
from typing import Union
def foo(x: Union[str, int]):
if isinstance(x, int):
x = 'a'
x + 'a'
z = x
y = [x]
y[0] + 'a'
# TODO: should we allow these two lines?
y + [1] # E: List item 0 has incompatible type "int"; expected "str"
z = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str")
x: int
y = [x]
[builtins fixtures/isinstancelist.pyi]
[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]
[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()
if int():
x = B()
x.z
x = foo()
x.z # E: "A" has no attribute "z"
x.y
[case testSingleMultiAssignment]
x = 'a'
(x,) = ('a',)
[case testUnionMultiAssignment]
from typing import Union
x: Union[int, str]
if int():
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:
if 1: # Without this, the assignment below could create a new variable "x" of type "int"
x = 1
if x:
x = 'a'
x = 1
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 + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
x = foo()
if bool():
continue
x = 'a'
x = 'a'
x + 'a'
[builtins fixtures/isinstancelist.pyi]
[case testUnionTryExcept]
class A:
y = A()
class B(A):
z = 1
x = A()
def f(): x # Prevent redefinition of x
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()
def f(): x # Prevent redefinition of x
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()
def f(): x # Prevent redefinition
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()
def f(): x # Prevent redefinition
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()
def f(): x # Prevent redefinition
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()
def f(): x # Prevents redefinition
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"
[case testUnionListIsinstance]
from typing import Union, List
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?
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]"
x + 1 # E: Unsupported operand types for + ("List[int]" and "int") \
# E: Unsupported operand types for + ("List[str]" and "int") \
# N: Left operand is of type "Union[List[int], List[str]]"
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 + ("List[int]" and "int") \
# E: Unsupported operand types for + ("List[str]" and "int") \
# N: Left operand is of type "Union[List[int], List[str], int]"
[builtins fixtures/isinstancelist.pyi]
[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()
if int():
x = 1
x = x + 1
x = foo()
x = x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
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: 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: 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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
z = h.pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
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: Item "B" of "Union[B, C]" has no attribute "method3"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceNeverWidens]
from typing import Union
class A: pass
class B: pass
class C: pass
a = A() # type: A
assert isinstance(a, (A, B))
reveal_type(a) # N: Revealed type is "__main__.A"
b = A() # type: Union[A, B]
assert isinstance(b, (A, B, C))
reveal_type(b) # N: Revealed type is "Union[__main__.A, __main__.B]"
[builtins fixtures/isinstance.pyi]
[case testMemberAssignmentChanges]
from typing import Union
class Dog:
paws = 1 # type: Union[int, str]
pet = Dog()
pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
pet.paws = 'a'
pet.paws + 'a'
pet.paws = 1
pet.paws + 1
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceSubClassMemberHard]
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]:
# TODO: should we allow this if iterable is of length one or zero?
h.pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
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: Union[int, str]
if isinstance(x, int):
for z in [1,2]:
break
else:
pass
y = x + 'asdad' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
foo()
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceThreeUnion]
from typing import Union, List
x: 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 + ("int" and "str") \
# E: Unsupported operand types for + ("List[int]" and "str") \
# N: Left operand is of type "Union[int, str, List[int]]"
x + [1] # E: Unsupported operand types for + ("int" and "List[int]") \
# E: Unsupported operand types for + ("str" and "List[int]") \
# N: Left operand is of type "Union[int, str, List[int]]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceThreeUnion2]
from typing import Union, List
x: 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[int]" and "str")
x + [1] # E: Unsupported operand types for + ("int" and "List[int]") \
# E: Unsupported operand types for + ("str" and "List[int]") \
# N: Left operand is of type "Union[int, str, List[int]]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceThreeUnion3]
from typing import Union, List
while bool():
x: Union[int, str, List[int]]
def f(): x # Prevent redefinition
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 + ("int" and "List[int]") \
# E: Unsupported operand types for + ("str" and "List[int]") \
# N: Left operand is of type "Union[int, str, List[int]]"
[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 + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
if isinstance(x, int):
break
x + 'a'
x = foo()
x + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
if isinstance(x, int):
break
x + 'a'
x = foo()
x + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
if isinstance(x, int):
break
x + 'a'
x + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]
[case testModifyRepeatedly]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x + 'a' # E: Unsupported operand types for + ("int" and "str") \
# N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]
[case testModifyLoop]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x = 'a'
[builtins fixtures/isinstancelist.pyi]
[case testModifyLoop2]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]
[case testModifyLoop3]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
x = 1
while bool():
x + 1
x = 'a'
break
else:
x + 1
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x = 1
for y in [1]:
x + 1
x = 'a'
break
else:
x + 1
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]
[case testModifyLoopWhile4]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
if bool():
x = 'a'
continue
else:
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x = 'a'
x + 'a'
[builtins fixtures/isinstancelist.pyi]
[case testModifyLoopFor4]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
if bool():
x = 'a'
continue
else:
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x = 'a'
x + 'a'
[builtins fixtures/isinstancelist.pyi]
[case testModifyNestedLoop]
from typing import Union
def foo() -> Union[int, str]: pass
x = foo()
def f(): x # Prevent redefinition
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 + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
x = 1
while bool():
while bool():
break
else:
x = 'a'
break
else:
x + 1
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
[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 + ("A") \
# N: Left operand is of type "Union[int, str, A]" \
# E: Unsupported operand types for + ("str" and "int")
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
while bool():
if isinstance(x, int):
x + 1
else:
x.a # E: Item "str" of "Union[str, A]" has no attribute "a"
x = 'a'
[builtins fixtures/isinstancelist.pyi]
[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) # N: Revealed type is "builtins.str"
reveal_type(x) # N: 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) # N: Revealed type is "builtins.str"
reveal_type(x) # N: 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]
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:
# Ensure A.__add__ and int.__add__ are different to
# force 'isinstance(y, int)' checks below to never succeed.
def __add__(self, other: A) -> 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
if isinstance(y, int) and y > 42:
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]
[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) # N: Revealed type is "builtins.int"
return x
[builtins fixtures/isinstance.pyi]
[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) # N: Revealed type is "builtins.int"
return x
[builtins fixtures/isinstance.pyi]
[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 "Optional[int]")
[builtins fixtures/isinstance.pyi]
[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 testIsinstanceWithOverlappingPromotionTypes]
from typing import Union
class FloatLike: pass
class IntLike(FloatLike): pass
def f1(x: Union[float, int]) -> None:
# We ignore promotions in isinstance checks
if isinstance(x, float):
reveal_type(x) # N: Revealed type is "builtins.float"
else:
reveal_type(x) # N: Revealed type is "builtins.int"
def f2(x: Union[FloatLike, IntLike]) -> None:
# ...but not regular subtyping relationships
if isinstance(x, FloatLike):
reveal_type(x) # N: Revealed type is "Union[__main__.FloatLike, __main__.IntLike]"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceOfSuperclass]
class A: pass
class B(A): pass
x = B()
if isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.B"
if not isinstance(x, A):
reveal_type(x) # unreachable
x = A()
reveal_type(x) # N: 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) # N: Revealed type is "__main__.<subclass of "B" and "A">"
else:
reveal_type(x) # N: Revealed type is "__main__.B"
reveal_type(x) # N: 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]
[case testIsinstanceOfGenericClassRetainsParameters]
from typing import List, Union
def f(x: Union[List[int], str]) -> None:
if isinstance(x, list):
x[0]() # E: "int" not callable
else:
reveal_type(x) # N: Revealed type is "builtins.str"
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.str]"
[builtins fixtures/isinstancelist.pyi]
[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) # N: Revealed type is "Union[__main__.B, __main__.C]"
f = x1.flag # type: int
else:
reveal_type(x1) # N: Revealed type is "__main__.A"
f = 0
reveal_type(x1) # N: Revealed type is "__main__.A"
x2 = A()
if isinstance(x2, A) or isinstance(x2, C):
reveal_type(x2) # N: Revealed type is "__main__.A"
f = x2.flag # E: "A" has no attribute "flag"
else:
# unreachable
1()
reveal_type(x2) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[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) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type(g) # N: Revealed type is "typing.Generator[builtins.int, None, None]"
reveal_type(d) # N: 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]
[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) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceWithUnknownType]
from typing import Union
def f(x: Union[int, str], typ: type) -> None:
if isinstance(x, (typ, int)):
x + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithBoundedType]
from typing import Union, Type
class A: pass
def f(x: Union[int, A], a: Type[A]) -> None:
if isinstance(x, (a, int)):
reveal_type(x) # N: Revealed type is "Union[builtins.int, __main__.A]"
else:
reveal_type(x) # N: Revealed type is "__main__.A"
reveal_type(x) # N: Revealed type is "Union[builtins.int, __main__.A]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithEmtpy2ndArg]
from typing import Union
def f(x: Union[int, str]) -> None:
if isinstance(x, ()):
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
else:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithTypeObject]
from typing import Union, Type
class A: pass
def f(x: Union[int, A], a: Type[A]) -> None:
if isinstance(x, a):
reveal_type(x) # N: Revealed type is "__main__.A"
elif isinstance(x, int):
reveal_type(x) # N: Revealed type is "builtins.int"
else:
reveal_type(x) # N: Revealed type is "__main__.A"
reveal_type(x) # N: Revealed type is "Union[builtins.int, __main__.A]"
[builtins fixtures/isinstancelist.pyi]
[case testIssubclassUnreachable]
from typing import Type, Sequence, Union
x: Type[str]
if issubclass(x, int):
reveal_type(x) # unreachable block
class X: pass
class Y(X): pass
class Z(X): pass
a: Union[Type[Y], Type[Z]]
if issubclass(a, X):
reveal_type(a) # N: Revealed type is "Union[Type[__main__.Y], Type[__main__.Z]]"
else:
reveal_type(a) # unreachable block
[builtins fixtures/isinstancelist.pyi]
[case testIssubclasDestructuringUnions1]
from typing import Union, List, Tuple, Dict, Type
def f(x: Union[Type[int], Type[str], Type[List]]) -> None:
if issubclass(x, (str, (int,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str]"
x()[1] # E: Value of type "Union[int, str]" is not indexable
else:
reveal_type(x) # N: Revealed type is "Type[builtins.list[Any]]"
reveal_type(x()) # N: Revealed type is "builtins.list[Any]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
if issubclass(x, (str, (list,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.str, builtins.list[Any]]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
[builtins fixtures/isinstancelist.pyi]
[case testIssubclasDestructuringUnions2]
from typing import Union, List, Tuple, Dict, Type
def f(x: Type[Union[int, str, List]]) -> None:
if issubclass(x, (str, (int,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str]"
x()[1] # E: Value of type "Union[int, str]" is not indexable
else:
reveal_type(x) # N: Revealed type is "Type[builtins.list[Any]]"
reveal_type(x()) # N: Revealed type is "builtins.list[Any]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
if issubclass(x, (str, (list,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.str, builtins.list[Any]]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
[builtins fixtures/isinstancelist.pyi]
[case testIssubclasDestructuringUnions3]
from typing import Union, List, Tuple, Dict, Type
def f(x: Type[Union[int, str, List]]) -> None:
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
if issubclass(x, (str, (int,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str]"
x()[1] # E: Value of type "Union[int, str]" is not indexable
else:
reveal_type(x) # N: Revealed type is "Type[builtins.list[Any]]"
reveal_type(x()) # N: Revealed type is "builtins.list[Any]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
if issubclass(x, (str, (list,))):
reveal_type(x) # N: Revealed type is "Union[Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.str, builtins.list[Any]]"
x()[1]
reveal_type(x) # N: Revealed type is "Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]"
reveal_type(x()) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.list[Any]]"
[builtins fixtures/isinstancelist.pyi]
[case testIssubclass]
from typing import Type, ClassVar
class Goblin:
level: int
class GoblinAmbusher(Goblin):
job: ClassVar[str] = 'Ranger'
def test_issubclass(cls: Type[Goblin]) -> None:
if issubclass(cls, GoblinAmbusher):
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.level
cls.job
ga = cls()
ga.level = 15
ga.job
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
else:
reveal_type(cls) # N: Revealed type is "Type[__main__.Goblin]"
cls.level
cls.job # E: "Type[Goblin]" has no attribute "job"
g = cls()
g.level = 15
g.job # E: "Goblin" has no attribute "job"
[builtins fixtures/isinstancelist.pyi]
[case testIssubclassDeepHierarchy]
from typing import Type, ClassVar
class Mob: pass
class Goblin(Mob):
level: int
class GoblinAmbusher(Goblin):
job: ClassVar[str] = 'Ranger'
def test_issubclass(cls: Type[Mob]) -> None:
if issubclass(cls, Goblin):
reveal_type(cls) # N: Revealed type is "Type[__main__.Goblin]"
cls.level
cls.job # E: "Type[Goblin]" has no attribute "job"
g = cls()
g.level = 15
g.job # E: "Goblin" has no attribute "job"
if issubclass(cls, GoblinAmbusher):
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.level
cls.job
g = cls()
g.level = 15
g.job
g.job = 'Warrior' # E: Cannot assign to class variable "job" via instance
else:
reveal_type(cls) # N: Revealed type is "Type[__main__.Mob]"
cls.job # E: "Type[Mob]" has no attribute "job"
cls.level # E: "Type[Mob]" has no attribute "level"
m = cls()
m.level = 15 # E: "Mob" has no attribute "level"
m.job # E: "Mob" has no attribute "job"
if issubclass(cls, GoblinAmbusher):
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.job
cls.level
ga = cls()
ga.level = 15
ga.job
ga.job = 'Warrior' # E: Cannot assign to class variable "job" via instance
if issubclass(cls, GoblinAmbusher):
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.level
cls.job
ga = cls()
ga.level = 15
ga.job
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
[builtins fixtures/isinstancelist.pyi]
[case testIssubclassTuple]
from typing import Type, ClassVar
class Mob: pass
class Goblin(Mob):
level: int
class GoblinAmbusher(Goblin):
job: ClassVar[str] = 'Ranger'
class GoblinDigger(Goblin):
job: ClassVar[str] = 'Thief'
def test_issubclass(cls: Type[Mob]) -> None:
if issubclass(cls, (Goblin, GoblinAmbusher)):
reveal_type(cls) # N: Revealed type is "Type[__main__.Goblin]"
cls.level
cls.job # E: "Type[Goblin]" has no attribute "job"
g = cls()
g.level = 15
g.job # E: "Goblin" has no attribute "job"
if issubclass(cls, GoblinAmbusher):
cls.level
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.job
ga = cls()
ga.level = 15
ga.job
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
else:
reveal_type(cls) # N: Revealed type is "Type[__main__.Mob]"
cls.job # E: "Type[Mob]" has no attribute "job"
cls.level # E: "Type[Mob]" has no attribute "level"
m = cls()
m.level = 15 # E: "Mob" has no attribute "level"
m.job # E: "Mob" has no attribute "job"
if issubclass(cls, GoblinAmbusher):
reveal_type(cls) # N: Revealed type is "Type[__main__.GoblinAmbusher]"
cls.job
cls.level
ga = cls()
ga.level = 15
ga.job
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
if issubclass(cls, (GoblinDigger, GoblinAmbusher)):
reveal_type(cls) # N: Revealed type is "Union[Type[__main__.GoblinDigger], Type[__main__.GoblinAmbusher]]"
cls.level
cls.job
g = cls()
g.level = 15
g.job
g.job = "Warrior" # E: Cannot assign to class variable "job" via instance
[builtins fixtures/isinstancelist.pyi]
[case testIssubclassBuiltins]
from typing import List, Type
class MyList(List): pass
class MyIntList(List[int]): pass
def f(cls: Type[object]) -> None:
if issubclass(cls, MyList):
reveal_type(cls) # N: Revealed type is "Type[__main__.MyList]"
cls()[0]
else:
reveal_type(cls) # N: Revealed type is "Type[builtins.object]"
cls()[0] # E: Value of type "object" is not indexable
if issubclass(cls, MyIntList):
reveal_type(cls) # N: Revealed type is "Type[__main__.MyIntList]"
cls()[0] + 1
[builtins fixtures/isinstancelist.pyi]
[case testIsinstanceTypeArgs]
from typing import Iterable, TypeVar
x = 1
isinstance(x, Iterable)
isinstance(x, Iterable[int]) # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, (int, Iterable[int])) # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, (int, (str, Iterable[int]))) # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstancelist.pyi]
[typing fixtures/typing-full.pyi]
[case testIsinstanceAnyAlias]
from typing import Any
A = Any
isinstance(object(), A) # E: Cannot use isinstance() with Any type
[builtins fixtures/isinstance.pyi]
[case testIsinstanceTypeArgsAliases]
from typing import Iterable, TypeVar
x = 1
T = TypeVar('T')
It = Iterable
It2 = Iterable[T]
isinstance(x, It[int]) # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, It)
isinstance(x, It2[int]) # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, It2) # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.pyi]
[case testIssubclassTypeArgs]
from typing import Iterable, TypeVar
x = int
issubclass(x, Iterable)
issubclass(x, Iterable[int]) # E: Parameterized generics cannot be used with class or instance checks
issubclass(x, (int, Iterable[int])) # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.pyi]
[case testIssubclassWithMetaclasses]
# flags: --no-strict-optional
class FooMetaclass(type): ...
class Foo(metaclass=FooMetaclass): ...
class Bar: ...
fm: FooMetaclass
reveal_type(fm) # N: Revealed type is "__main__.FooMetaclass"
if issubclass(fm, Foo):
reveal_type(fm) # N: Revealed type is "Type[__main__.Foo]"
if issubclass(fm, Bar):
reveal_type(fm) # N: Revealed type is "None"
[builtins fixtures/isinstance.pyi]
[case testIssubclassWithMetaclassesStrictOptional]
class FooMetaclass(type): ...
class BarMetaclass(type): ...
class Foo(metaclass=FooMetaclass): ...
class Bar(metaclass=BarMetaclass): ...
class Baz: ...
fm: FooMetaclass
reveal_type(fm) # N: Revealed type is "__main__.FooMetaclass"
if issubclass(fm, Foo):
reveal_type(fm) # N: Revealed type is "Type[__main__.Foo]"
if issubclass(fm, Bar):
reveal_type(fm) # N: Revealed type is "<nothing>"
if issubclass(fm, Baz):
reveal_type(fm) # N: Revealed type is "<nothing>"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceAndNarrowTypeVariable]
from typing import TypeVar
class A: pass
class B(A): pass
T = TypeVar('T', bound=A)
def f(x: T) -> None:
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.B"
else:
reveal_type(x) # N: Revealed type is "T`-1"
reveal_type(x) # N: Revealed type is "T`-1"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceAndTypeType]
from typing import Type
def f(x: Type[int]) -> None:
if isinstance(x, type):
reveal_type(x) # N: Revealed type is "Type[builtins.int]"
else:
reveal_type(x) # Unreachable
reveal_type(x) # N: Revealed type is "Type[builtins.int]"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceVariableSubstitution]
T = (int, str)
U = (list, T)
x: object = None
if isinstance(x, T):
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
if isinstance(x, U):
reveal_type(x) # N: Revealed type is "Union[builtins.list[Any], builtins.int, builtins.str]"
if isinstance(x, (set, (list, T))):
reveal_type(x) # N: Revealed type is "Union[builtins.set[Any], builtins.list[Any], builtins.int, builtins.str]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceTooFewArgs]
isinstance() # E: Missing positional arguments "x", "t" in call to "isinstance"
x: object
if isinstance(): # E: Missing positional arguments "x", "t" in call to "isinstance"
x = 1
reveal_type(x) # N: Revealed type is "builtins.int"
if isinstance(x): # E: Missing positional argument "t" in call to "isinstance"
x = 1
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/isinstancelist.pyi]
[case testIsSubclassTooFewArgs]
from typing import Type
issubclass() # E: Missing positional arguments "x", "t" in call to "issubclass"
y: Type[object]
if issubclass(): # E: Missing positional arguments "x", "t" in call to "issubclass"
reveal_type(y) # N: Revealed type is "Type[builtins.object]"
if issubclass(y): # E: Missing positional argument "t" in call to "issubclass"
reveal_type(y) # N: Revealed type is "Type[builtins.object]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceTooManyArgs]
isinstance(1, 1, 1) # E: Too many arguments for "isinstance" \
# E: Argument 2 to "isinstance" has incompatible type "int"; expected "Union[type, Tuple[Any, ...]]"
x: object
if isinstance(x, str, 1): # E: Too many arguments for "isinstance"
reveal_type(x) # N: Revealed type is "builtins.object"
x = 1
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/isinstancelist.pyi]
[case testIsinstanceNarrowAny]
from typing import Any
def narrow_any_to_str_then_reassign_to_int() -> None:
v = 1 # type: Any
if isinstance(v, str):
reveal_type(v) # N: Revealed type is "builtins.str"
v = 2
reveal_type(v) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testNarrowTypeAfterInList]
from typing import List, Optional
x: List[int]
y: Optional[int]
if y in x:
reveal_type(y) # N: Revealed type is "builtins.int"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
if y not in x:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "builtins.int"
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInListOfOptional]
from typing import List, Optional
x: List[Optional[int]]
y: Optional[int]
if y not in x:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInListNonOverlapping]
from typing import List, Optional
x: List[str]
y: Optional[int]
if y in x:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInListNested]
from typing import List, Optional, Any
x: Optional[int]
lst: Optional[List[int]]
nested_any: List[List[Any]]
if lst in nested_any:
reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int]"
if x in nested_any:
reveal_type(x) # N: Revealed type is "Union[builtins.int, None]"
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInTuple]
from typing import Optional
class A: pass
class B(A): pass
class C(A): pass
y: Optional[B]
if y in (B(), C()):
reveal_type(y) # N: Revealed type is "__main__.B"
else:
reveal_type(y) # N: Revealed type is "Union[__main__.B, None]"
[builtins fixtures/tuple.pyi]
[out]
[case testNarrowTypeAfterInNamedTuple]
from typing import NamedTuple, Optional
class NT(NamedTuple):
x: int
y: int
nt: NT
y: Optional[int]
if y not in nt:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]
[out]
[case testNarrowTypeAfterInDict]
from typing import Dict, Optional
x: Dict[str, int]
y: Optional[str]
if y in x:
reveal_type(y) # N: Revealed type is "builtins.str"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.str, None]"
if y not in x:
reveal_type(y) # N: Revealed type is "Union[builtins.str, None]"
else:
reveal_type(y) # N: Revealed type is "builtins.str"
[builtins fixtures/dict.pyi]
[out]
[case testNarrowTypeAfterInNoAnyOrObject]
from typing import Any, List, Optional
x: List[Any]
z: List[object]
y: Optional[int]
if y in x:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
if y not in z:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
[typing fixtures/typing-medium.pyi]
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInUserDefined]
from typing import Container, Optional
class C(Container[int]):
def __contains__(self, item: object) -> bool:
return item is 'surprise'
y: Optional[int]
# We never trust user defined types
if y in C():
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
if y not in C():
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.int, None]"
[typing fixtures/typing-full.pyi]
[builtins fixtures/list.pyi]
[out]
[case testNarrowTypeAfterInSet]
from typing import Optional, Set
s: Set[str]
y: Optional[str]
if y in {'a', 'b', 'c'}:
reveal_type(y) # N: Revealed type is "builtins.str"
else:
reveal_type(y) # N: Revealed type is "Union[builtins.str, None]"
if y not in s:
reveal_type(y) # N: Revealed type is "Union[builtins.str, None]"
else:
reveal_type(y) # N: Revealed type is "builtins.str"
[builtins fixtures/set.pyi]
[out]
[case testNarrowTypeAfterInTypedDict]
from typing import Optional
from mypy_extensions import TypedDict
class TD(TypedDict):
a: int
b: str
td: TD
def f() -> None:
x: Optional[str]
if x not in td:
return
reveal_type(x) # N: Revealed type is "builtins.str"
[typing fixtures/typing-typeddict.pyi]
[builtins fixtures/dict.pyi]
[out]
[case testIsinstanceWidensWithAnyArg]
from typing import Any
class A: ...
B: Any
x: A
x.foo() # E: "A" has no attribute "foo"
assert isinstance(x, B)
x.foo()
reveal_type(x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceWidensUnionWithAnyArg]
from typing import Any, Union
class A: ...
B: Any
x: Union[A, B]
reveal_type(x) # N: Revealed type is "Union[__main__.A, Any]"
assert isinstance(x, B)
reveal_type(x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testIsinstanceIgnoredImport]
from typing import Union
from foo import A # type: ignore
def f(x: Union[A, str]) -> None:
x.method_only_in_a() # E: Item "str" of "Union[Any, str]" has no attribute "method_only_in_a"
if isinstance(x, A):
x.method_only_in_a()
[builtins fixtures/isinstance.pyi]
[case testIsinstanceIgnoredImportDualAny]
from typing import Any
from foo import Bad, OtherBad # type: ignore
x: Any
if isinstance(x, Bad):
reveal_type(x) # N: Revealed type is "Any"
else:
reveal_type(x) # N: Revealed type is "Any"
if isinstance(x, (Bad, OtherBad)):
reveal_type(x) # N: Revealed type is "Any"
else:
reveal_type(x) # N: Revealed type is "Any"
y: object
if isinstance(y, Bad):
reveal_type(y) # N: Revealed type is "Any"
else:
reveal_type(y) # N: Revealed type is "builtins.object"
class Ok: pass
z: Any
if isinstance(z, Ok):
reveal_type(z) # N: Revealed type is "__main__.Ok"
else:
reveal_type(z) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceInitialNoneCheckSkipsImpossibleCasesNoStrictOptional]
from typing import Optional, Union
class A: pass
def foo1(x: Union[A, str, None]) -> None:
if x is None:
reveal_type(x) # N: Revealed type is "None"
elif isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.A"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
def foo2(x: Optional[str]) -> None:
if x is None:
reveal_type(x) # N: Revealed type is "None"
elif isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "str" and "A">"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceInitialNoneCheckSkipsImpossibleCasesInNoStrictOptional]
# flags: --no-strict-optional
from typing import Optional, Union
class A: pass
def foo1(x: Union[A, str, None]) -> None:
if x is None:
reveal_type(x) # N: Revealed type is "None"
elif isinstance(x, A):
# Note that Union[None, A] == A in no-strict-optional
reveal_type(x) # N: Revealed type is "__main__.A"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
def foo2(x: Optional[str]) -> None:
if x is None:
reveal_type(x) # N: Revealed type is "None"
elif isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "str" and "A">"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
[builtins fixtures/isinstance.pyi]
[case testNoneCheckDoesNotNarrowWhenUsingTypeVars]
# Note: this test (and the following one) are testing checker.conditional_type_map:
# if you set the 'prohibit_none_typevar_overlap' keyword argument to False when calling
# 'is_overlapping_types', the binder will incorrectly infer that 'out' has a type of
# Union[T, None] after the if statement.
from typing import TypeVar
T = TypeVar('T')
def foo(x: T) -> T:
out = None
out = x
if out is None:
pass
return out
[builtins fixtures/isinstance.pyi]
[case testNoneCheckDoesNotNarrowWhenUsingTypeVarsNoStrictOptional]
# flags: --no-strict-optional
from typing import TypeVar
T = TypeVar('T')
def foo(x: T) -> T:
out = None
out = x
if out is None:
pass
return out
[builtins fixtures/isinstance.pyi]
[case testNoneAndGenericTypesOverlapNoStrictOptional]
# flags: --no-strict-optional
from typing import Union, Optional, List
# Note: this test is indirectly making sure meet.is_overlapping_types
# correctly ignores 'None' in unions.
def foo(x: Optional[List[str]]) -> None:
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], None]"
assert isinstance(x, list)
reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]"
def bar(x: Union[List[str], List[int], None]) -> None:
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list[builtins.int], None]"
assert isinstance(x, list)
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list[builtins.int]]"
[builtins fixtures/isinstancelist.pyi]
[case testNoneAndGenericTypesOverlapStrictOptional]
from typing import Union, Optional, List
# This test is the same as the one above, except for strict-optional.
# It isn't testing anything explicitly and mostly exists for the sake
# of completeness.
def foo(x: Optional[List[str]]) -> None:
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], None]"
assert isinstance(x, list)
reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]"
def bar(x: Union[List[str], List[int], None]) -> None:
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list[builtins.int], None]"
assert isinstance(x, list)
reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list[builtins.int]]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithStarExpression]
from typing import Union, List, Tuple
def f(var: Union[List[str], Tuple[str, str], str]) -> None:
reveal_type(var) # N: Revealed type is "Union[builtins.list[builtins.str], Tuple[builtins.str, builtins.str], builtins.str]"
if isinstance(var, (list, *(str, int))):
reveal_type(var) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.str]"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithStarExpressionAndVariable]
from typing import Union
def f(var: Union[int, str]) -> None:
reveal_type(var) # N: Revealed type is "Union[builtins.int, builtins.str]"
some_types = (str, tuple)
another_type = list
if isinstance(var, (*some_types, another_type)):
reveal_type(var) # N: Revealed type is "builtins.str"
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceWithWrongStarExpression]
var = 'some string'
if isinstance(var, *(str, int)): # E: Too many arguments for "isinstance"
pass
[builtins fixtures/isinstancelist.pyi]
[case testIsInstanceAdHocIntersectionBasic]
class A:
def f1(self) -> int: ...
class B:
def f2(self) -> int: ...
class C:
def f3(self) -> int: ...
x: A
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
if isinstance(x, C):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A", "B", and "C">"
reveal_type(x.f1()) # N: Revealed type is "builtins.int"
reveal_type(x.f2()) # N: Revealed type is "builtins.int"
reveal_type(x.f3()) # N: Revealed type is "builtins.int"
x.bad() # E: "<subclass of "A", "B", and "C">" has no attribute "bad"
else:
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
else:
reveal_type(x) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionRepeatedChecks]
# flags: --warn-unreachable
class A: pass
class B: pass
x: A
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
if isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionIncompatibleClasses]
# flags: --warn-unreachable
class A:
def f(self) -> int: ...
class B:
def f(self) -> str: ...
class C:
def f(self) -> str: ...
class Example(A, B): pass # E: Definition of "f" in base class "A" is incompatible with definition in base class "B"
x: A
if isinstance(x, B): # E: Subclass of "A" and "B" cannot exist: would have incompatible method signatures
reveal_type(x) # E: Statement is unreachable
else:
reveal_type(x) # N: Revealed type is "__main__.A"
y: C
if isinstance(y, B):
reveal_type(y) # N: Revealed type is "__main__.<subclass of "C" and "B">"
if isinstance(y, A): # E: Subclass of "C", "B", and "A" cannot exist: would have incompatible method signatures
reveal_type(y) # E: Statement is unreachable
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionReversed]
# flags: --warn-unreachable
from abc import abstractmethod
from typing_extensions import Literal
class A0:
def f(self) -> Literal[0]:
...
class A1:
def f(self) -> Literal[1]:
...
class A2:
def f(self) -> Literal[2]:
...
class B:
@abstractmethod
def f(self) -> Literal[1, 2]:
...
def t0(self) -> None:
if isinstance(self, A0): # E: Subclass of "B" and "A0" cannot exist: would have incompatible method signatures
x0: Literal[0] = self.f() # E: Statement is unreachable
def t1(self) -> None:
if isinstance(self, A1):
reveal_type(self) # N: Revealed type is "__main__.<subclass of "A1" and "B">"
x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1]", variable has type "Literal[0]")
x1: Literal[1] = self.f()
def t2(self) -> None:
if isinstance(self, (A0, A1)):
reveal_type(self) # N: Revealed type is "__main__.<subclass of "A1" and "B">1"
x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1]", variable has type "Literal[0]")
x1: Literal[1] = self.f()
def t3(self) -> None:
if isinstance(self, (A1, A2)):
reveal_type(self) # N: Revealed type is "Union[__main__.<subclass of "A1" and "B">2, __main__.<subclass of "A2" and "B">]"
x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1, 2]", variable has type "Literal[0]")
x1: Literal[1] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1, 2]", variable has type "Literal[1]")
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionGenerics]
# flags: --warn-unreachable
from typing import Generic, TypeVar
class Parent: pass
class Child(Parent): pass
T = TypeVar('T')
class A(Generic[T]):
def f(self) -> T: ...
class B:
def f(self) -> Parent: ...
x: A[int]
if isinstance(x, B): # E: Subclass of "A[int]" and "B" cannot exist: would have incompatible method signatures
reveal_type(x) # E: Statement is unreachable
else:
reveal_type(x) # N: Revealed type is "__main__.A[builtins.int]"
y: A[Parent]
if isinstance(y, B):
reveal_type(y) # N: Revealed type is "__main__.<subclass of "A" and "B">"
reveal_type(y.f()) # N: Revealed type is "__main__.Parent"
else:
reveal_type(y) # N: Revealed type is "__main__.A[__main__.Parent]"
z: A[Child]
if isinstance(z, B):
reveal_type(z) # N: Revealed type is "__main__.<subclass of "A" and "B">1"
reveal_type(z.f()) # N: Revealed type is "__main__.Child"
else:
reveal_type(z) # N: Revealed type is "__main__.A[__main__.Child]"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionGenericsWithValues]
# flags: --warn-unreachable
from typing import TypeVar
class A:
attr: int
class B:
attr: int
class C:
attr: str
T1 = TypeVar('T1', A, B)
def f1(x: T1) -> T1:
if isinstance(x, A):
reveal_type(x) # N: Revealed type is "__main__.A" \
# N: Revealed type is "__main__.<subclass of "B" and "A">"
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">" \
# N: Revealed type is "__main__.<subclass of "B" and "A">"
else:
reveal_type(x) # N: Revealed type is "__main__.A"
else:
reveal_type(x) # N: Revealed type is "__main__.B"
return x
T2 = TypeVar('T2', B, C)
def f2(x: T2) -> T2:
if isinstance(x, B):
reveal_type(x) # N: Revealed type is "__main__.B"
# Note: even though --warn-unreachable is set, we don't report
# errors for the below: we don't yet have a way of filtering out
# reachability errors that occur for only one variation of the
# TypeVar yet.
if isinstance(x, C):
reveal_type(x)
else:
reveal_type(x) # N: Revealed type is "__main__.B"
else:
reveal_type(x) # N: Revealed type is "__main__.C"
return x
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionGenericsWithValuesDirectReturn]
# flags: --warn-unreachable
from typing import TypeVar
class A:
attr: int
class B:
attr: int
class C:
attr: str
T1 = TypeVar('T1', A, B)
def f1(x: T1) -> T1:
if isinstance(x, A):
# The error message is confusing, but we indeed do run into problems if
# 'x' is a subclass of A and B
return A() # E: Incompatible return value type (got "A", expected "B")
else:
return B()
T2 = TypeVar('T2', B, C)
def f2(x: T2) -> T2:
if isinstance(x, B):
# In contrast, it's impossible for a subclass of "B" and "C" to
# exist, so this is fine
return B()
else:
return C()
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionUsage]
# flags: --warn-unreachable
class A: pass
class B: pass
class Concrete(A, B): pass
def accept_a(a: A) -> None: pass
def accept_b(a: B) -> None: pass
def accept_concrete(c: Concrete) -> None: pass
x: A
if isinstance(x, B):
var = x
reveal_type(var) # N: Revealed type is "__main__.<subclass of "A" and "B">"
accept_a(var)
accept_b(var)
accept_concrete(var) # E: Argument 1 to "accept_concrete" has incompatible type "<subclass of "A" and "B">"; expected "Concrete"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionReinfer]
# flags: --warn-unreachable
class A: pass
class B: pass
x: A
assert isinstance(x, B)
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">"
y: A
assert isinstance(y, B)
reveal_type(y) # N: Revealed type is "__main__.<subclass of "A" and "B">1"
x = y
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "B">1"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionWithUnions]
# flags: --warn-unreachable
from typing import Type, Union
class A: pass
class B: pass
class C: pass
class D: pass
v1: A
if isinstance(v1, (B, C)):
reveal_type(v1) # N: Revealed type is "Union[__main__.<subclass of "A" and "B">, __main__.<subclass of "A" and "C">]"
v2: Union[A, B]
if isinstance(v2, C):
reveal_type(v2) # N: Revealed type is "Union[__main__.<subclass of "A" and "C">1, __main__.<subclass of "B" and "C">]"
v3: Union[A, B]
if isinstance(v3, (C, D)):
reveal_type(v3) # N: Revealed type is "Union[__main__.<subclass of "A" and "C">2, __main__.<subclass of "A" and "D">, __main__.<subclass of "B" and "C">1, __main__.<subclass of "B" and "D">]"
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionSameNames]
# flags: --warn-unreachable
from foo import A as A2
class A: pass
x: A
if isinstance(x, A2):
reveal_type(x) # N: Revealed type is "__main__.<subclass of "A" and "A">"
[file foo.py]
class A: pass
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionBadMro]
# flags: --warn-unreachable
class X: pass
class Y: pass
class A(X, Y): pass
class B(Y, X): pass
foo: A
if isinstance(foo, B): # E: Subclass of "A" and "B" cannot exist: would have inconsistent method resolution order
reveal_type(foo) # E: Statement is unreachable
[builtins fixtures/isinstance.pyi]
[case testIsInstanceAdHocIntersectionAmbiguousClass]
# flags: --warn-unreachable
from typing import Any
class Concrete:
x: int
class Ambiguous:
x: Any
# We bias towards assuming these two classes could be overlapping
foo: Concrete
if isinstance(foo, Ambiguous):
reveal_type(foo) # N: Revealed type is "__main__.<subclass of "Concrete" and "Ambiguous">"
reveal_type(foo.x) # N: Revealed type is "builtins.int"
[builtins fixtures/isinstance.pyi]
[case testIsSubclassAdHocIntersection]
# flags: --warn-unreachable
from typing import Type
class A:
x: int
class B:
x: int
class C:
x: str
x: Type[A]
if issubclass(x, B):
reveal_type(x) # N: Revealed type is "Type[__main__.<subclass of "A" and "B">]"
if issubclass(x, C): # E: Subclass of "A", "B", and "C" cannot exist: would have incompatible method signatures
reveal_type(x) # E: Statement is unreachable
else:
reveal_type(x) # N: Revealed type is "Type[__main__.<subclass of "A" and "B">]"
else:
reveal_type(x) # N: Revealed type is "Type[__main__.A]"
[builtins fixtures/isinstance.pyi]
[case testTypeEqualsCheck]
from typing import Any
y: Any
if type(y) == int:
reveal_type(y) # N: Revealed type is "builtins.int"
[case testMultipleTypeEqualsCheck]
from typing import Any
x: Any
y: Any
if type(x) == type(y) == int:
reveal_type(y) # N: Revealed type is "builtins.int"
reveal_type(x) # N: Revealed type is "builtins.int"
[case testTypeEqualsCheckUsingIs]
from typing import Any
y: Any
if type(y) is int:
reveal_type(y) # N: Revealed type is "builtins.int"
[case testTypeEqualsNarrowingUnionWithElse]
from typing import Union
x: Union[int, str]
if type(x) is int:
reveal_type(x) # N: Revealed type is "builtins.int"
else:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
[case testTypeEqualsMultipleTypesShouldntNarrow]
# make sure we don't do any narrowing if there are multiple types being compared
from typing import Union
x: Union[int, str]
if type(x) == int == str:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
else:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
# mypy thinks int isn't defined unless we include this
[builtins fixtures/primitives.pyi]
[case testTypeNotEqualsCheck]
from typing import Union
x: Union[int, str]
if type(x) != int:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
else:
reveal_type(x) # N: Revealed type is "builtins.int"
# mypy thinks int isn't defined unless we include this
[builtins fixtures/primitives.pyi]
[case testTypeNotEqualsCheckUsingIsNot]
from typing import Union
x: Union[int, str]
if type(x) is not int:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
else:
reveal_type(x) # N: Revealed type is "builtins.int"
[case testNarrowInElseCaseIfFinal]
from typing import final, Union
@final
class C:
pass
class D:
pass
x: Union[C, D]
if type(x) is C:
reveal_type(x) # N: Revealed type is "__main__.C"
else:
reveal_type(x) # N: Revealed type is "__main__.D"
[case testNarrowInIfCaseIfFinalUsingIsNot]
from typing import final, Union
@final
class C:
pass
class D:
pass
x: Union[C, D]
if type(x) is not C:
reveal_type(x) # N: Revealed type is "__main__.D"
else:
reveal_type(x) # N: Revealed type is "__main__.C"
[case testHasAttrExistingAttribute]
class C:
x: int
c: C
if hasattr(c, "x"):
reveal_type(c.x) # N: Revealed type is "builtins.int"
else:
# We don't mark this unreachable since people may check for deleted attributes
reveal_type(c.x) # N: Revealed type is "builtins.int"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeInstance]
class B: ...
b: B
if hasattr(b, "x"):
reveal_type(b.x) # N: Revealed type is "Any"
else:
b.x # E: "B" has no attribute "x"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeFunction]
def foo(x: int) -> None: ...
if hasattr(foo, "x"):
reveal_type(foo.x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeClassObject]
class C: ...
if hasattr(C, "x"):
reveal_type(C.x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeTypeType]
from typing import Type
class C: ...
c: Type[C]
if hasattr(c, "x"):
reveal_type(c.x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeTypeVar]
from typing import TypeVar
T = TypeVar("T")
def foo(x: T) -> T:
if hasattr(x, "x"):
reveal_type(x.x) # N: Revealed type is "Any"
return x
else:
return x
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeChained]
class B: ...
b: B
if hasattr(b, "x"):
reveal_type(b.x) # N: Revealed type is "Any"
elif hasattr(b, "y"):
reveal_type(b.y) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeNested]
class A: ...
class B: ...
x: A
if hasattr(x, "x"):
if isinstance(x, B):
reveal_type(x.x) # N: Revealed type is "Any"
if hasattr(x, "x") and hasattr(x, "y"):
reveal_type(x.x) # N: Revealed type is "Any"
reveal_type(x.y) # N: Revealed type is "Any"
if hasattr(x, "x"):
if hasattr(x, "y"):
reveal_type(x.x) # N: Revealed type is "Any"
reveal_type(x.y) # N: Revealed type is "Any"
if hasattr(x, "x") or hasattr(x, "y"):
x.x # E: "A" has no attribute "x"
x.y # E: "A" has no attribute "y"
[builtins fixtures/isinstance.pyi]
[case testHasAttrPreciseType]
class A: ...
x: A
if hasattr(x, "a") and isinstance(x.a, int):
reveal_type(x.a) # N: Revealed type is "builtins.int"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeUnion]
from typing import Union
class A: ...
class B:
x: int
xu: Union[A, B]
if hasattr(xu, "x"):
reveal_type(xu) # N: Revealed type is "Union[__main__.A, __main__.B]"
reveal_type(xu.x) # N: Revealed type is "Union[Any, builtins.int]"
else:
reveal_type(xu) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeOuterUnion]
from typing import Union
class A: ...
class B: ...
xu: Union[A, B]
if isinstance(xu, B):
if hasattr(xu, "x"):
reveal_type(xu.x) # N: Revealed type is "Any"
if isinstance(xu, B) and hasattr(xu, "x"):
reveal_type(xu.x) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[case testHasAttrDoesntInterfereGetAttr]
class C:
def __getattr__(self, attr: str) -> str: ...
c: C
if hasattr(c, "foo"):
reveal_type(c.foo) # N: Revealed type is "builtins.str"
[builtins fixtures/isinstance.pyi]
[case testHasAttrMissingAttributeLiteral]
from typing import Final
class B: ...
b: B
ATTR: Final = "x"
if hasattr(b, ATTR):
reveal_type(b.x) # N: Revealed type is "Any"
else:
b.x # E: "B" has no attribute "x"
[builtins fixtures/isinstance.pyi]
[case testHasAttrDeferred]
def foo() -> str: ...
class Test:
def stream(self) -> None:
if hasattr(self, "_body"):
reveal_type(self._body) # N: Revealed type is "builtins.str"
def body(self) -> str:
if not hasattr(self, "_body"):
self._body = foo()
return self._body
[builtins fixtures/isinstance.pyi]
[case testHasAttrModule]
import mod
if hasattr(mod, "y"):
reveal_type(mod.y) # N: Revealed type is "Any"
reveal_type(mod.x) # N: Revealed type is "builtins.int"
else:
mod.y # E: Module has no attribute "y"
reveal_type(mod.x) # N: Revealed type is "builtins.int"
if hasattr(mod, "x"):
mod.y # E: Module has no attribute "y"
reveal_type(mod.x) # N: Revealed type is "builtins.int"
else:
mod.y # E: Module has no attribute "y"
reveal_type(mod.x) # N: Revealed type is "builtins.int"
[file mod.py]
x: int
[builtins fixtures/module.pyi]
[case testHasAttrDoesntInterfereModuleGetAttr]
import mod
if hasattr(mod, "y"):
reveal_type(mod.y) # N: Revealed type is "builtins.str"
[file mod.py]
def __getattr__(attr: str) -> str: ...
[builtins fixtures/module.pyi]