scripts/tests/proof_generator/test_infer_imports.py
scripts/tests/proof_generator/test_infer_imports.pyBrowse 41 files
1,288 tokens
5,205 bytes
Token encoding: o200k_base
Snapshot a9fb1c3
← Back to SKILL.md
1import subprocess2import sys3from pathlib import Path4 5import pytest6 7sys.path.insert(0, str(Path(__file__).resolve().parents[2]))8 9from generator_testlib import ( # noqa: F40110 _commit,11 _free_function_move_with_module_level_caller,12 _git,13 _method_onto_class,14 _write,15)16from mechanical_refactor_proof_generator import (17 infer_recipe,18 recipe_to_script,19)20 21 22def test_infer_recipe_infers_added_module_imports(repo: Path) -> None:23 """An import the destination module gains (the moved code needs it) is inferred."""24 _write(25 repo,26 **{27 "model.py": (28 "import gc\n"29 "\n"30 "class M:\n"31 " @staticmethod\n"32 " def foo(self):\n"33 " gc.collect()\n"34 " return 1\n"35 "\n"36 " def other(self):\n"37 " return 0\n"38 ),39 "comp.py": "class C:\n def keep(self):\n return 1\n",40 },41 )42 _commit(repo, "base")43 _write(44 repo,45 **{46 "model.py": "class M:\n def other(self):\n return 0\n",47 "comp.py": (48 "import gc\n"49 "\n"50 "class C:\n"51 " def keep(self):\n"52 " return 1\n"53 "\n"54 " def foo(self):\n"55 " gc.collect()\n"56 " return 1\n"57 ),58 },59 )60 _commit(repo, "move foo onto C")61 recipe = infer_recipe("HEAD", str(repo))62 assert {"path": "comp.py", "text": "import gc"} in recipe.import_additions63 64 65def test_infer_recipe_module_level_import_repoint_realised_by_diff(repo: Path) -> None:66 """A module-level consumer whose import is repointed old -> new yields a remove of the old67 name and an add of the new -- not a reliance on the formatter pruning a duplicate.68 """69 _free_function_move_with_module_level_caller(repo)70 recipe = infer_recipe("HEAD", str(repo))71 assert recipe.repaths == []72 assert {73 "path": "caller.py",74 "module": "model",75 "name": "resolve",76 "asname": None,77 } in recipe.module_import_removals78 assert {"path": "caller.py", "text": "from util import resolve"} in (79 recipe.import_additions80 )81 82 83def test_infer_recipe_removes_an_import_the_source_no_longer_uses(repo: Path) -> None:84 """When the moved body took the source's only use of an import, the source's lost name is85 realised as a removal (deterministic, not left to the formatter)."""86 _write(87 repo,88 **{89 "model.py": (90 "import gc\n"91 "\n"92 "class M:\n"93 " @staticmethod\n"94 " def foo(self):\n"95 " gc.collect()\n"96 " return 1\n"97 "\n"98 " def other(self):\n"99 " return 0\n"100 ),101 "comp.py": "class C:\n def keep(self):\n return 1\n",102 },103 )104 _commit(repo, "base")105 _write(106 repo,107 **{108 "model.py": "class M:\n def other(self):\n return 0\n",109 "comp.py": (110 "import gc\n"111 "\n"112 "class C:\n"113 " def keep(self):\n"114 " return 1\n"115 "\n"116 " def foo(self):\n"117 " gc.collect()\n"118 " return 1\n"119 ),120 },121 )122 _commit(repo, "move foo onto C")123 recipe = infer_recipe("HEAD", str(repo))124 assert {125 "path": "model.py",126 "module": None,127 "name": "gc",128 "asname": None,129 } in recipe.module_import_removals130 131 132def test_infer_recipe_adds_wholly_new_module_import_verbatim(repo: Path) -> None:133 """An import gained from a module not present in base is captured as the target's verbatim134 statement (so an exploded/magic-comma wrapping is reproduced, not collapsed per-name).135 """136 _write(137 repo,138 **{139 "model.py": "def keep():\n return 0\n\n\ndef solve(x):\n return x\n",140 "util.py": "import os\n",141 "caller.py": (142 "from model import solve\n\n\ndef run():\n return solve(1)\n"143 ),144 },145 )146 _commit(repo, "base")147 _write(148 repo,149 **{150 "model.py": "def keep():\n return 0\n",151 "util.py": "import os\n\n\ndef solve(x):\n return x\n",152 "caller.py": (153 "from util import (\n solve,\n)\n\n\ndef run():\n return solve(1)\n"154 ),155 },156 )157 _commit(repo, "move solve to util")158 recipe = infer_recipe("HEAD", str(repo))159 caller_adds = [160 a["text"] for a in recipe.import_additions if a["path"] == "caller.py"161 ]162 assert "from util import (\n solve,\n)" in caller_adds163 assert {164 "path": "caller.py",165 "module": "model",166 "name": "solve",167 "asname": None,168 } in recipe.module_import_removals169