89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
"""Verterbate the reconstruct unused-arg smell fix in chunker.py (forge lane).
|
|
|
|
CHECK target. Exits 0 (correct) iff ALL of:
|
|
(a) ``reconstruct`` has NO unused parameters (the AST unused-arg detector, the
|
|
same one ``_smell_scan_refactored.py`` uses, reports nothing for it), AND
|
|
(b) ``reconstruct``'s body contains an explicit ``del overlap_tokens`` marking
|
|
the retained-for-symmetry no-op, AND
|
|
(c) the chunker test suite passes (behavior preserved).
|
|
Otherwise exits 1. No fallback arms: the script's own exit code IS the verdict.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import subprocess
|
|
import sys
|
|
|
|
PATH = "/root/troupe-standup/wizard-work/forge/chunker.py"
|
|
TESTS = ["python", "-m", "pytest", "test_chunker_refactor.py", "-q"]
|
|
|
|
|
|
def find_unused_arguments(tree: ast.AST) -> list[tuple[str, str, int]]:
|
|
results: list[tuple[str, str, int]] = []
|
|
for node in ast.walk(tree):
|
|
if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
continue
|
|
for arg in node.args.args:
|
|
if arg.arg == "self":
|
|
continue
|
|
used = any(
|
|
(isinstance(n, ast.Name) and n.id == arg.arg)
|
|
or (isinstance(n, ast.Attribute) and n.attr == arg.arg)
|
|
for n in ast.walk(node)
|
|
)
|
|
if not used:
|
|
results.append((node.name, arg.arg, node.lineno))
|
|
return results
|
|
|
|
|
|
def reconstruct_node(tree: ast.AST) -> ast.FunctionDef | None:
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, ast.FunctionDef) and node.name == "reconstruct":
|
|
return node
|
|
return None
|
|
|
|
|
|
def has_del_overlap_tokens(func: ast.FunctionDef) -> bool:
|
|
for node in ast.walk(func):
|
|
if isinstance(node, ast.Delete):
|
|
for tgt in node.targets:
|
|
if isinstance(tgt, ast.Name) and tgt.id == "overlap_tokens":
|
|
return True
|
|
return False
|
|
|
|
|
|
def main() -> int:
|
|
src = open(PATH).read()
|
|
tree = ast.parse(src)
|
|
|
|
# (a) no unused args on reconstruct specifically.
|
|
unused = find_unused_arguments(tree)
|
|
recon_unused = [u for u in unused if u[0] == "reconstruct"]
|
|
if recon_unused:
|
|
print(f"FAIL (a): reconstruct still has unused args: {recon_unused}")
|
|
return 1
|
|
print("OK (a): reconstruct has no unused arguments")
|
|
|
|
# (b) explicit del marker present inside reconstruct body.
|
|
func = reconstruct_node(tree)
|
|
if func is None:
|
|
print("FAIL (b): reconstruct() not found")
|
|
return 1
|
|
if not has_del_overlap_tokens(func):
|
|
print("FAIL (b): no `del overlap_tokens` marker in reconstruct body")
|
|
return 1
|
|
print("OK (b): `del overlap_tokens` present in reconstruct body")
|
|
|
|
# (c) behavior preserved: chunker test suite.
|
|
proc = subprocess.run(TESTS, cwd="/root/troupe-standup/wizard-work/forge")
|
|
if proc.returncode != 0:
|
|
print(f"FAIL (c): chunker test suite exited {proc.returncode}")
|
|
return 1
|
|
print("OK (c): chunker test suite passes")
|
|
print("VERDICT: reconstruct unused-arg smell fixed, behavior preserved")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|