Spaces:
Sleeping
Sleeping
| # tools/restructure_imports.py | |
| """One-shot codemod: rewrite proteus import paths for the game/web restructure. | |
| Usage: | |
| python tools/restructure_imports.py <file_or_dir> [<file_or_dir> ...] | |
| NEVER run this on tools/ — this file contains the rule strings themselves. | |
| Rules apply IN ORDER (most-specific first) so prefix collisions resolve | |
| correctly: | |
| * grid.scenarios (plural) before grid.scenario (singular) before grid (bare) | |
| * runtime.metrics/persona/rollout/aggregate before runtime (bare) | |
| Each rule matches a dotted path at a word boundary so 'proteus.grid' does not | |
| hit 'proteus.gridx', and (because longer rules run first) does not pre-empt | |
| 'proteus.grid.game'. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| import sys | |
| from pathlib import Path | |
| RULES: list[tuple[str, str]] = [ | |
| # grid family — plural, then singular, then submodules, then bare | |
| ("proteus.grid.scenarios", "proteus.game.scenarios"), | |
| ("proteus.grid.scenario", "proteus.game.scenarios.base"), | |
| ("proteus.grid.game", "proteus.game.engine.grid"), | |
| ("proteus.grid.difficulty", "proteus.game.engine.difficulty"), | |
| ("proteus.grid.ascii_view", "proteus.game.engine.ascii_view"), | |
| ("proteus.grid", "proteus.game.scenarios"), | |
| # arc_grid (engine + rendering) | |
| ("proteus.arc_grid", "proteus.game.engine"), | |
| # runtime — metrics group out to game.metrics (specific first), then bare | |
| ("proteus.runtime.metrics", "proteus.game.metrics.metrics"), | |
| ("proteus.runtime.persona", "proteus.game.metrics.persona"), | |
| ("proteus.runtime.rollout", "proteus.game.metrics.rollout"), | |
| ("proteus.runtime.aggregate", "proteus.game.metrics.aggregate"), | |
| ("proteus.runtime", "proteus.game.runtime"), | |
| # agents / viz | |
| ("proteus.agents", "proteus.game.agents"), | |
| ("proteus.viz", "proteus.game.viz"), | |
| # web -> web.local (arena is new; no old refs) | |
| ("proteus.web", "proteus.web.local"), | |
| ] | |
| COMPILED = [(re.compile(r"\b" + re.escape(old) + r"(?![\w])"), new) | |
| for old, new in RULES] | |
| def rewrite(text: str) -> str: | |
| for pat, new in COMPILED: | |
| text = pat.sub(new, text) | |
| return text | |
| def iter_py(paths: list[str]): | |
| for p in paths: | |
| path = Path(p) | |
| if path.is_dir(): | |
| yield from sorted(path.rglob("*.py")) | |
| elif path.suffix == ".py": | |
| yield path | |
| def main(argv: list[str]) -> int: | |
| changed = 0 | |
| for path in iter_py(argv): | |
| old = path.read_text() | |
| new = rewrite(old) | |
| if new != old: | |
| path.write_text(new) | |
| changed += 1 | |
| print(f"rewrote {path}") | |
| print(f"--- {changed} files changed ---") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main(sys.argv[1:])) | |