| from __future__ import annotations |
| |
| import unittest |
| from typing import cast |
| |
| from mypy.build import Graph |
| from mypy.nodes import Import, MypyFile |
| from mypy.options import Options |
| from mypyc.errors import Errors |
| from mypyc.irbuild.builder import IRBuilder |
| from mypyc.irbuild.mapper import Mapper |
| from mypyc.irbuild.prebuildvisitor import PreBuildVisitor |
| from mypyc.irbuild.statement import ( |
| IMPORT_NATIVE_ATTR, |
| IMPORT_NATIVE_SUBMODULE, |
| IMPORT_NON_NATIVE, |
| classify_import_from, |
| group_consecutive, |
| import_globals_id_and_name, |
| split_import_group_to_python_and_native, |
| ) |
| from mypyc.irbuild.visitor import IRBuilderVisitor |
| from mypyc.options import CompilerOptions |
| |
| |
| def make_builder( |
| *, |
| module_name: str = "pkg.current", |
| native_modules: set[str] | None = None, |
| same_group_modules: set[str] | None = None, |
| graph: set[str] | None = None, |
| ) -> IRBuilder: |
| native_modules = native_modules or set() |
| same_group_modules = same_group_modules or set() |
| group_map: dict[str, str | None] = {module_name: "current-group"} |
| for module in native_modules: |
| group_map[module] = "current-group" if module in same_group_modules else "other-group" |
| |
| errors = Errors(Options()) |
| current_file = MypyFile([], []) |
| current_file._fullname = module_name |
| pbv = PreBuildVisitor(errors, current_file, {}, {}) |
| builder = IRBuilder( |
| module_name, |
| {}, |
| cast(Graph, {name: object() for name in (graph or set())}), |
| errors, |
| Mapper(group_map), |
| pbv, |
| IRBuilderVisitor(), |
| CompilerOptions(), |
| {}, |
| ) |
| builder.set_module(module_name, module_name.replace(".", "/") + ".py") |
| return builder |
| |
| |
| class TestStatementHelpers(unittest.TestCase): |
| def test_import_globals_id_and_name_for_plain_import(self) -> None: |
| assert import_globals_id_and_name("foo.bar", None) == ("foo", "foo") |
| |
| def test_import_globals_id_and_name_for_import_as(self) -> None: |
| assert import_globals_id_and_name("foo.bar", "baz") == ("foo.bar", "baz") |
| |
| def test_split_import_group_to_python_and_native_preserves_runs(self) -> None: |
| builder = make_builder( |
| native_modules={"pkg.alpha", "pkg.beta", "pkg.gamma"}, |
| same_group_modules={"pkg.alpha", "pkg.beta", "pkg.gamma"}, |
| ) |
| group = [ |
| Import([("pkg.alpha", None), ("py_mod", None)]), |
| Import([("pkg.beta", "beta_alias"), ("foreign.mod", None), ("pkg.gamma", None)]), |
| ] |
| group[0].line = 10 |
| group[1].line = 20 |
| |
| result = split_import_group_to_python_and_native(builder, group) |
| |
| assert result == [ |
| ([("pkg.alpha", None, 10)], True), |
| ([("py_mod", None, 10)], False), |
| ([("pkg.beta", "beta_alias", 20)], True), |
| ([("foreign.mod", None, 20)], False), |
| ([("pkg.gamma", None, 20)], True), |
| ] |
| |
| def test_group_consecutive_groups_by_kind_and_preserves_aliases(self) -> None: |
| buckets = group_consecutive( |
| [ |
| (IMPORT_NATIVE_SUBMODULE, "a", "a"), |
| (IMPORT_NATIVE_SUBMODULE, "b", "b_alias"), |
| (IMPORT_NON_NATIVE, "c", "c"), |
| (IMPORT_NATIVE_ATTR, "d", "d_alias"), |
| (IMPORT_NATIVE_ATTR, "e", "e"), |
| ] |
| ) |
| |
| assert [(bucket.kind, bucket.names, bucket.as_names) for bucket in buckets] == [ |
| (IMPORT_NATIVE_SUBMODULE, ["a", "b"], ["a", "b_alias"]), |
| (IMPORT_NON_NATIVE, ["c"], ["c"]), |
| (IMPORT_NATIVE_ATTR, ["d", "e"], ["d_alias", "e"]), |
| ] |
| |
| def test_classify_import_from_groups_consecutive_kinds(self) -> None: |
| builder = make_builder( |
| native_modules={"pkg.native_a", "pkg.native_b"}, |
| same_group_modules={"pkg.native_a", "pkg.native_b"}, |
| graph={"pkg.native_a", "pkg.native_b", "pkg.foreign_a", "pkg.foreign_b"}, |
| ) |
| |
| buckets = classify_import_from( |
| builder, |
| "pkg", |
| ["native_a", "native_b", "foreign_a", "foreign_b"], |
| ["native_a", "native_b_alias", "foreign_a", "foreign_b_alias"], |
| parent_is_native=True, |
| ) |
| |
| assert [(bucket.kind, bucket.names, bucket.as_names) for bucket in buckets] == [ |
| (IMPORT_NATIVE_SUBMODULE, ["native_a", "native_b"], ["native_a", "native_b_alias"]), |
| (IMPORT_NON_NATIVE, ["foreign_a", "foreign_b"], ["foreign_a", "foreign_b_alias"]), |
| ] |
| |
| def test_classify_import_from_treats_missing_name_under_native_parent_as_attr(self) -> None: |
| builder = make_builder(graph={"pkg.foreign"}) |
| |
| buckets = classify_import_from( |
| builder, |
| "pkg", |
| ["attr_name", "foreign"], |
| ["attr_alias", "foreign_alias"], |
| parent_is_native=True, |
| ) |
| |
| assert [(bucket.kind, bucket.names, bucket.as_names) for bucket in buckets] == [ |
| (IMPORT_NATIVE_ATTR, ["attr_name"], ["attr_alias"]), |
| (IMPORT_NON_NATIVE, ["foreign"], ["foreign_alias"]), |
| ] |
| |
| def test_classify_import_from_without_native_parent_never_uses_native_attr(self) -> None: |
| builder = make_builder() |
| |
| buckets = classify_import_from( |
| builder, "pkg", ["attr_name"], ["attr_alias"], parent_is_native=False |
| ) |
| |
| assert [(bucket.kind, bucket.names, bucket.as_names) for bucket in buckets] == [ |
| (IMPORT_NON_NATIVE, ["attr_name"], ["attr_alias"]) |
| ] |