| -- Type checker test cases for conditional checks that result in some | |
| -- blocks classified as unreachable (they are not type checked or semantically | |
| -- analyzed). | |
| -- | |
| -- For example, we skip blocks that will not be executed on the active | |
| -- Python version. | |
| [case testConditionalTypeAliasPY3] | |
| import typing | |
| def f(): pass | |
| PY3 = f() | |
| if PY3: | |
| t = int | |
| x = object() + 'x' # E: Unsupported left operand type for + ("object") | |
| else: | |
| t = str | |
| y = 'x' / 1 | |
| x | |
| z = 1 # type: t | |
| [case testConditionalAssignmentPY2] | |
| import typing | |
| def f(): pass | |
| PY2 = f() | |
| if PY2: | |
| x = object() + 'x' | |
| else: | |
| y = 'x' / 1 # E: Unsupported left operand type for / ("str") | |
| y | |
| [case testConditionalImport] | |
| import typing | |
| def f(): pass | |
| PY2 = f() | |
| if PY2: | |
| import fuzzybar | |
| from barbar import * | |
| from pawwaw import a, bc | |
| else: | |
| import m | |
| [file m.py] | |
| import typing | |
| x = 1 | |
| if int(): | |
| x = 'a' | |
| [out] | |
| tmp/m.py:4: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testNegatedMypyConditional] | |
| import typing | |
| MYPY = 0 | |
| if not MYPY: | |
| import xyz753 | |
| else: | |
| import pow123 # E | |
| [builtins fixtures/bool.pyi] | |
| [out] | |
| main:6: error: Cannot find implementation or library stub for module named "pow123" | |
| main:6: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testMypyConditional] | |
| import typing | |
| MYPY = 0 | |
| if MYPY: | |
| None + 1 # E: Unsupported left operand type for + ("None") | |
| else: | |
| None + '' | |
| [builtins fixtures/bool.pyi] | |
| [case testTypeCheckingConditional] | |
| import typing | |
| if typing.TYPE_CHECKING: | |
| import pow123 # E | |
| else: | |
| import xyz753 | |
| [typing fixtures/typing-medium.pyi] | |
| [out] | |
| main:3: error: Cannot find implementation or library stub for module named "pow123" | |
| main:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testTypeCheckingConditionalFromImport] | |
| from typing import TYPE_CHECKING | |
| if TYPE_CHECKING: | |
| import pow123 # E | |
| else: | |
| import xyz753 | |
| [typing fixtures/typing-medium.pyi] | |
| [out] | |
| main:3: error: Cannot find implementation or library stub for module named "pow123" | |
| main:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testNegatedTypeCheckingConditional] | |
| import typing | |
| if not typing.TYPE_CHECKING: | |
| import pow123 # E | |
| else: | |
| import xyz753 | |
| [builtins fixtures/bool.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [out] | |
| main:5: error: Cannot find implementation or library stub for module named "xyz753" | |
| main:5: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testUndefinedTypeCheckingConditional] | |
| if not TYPE_CHECKING: # E | |
| import pow123 | |
| else: | |
| import xyz753 | |
| [builtins fixtures/bool.pyi] | |
| [out] | |
| main:1: error: Name "TYPE_CHECKING" is not defined | |
| main:4: error: Cannot find implementation or library stub for module named "xyz753" | |
| main:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testConditionalClassDefPY3] | |
| def f(): pass | |
| PY3 = f() | |
| if PY3: | |
| pass | |
| else: | |
| class X(object): | |
| pass | |
| [case testUnreachabilityAndElifPY3] | |
| def f(): pass | |
| PY3 = f() | |
| if PY3: | |
| pass | |
| elif bool(): | |
| import nonexistent | |
| 1 + '' | |
| else: | |
| import bad_name | |
| 1 + '' | |
| [builtins fixtures/bool.pyi] | |
| [out] | |
| [case testSysVersionInfo] | |
| import sys | |
| if sys.version_info[0] >= 3: | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| reveal_type(foo()) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoReversedOperandsOrder] | |
| import sys | |
| if (3,) <= sys.version_info: | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| reveal_type(foo()) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoNegated] | |
| import sys | |
| if not (sys.version_info[0] < 3): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| reveal_type(foo()) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced1] | |
| import sys | |
| if sys.version_info[:1] >= (3,): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced2] | |
| import sys | |
| if sys.version_info[:2] >= (3, 0): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced3] | |
| import sys | |
| if sys.version_info[:] >= (3, 0): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced4] | |
| import sys | |
| if sys.version_info[0:2] >= (3, 0): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced5] | |
| import sys | |
| if sys.version_info[0:] >= (3,): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced6] | |
| import sys | |
| if sys.version_info[1:] >= (5,): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced7] | |
| import sys | |
| if sys.version_info >= (3, 5): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced8] | |
| # Our pyversion only has (major, minor), | |
| # so testing for (major, minor, bugfix) is unsupported. | |
| import sys | |
| if sys.version_info >= (3, 5, 0): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' # E: All conditional function variants must have identical signatures \ | |
| # N: Original: \ | |
| # N: def foo() -> int \ | |
| # N: Redefinition: \ | |
| # N: def foo() -> str | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoSliced9] | |
| # Our pyversion only has (major, minor), | |
| # so testing for (minor, bugfix) is unsupported (also it's silly :-). | |
| import sys | |
| if sys.version_info[1:] >= (5, 0): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' # E: All conditional function variants must have identical signatures \ | |
| # N: Original: \ | |
| # N: def foo() -> int \ | |
| # N: Redefinition: \ | |
| # N: def foo() -> str | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatform1] | |
| import sys | |
| if sys.platform == 'fictional': | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + '' | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatform2] | |
| import sys | |
| if sys.platform != 'fictional': | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformNegated] | |
| import sys | |
| if not (sys.platform == 'fictional'): | |
| def foo() -> int: return 0 | |
| else: | |
| def foo() -> str: return '' | |
| foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoClass] | |
| import sys | |
| if sys.version_info < (3, 5): | |
| class C: | |
| pass | |
| else: | |
| class C: | |
| def foo(self) -> int: return 0 | |
| C().foo() + 0 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoImport] | |
| import sys | |
| if sys.version_info >= (3, 5): | |
| import collections | |
| else: | |
| collections = None | |
| Pt = collections.namedtuple('Pt', 'x y z') | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoVariable] | |
| import sys | |
| if sys.version_info >= (3, 5): | |
| x = '' | |
| else: | |
| x = 0 | |
| x + '' | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoInClass] | |
| import sys | |
| class C: | |
| if sys.version_info >= (3, 5): | |
| def foo(self) -> int: return 0 | |
| else: | |
| def foo(self) -> str: return '' | |
| reveal_type(C().foo()) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysVersionInfoInFunction] | |
| import sys | |
| def foo() -> None: | |
| if sys.version_info >= (3, 5): | |
| x = '' | |
| else: | |
| x = 0 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformInMethod] | |
| import sys | |
| class C: | |
| def foo(self) -> None: | |
| if sys.platform != 'fictional': | |
| x = '' | |
| else: | |
| x = 0 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformInFunctionImport1] | |
| import sys | |
| def foo() -> None: | |
| if sys.platform != 'fictional': | |
| import a | |
| else: | |
| import b as a | |
| a.x | |
| [file a.py] | |
| x = 1 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformInFunctionImport2] | |
| import sys | |
| def foo() -> None: | |
| if sys.platform == 'fictional': | |
| import b as a | |
| else: | |
| import a | |
| a.x | |
| [file a.py] | |
| x = 1 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformInFunctionImport3] | |
| from typing import Callable | |
| import sys | |
| def idf(x: Callable[[], None]) -> Callable[[], None]: return x | |
| @idf | |
| def foo() -> None: | |
| if sys.platform == 'fictional': | |
| import b as a | |
| else: | |
| import a | |
| a.x | |
| [file a.py] | |
| x = 1 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformInMethodImport2] | |
| import sys | |
| class A: | |
| def foo(self) -> None: | |
| if sys.platform == 'fictional': | |
| import b as a | |
| else: | |
| import a | |
| a.x | |
| [file a.py] | |
| x = 1 | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testCustomSysVersionInfo] | |
| # flags: --python-version 3.11 | |
| import sys | |
| if sys.version_info >= (3, 11): | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [case testCustomSysVersionInfo2] | |
| # flags: --python-version 3.11 | |
| import sys | |
| if sys.version_info >= (3, 12): | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [case testCustomSysPlatform] | |
| # flags: --platform linux | |
| import sys | |
| if sys.platform == 'linux': | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testCustomSysPlatform2] | |
| # flags: --platform win32 | |
| import sys | |
| if sys.platform == 'linux': | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testCustomSysPlatformStartsWith] | |
| # flags: --platform win32 | |
| import sys | |
| if sys.platform.startswith('win'): | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testCustomSysPlatformMembershipTuple] | |
| # flags: --platform linux | |
| import sys | |
| if sys.platform in ('linux', 'darwin'): | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| if sys.platform not in ('win32', 'cygwin'): | |
| y = "foo" | |
| else: | |
| y = 3 | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| if sys.platform in ('win32', 'cygwin'): | |
| z = "foo" | |
| else: | |
| z = 3 | |
| reveal_type(z) # N: Revealed type is "builtins.int" | |
| if sys.platform not in ('linux', 'darwin'): | |
| w = "foo" | |
| else: | |
| w = 3 | |
| reveal_type(w) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testCustomSysPlatformMembershipSet] | |
| # flags: --platform linux | |
| import sys | |
| if sys.platform in {'linux', 'darwin'}: | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| if sys.platform not in {'linux', 'darwin'}: | |
| y = "foo" | |
| else: | |
| y = 3 | |
| reveal_type(y) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/set.pyi] | |
| [out] | |
| [case testCustomSysPlatformMembershipList] | |
| # flags: --platform linux | |
| import sys | |
| if sys.platform in ['linux', 'darwin']: | |
| x = "foo" | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| if sys.platform not in ['linux', 'darwin']: | |
| y = "foo" | |
| else: | |
| y = 3 | |
| reveal_type(y) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testSysPlatformMembershipUnknown] | |
| # flags: --platform linux | |
| import sys | |
| platform = sys.platform | |
| if sys.platform in ('linux', platform): | |
| y = "foo" | |
| else: | |
| y = 3 # E: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testSysPlatformMembershipDictIsUnknown] | |
| # flags: --platform linux | |
| import sys | |
| if sys.platform in {'linux': 'hi', 'darwin': 'bye'}: | |
| y = "foo" | |
| else: | |
| y = 3 # E: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/dict.pyi] | |
| [out] | |
| [case testShortCircuitInExpression] | |
| import typing | |
| def make() -> bool: pass | |
| PY2 = PY3 = make() | |
| a = PY2 and str() | |
| b = PY3 and str() | |
| c = PY2 or str() | |
| d = PY3 or str() | |
| e = (PY2 or PY3) and str() | |
| f = (PY3 or PY2) and str() | |
| g = (PY2 or PY3) or str() | |
| h = (PY3 or PY2) or str() | |
| reveal_type(a) # N: Revealed type is "builtins.bool" | |
| reveal_type(b) # N: Revealed type is "builtins.str" | |
| reveal_type(c) # N: Revealed type is "builtins.str" | |
| reveal_type(d) # N: Revealed type is "builtins.bool" | |
| reveal_type(e) # N: Revealed type is "builtins.str" | |
| reveal_type(f) # N: Revealed type is "builtins.str" | |
| reveal_type(g) # N: Revealed type is "builtins.bool" | |
| reveal_type(h) # N: Revealed type is "builtins.bool" | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [case testConditionalValuesBinaryOps] | |
| # flags: --platform linux | |
| import sys | |
| t_and_t = (sys.platform == 'linux' and sys.platform == 'linux') and str() | |
| t_or_t = (sys.platform == 'linux' or sys.platform == 'linux') and str() | |
| t_and_f = (sys.platform == 'linux' and sys.platform == 'windows') and str() | |
| t_or_f = (sys.platform == 'linux' or sys.platform == 'windows') and str() | |
| f_and_t = (sys.platform == 'windows' and sys.platform == 'linux') and str() | |
| f_or_t = (sys.platform == 'windows' or sys.platform == 'linux') and str() | |
| f_and_f = (sys.platform == 'windows' and sys.platform == 'windows') and str() | |
| f_or_f = (sys.platform == 'windows' or sys.platform == 'windows') and str() | |
| reveal_type(t_and_t) # N: Revealed type is "builtins.str" | |
| reveal_type(t_or_t) # N: Revealed type is "builtins.str" | |
| reveal_type(f_and_t) # N: Revealed type is "builtins.bool" | |
| reveal_type(f_or_t) # N: Revealed type is "builtins.str" | |
| reveal_type(t_and_f) # N: Revealed type is "builtins.bool" | |
| reveal_type(t_or_f) # N: Revealed type is "builtins.str" | |
| reveal_type(f_and_f) # N: Revealed type is "builtins.bool" | |
| reveal_type(f_or_f) # N: Revealed type is "builtins.bool" | |
| [builtins fixtures/ops.pyi] | |
| [case testConditionalValuesNegation] | |
| # flags: --platform linux | |
| import sys | |
| not_t = not sys.platform == 'linux' and str() | |
| not_f = not sys.platform == 'windows' and str() | |
| not_and_t = not (sys.platform == 'linux' and sys.platform == 'linux') and str() | |
| not_and_f = not (sys.platform == 'linux' and sys.platform == 'windows') and str() | |
| not_or_t = not (sys.platform == 'linux' or sys.platform == 'linux') and str() | |
| not_or_f = not (sys.platform == 'windows' or sys.platform == 'windows') and str() | |
| reveal_type(not_t) # N: Revealed type is "builtins.bool" | |
| reveal_type(not_f) # N: Revealed type is "builtins.str" | |
| reveal_type(not_and_t) # N: Revealed type is "builtins.bool" | |
| reveal_type(not_and_f) # N: Revealed type is "builtins.str" | |
| reveal_type(not_or_t) # N: Revealed type is "builtins.bool" | |
| reveal_type(not_or_f) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [case testConditionalValuesUnsupportedOps] | |
| # flags: --platform linux | |
| import sys | |
| unary_minus = -(sys.platform == 'linux') and str() | |
| binary_minus = ((sys.platform == 'linux') - (sys.platform == 'linux')) and str() | |
| reveal_type(unary_minus) # N: Revealed type is "Literal[0] | builtins.str" | |
| reveal_type(binary_minus) # N: Revealed type is "Literal[0] | builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [case testMypyFalseValuesInBinaryOps_no_empty] | |
| # flags: --platform linux | |
| import sys | |
| from typing import TYPE_CHECKING | |
| MYPY = 0 | |
| if TYPE_CHECKING and sys.platform == 'linux': | |
| def foo1() -> int: ... | |
| if sys.platform == 'linux' and TYPE_CHECKING: | |
| def foo2() -> int: ... | |
| if MYPY and sys.platform == 'linux': | |
| def foo3() -> int: ... | |
| if sys.platform == 'linux' and MYPY: | |
| def foo4() -> int: ... | |
| if TYPE_CHECKING or sys.platform == 'linux': | |
| def bar1() -> int: ... # E: Missing return statement | |
| if sys.platform == 'linux' or TYPE_CHECKING: | |
| def bar2() -> int: ... # E: Missing return statement | |
| if MYPY or sys.platform == 'linux': | |
| def bar3() -> int: ... # E: Missing return statement | |
| if sys.platform == 'linux' or MYPY: | |
| def bar4() -> int: ... # E: Missing return statement | |
| [builtins fixtures/ops.pyi] | |
| [case testShortCircuitAndWithConditionalAssignment] | |
| # flags: --platform linux | |
| import sys | |
| def f(): pass | |
| PY2 = f() | |
| if PY2 and sys.platform == 'linux': | |
| x = 'foo' | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| if sys.platform == 'linux' and PY2: | |
| y = 'foo' | |
| else: | |
| y = 3 | |
| reveal_type(y) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [case testShortCircuitOrWithConditionalAssignment] | |
| # flags: --platform linux | |
| import sys | |
| def f(): pass | |
| PY2 = f() | |
| if PY2 or sys.platform == 'linux': | |
| x = 'foo' | |
| else: | |
| x = 3 | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| if sys.platform == 'linux' or PY2: | |
| y = 'foo' | |
| else: | |
| y = 3 | |
| reveal_type(y) # N: Revealed type is "builtins.str" | |
| [builtins fixtures/ops.pyi] | |
| [case testShortCircuitNoEvaluation] | |
| # flags: --platform linux --always-false COMPILE_TIME_FALSE | |
| import sys | |
| if sys.platform == 'darwin': | |
| mac_only = 'junk' | |
| # `mac_only` should not be evaluated | |
| if sys.platform == 'darwin' and mac_only: | |
| pass | |
| if sys.platform == 'linux' or mac_only: | |
| pass | |
| COMPILE_TIME_FALSE = 'junk' | |
| if COMPILE_TIME_FALSE: | |
| compile_time_false_only = 'junk' | |
| # `compile_time_false_only` should not be evaluated | |
| if COMPILE_TIME_FALSE and compile_time_false_only: | |
| pass | |
| if not COMPILE_TIME_FALSE or compile_time_false_only: | |
| pass | |
| MYPY = False | |
| if not MYPY: | |
| mypy_only = 'junk' | |
| # `mypy_only` should not be evaluated | |
| if not MYPY and mypy_only: | |
| pass | |
| if MYPY or mypy_only: | |
| pass | |
| [builtins fixtures/ops.pyi] | |
| [case testSemanticAnalysisFalseButTypeNarrowingTrue] | |
| # flags: --always-false COMPILE_TIME_FALSE | |
| from typing import Literal | |
| indeterminate: str | |
| COMPILE_TIME_FALSE: Literal[True] # type-narrowing: mapped in 'if' only | |
| a = COMPILE_TIME_FALSE or indeterminate | |
| reveal_type(a) # N: Revealed type is "builtins.str" | |
| b = indeterminate or COMPILE_TIME_FALSE | |
| reveal_type(b) # N: Revealed type is "builtins.str | Literal[True]" | |
| [typing fixtures/typing-medium.pyi] | |
| [case testSemanticAnalysisTrueButTypeNarrowingFalse] | |
| # flags: --always-true COMPILE_TIME_TRUE | |
| from typing import Literal | |
| indeterminate: str | |
| COMPILE_TIME_TRUE: Literal[False] # type narrowed to `else` only | |
| a = COMPILE_TIME_TRUE or indeterminate | |
| reveal_type(a) # N: Revealed type is "Literal[False]" | |
| b = indeterminate or COMPILE_TIME_TRUE | |
| reveal_type(b) # N: Revealed type is "builtins.str | Literal[False]" | |
| [typing fixtures/typing-medium.pyi] | |
| [case testConditionalAssertWithoutElse] | |
| import typing | |
| class A: pass | |
| class B(A): pass | |
| x = A() | |
| reveal_type(x) # N: Revealed type is "__main__.A" | |
| if typing.TYPE_CHECKING: | |
| assert isinstance(x, B) | |
| reveal_type(x) # N: Revealed type is "__main__.B" | |
| reveal_type(x) # N: Revealed type is "__main__.B" | |
| [builtins fixtures/isinstancelist.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testUnreachableWhenSuperclassIsAny] | |
| from somewhere import Parent # type: ignore | |
| class Child(Parent): | |
| def foo(self) -> int: | |
| reveal_type(self) # N: Revealed type is "__main__.Child" | |
| if self is None: | |
| reveal_type(self) | |
| return None | |
| reveal_type(self) # N: Revealed type is "__main__.Child" | |
| return 3 | |
| def bar(self) -> int: | |
| if 1: | |
| self = super(Child, self).something() | |
| reveal_type(self) # N: Revealed type is "Any" | |
| if self is None: | |
| reveal_type(self) # N: Revealed type is "None" | |
| return None # E: Incompatible return value type (got "None", expected "int") | |
| reveal_type(self) # N: Revealed type is "Any" | |
| return 3 | |
| [builtins fixtures/isinstance.pyi] | |
| [case testUnreachableWhenSuperclassIsAnyNoStrictOptional] | |
| # flags: --no-strict-optional | |
| from typing import Any | |
| Parent: Any | |
| class Child(Parent): | |
| def foo(self) -> int: | |
| reveal_type(self) # N: Revealed type is "__main__.Child" | |
| if self is None: | |
| reveal_type(self) # N: Revealed type is "None" | |
| return None | |
| reveal_type(self) # N: Revealed type is "__main__.Child" | |
| return 3 | |
| [builtins fixtures/isinstance.pyi] | |
| [case testUnreachableAfterToplevelAssert] | |
| import sys | |
| reveal_type(0) # N: Revealed type is "Literal[0]?" | |
| assert sys.platform == 'lol' | |
| reveal_type('') # No error here :-) | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssert2] | |
| import sys | |
| reveal_type(0) # N: Revealed type is "Literal[0]?" | |
| assert sys.version_info[0] == 1 | |
| reveal_type('') # No error here :-) | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssert3] | |
| reveal_type(0) # N: Revealed type is "Literal[0]?" | |
| MYPY = False | |
| assert not MYPY | |
| reveal_type('') # No error here :-) | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssert4] | |
| # flags: --always-false NOPE | |
| reveal_type(0) # N: Revealed type is "Literal[0]?" | |
| NOPE = False | |
| assert NOPE | |
| reveal_type('') # No error here :-) | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssertImport] | |
| import foo | |
| foo.bar() # E: Module has no attribute "bar" | |
| [file foo.py] | |
| import sys | |
| assert sys.platform == 'lol' | |
| def bar() -> None: pass | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssertImport2] | |
| # flags: --platform lol | |
| import foo | |
| foo.bar() # No error :-) | |
| [file foo.py] | |
| import sys | |
| assert sys.platform == 'lol' | |
| def bar() -> None: pass | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssertImportThirdParty] | |
| # flags: --platform unknown | |
| import sys | |
| assert sys.platform == 'linux' | |
| import does_not_exist | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableAfterToplevelAssertImportThirdParty2] | |
| # flags: --platform unknown | |
| import sys | |
| import bad; assert sys.platform == 'linux'; import does_not_exist | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| main:3: error: Cannot find implementation or library stub for module named "bad" | |
| main:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testUnreachableAfterToplevelAssertNotInsideIf] | |
| import sys | |
| if sys.version_info[0] >= 2: | |
| assert sys.platform == 'lol' | |
| reveal_type('') # N: Revealed type is "Literal['']?" | |
| reveal_type('') # N: Revealed type is "Literal['']?" | |
| [builtins fixtures/ops.pyi] | |
| [case testUnreachableFlagWithBadControlFlow1] | |
| # flags: --warn-unreachable | |
| a: int | |
| if isinstance(a, int): | |
| reveal_type(a) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(a) # E: Statement is unreachable | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagWithBadControlFlow2] | |
| # flags: --warn-unreachable | |
| b: int | |
| while isinstance(b, int): | |
| reveal_type(b) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(b) # E: Statement is unreachable | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagWithBadControlFlow3] | |
| # flags: --warn-unreachable | |
| def foo(c: int) -> None: | |
| reveal_type(c) # N: Revealed type is "builtins.int" | |
| assert not isinstance(c, int) | |
| reveal_type(c) # E: Statement is unreachable | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagWithBadControlFlow4] | |
| # flags: --warn-unreachable | |
| d: int | |
| if False: | |
| reveal_type(d) # E: Statement is unreachable | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagWithBadControlFlow5] | |
| # flags: --warn-unreachable | |
| e: int | |
| if True: | |
| reveal_type(e) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(e) # E: Statement is unreachable | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagStatementAfterReturn] | |
| # flags: --warn-unreachable | |
| def foo(x: int) -> None: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return | |
| reveal_type(x) # E: Statement is unreachable | |
| [case testUnreachableFlagTryBlocks] | |
| # flags: --warn-unreachable | |
| def foo(x: int) -> int: | |
| try: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x | |
| reveal_type(x) # E: Statement is unreachable | |
| finally: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| if True: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(x) # E: Statement is unreachable | |
| def bar(x: int) -> int: | |
| try: | |
| if True: | |
| raise Exception() | |
| reveal_type(x) # E: Statement is unreachable | |
| except: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x | |
| else: | |
| reveal_type(x) # E: Statement is unreachable | |
| def baz(x: int) -> int: | |
| try: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| except: | |
| # Mypy assumes all lines could throw an exception | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| return x | |
| [builtins fixtures/exception.pyi] | |
| [case testUnreachableFlagIgnoresSemanticAnalysisUnreachable] | |
| # flags: --warn-unreachable --python-version 3.10 --platform win32 --always-false FOOBAR | |
| import sys | |
| from typing import TYPE_CHECKING | |
| def f1(x: int) -> None: | |
| if TYPE_CHECKING: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(x) | |
| def f2(x: int) -> None: | |
| if not TYPE_CHECKING: | |
| reveal_type(x) | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| def f3(x: int) -> None: | |
| if sys.platform == 'darwin': | |
| reveal_type(x) | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| def f4(x: int) -> None: | |
| if sys.platform == 'win32': | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(x) | |
| def f5(x: int) -> None: | |
| if sys.version_info == (2, 7): | |
| reveal_type(x) | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| def f6(x: int) -> None: | |
| if sys.version_info >= (3, 10): | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(x) | |
| if sys.version_info >= (3, 11): | |
| reveal_type(x) | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| def f7(x: int) -> None: | |
| FOOBAR = "" | |
| if FOOBAR: | |
| reveal_type(x) | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| [builtins fixtures/ops.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testUnreachableFlagIgnoresSemanticAnalysisExprUnreachable] | |
| # flags: --warn-unreachable --always-false FOOBAR | |
| import sys | |
| from typing import TYPE_CHECKING | |
| FOOBAR = "" | |
| def foo() -> bool: ... | |
| lst = [1, 2, 3] | |
| a = FOOBAR and foo() | |
| b = (not FOOBAR) or foo() | |
| c = 1 if FOOBAR else 2 | |
| d = [x for x in lst if FOOBAR] | |
| [builtins fixtures/list.pyi] | |
| [typing fixtures/typing-medium.pyi] | |
| [case testUnreachableFlagOkWithDeadStatements] | |
| # flags: --warn-unreachable | |
| from typing import NoReturn | |
| def assert_never(x: NoReturn) -> NoReturn: | |
| assert False | |
| def nonthrowing_assert_never(x: NoReturn) -> None: ... | |
| def expect_str(x: str) -> str: pass | |
| x: int | |
| if False: | |
| assert False | |
| reveal_type(x) # E: Statement is unreachable | |
| if False: | |
| raise Exception() | |
| reveal_type(x) # E: Statement is unreachable | |
| if False: | |
| assert_never(x) | |
| reveal_type(x) # E: Statement is unreachable | |
| if False: | |
| nonthrowing_assert_never(x) # E: Statement is unreachable | |
| reveal_type(x) | |
| if False: | |
| # Ignore obvious type errors | |
| assert_never(expect_str(x)) | |
| reveal_type(x) # E: Statement is unreachable | |
| [builtins fixtures/exception.pyi] | |
| [case testNeverVariants] | |
| from typing import Never | |
| from typing_extensions import Never as TENever | |
| from typing import NoReturn | |
| from typing_extensions import NoReturn as TENoReturn | |
| from mypy_extensions import NoReturn as MENoReturn | |
| bottom1: Never | |
| reveal_type(bottom1) # N: Revealed type is "Never" | |
| bottom2: TENever | |
| reveal_type(bottom2) # N: Revealed type is "Never" | |
| bottom3: NoReturn | |
| reveal_type(bottom3) # N: Revealed type is "Never" | |
| bottom4: TENoReturn | |
| reveal_type(bottom4) # N: Revealed type is "Never" | |
| bottom5: MENoReturn | |
| reveal_type(bottom5) # N: Revealed type is "Never" | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagExpressions] | |
| # flags: --warn-unreachable | |
| def foo() -> bool: ... | |
| lst = [1, 2, 3, 4] | |
| a = True or foo() # E: Right operand of "or" is never evaluated | |
| b = 42 or False # E: Right operand of "or" is never evaluated | |
| d = False and foo() # E: Right operand of "and" is never evaluated | |
| e = True or (True or (True or foo())) # E: Right operand of "or" is never evaluated | |
| f = (True or foo()) or (True or foo()) # E: Right operand of "or" is never evaluated | |
| k = [x for x in lst if isinstance(x, int) or foo()] # E: Right operand of "or" is never evaluated | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableFlagMiscTestCaseMissingMethod] | |
| # flags: --warn-unreachable | |
| class Case1: | |
| def test1(self) -> bool: | |
| return False and self.missing() # E: Right operand of "and" is never evaluated | |
| def test2(self) -> bool: | |
| return not self.property_decorator_missing and self.missing() # E: Function "property_decorator_missing" could always be true in boolean context \ | |
| # E: Right operand of "and" is never evaluated | |
| def property_decorator_missing(self) -> bool: | |
| return True | |
| [builtins fixtures/bool.pyi] | |
| [case testUnreachableFlagWithGenerics] | |
| # flags: --warn-unreachable | |
| from typing import TypeVar, Generic | |
| T1 = TypeVar('T1', bound=int) | |
| T2 = TypeVar('T2', int, str) | |
| T3 = TypeVar('T3', None, str) | |
| def test1(x: T1) -> T1: | |
| if isinstance(x, int): | |
| reveal_type(x) # N: Revealed type is "T1`-1" | |
| else: | |
| reveal_type(x) # E: Statement is unreachable | |
| return x | |
| def test2(x: T2) -> T2: | |
| if isinstance(x, int): | |
| reveal_type(x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(x) # N: Revealed type is "builtins.str" | |
| if False: | |
| # This is unreachable, but we don't report an error, unfortunately. | |
| # The presence of the TypeVar with values unfortunately currently shuts | |
| # down type-checking for this entire function. | |
| # TODO: Find a way of removing this limitation | |
| reveal_type(x) | |
| return x | |
| class Test3(Generic[T2]): | |
| x: T2 | |
| def func(self) -> None: | |
| if isinstance(self.x, int): | |
| reveal_type(self.x) # N: Revealed type is "builtins.int" | |
| else: | |
| reveal_type(self.x) # N: Revealed type is "builtins.str" | |
| if False: | |
| # Same issue as above | |
| reveal_type(self.x) | |
| class Test4(Generic[T3]): | |
| def __init__(self, x: T3): | |
| # https://github.com/python/mypy/issues/9456 | |
| # On TypeVars with value restrictions, we currently have no way | |
| # of checking a statement for all the type expansions. | |
| # Thus unreachable warnings are disabled | |
| if x and False: | |
| pass | |
| # This test should fail after this limitation is removed. | |
| if False and x: | |
| pass | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testUnreachableBlockStaysUnreachableWithTypeVarConstraints] | |
| # flags: --always-false COMPILE_TIME_FALSE | |
| from typing import TypeVar | |
| COMPILE_TIME_FALSE = False | |
| T = TypeVar("T", int, str) | |
| def foo(x: T) -> T: | |
| if COMPILE_TIME_FALSE: | |
| return "bad" | |
| return x | |
| [case testUnreachableFlagContextManagersNoSuppress] | |
| # flags: --warn-unreachable | |
| from contextlib import contextmanager | |
| from typing import Literal, Optional, Iterator, Any | |
| class DoesNotSuppress1: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Optional[bool]: ... | |
| class DoesNotSuppress2: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Literal[False]: ... | |
| class DoesNotSuppress3: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Any: ... | |
| class DoesNotSuppress4: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> None: ... | |
| @contextmanager | |
| def simple() -> Iterator[int]: | |
| yield 3 | |
| def cond() -> bool: ... | |
| def noop() -> None: ... | |
| def f_no_suppress_1a() -> int: | |
| with DoesNotSuppress1(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_1b() -> int: | |
| with DoesNotSuppress1(): | |
| if cond(): | |
| return 3 | |
| else: | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_2() -> int: | |
| with DoesNotSuppress2(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_3() -> int: | |
| with DoesNotSuppress3(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_4() -> int: | |
| with DoesNotSuppress4(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_5() -> int: | |
| with simple(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| [typing fixtures/typing-medium.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagContextManagersSuppressed] | |
| # flags: --warn-unreachable | |
| from contextlib import contextmanager | |
| from typing import Optional, Iterator, Literal, Any | |
| class DoesNotSuppress: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Optional[bool]: ... | |
| class Suppresses1: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> bool: ... | |
| class Suppresses2: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Literal[True]: ... | |
| def cond() -> bool: ... | |
| def noop() -> None: ... | |
| def f_suppress_1a() -> int: # E: Missing return statement | |
| with Suppresses1(): | |
| return 3 | |
| noop() | |
| def f_suppress_1b() -> int: # E: Missing return statement | |
| with Suppresses1(): | |
| if cond(): | |
| return 3 | |
| else: | |
| return 3 | |
| noop() | |
| def f_suppress_2() -> int: # E: Missing return statement | |
| with Suppresses2(): | |
| return 3 | |
| noop() | |
| def f_mix() -> int: # E: Missing return statement | |
| with DoesNotSuppress(), Suppresses1(), DoesNotSuppress(): | |
| return 3 | |
| noop() | |
| [typing fixtures/typing-medium.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagContextManagersSuppressedNoStrictOptional] | |
| # flags: --warn-unreachable --no-strict-optional | |
| from contextlib import contextmanager | |
| from typing import Optional, Iterator, Literal, Any | |
| class DoesNotSuppress1: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Optional[bool]: ... | |
| # Normally, this should suppress. But when strict-optional mode is disabled, we can't | |
| # necessarily distinguish between bool and Optional[bool]. So we default to assuming | |
| # no suppression, since that's what most context managers will do. | |
| class DoesNotSuppress2: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> bool: ... | |
| # But if we see Literal[True], it's pretty unlikely the return type is actually meant to | |
| # be 'Optional[Literal[True]]'. So, we optimistically assume this is meant to be suppressing. | |
| class Suppresses: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> Literal[True]: ... | |
| def noop() -> None: ... | |
| def f_no_suppress_1() -> int: | |
| with DoesNotSuppress1(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_no_suppress_2() -> int: | |
| with DoesNotSuppress1(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_suppress() -> int: # E: Missing return statement | |
| with Suppresses(): | |
| return 3 | |
| noop() | |
| [typing fixtures/typing-medium.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagContextAsyncManagersNoSuppress] | |
| # flags: --warn-unreachable | |
| from contextlib import asynccontextmanager | |
| from typing import Optional, AsyncIterator, Literal, Any | |
| class DoesNotSuppress1: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> Optional[bool]: ... | |
| class DoesNotSuppress2: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> Literal[False]: ... | |
| class DoesNotSuppress3: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> Any: ... | |
| class DoesNotSuppress4: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> None: ... | |
| @asynccontextmanager | |
| async def simple() -> AsyncIterator[int]: | |
| yield 3 | |
| def cond() -> bool: ... | |
| def noop() -> None: ... | |
| async def f_no_suppress_1a() -> int: | |
| async with DoesNotSuppress1(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_no_suppress_1b() -> int: | |
| async with DoesNotSuppress1(): | |
| if cond(): | |
| return 3 | |
| else: | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_no_suppress_2() -> int: | |
| async with DoesNotSuppress2(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_no_suppress_3() -> int: | |
| async with DoesNotSuppress3(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_no_suppress_4() -> int: | |
| async with DoesNotSuppress4(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_no_suppress_5() -> int: | |
| async with simple(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| [typing fixtures/typing-full.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagContextAsyncManagersSuppressed] | |
| # flags: --warn-unreachable | |
| from contextlib import asynccontextmanager | |
| from typing import Optional, AsyncIterator, Literal, Any | |
| class DoesNotSuppress: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> Optional[bool]: ... | |
| class Suppresses1: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> bool: ... | |
| class Suppresses2: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> Literal[True]: ... | |
| def cond() -> bool: ... | |
| def noop() -> None: ... | |
| async def f_suppress_1() -> int: # E: Missing return statement | |
| async with Suppresses1(): | |
| return 3 | |
| noop() | |
| async def f_suppress_2() -> int: # E: Missing return statement | |
| async with Suppresses1(): | |
| if cond(): | |
| return 3 | |
| else: | |
| return 3 | |
| noop() | |
| async def f_suppress_3() -> int: # E: Missing return statement | |
| async with Suppresses2(): | |
| return 3 | |
| noop() | |
| async def f_mix() -> int: # E: Missing return statement | |
| async with DoesNotSuppress(), Suppresses1(), DoesNotSuppress(): | |
| return 3 | |
| noop() | |
| [typing fixtures/typing-full.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFlagContextAsyncManagersAbnormal] | |
| # flags: --warn-unreachable | |
| from contextlib import asynccontextmanager | |
| from typing import Optional, AsyncIterator, Literal, Any | |
| class RegularManager: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> bool: ... | |
| class AsyncManager: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> bool: ... | |
| def noop() -> None: ... | |
| async def f_bad_1() -> int: | |
| async with RegularManager(): # E: "RegularManager" has no attribute "__aenter__"; maybe "__enter__"? \ | |
| # E: "RegularManager" has no attribute "__aexit__"; maybe "__exit__"? | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| def f_bad_2() -> int: | |
| with AsyncManager(): # E: "AsyncManager" has no attribute "__enter__"; maybe "__aenter__"? \ | |
| # E: "AsyncManager" has no attribute "__exit__"; maybe "__aexit__"? | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| # TODO: We should consider reporting an error when the user tries using | |
| # context manager with malformed signatures instead of silently continuing. | |
| class RegularManagerMalformedSignature: | |
| def __enter__(self) -> int: ... | |
| def __exit__(self, exctype: object, excvalue: object, traceback: object) -> object: ... | |
| class AsyncManagerMalformedSignature: | |
| async def __aenter__(self) -> int: ... | |
| async def __aexit__(self, exctype: object, excvalue: object, traceback: object) -> object: ... | |
| def f_malformed_1() -> int: | |
| with RegularManagerMalformedSignature(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| async def f_malformed_2() -> int: | |
| async with AsyncManagerMalformedSignature(): | |
| return 3 | |
| noop() # E: Statement is unreachable | |
| [typing fixtures/typing-full.pyi] | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableUntypedFunction] | |
| # flags: --warn-unreachable | |
| def test_untyped_fn(obj): | |
| assert obj.prop is True | |
| obj.update(prop=False) | |
| obj.reload() | |
| assert obj.prop is False | |
| reveal_type(obj.prop) | |
| def test_typed_fn(obj) -> None: | |
| assert obj.prop is True | |
| obj.update(prop=False) | |
| obj.reload() | |
| assert obj.prop is False | |
| reveal_type(obj.prop) # E: Statement is unreachable | |
| [case testUnreachableCheckedUntypedFunction] | |
| # flags: --warn-unreachable --check-untyped-defs | |
| def test_untyped_fn(obj): | |
| assert obj.prop is True | |
| obj.update(prop=False) | |
| obj.reload() | |
| assert obj.prop is False | |
| reveal_type(obj.prop) # E: Statement is unreachable | |
| [case testConditionalTypeVarException] | |
| # every part of this test case was necessary to trigger the crash | |
| import sys | |
| from typing import TypeVar | |
| T = TypeVar("T", int, str) | |
| def f(t: T) -> None: | |
| if sys.platform == "lol": | |
| try: | |
| pass | |
| except BaseException as e: | |
| pass | |
| [builtins fixtures/dict.pyi] | |
| [case testUnreachableLiteral] | |
| # flags: --warn-unreachable | |
| from typing import Literal | |
| def nope() -> Literal[False]: ... | |
| def f() -> None: | |
| if nope(): | |
| x = 1 # E: Statement is unreachable | |
| [builtins fixtures/dict.pyi] | |
| [case testUnreachableLiteralFrom__bool__] | |
| # flags: --warn-unreachable | |
| from typing import Literal | |
| class Truth: | |
| def __bool__(self) -> Literal[True]: ... | |
| class Lie: | |
| def __bool__(self) -> Literal[False]: ... | |
| class Maybe: | |
| def __bool__(self) -> Literal[True | False]: ... | |
| t = Truth() | |
| if t: | |
| x = 1 | |
| else: | |
| x = 2 # E: Statement is unreachable | |
| if Lie(): | |
| x = 3 # E: Statement is unreachable | |
| if Maybe(): | |
| x = 4 | |
| def foo() -> bool: ... | |
| y = Truth() or foo() # E: Right operand of "or" is never evaluated | |
| z = Lie() and foo() # E: Right operand of "and" is never evaluated | |
| [builtins fixtures/dict.pyi] | |
| [case testUnreachableModuleBody1] | |
| # flags: --warn-unreachable | |
| from typing import NoReturn | |
| def foo() -> NoReturn: | |
| raise Exception("foo") | |
| foo() | |
| x = 1 # E: Statement is unreachable | |
| [builtins fixtures/exception.pyi] | |
| [case testUnreachableModuleBody2] | |
| # flags: --warn-unreachable | |
| raise Exception | |
| x = 1 # E: Statement is unreachable | |
| [builtins fixtures/exception.pyi] | |
| [case testUnreachableNoReturnBinaryOps] | |
| # flags: --warn-unreachable | |
| from typing import NoReturn | |
| a: NoReturn | |
| a and 1 # E: Right operand of "and" is never evaluated | |
| a or 1 # E: Right operand of "or" is never evaluated | |
| a or a # E: Right operand of "or" is never evaluated | |
| 1 and a and 1 # E: Right operand of "and" is never evaluated | |
| a and a # E: Right operand of "and" is never evaluated | |
| [builtins fixtures/exception.pyi] | |
| [case testUnreachableFlagWithTerminalBranchInDeferredNode] | |
| # flags: --warn-unreachable | |
| from typing import NoReturn | |
| def assert_never(x: NoReturn) -> NoReturn: ... | |
| def force_forward_ref() -> int: | |
| return 4 | |
| def f(value: None) -> None: | |
| x | |
| if value is not None: | |
| assert_never(value) | |
| x = force_forward_ref() | |
| [builtins fixtures/exception.pyi] | |
| [case testSetitemNoReturn] | |
| # flags: --warn-unreachable | |
| from typing import NoReturn | |
| class Foo: | |
| def __setitem__(self, key: str, value: str) -> NoReturn: | |
| raise Exception | |
| Foo()['a'] = 'a' | |
| x = 0 # E: Statement is unreachable | |
| [builtins fixtures/exception.pyi] | |
| [case TestNoImplicNoReturnFromError] | |
| # flags: --warn-unreachable | |
| from typing import TypeVar | |
| T = TypeVar("T") | |
| class Foo: | |
| def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar | |
| raise Exception | |
| def f() -> None: | |
| Foo()['a'] = 'a' | |
| x = 0 # This should not be reported as unreachable | |
| [builtins fixtures/exception.pyi] | |
| [case testIntentionallyEmptyGeneratorFunction] | |
| # flags: --warn-unreachable | |
| from typing import Generator | |
| def f() -> Generator[None, None, None]: | |
| return | |
| yield | |
| [case testIntentionallyEmptyGeneratorFunction_None] | |
| # flags: --warn-unreachable | |
| from typing import Generator | |
| def f() -> Generator[None, None, None]: | |
| return None | |
| yield None | |
| [case testLambdaNoReturn] | |
| # flags: --warn-unreachable | |
| from typing import Callable, NoReturn | |
| def foo() -> NoReturn: | |
| raise | |
| f1 = lambda: foo() | |
| x = 0 # not unreachable | |
| f2: Callable[[], NoReturn] = lambda: foo() | |
| x = 0 # not unreachable | |
| [case testAttributeNoReturn] | |
| # flags: --warn-unreachable | |
| from typing import Optional, NoReturn, TypeVar | |
| def foo() -> NoReturn: | |
| raise | |
| T = TypeVar("T") | |
| def bar(x: Optional[list[T]] = None) -> T: | |
| ... | |
| reveal_type(bar().attr) # N: Revealed type is "Never" | |
| 1 # not unreachable | |
| reveal_type(foo().attr) # N: Revealed type is "Never" | |
| 1 # E: Statement is unreachable | |
| [case testIgnoreReturningNotImplemented] | |
| # flags: --warn-unreachable | |
| class C: | |
| def __add__(self, o: C) -> C: | |
| if not isinstance(o, C): | |
| return NotImplemented | |
| return C() | |
| def __sub__(self, o: C) -> C: | |
| if isinstance(o, C): | |
| return C() | |
| return NotImplemented | |
| def __mul__(self, o: C) -> C: | |
| if isinstance(o, C): | |
| return C() | |
| else: | |
| return NotImplemented | |
| [builtins fixtures/isinstance.pyi] | |
| [case testIgnoreReturningNotImplementedSimple] | |
| # flags: --warn-unreachable | |
| -- This behavior may or may not actually be desirable. | |
| -- This test just serves to document mypy's current behavior. | |
| -- And mypy's handling of NotImplemented has long been known | |
| -- to be suboptimal, eg https://github.com/python/mypy/issues/363. | |
| -- If you change this behavior, please change the corresponding docs | |
| -- https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-warn-unreachable | |
| def foo() -> None: | |
| return None | |
| return NotImplemented #no error | |
| return None # E: Statement is unreachable | |
| [builtins fixtures/isinstance.pyi] | |
| [case testPassAndEllipsisUnreachable] | |
| # flags: --warn-unreachable | |
| def f() -> None: | |
| return | |
| pass # E: Statement is unreachable | |
| def g() -> None: | |
| return | |
| ... # E: Statement is unreachable | |
| [builtins fixtures/isinstance.pyi] | |
| [case testUnreachableStatementPrettyHighlighting] | |
| # flags: --warn-unreachable --pretty | |
| def x() -> None: | |
| assert False | |
| if 5: | |
| pass | |
| [out] | |
| main:4: error: Statement is unreachable | |
| if 5: | |
| ^~~~~ | |
| [case testReachableEqualityNarrowingAny] | |
| # flags: --warn-unreachable | |
| # https://github.com/python/mypy/issues/20532 | |
| from __future__ import annotations | |
| from typing import Any | |
| def print(s: str): pass | |
| def main(contents: Any, commit: str | None) -> None: | |
| if ( | |
| contents.get("commit") == commit | |
| and (commit is not None or print("can_be_reached")) | |
| ): | |
| pass | |
| main({"commit": None}, None) | |
| [builtins fixtures/tuple.pyi] | |
| [case testUnreachableFunctionAfterTopLevelAssert] | |
| def foo() -> int: | |
| ... | |
| raise Exception | |
| x = foo() | |
| def test() -> None: | |
| # It is questionable to allow this, this test exists to check 1:1 | |
| # behavior match of parallel checking with sequential checking. | |
| x + "hm..." | |
| class C: | |
| def test(self) -> None: | |
| x + "same here..." | |
| [builtins fixtures/exception.pyi] | |
| [case testUnreachableFunctionAfterClassLevelAssert] | |
| def foo() -> int: | |
| ... | |
| class C: | |
| x = foo() | |
| raise Exception | |
| def test(self) -> None: | |
| # It is questionable to allow this, this test exists to check 1:1 | |
| # behavior match of parallel checking with sequential checking. | |
| C.x + "hm..." | |
| def test_outer() -> None: | |
| C.x + "no way" # E: Unsupported left operand type for + ("int") | |
| [builtins fixtures/exception.pyi] | |
| [case testIgnoreInPlatformSpecificCodeUsed] | |
| # flags: --warn-unused-ignores --platform unknown | |
| import sys | |
| assert sys.platform == "win32" | |
| 42 + "no way" # type: ignore[operator] | |
| [builtins fixtures/isinstancelist.pyi] | |
| [case testCheckUnreachableBasics] | |
| # flags: --check-unreachable --warn-unreachable | |
| if False: | |
| reveal_type(5) # E: Statement is unreachable \ | |
| # N: Revealed type is "Literal[5]?" | |
| [case testCheckUnreachableOnlyFlagsOnce] | |
| # flags: --check-unreachable --warn-unreachable | |
| if False: | |
| if False: # E: Statement is unreachable | |
| "not flagged!" | |
| [case testCheckUnreachableHandlesFinallyRight] | |
| # flags: --check-unreachable --warn-unreachable | |
| def f1() -> None: | |
| # it doesn't reset suppression | |
| assert False | |
| try: # E: Statement is unreachable | |
| pass | |
| finally: | |
| reveal_type(5) # N: Revealed type is "Literal[5]?" | |
| "something" | |
| def f2() -> None: | |
| # but it does still mark things after as unreachable | |
| try: | |
| pass | |
| finally: | |
| assert False | |
| reveal_type(5) # E: Statement is unreachable \ | |
| # N: Revealed type is "Literal[5]?" | |
| "something" # E: Statement is unreachable |