scripts/tests/reproduction_utils/test_extract_to_new_module.py
scripts/tests/reproduction_utils/test_extract_to_new_module.pyBrowse 41 files
1,015 tokens
3,750 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 9import mechanical_refactor_reproduction_utils as rr10from mechanical_refactor_reproduction_utils import (11 Repro,12 _def_span,13 _find_class,14 _find_def,15 _replace_span,16 _slice_span,17 dedent,18 exec_command,19 git_add_and_commit,20 verify_mechanical_refactor,21)22from reproduction_testlib import _apply, _commit, _git, _write # noqa: F40123 24# --- extract_to_new_module -----------------------------------------------------25 26 27def test_extract_to_new_module_cuts_trailing_block(tmp_path: Path) -> None:28 """Cuts the trailing scaffolding+def block into a new file, prepending the future import."""29 (tmp_path / "src.py").write_text(30 "class M:\n"31 " def keep(self):\n"32 " return 1\n"33 "\n"34 "\n"35 "import logging\n"36 "\n"37 "logger = logging.getLogger(__name__)\n"38 "\n"39 "\n"40 "def foo(x):\n"41 " return x + 1\n"42 )43 r = Repro("b", "t").extract_to_new_module(44 "src.py", "new.py", symbols=["foo"], future_import=True45 )46 _apply(r, tmp_path)47 assert (tmp_path / "src.py").read_text() == (48 "class M:\n def keep(self):\n return 1\n\n\n"49 )50 assert (tmp_path / "new.py").read_text() == (51 "from __future__ import annotations\n"52 "import logging\n"53 "\n"54 "logger = logging.getLogger(__name__)\n"55 "\n"56 "\n"57 "def foo(x):\n"58 " return x + 1\n"59 )60 61 62def test_extract_to_new_module_carries_a_trailing_class(tmp_path: Path) -> None:63 """A class in the staged tail (not just a def) travels with the cut block."""64 (tmp_path / "src.py").write_text(65 "class M:\n"66 " pass\n"67 "\n"68 "\n"69 "from dataclasses import dataclass\n"70 "\n"71 "\n"72 "@dataclass\n"73 "class Cfg:\n"74 " x: int\n"75 "\n"76 "\n"77 "def foo():\n"78 " return Cfg(1)\n"79 )80 r = Repro("b", "t").extract_to_new_module(81 "src.py", "new.py", symbols=["Cfg", "foo"], future_import=False82 )83 _apply(r, tmp_path)84 assert (tmp_path / "src.py").read_text() == "class M:\n pass\n\n\n"85 assert "class Cfg:" in (tmp_path / "new.py").read_text()86 assert "def foo():" in (tmp_path / "new.py").read_text()87 88 89# --- extract_symbols_to_new_module ---------------------------------------------90 91 92# --- adversarial audit: module extraction ----------------------------------------93 94 95def test_extract_to_new_module_asserts_when_symbol_not_in_the_tail(96 tmp_path: Path,97) -> None:98 """A wanted symbol above a non-scaffolding statement is not in the tail and raises."""99 (tmp_path / "src.py").write_text(100 "def wanted():\n return 1\n\n\nprint('side effect')\n"101 )102 r = Repro("b", "t").extract_to_new_module("src.py", "n.py", symbols=["wanted"])103 with pytest.raises(AssertionError):104 _apply(r, tmp_path)105 106 107def test_extract_to_new_module_refuses_a_trailing_main_guard(tmp_path: Path) -> None:108 """A trailing __main__ guard is executable code, not scaffolding: the tail cut raises."""109 (tmp_path / "src.py").write_text(110 "class Keep:\n"111 " pass\n"112 "\n"113 "\n"114 "def foo():\n"115 " return 1\n"116 "\n"117 "\n"118 'if __name__ == "__main__":\n'119 " foo()\n"120 )121 r = Repro("b", "t").extract_to_new_module(122 "src.py", "new.py", symbols=["foo"], future_import=False123 )124 with pytest.raises(AssertionError):125 _apply(r, tmp_path)126 assert "__main__" in (tmp_path / "src.py").read_text()127