| -- Tests for strict Optional behavior |
| |
| [case testImplicitNoneType] |
| x = None # E: Need type annotation for "x" |
| x() # E: "None" not callable |
| |
| [case testImplicitNoneTypeInNestedFunction] |
| def f() -> None: |
| def g() -> None: |
| 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) # N: Revealed type is 'builtins.int' |
| else: |
| reveal_type(x) # N: Revealed type is 'None' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testIfCases] |
| from typing import Optional |
| x = None # type: Optional[int] |
| if x: |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testIfNotCases] |
| from typing import Optional |
| x = None # type: Optional[int] |
| if not x: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| else: |
| reveal_type(x) # N: 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) # N: Revealed type is 'builtins.int' |
| else: |
| reveal_type(x) # N: Revealed type is 'None' |
| [builtins fixtures/bool.pyi] |
| |
| [case testIsNoneCases] |
| from typing import Optional |
| x = None # type: Optional[int] |
| if x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| else: |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testAnyCanBeNone] |
| from typing import Optional, Any |
| x = None # type: Any |
| if x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| else: |
| reveal_type(x) # N: Revealed type is 'Any' |
| [builtins fixtures/bool.pyi] |
| |
| [case testOrCases] |
| from typing import Optional |
| x = None # type: Optional[str] |
| y1 = x or 'a' |
| reveal_type(y1) # N: Revealed type is 'builtins.str' |
| y2 = x or 1 |
| reveal_type(y2) # N: Revealed type is 'Union[builtins.str, builtins.int]' |
| z1 = 'a' or x |
| reveal_type(z1) # N: Revealed type is 'Union[builtins.str, None]' |
| z2 = int() or x |
| reveal_type(z2) # N: Revealed type is 'Union[builtins.int, builtins.str, None]' |
| |
| [case testAndCases] |
| from typing import Optional |
| x = None # type: Optional[str] |
| y1 = x and 'b' |
| reveal_type(y1) # N: Revealed type is 'Union[builtins.str, None]' |
| y2 = x and 1 # x could be '', so... |
| reveal_type(y2) # N: Revealed type is 'Union[builtins.str, None, builtins.int]' |
| z1 = 'b' and x |
| reveal_type(z1) # N: Revealed type is 'Union[builtins.str, None]' |
| z2 = int() and x |
| reveal_type(z2) # N: Revealed type is 'Union[builtins.int, builtins.str, None]' |
| |
| [case testLambdaReturningNone] |
| f = lambda: None |
| x = f() |
| reveal_type(x) # N: Revealed type is 'None' |
| |
| [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 + ("None") \ |
| # N: Left operand is of type "Optional[int]" |
| f(None) |
| [out] |
| |
| [case testNoInferOptionalFromDefaultNone] |
| # flags: --no-implicit-optional |
| def f(x: int = None) -> None: # E: Incompatible default for argument "x" (default has type "None", argument has type "int") |
| pass |
| [out] |
| |
| [case testInferOptionalFromDefaultNoneComment] |
| def f(x=None): |
| # type: (int) -> None |
| x + 1 # E: Unsupported left operand type for + ("None") \ |
| # N: Left operand is of type "Optional[int]" |
| f(None) |
| [out] |
| |
| [case testNoInferOptionalFromDefaultNoneComment] |
| # flags: --no-implicit-optional |
| def f(x=None): # E: Incompatible default for argument "x" (default has type "None", argument has type "int") |
| # type: (int) -> None |
| pass |
| [out] |
| |
| [case testInferOptionalType] |
| x = None |
| if bool(): |
| # scope limit assignment |
| x = 1 |
| # in scope of the assignment, x is an int |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| # out of scope of the assignment, it's an Optional[int] |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testInferOptionalTypeLocallyBound] |
| x = None |
| x = 1 |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| |
| [case testInferOptionalAnyType] |
| from typing import Any |
| x = None |
| a = None # type: Any |
| if bool(): |
| x = a |
| reveal_type(x) # N: Revealed type is 'Any' |
| reveal_type(x) # N: Revealed type is 'Union[Any, None]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testInferOptionalTypeFromOptional] |
| from typing import Optional |
| y = None # type: Optional[int] |
| x = None |
| x = y |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, 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[None, None]"; 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") |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testOverloadWithNone] |
| from foo import * |
| [file foo.pyi] |
| from typing import overload |
| @overload |
| def f(x: None) -> str: pass |
| @overload |
| def f(x: int) -> int: pass |
| reveal_type(f(None)) # N: Revealed type is 'builtins.str' |
| reveal_type(f(0)) # N: 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: note: Revealed type is 'Union[builtins.int, None]' |
| main:5: note: Revealed type is 'Union[builtins.int, None]' |
| |
| [case testOptionalTypeOrTypeComplexUnion] |
| from typing import Union |
| def f(a: Union[int, str, None]) -> None: |
| reveal_type(a or 'default') |
| [out] |
| main:3: note: 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 = None |
| b = "foo" |
| reveal_type(a and b) # N: Revealed type is '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: "f" does not return a value |
| f() + 1 # E: "f" does not return a value |
| g(f()) # E: "f" 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) # N: Revealed type is 'Union[Literal[0]?, None]' |
| [builtins fixtures/bool.pyi] |
| |
| [case testListWithNone] |
| reveal_type([0, None, 0]) # N: Revealed type is 'builtins.list[Union[builtins.int, 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 |
| |
| [builtins fixtures/primitives.pyi] |
| |
| [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" |
| [builtins fixtures/primitives.pyi] |
| [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 |
| [builtins fixtures/primitives.pyi] |
| [out] |
| tmp/a.py:3: error: Unsupported left operand type for + ("None") |
| tmp/a.py:3: note: Left operand is of type "Optional[str]" |
| |
| [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) # N: Revealed type is 'typing.Generator[builtins.str, None, None]' |
| l = [f()] |
| reveal_type(l) # N: Revealed type is 'builtins.list[typing.Generator*[builtins.str, None, None]]' |
| [builtins fixtures/list.pyi] |
| |
| [case testNoneListTernary] |
| x = [None] if "" else [1] # E: List item 0 has incompatible type "int"; expected "None" |
| [builtins fixtures/list.pyi] |
| |
| [case testListIncompatibleErrorMessage] |
| from typing import List, Callable |
| |
| def foo(l: List[Callable[[], str]]) -> None: pass |
| def f() -> int: |
| return 42 |
| |
| foo([f]) # E: List item 0 has incompatible type "Callable[[], int]"; expected "Callable[[], str]" |
| [builtins fixtures/list.pyi] |
| |
| [case testInferEqualsNotOptional] |
| from typing import Optional |
| x = '' # type: Optional[str] |
| if x == '<string>': |
| reveal_type(x) # N: Revealed type is 'builtins.str' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, None]' |
| if x is '<string>': |
| reveal_type(x) # N: Revealed type is 'builtins.str' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, None]' |
| [builtins fixtures/ops.pyi] |
| |
| [case testInferEqualsNotOptionalWithUnion] |
| from typing import Union |
| x = '' # type: Union[str, int, None] |
| if x == '<string>': |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| if x is '<string>': |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| [builtins fixtures/ops.pyi] |
| |
| [case testInferEqualsNotOptionalWithOverlap] |
| from typing import Union |
| x = '' # type: Union[str, int, None] |
| if x == object(): |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| if x is object(): |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| [builtins fixtures/ops.pyi] |
| |
| [case testInferEqualsStillOptionalWithNoOverlap] |
| from typing import Optional |
| x = '' # type: Optional[str] |
| if x == 0: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, None]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, None]' |
| if x is 0: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, None]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, 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) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| if x is y: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.str, builtins.int, None]' |
| [builtins fixtures/ops.pyi] |
| |
| [case testInferEqualsNotOptionalWithMultipleArgs] |
| from typing import Optional |
| x: Optional[int] |
| y: Optional[int] |
| if x == y == 1: |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| reveal_type(y) # N: Revealed type is 'builtins.int' |
| else: |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| reveal_type(y) # N: Revealed type is 'Union[builtins.int, None]' |
| |
| class A: pass |
| a: Optional[A] |
| b: Optional[A] |
| if a == b == object(): |
| reveal_type(a) # N: Revealed type is '__main__.A' |
| reveal_type(b) # N: Revealed type is '__main__.A' |
| else: |
| reveal_type(a) # N: Revealed type is 'Union[__main__.A, None]' |
| reveal_type(b) # N: Revealed type is 'Union[__main__.A, None]' |
| [builtins fixtures/ops.pyi] |
| |
| [case testInferInWithErasedTypes] |
| from typing import TypeVar, Callable |
| |
| T = TypeVar('T') |
| def foo(f: Callable[[T], bool], it: T) -> None: ... |
| |
| foo(lambda x: x in [1, 2] and bool(), 3) |
| [builtins fixtures/list.pyi] |
| |
| [case testWarnNoReturnWorksWithStrictOptional] |
| # flags: --warn-no-return |
| def f() -> None: |
| 1 + 1 # no error |
| |
| def g() -> int: |
| 1 + 1 # |
| [out] |
| main:5: error: 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] |
| if int(): |
| x = f(1) |
| if int(): |
| x = f('x') # E: Argument 1 to "f" has incompatible type "str"; expected "int" |
| |
| x.x = 1 # E: Item "None" of "Optional[Node[int]]" has no attribute "x" |
| if x is not None: |
| x.x = 1 # OK here |
| |
| [builtins fixtures/ops.pyi] |
| |
| [case testOptionalTypeNarrowedInBooleanStatement] |
| from typing import Optional |
| |
| x: Optional[int] = None |
| x is not None and x + 42 |
| x is not None and x + '42' # E: Unsupported operand types for + ("int" and "str") |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testInvalidBooleanBranchIgnored] |
| from typing import Optional |
| |
| x: None = None |
| x is not None and x + 42 |
| [builtins fixtures/isinstance.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] |
| |
| [case testDontSimplifyNoneUnionsWithStrictOptional] |
| from typing import Any, TypeVar, Union |
| A = None # type: Any |
| class C(A): pass |
| T = TypeVar('T') |
| S = TypeVar('S') |
| def u(x: T, y: S) -> Union[S, T]: pass |
| a = None # type: Any |
| |
| # Test both orders |
| reveal_type(u(C(), None)) # N: Revealed type is 'Union[None, __main__.C*]' |
| reveal_type(u(None, C())) # N: Revealed type is 'Union[__main__.C*, None]' |
| |
| reveal_type(u(a, None)) # N: Revealed type is 'Union[None, Any]' |
| reveal_type(u(None, a)) # N: Revealed type is 'Union[Any, None]' |
| |
| reveal_type(u(1, None)) # N: Revealed type is 'Union[None, builtins.int*]' |
| reveal_type(u(None, 1)) # N: Revealed type is 'Union[builtins.int*, None]' |
| |
| [case testOptionalAndAnyBaseClass] |
| from typing import Any, Optional |
| A = None # type: Any |
| class C(A): |
| pass |
| x = None # type: Optional[C] |
| x.foo() # E: Item "None" of "Optional[C]" has no attribute "foo" |
| |
| [case testIsinstanceAndOptionalAndAnyBase] |
| from typing import Any, Optional |
| |
| B = None # type: Any |
| class A(B): pass |
| |
| def f(a: Optional[A]): |
| reveal_type(a) # N: Revealed type is 'Union[__main__.A, None]' |
| if a is not None: |
| reveal_type(a) # N: Revealed type is '__main__.A' |
| else: |
| reveal_type(a) # N: Revealed type is 'None' |
| reveal_type(a) # N: Revealed type is 'Union[__main__.A, None]' |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testFlattenOptionalUnion] |
| from typing import Optional, Union |
| |
| x: Optional[Union[int, str]] |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, builtins.str, None]' |
| y: Optional[Union[int, None]] |
| reveal_type(y) # N: Revealed type is 'Union[builtins.int, None]' |
| |
| [case testOverloadWithNoneAndOptional] |
| from typing import overload, Optional |
| |
| @overload |
| def f(x: int) -> str: ... |
| @overload |
| def f(x: Optional[int]) -> Optional[str]: ... |
| def f(x): return x |
| |
| reveal_type(f(1)) # N: Revealed type is 'builtins.str' |
| reveal_type(f(None)) # N: Revealed type is 'Union[builtins.str, None]' |
| x: Optional[int] |
| reveal_type(f(x)) # N: Revealed type is 'Union[builtins.str, None]' |
| |
| [case testUnionTruthinessTracking] |
| from typing import Optional, Any |
| def test_or_shortcut(value: Optional[Any]) -> None: |
| if not value: |
| pass |
| if not value or value.get('foo') == 'hello': |
| pass |
| [builtins fixtures/bool.pyi] |
| |
| [case testNarrowingFromObjectToOptional] |
| from typing import Optional |
| x: object |
| y: Optional[int] |
| x = y |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| [out] |
| |
| [case testNarrowOptionalOutsideLambda] |
| from typing import Optional |
| |
| class A: |
| a: int |
| |
| def f(x: Optional[A]) -> None: |
| assert x |
| lambda: x.a |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testNarrowOptionalOutsideLambdaWithDeferred] |
| from typing import Optional |
| |
| class A: |
| a: int |
| |
| def f(self, x: Optional['A']) -> None: |
| assert x |
| lambda: (self.y, x.a) # E: Cannot determine type of 'y' |
| self.y = int() |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testDeferredAndOptionalInferenceSpecialCase] |
| def f() -> str: |
| y |
| x = None |
| if int(): |
| x = '' |
| if x is None: |
| x = '' |
| g(x) |
| return x |
| |
| def g(x: str) -> None: pass |
| |
| y = int() |
| [builtins fixtures/bool.pyi] |
| |
| [case testOptionalAssignAny1] |
| from typing import Optional |
| def f(): |
| return 0 |
| |
| def g(x: Optional[int]) -> int: |
| if x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| # As a special case for Unions containing None, during |
| x = f() |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, Any]' |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, Any]' |
| return x |
| |
| [builtins fixtures/bool.pyi] |
| |
| [case testOptionalAssignAny2] |
| from typing import Optional |
| def f(): |
| return 0 |
| |
| def g(x: Optional[int]) -> int: |
| if x is None: |
| reveal_type(x) # N: Revealed type is 'None' |
| x = 1 |
| reveal_type(x) # N: Revealed type is 'builtins.int' |
| # Since we've assigned to x, the special case None behavior shouldn't happen |
| x = f() |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]' |
| return x # E: Incompatible return value type (got "Optional[int]", expected "int") |
| |
| [builtins fixtures/bool.pyi] |
| |
| [case testOptionalAssignAny3] |
| from typing import Optional |
| def f(): |
| return 0 |
| |
| def g(x: Optional[int]) -> int: |
| if x is not None: |
| return x |
| reveal_type(x) # N: Revealed type is 'None' |
| if 1: |
| x = f() |
| reveal_type(x) # N: Revealed type is 'Union[builtins.int, Any]' |
| return x |
| |
| [builtins fixtures/bool.pyi] |
| |
| [case testStrictOptionalCovarianceCrossModule] |
| # flags: --config-file tmp/mypy.ini |
| from a import asdf |
| x = ["lol"] |
| asdf(x) |
| |
| [file a.py] |
| from typing import List, Optional |
| |
| def asdf(x: List[Optional[str]]) -> None: |
| pass |
| |
| x = ["lol"] |
| asdf(x) |
| |
| [file mypy.ini] |
| \[mypy] |
| \[mypy-a] |
| strict_optional = False |
| [out] |
| main:4: error: Argument 1 to "asdf" has incompatible type "List[str]"; expected "List[Optional[str]]" |
| main:4: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance |
| main:4: note: Consider using "Sequence" instead, which is covariant |
| [builtins fixtures/list.pyi] |