blob: eca81bf8d37f89c72e125f25f816980c469e25b3 [file]
-- Tests for strict Optional behavior
[case testImplicitNoneType]
x = None
x() # E: None not callable
[case testExplicitNoneType]
x = None # type: None
x() # E: None not callable
[case testNoneMemberOfOptional]
from typing import Optional
x = None # type: Optional[int]
[case testTypeMemberOfOptional]
from typing import Optional
x = 0 # type: Optional[int]
[case testNoneNotMemberOfType]
x = None # type: int
[out]
main:1: error: Incompatible types in assignment (expression has type None, variable has type "int")
[case testTypeNotMemberOfNone]
x = 0 # type: None
[out]
main:1: error: Incompatible types in assignment (expression has type "int", variable has type None)
[case testOptionalNotMemberOfType]
from typing import Optional
def f(a: int) -> None: pass
x = None # type: Optional[int]
f(x) # E: Argument 1 to "f" has incompatible type "Optional[int]"; expected "int"
[case testIsinstanceCases]
from typing import Optional
x = None # type: Optional[int]
if isinstance(x, int):
reveal_type(x) # E: Revealed type is 'builtins.int'
else:
reveal_type(x) # E: Revealed type is 'builtins.None'
[builtins fixtures/isinstance.pyi]
[case testIfCases]
from typing import Optional
x = None # type: Optional[int]
if x:
reveal_type(x) # E: Revealed type is 'builtins.int'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.None]'
[builtins fixtures/bool.pyi]
[case testIfNotCases]
from typing import Optional
x = None # type: Optional[int]
if not x:
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.None]'
else:
reveal_type(x) # E: Revealed type is 'builtins.int'
[builtins fixtures/bool.pyi]
[case testIsNotNoneCases]
from typing import Optional
x = None # type: Optional[int]
if x is not None:
reveal_type(x) # E: Revealed type is 'builtins.int'
else:
reveal_type(x) # E: Revealed type is 'builtins.None'
[builtins fixtures/bool.pyi]
[case testIsNoneCases]
from typing import Optional
x = None # type: Optional[int]
if x is None:
reveal_type(x) # E: Revealed type is 'builtins.None'
else:
reveal_type(x) # E: Revealed type is 'builtins.int'
[builtins fixtures/bool.pyi]
[case testOrCases]
from typing import Optional
x = None # type: Optional[str]
y1 = x or 'a'
reveal_type(y1) # E: Revealed type is 'builtins.str'
y2 = x or 1
reveal_type(y2) # E: Revealed type is 'Union[builtins.str, builtins.int]'
z1 = 'a' or x
reveal_type(z1) # E: Revealed type is 'Union[builtins.str, builtins.None]'
z2 = int() or x
reveal_type(z2) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.None]'
[case testAndCases]
from typing import Optional
x = None # type: Optional[str]
y1 = x and 'b'
reveal_type(y1) # E: Revealed type is 'Union[builtins.str, builtins.None]'
y2 = x and 1 # x could be '', so...
reveal_type(y2) # E: Revealed type is 'Union[builtins.str, builtins.None, builtins.int]'
z1 = 'b' and x
reveal_type(z1) # E: Revealed type is 'Union[builtins.str, builtins.None]'
z2 = int() and x
reveal_type(z2) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.None]'
[case testLambdaReturningNone]
f = lambda: None
x = f() # E: Function does not return a value
[case testNoneArgumentType]
def f(x: None) -> None: pass
f(None)
[case testInferOptionalFromDefaultNone]
def f(x: int = None) -> None:
x + 1 # E: Unsupported left operand type for + (some union)
f(None)
[out]
[case testInferOptionalFromDefaultNoneWithFastParser]
# flags: --fast-parser
def f(x: int = None) -> None:
x + 1 # E: Unsupported left operand type for + (some union)
f(None)
[out]
[case testInferOptionalFromDefaultNoneComment]
def f(x=None):
# type: (int) -> None
x + 1 # E: Unsupported left operand type for + (some union)
f(None)
[out]
[case testInferOptionalFromDefaultNoneCommentWithFastParser]
# flags: --fast-parser
def f(x=None):
# type: (int) -> None
x + 1 # E: Unsupported left operand type for + (some union)
f(None)
[out]
[case testInferOptionalType]
x = None
if bool():
# scope limit assignment
x = 1
# in scope of the assignment, x is an int
reveal_type(x) # E: Revealed type is 'builtins.int'
# out of scope of the assignment, it's an Optional[int]
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.None]'
[builtins fixtures/bool.pyi]
[case testInferOptionalTypeLocallyBound]
x = None
x = 1
reveal_type(x) # E: Revealed type is 'builtins.int'
[case testInferOptionalTypeFromOptional]
from typing import Optional
y = None # type: Optional[int]
x = None
x = y
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.None]'
[case testInferOptionalListType]
x = [None]
x.append(1) # E: Argument 1 to "append" of "list" has incompatible type "int"; expected None
[builtins fixtures/list.pyi]
[case testInferNonOptionalListType]
x = []
x.append(1)
x() # E: List[int] not callable
[builtins fixtures/list.pyi]
[case testInferOptionalDictKeyValueTypes]
x = {None: None}
x["bar"] = 1
[builtins fixtures/dict.pyi]
[out]
main:2: error: Invalid index type "str" for "dict"; expected type None
main:2: error: Incompatible types in assignment (expression has type "int", target has type None)
[case testInferNonOptionalDictType]
x = {}
x["bar"] = 1
x() # E: Dict[str, int] not callable
[builtins fixtures/dict.pyi]
[case testNoneClassVariable]
from typing import Optional
class C:
x = None # type: int
def __init__(self) -> None:
self.x = 0
[case testNoneClassVariableInInit]
from typing import Optional
class C:
x = None # type: int
def __init__(self) -> None:
self.x = None # E: Incompatible types in assignment (expression has type None, variable has type "int")
[out]
[case testMultipleAssignmentNoneClassVariableInInit]
from typing import Optional
class C:
x, y = None, None # type: int, str
def __init__(self) -> None:
self.x = None # E: Incompatible types in assignment (expression has type None, variable has type "int")
self.y = None # E: Incompatible types in assignment (expression has type None, variable has type "str")
[out]
[case testOverloadWithNone]
from typing import overload
@overload
def f(x: None) -> str: pass
@overload
def f(x: int) -> int: pass
reveal_type(f(None)) # E: Revealed type is 'builtins.str'
reveal_type(f(0)) # E: Revealed type is 'builtins.int'
[case testOptionalTypeOrTypePlain]
from typing import Optional
def f(a: Optional[int]) -> int:
return a or 0
[out]
[case testOptionalTypeOrTypeTypeVar]
from typing import Optional, TypeVar
T = TypeVar('T')
def f(a: Optional[T], b: T) -> T:
return a or b
[out]
[case testOptionalTypeOrTypeBothOptional]
from typing import Optional
def f(a: Optional[int], b: Optional[int]) -> None:
reveal_type(a or b)
def g(a: int, b: Optional[int]) -> None:
reveal_type(a or b)
[out]
main:3: error: Revealed type is 'Union[builtins.int, builtins.None]'
main:5: error: Revealed type is 'Union[builtins.int, builtins.None]'
[case testOptionalTypeOrTypeComplexUnion]
from typing import Union
def f(a: Union[int, str, None]) -> None:
reveal_type(a or 'default')
[out]
main:3: error: Revealed type is 'Union[builtins.int, builtins.str]'
[case testOptionalTypeOrTypeNoTriggerPlain]
from typing import Optional
def f(a: Optional[int], b: int) -> int:
return b or a
[out]
main:3: error: Incompatible return value type (got "Optional[int]", expected "int")
[case testOptionalTypeOrTypeNoTriggerTypeVar]
from typing import Optional, TypeVar
T = TypeVar('T')
def f(a: Optional[T], b: T) -> T:
return b or a
[out]
main:4: error: Incompatible return value type (got "Optional[T]", expected "T")
[case testNoneOrStringIsString]
def f() -> str:
a = None
b = ''
return a or b
[out]
[case testNoneOrTypeVarIsTypeVar]
from typing import TypeVar
T = TypeVar('T')
def f(b: T) -> T:
a = None
return a or b
[out]
[case testYieldNothingInFunctionReturningGenerator]
from typing import Generator
def f() -> Generator[None, None, None]:
yield
[out]
[case testNoneAndStringIsNone]
a = None
b = "foo"
reveal_type(a and b) # E: Revealed type is 'builtins.None'
[case testNoneMatchesObjectInOverload]
import a
a.f(None)
[file a.pyi]
from typing import overload
@overload
def f() -> None: ...
@overload
def f(o: object) -> None: ...
[case testGenericSubclassReturningNone]
from typing import Generic, TypeVar
T = TypeVar('T')
class Base(Generic[T]):
def f(self) -> T:
pass
class SubNone(Base[None]):
def f(self) -> None:
pass
class SubInt(Base[int]):
def f(self) -> int:
return 1
[case testUseOfNoneReturningFunction]
from typing import Optional
def f() -> None:
pass
def g(x: Optional[int]) -> int:
pass
x = f() # E: Function does not return a value
f() + 1 # E: Function does not return a value
g(f()) # E: Function does not return a value
[case testEmptyReturn]
def f() -> None:
return
[case testReturnNone]
def f() -> None:
return None
[case testNoneCallable]
from typing import Callable
def f() -> None: pass
x = f # type: Callable[[], None]
[case testOptionalCallable]
from typing import Callable, Optional
T = Optional[Callable[..., None]]
[case testAnyTypeInPartialTypeList]
# flags: --check-untyped-defs
def f(): ...
def lookup_field(name, obj):
try:
pass
except:
attr = f()
else:
attr = None
[case testTernaryWithNone]
reveal_type(None if bool() else 0) # E: Revealed type is 'Union[builtins.int, builtins.None]'
[builtins fixtures/bool.pyi]
[case testListWithNone]
reveal_type([0, None, 0]) # E: Revealed type is 'builtins.list[Union[builtins.int, builtins.None]]'
[builtins fixtures/list.pyi]
[case testOptionalWhitelistSuppressesOptionalErrors]
# flags: --strict-optional-whitelist
import a
import b
[file a.py]
from typing import Optional
x = None # type: Optional[str]
x + "foo"
[file b.py]
from typing import Optional
x = None # type: Optional[int]
x + 1
[case testOptionalWhitelistPermitsOtherErrors]
# flags: --strict-optional-whitelist
import a
import b
[file a.py]
from typing import Optional
x = None # type: Optional[str]
x + "foo"
[file b.py]
from typing import Optional
x = None # type: Optional[int]
x + 1
1 + "foo"
[out]
tmp/b.py:4: error: Unsupported operand types for + ("int" and "str")
[case testOptionalWhitelistPermitsWhitelistedFiles]
# flags: --strict-optional-whitelist **/a.py
import a
import b
[file a.py]
from typing import Optional
x = None # type: Optional[str]
x + "foo"
[file b.py]
from typing import Optional
x = None # type: Optional[int]
x + 1
[out]
tmp/a.py:3: error: Unsupported left operand type for + (some union)
[case testNoneContextInference]
from typing import Dict, List
def f() -> List[None]:
return []
def g() -> Dict[None, None]:
return {}
[builtins fixtures/dict.pyi]
[case testRaiseFromNone]
raise BaseException from None
[builtins fixtures/exception.pyi]
[case testOptionalNonPartialTypeWithNone]
from typing import Generator
def f() -> Generator[str, None, None]: pass
x = f()
reveal_type(x) # E: Revealed type is 'typing.Generator[builtins.str, builtins.None, builtins.None]'
l = [f()]
reveal_type(l) # E: Revealed type is 'builtins.list[typing.Generator*[builtins.str, builtins.None, builtins.None]]'
[builtins fixtures/list.pyi]
[case testNoneListTernary]
x = [None] if "" else [1] # E: List item 0 has incompatible type "int"
[builtins fixtures/list.pyi]
[case testInferEqualsNotOptional]
from typing import Optional
x = '' # type: Optional[str]
if x == '<string>':
reveal_type(x) # E: Revealed type is 'builtins.str'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.None]'
[builtins fixtures/ops.pyi]
[case testInferEqualsNotOptionalWithUnion]
from typing import Union
x = '' # type: Union[str, int, None]
if x == '<string>':
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int]'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int, builtins.None]'
[builtins fixtures/ops.pyi]
[case testInferEqualsNotOptionalWithOverlap]
from typing import Union
x = '' # type: Union[str, int, None]
if x == object():
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int]'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int, builtins.None]'
[builtins fixtures/ops.pyi]
[case testInferEqualsStillOptionalWithNoOverlap]
from typing import Optional
x = '' # type: Optional[str]
if x == 0:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.None]'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.None]'
[builtins fixtures/ops.pyi]
[case testInferEqualsStillOptionalWithBothOptional]
from typing import Union
x = '' # type: Union[str, int, None]
y = '' # type: Union[str, None]
if x == y:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int, builtins.None]'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.int, builtins.None]'
[builtins fixtures/ops.pyi]
[case testWarnNoReturnWorksWithStrictOptional]
# flags: --warn-no-return
def f() -> None:
1 + 1 # no error
def g() -> int:
1 + 1 #
[out]
main:5: note: Missing return statement
[case testGenericTypeAliasesOptional]
from typing import TypeVar, Generic, Optional
T = TypeVar('T')
class Node(Generic[T]):
def __init__(self, x: T) -> None:
self.x = x
ONode = Optional[Node[T]]
def f(x: T) -> ONode[T]:
if 1 > 0:
return Node(x)
else:
return None
x = None # type: ONode[int]
x = f(1)
x = f('x') # E: Argument 1 to "f" has incompatible type "str"; expected "int"
x.x = 1 # E: Some element of union has no attribute "x"
if x is not None:
x.x = 1 # OK here
[builtins fixtures/ops.pyi]
[case testOptionalLambdaInference]
from typing import Optional, Callable
f = None # type: Optional[Callable[[int], None]]
f = lambda x: None
f(0)
[builtins fixtures/function.pyi]