scripts/tests/proof_generator/test_infer_extracts.py
scripts/tests/proof_generator/test_infer_extracts.pyBrowse 41 files
1,588 tokens
6,747 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_new_file_extract_from_class_method_unsupported(23 repo: Path,24) -> None:25 """A method still inside the class cut straight into a new module cannot be cut as a26 top-level symbol, so the extract is reported unsupported (prep must lift it out first).27 """28 _write(29 repo,30 **{31 "model.py": (32 "class M:\n"33 " @staticmethod\n"34 " def foo(self):\n"35 " return 1\n"36 "\n"37 " def other(self):\n"38 " return 0\n"39 )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 "newmod.py": "def foo():\n return 1\n",48 },49 )50 _commit(repo, "extract foo to a new module")51 recipe = infer_recipe("HEAD", str(repo))52 assert recipe.supported is False53 assert any("not all top-level" in note for note in recipe.notes)54 55 56def test_infer_recipe_new_file_extract_from_staged_tail(repo: Path) -> None:57 """A staged trailing block (scaffolding + def at the source tail) cut into a new file58 infers an extract_to_new_module, prepending the future import."""59 _write(60 repo,61 **{62 "model.py": (63 "class M:\n"64 " def keep(self):\n"65 " return 1\n"66 "\n"67 "\n"68 "import logging\n"69 "\n"70 "logger = logging.getLogger(__name__)\n"71 "\n"72 "\n"73 "def foo(x):\n"74 " return x + 1\n"75 )76 },77 )78 _commit(repo, "base")79 _write(80 repo,81 **{82 "model.py": "class M:\n def keep(self):\n return 1\n",83 "newmod.py": (84 "from __future__ import annotations\n"85 "\n"86 "import logging\n"87 "\n"88 "logger = logging.getLogger(__name__)\n"89 "\n"90 "\n"91 "def foo(x):\n"92 " return x + 1\n"93 ),94 },95 )96 _commit(repo, "extract foo to a new module")97 recipe = infer_recipe("HEAD", str(repo))98 assert recipe.supported99 assert recipe.moves == []100 assert recipe.extracts == [101 {102 "src": "model.py",103 "dst": "newmod.py",104 "symbols": ["foo"],105 "future_import": True,106 }107 ]108 109 110def test_infer_recipe_scattered_new_module_extract(repo: Path) -> None:111 """Scattered top-level defs cut into a new module (no staged trailing block) infer a scatter112 extract with the authored header and target order, not UNSUPPORTED."""113 _write(114 repo,115 **{116 "common.py": (117 "import os\n"118 "\n"119 "\n"120 "def keep():\n"121 " return 0\n"122 "\n"123 "\n"124 "def beta():\n"125 " return 2\n"126 "\n"127 "\n"128 "def stay():\n"129 " return 9\n"130 "\n"131 "\n"132 "def alpha():\n"133 " return 1\n"134 ),135 },136 )137 _commit(repo, "base")138 _write(139 repo,140 **{141 "common.py": (142 "import os\n"143 "\n"144 "\n"145 "def keep():\n"146 " return 0\n"147 "\n"148 "\n"149 "def stay():\n"150 " return 9\n"151 ),152 "alloc.py": (153 "from __future__ import annotations\n"154 "\n"155 "import logging\n"156 "\n"157 "logger = logging.getLogger(__name__)\n"158 "\n"159 "\n"160 "def alpha():\n"161 " return 1\n"162 "\n"163 "\n"164 "def beta():\n"165 " return 2\n"166 ),167 },168 )169 _commit(repo, "extract alpha, beta to alloc.py")170 recipe = infer_recipe("HEAD", str(repo))171 assert recipe.supported172 assert recipe.extracts == []173 assert recipe.moves == []174 assert len(recipe.scatter_extracts) == 1175 sx = recipe.scatter_extracts[0]176 assert sx["src"] == "common.py" and sx["dst"] == "alloc.py"177 assert sorted(sx["symbols"]) == ["alpha", "beta"]178 assert sx["order"] == ["alpha", "beta"]179 assert sx["header"].startswith("from __future__ import annotations\n")180 assert "logger = logging.getLogger(__name__)" in sx["header"]181 assert sx["drop_assigns"] == []182 script = recipe_to_script(recipe, "extract alpha, beta to alloc.py")183 assert "extract_symbols_to_new_module" in script184 185 186def test_infer_recipe_scatter_extract_drops_relocated_constant(repo: Path) -> None:187 """A module-level constant relocated into the new module is inferred as a drop_assign so the188 scatter extract removes it from the source too; a constant the source keeps is not.189 """190 _write(191 repo,192 **{193 "common.py": (194 "from u import is_hip\n"195 "\n"196 "_IS_HIP = is_hip()\n"197 "logger = 1\n"198 "\n"199 "\n"200 "def moved():\n"201 " return _IS_HIP\n"202 "\n"203 "\n"204 "def keep():\n"205 " return logger\n"206 ),207 },208 )209 _commit(repo, "base")210 _write(211 repo,212 **{213 "common.py": ("logger = 1\n\n\ndef keep():\n return logger\n"),214 "alloc.py": (215 "from __future__ import annotations\n"216 "\n"217 "from u import is_hip\n"218 "\n"219 "_IS_HIP = is_hip()\n"220 "\n"221 "\n"222 "def moved():\n"223 " return _IS_HIP\n"224 ),225 },226 )227 _commit(repo, "extract moved to alloc.py")228 recipe = infer_recipe("HEAD", str(repo))229 assert len(recipe.scatter_extracts) == 1230 assert recipe.scatter_extracts[0]["drop_assigns"] == ["_IS_HIP"]231