| from __future__ import annotations |
| |
| import tempfile |
| import unittest |
| from pathlib import Path |
| |
| import pytest |
| |
| from mypy import build |
| from mypy.options import Options |
| from mypyc.build import construct_groups |
| from mypyc.codegen import emitmodule |
| from mypyc.errors import Errors |
| from mypyc.irbuild.mapper import Mapper |
| from mypyc.options import CompilerOptions |
| |
| |
| class FakeSCC: |
| def __init__(self, mod_ids: list[str]) -> None: |
| self.mod_ids = mod_ids |
| |
| |
| class TestEmitModule(unittest.TestCase): |
| def test_compile_modules_to_ir_orders_scc_members_deterministically(self) -> None: |
| with tempfile.TemporaryDirectory() as tmp_dir, pytest.MonkeyPatch.context() as monkeypatch: |
| tmp_path = Path(tmp_dir) |
| a_py = tmp_path / "a.py" |
| b_py = tmp_path / "b.py" |
| a_py.write_text("import b\n\nclass A: pass\nclass C(A): pass\n", encoding="utf-8") |
| b_py.write_text( |
| "import a\n\nclass B(a.A): pass\nclass D(a.A): pass\n", encoding="utf-8" |
| ) |
| |
| sources = [ |
| build.BuildSource(str(a_py), "a", None), |
| build.BuildSource(str(b_py), "b", None), |
| ] |
| options = Options() |
| options.preserve_asts = True |
| options.mypy_path = [str(tmp_path)] |
| options.cache_dir = str(tmp_path / ".mypy_cache") |
| for source in sources: |
| options.per_module_options.setdefault(source.module, {})["mypyc"] = True |
| |
| compiler_options = CompilerOptions(strict_traceback_checks=True) |
| groups = construct_groups( |
| sources, False, use_shared_lib=True, group_name_override=None |
| ) |
| result = emitmodule.parse_and_typecheck(sources, options, compiler_options, groups) |
| try: |
| group_map = { |
| source.module: lib_name for group, lib_name in groups for source in group |
| } |
| children_by_order = [] |
| for order in (["a", "b"], ["b", "a"]): |
| monkeypatch.setattr( |
| emitmodule, |
| "sorted_components", |
| lambda graph, order=order: [FakeSCC(order)], |
| ) |
| mapper = Mapper(group_map) |
| errors = Errors(options) |
| modules = emitmodule.compile_modules_to_ir( |
| result, mapper, compiler_options, errors |
| ) |
| assert errors.num_errors == 0, errors.new_messages() |
| classes = { |
| cl.fullname: cl for module in modules.values() for cl in module.classes |
| } |
| children = classes["a.A"].children |
| assert children is not None |
| children_by_order.append([child.fullname for child in children]) |
| |
| assert children_by_order[1] == children_by_order[0] |
| finally: |
| result.manager.metastore.close() |