blob: 71704788ff7dcede31222e2c2941c07123ffa1ac [file]
-- Test cases for import returned by the native parser using a side channel
-- In particular, test import flags related to reachability and priority when ordering SCCs
[case testNoImport]
# No imports
print()
[out]
[case testSimpleImport]
import foo
[out]
1: import foo
[case testMultipleImports]
import foo
import bar
import baz
[out]
1: import foo
2: import bar
3: import baz
[case testImportAs]
import foo as f
import bar as b
[out]
1: import foo as f
2: import bar as b
[case testFromImport]
from foo import bar
[out]
1: from foo import bar
[case testFromImportMultiple]
from foo import bar, baz, qux
[out]
1: from foo import bar, baz, qux
[case testFromImportAs]
from foo import bar as b, baz as z
[out]
1: from foo import bar as b, baz as z
[case testRelativeImport]
from . import foo
from .. import bar
from ...baz import qux
[out]
1: from . import foo
2: from .. import bar
3: from ...baz import qux
[case testNonTopLevelImport]
def f():
import foo
from bar import baz
[out]
2: import foo [not top_level]
3: from bar import baz [not top_level]
[case testImportInClass]
class Foo:
import bar
[out]
2: import bar
[case testUnreachableImportPY2]
# Imports in unreachable blocks should not appear
if PY2:
import unreachable_module
import reachable_module
[out]
4: import reachable_module
[case testReachableImportPY3]
# Imports in reachable if PY3 blocks should appear
if PY3:
import reachable_module
[out]
3: import reachable_module
[case testUnreachableElseBlock]
# Imports in unreachable else block should not appear
if PY3:
import reachable
else:
import unreachable
[out]
3: import reachable
[case testMixedReachableUnreachable]
# Mix of reachable and unreachable imports
import before
if PY2:
import unreachable_in_if
else:
import reachable_in_else
import after
[out]
2: import before
6: import reachable_in_else
7: import after
[case testNestedUnreachable]
# Nested unreachable blocks
if PY2:
import outer_unreachable
if True:
import inner_unreachable
import reachable
[out]
6: import reachable
[case testUnreachableWithTopLevel]
# Unreachable imports together with top_level flag handling
def f():
if PY2:
import unreachable_func
import reachable_func
if PY2:
import unreachable_top
import reachable_top
[out]
5: import reachable_func [not top_level]
8: import reachable_top
[case testVersionCheckUnreachable]
# sys.version_info check makes else unreachable
import sys
if sys.version_info >= (3, 8):
import reachable_version_check
else:
import unreachable_old_version
[out]
2: import sys
4: import reachable_version_check
[case testMultipeBranchesUnreachable]
if PY2:
import unreachable_if
elif PY2:
import unreachable_elif
else:
import reachable_else
[out]
6: import reachable_else
[case testMypyOnlyImport]
# Imports in TYPE_CHECKING blocks are mypy_only
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import mypy_only_module
import regular_module
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_module [mypy_only]
5: import regular_module
[case testMypyNameAlias]
# MYPY is also recognized as mypy_only
if MYPY:
import only_for_mypy
import for_everyone
[out]
3: import only_for_mypy [mypy_only]
4: import for_everyone
[case testMypyOnlyElseBranch]
# Else branch of TYPE_CHECKING is unreachable (runtime-only, not analyzed by mypy)
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import for_mypy
else:
import for_runtime
[out]
2: from typing import TYPE_CHECKING
4: import for_mypy [mypy_only]
[case testNestedMypyOnly]
# Nested blocks inside TYPE_CHECKING are also mypy_only
from typing import TYPE_CHECKING
if TYPE_CHECKING:
if True:
import deeply_nested
import also_mypy_only
[out]
2: from typing import TYPE_CHECKING
5: import deeply_nested [mypy_only]
6: import also_mypy_only [mypy_only]
[case testMypyOnlyInFunction]
# Mypy-only imports in functions
from typing import TYPE_CHECKING
def f():
if TYPE_CHECKING:
import mypy_func_import
import regular_func_import
[out]
2: from typing import TYPE_CHECKING
5: import mypy_func_import [not top_level, mypy_only]
6: import regular_func_import [not top_level]
[case testMypyOnlyElifBranch]
# Elif after TYPE_CHECKING is unreachable (runtime-only)
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import for_mypy
elif True:
import for_runtime_elif
[out]
2: from typing import TYPE_CHECKING
4: import for_mypy [mypy_only]
[case testNotMypyFalseBranch]
# Not TYPE_CHECKING makes body unreachable, else is mypy_only
from typing import TYPE_CHECKING
if not TYPE_CHECKING:
import runtime_only
else:
import mypy_only
[out]
2: from typing import TYPE_CHECKING
6: import mypy_only [mypy_only]
[case testMixedMypyOnlyAndUnreachable]
# Combination of mypy_only and unreachable
from typing import TYPE_CHECKING
if PY2:
import unreachable_py2
if TYPE_CHECKING:
import mypy_only_import
if PY3:
import always_reachable
[out]
2: from typing import TYPE_CHECKING
6: import mypy_only_import [mypy_only]
8: import always_reachable
[case testTypingExtensionsTypeChecking]
# typing_extensions.TYPE_CHECKING is also recognized
from typing_extensions import TYPE_CHECKING
if TYPE_CHECKING:
import mypy_import
[out]
2: from typing_extensions import TYPE_CHECKING
4: import mypy_import [mypy_only]
[case testUnknownCondition]
# Unknown conditions - all branches reachable
if x:
import in_if
else:
import in_else
[out]
3: import in_if
5: import in_else
[case testUnknownConditionWithElif]
# Unknown conditions with elif
if unknown_var:
import first
elif another_var:
import second
else:
import third
[out]
3: import first
5: import second
7: import third
[case testMixedKnownUnknown]
# Mix of known and unknown conditions
if TYPE_CHECKING:
import mypy_only
if some_var:
import maybe_reachable
if PY2:
import unreachable
[out]
3: import mypy_only [mypy_only]
5: import maybe_reachable
[case testNestedUnknownInMypyOnly]
# Unknown condition nested in mypy-only block
from typing import TYPE_CHECKING
if TYPE_CHECKING:
if condition:
import nested_mypy
import also_mypy
[out]
2: from typing import TYPE_CHECKING
5: import nested_mypy [mypy_only]
6: import also_mypy [mypy_only]
[case testUnknownAfterMypyTrue]
# Unknown elif after TYPE_CHECKING is unreachable
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import for_mypy
elif x:
import unreachable_elif
[out]
2: from typing import TYPE_CHECKING
4: import for_mypy [mypy_only]
[case testStarImport]
from foo import *
[out]
1: from foo import *
[case testStarImportInFunction]
def f():
from foo import *
[out]
2: from foo import * [not top_level]
[case testMypyOnlyStarImport]
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mypy_types import *
from regular import *
[out]
1: from typing import TYPE_CHECKING
3: from mypy_types import * [mypy_only]
4: from regular import *
[case testUnreachableStarImport]
if PY2:
from unreachable import *
from reachable import *
[out]
3: from reachable import *
[case testNotPY2]
# not PY2 should be always true
if not PY2:
import always_reachable
[out]
3: import always_reachable
[case testNotPY3]
# not PY3 should be always false
if not PY3:
import unreachable
import reachable
[out]
4: import reachable
[case testNotPY3Else]
# not PY3 else branch should be reachable
if not PY3:
import unreachable_if
else:
import reachable_else
[out]
5: import reachable_else
[case testBoolAndAlwaysTrueWithMypyTrue]
# PY3 and TYPE_CHECKING - both true, result is mypy_true
from typing import TYPE_CHECKING
if PY3 and TYPE_CHECKING:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_import [mypy_only]
[case testBoolAndAlwaysTrueWithUnknown]
# PY3 and unknown - result is unknown, both branches reachable
if PY3 and some_var:
import maybe_reachable
else:
import also_maybe_reachable
[out]
3: import maybe_reachable
5: import also_maybe_reachable
[case testBoolAndAlwaysFalseWithAnything]
# PY2 and anything - result is always false
if PY2 and some_var:
import unreachable
import reachable
[out]
4: import reachable
[case testBoolAndMypyFalseWithAlwaysTrue]
# not TYPE_CHECKING and PY3 - result is mypy_false, else is mypy_only
from typing import TYPE_CHECKING
if not TYPE_CHECKING and PY3:
import runtime_only
else:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
6: import mypy_only_import [mypy_only]
[case testBoolAndMypyTrueOnly]
# MYPY and TYPE_CHECKING - both mypy_true, result is mypy_true
from typing import TYPE_CHECKING
if MYPY and TYPE_CHECKING:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_import [mypy_only]
[case testBoolOrAlwaysTrueWithAnything]
# PY3 or anything - result is always true
if PY3 or some_var:
import always_reachable
else:
import unreachable_else
[out]
3: import always_reachable
[case testBoolOrMypyTrueWithAlwaysFalse]
# TYPE_CHECKING or PY2 - result is mypy_true
from typing import TYPE_CHECKING
if TYPE_CHECKING or PY2:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_import [mypy_only]
[case testBoolOrMypyFalseOnly]
# not MYPY or not TYPE_CHECKING - all mypy_false, result is mypy_false, else is mypy_only
from typing import TYPE_CHECKING
if not MYPY or not TYPE_CHECKING:
import runtime_only
else:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
6: import mypy_only_import [mypy_only]
[case testBoolOrAlwaysFalseWithUnknown]
# PY2 or unknown - result is unknown, both branches reachable
if PY2 or some_var:
import maybe_reachable
else:
import also_maybe_reachable
[out]
3: import maybe_reachable
5: import also_maybe_reachable
[case testBoolOrAllFalse]
# PY2 or not TYPE_CHECKING - all false values, result is always_false, else is unreachable
from typing import TYPE_CHECKING
if PY2 or not TYPE_CHECKING:
import runtime_only
else:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
6: import mypy_only_import
[case testBoolComplexAndOr]
# Complex: (PY3 and TYPE_CHECKING) or PY2 - evaluates to mypy_true
from typing import TYPE_CHECKING
if (PY3 and TYPE_CHECKING) or PY2:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_import [mypy_only]
[case testBoolMultipleOr]
# Multiple or: PY2 or PY2 or TYPE_CHECKING - result is mypy_true
from typing import TYPE_CHECKING
if PY2 or PY2 or TYPE_CHECKING:
import mypy_only_import
[out]
2: from typing import TYPE_CHECKING
4: import mypy_only_import [mypy_only]
[case testBoolMultipleAnd]
# Multiple and: PY3 and PY3 and PY3 - result is always_true
if PY3 and PY3 and PY3:
import always_reachable
else:
import unreachable_else
[out]
3: import always_reachable
[case testVersionInfoIndexMajor]
# sys.version_info[0] == 3 should be always true for Python 3.10
import sys
if sys.version_info[0] == 3:
import reachable_py3
else:
import unreachable_not_py3
[out]
2: import sys
4: import reachable_py3
[case testVersionInfoIndexMajorNotEqual]
# sys.version_info[0] == 2 should be always false for Python 3.10
import sys
if sys.version_info[0] == 2:
import unreachable_py2
import reachable
[out]
2: import sys
5: import reachable
[case testVersionInfoIndexMinor]
# sys.version_info[1] >= 10 should be always true for Python 3.10
import sys
if sys.version_info[1] >= 10:
import reachable_310_plus
else:
import unreachable_pre_310
[out]
2: import sys
4: import reachable_310_plus
[case testVersionInfoIndexMinorLess]
# sys.version_info[1] < 10 should be always false for Python 3.10
import sys
if sys.version_info[1] < 10:
import unreachable_pre_310
import reachable
[out]
2: import sys
5: import reachable
[case testVersionInfoIndexMinorGreater]
# sys.version_info[1] > 9 should be always true for Python 3.10
import sys
if sys.version_info[1] > 9:
import reachable_310_plus
[out]
2: import sys
4: import reachable_310_plus
[case testVersionInfoIndexLessOrEqual]
# sys.version_info[0] <= 3 should be always true for Python 3.10
import sys
if sys.version_info[0] <= 3:
import reachable_py3_or_less
[out]
2: import sys
4: import reachable_py3_or_less
[case testVersionInfoIndexNotEqual]
# sys.version_info[0] != 2 should be always true for Python 3.10
import sys
if sys.version_info[0] != 2:
import reachable_not_py2
[out]
2: import sys
4: import reachable_not_py2
[case testVersionInfoSliceExplicit]
# sys.version_info[:2] >= (3, 10) should be always true for Python 3.10
import sys
if sys.version_info[:2] >= (3, 10):
import reachable_310_plus
else:
import unreachable_pre_310
[out]
2: import sys
4: import reachable_310_plus
[case testVersionInfoSliceExplicitBothBounds]
# sys.version_info[0:2] >= (3, 10) should be always true for Python 3.10
import sys
if sys.version_info[0:2] >= (3, 10):
import reachable_310_plus
[out]
2: import sys
4: import reachable_310_plus
[case testVersionInfoSliceExplicitLess]
# sys.version_info[:2] < (3, 10) should be always false for Python 3.10
import sys
if sys.version_info[:2] < (3, 10):
import unreachable_pre_310
import reachable
[out]
2: import sys
5: import reachable
[case testVersionInfoSliceSingleElement]
# sys.version_info[:1] >= (3,) should be always true for Python 3.10
import sys
if sys.version_info[:1] >= (3,):
import reachable_py3
[out]
2: import sys
4: import reachable_py3
[case testVersionInfoSliceSingleElementLess]
# sys.version_info[:1] < (3,) should be always false for Python 3.10
import sys
if sys.version_info[:1] < (3,):
import unreachable_py2
import reachable
[out]
2: import sys
5: import reachable
[case testVersionInfoReversedOperands]
# (3, 8) <= sys.version_info should be always true for Python 3.10
import sys
if (3, 8) <= sys.version_info:
import reachable_38_plus
[out]
2: import sys
4: import reachable_38_plus
[case testVersionInfoReversedGreater]
# (3, 11) > sys.version_info should be always true for Python 3.10
import sys
if (3, 11) > sys.version_info:
import reachable_pre_311
[out]
2: import sys
4: import reachable_pre_311
[case testVersionInfoReversedEquals]
# (3, 10) == sys.version_info should be always true for Python 3.10
import sys
if (3, 10) == sys.version_info:
import reachable_exactly_310
[out]
2: import sys
4: import reachable_exactly_310
[case testVersionInfoEquals]
# sys.version_info == (3, 10) should be always true for Python 3.10
import sys
if sys.version_info == (3, 10):
import reachable_exactly_310
else:
import unreachable_not_310
[out]
2: import sys
4: import reachable_exactly_310
[case testVersionInfoNotEquals]
# sys.version_info != (3, 11) should be always true for Python 3.10
import sys
if sys.version_info != (3, 11):
import reachable_not_311
[out]
2: import sys
4: import reachable_not_311
[case testVersionInfoNotEqualsExact]
# sys.version_info != (3, 10) should be always false for Python 3.10
import sys
if sys.version_info != (3, 10):
import unreachable_not_310
import reachable
[out]
2: import sys
5: import reachable
[case testVersionInfoSliceMinorOnly]
# sys.version_info[1:2] >= (10,) should be always true for Python 3.10
import sys
if sys.version_info[1:2] >= (10,):
import reachable_minor_10_plus
[out]
2: import sys
4: import reachable_minor_10_plus
[case testAttributeTypeChecking]
# typing.TYPE_CHECKING should be recognized as mypy_true
import typing
if typing.TYPE_CHECKING:
import mypy_only_import
[out]
2: import typing
4: import mypy_only_import [mypy_only]
[case testAttributeMYPY]
# foo.MYPY should be recognized as mypy_true
import foo
if foo.MYPY:
import mypy_only_import
[out]
2: import foo
4: import mypy_only_import [mypy_only]
[case testAttributePY2]
# bar.PY2 should be recognized as always_false
import bar
if bar.PY2:
import unreachable
import reachable
[out]
2: import bar
5: import reachable
[case testAttributePY3]
# baz.PY3 should be recognized as always_true
import baz
if baz.PY3:
import always_reachable
[out]
2: import baz
4: import always_reachable
[case testVersionInfoWithBoolAnd]
# Combining version check with TYPE_CHECKING using and
import sys
from typing import TYPE_CHECKING
if sys.version_info >= (3, 8) and TYPE_CHECKING:
import mypy_only_import
[out]
2: import sys
3: from typing import TYPE_CHECKING
5: import mypy_only_import [mypy_only]
[case testVersionInfoWithBoolOr]
# Combining version check with PY2 using or - should be always_true
import sys
if sys.version_info >= (3, 8) or PY2:
import always_reachable
else:
import unreachable_else
[out]
2: import sys
4: import always_reachable
[case testComplexBoolVersionMypyUnknown]
# Complex: (MYPY or unknown) evaluates to MYPY_TRUE, and version_info >= (3,8) is ALWAYS_TRUE
# ALWAYS_TRUE and MYPY_TRUE evaluates to MYPY_TRUE
import sys
if sys.version_info >= (3, 8) and (MYPY or unknown_var):
import mypy_only_import
[out]
3: import sys
5: import mypy_only_import [mypy_only]