tools (volt): doc_census_check -- a --tools filter that matches nothing is rc 2, not '0 tools scanned' + rc 0; 35 cells
This commit is contained in:
1 parent
8932d06748
commit
76043b7a3a
1 file changed
+27
-3
@@ -123,7 +123,7 @@ SCOPE, STATED RATHER THAN IMPLIED
|
||||
|
||||
USAGE
|
||||
python3 doc_census_check.py [--repo DIR] [--rev HEAD] [--tools NAME...]
|
||||
[--json OUT] [--no-run] [--selftest] # selftest: 33 cells, one per claim class
|
||||
[--json OUT] [--no-run] [--selftest] # selftest: 35 cells, one per claim class
|
||||
"""
|
||||
import argparse
|
||||
import ast
|
||||
@@ -625,6 +625,14 @@ def _fixture_checks():
|
||||
counts({**synthetic, "selftest_leg": False})[4],
|
||||
["no --selftest: leg 2 absent"])
|
||||
|
||||
# --tools: a filter that matches nothing must not read as a clean scan.
|
||||
check("tools: a bare basename is reported missing, not scanned as zero",
|
||||
resolve_tools(["checkin_check.py"], {"tools/checkin_check.py"}),
|
||||
(["checkin_check.py"], ["checkin_check.py"]))
|
||||
check("tools: no filter means every tracked tool and nothing missing",
|
||||
resolve_tools(None, {"tools/b.py", "tools/a.py", "README.md"}),
|
||||
(["tools/a.py", "tools/b.py"], []))
|
||||
|
||||
print(f"selftest: {cells[0]} cells, {cells[0] - bad[0]} passed, {bad[0]} failed")
|
||||
return 0 if ok else 1
|
||||
|
||||
@@ -872,6 +880,17 @@ def counts(rep):
|
||||
len(rep["verdicts"]), notes)
|
||||
|
||||
|
||||
def resolve_tools(requested, tree):
|
||||
"""(tools, missing). A requested name that is not tracked at the rev is
|
||||
REPORTED, never silently dropped: `--tools checkin_check.py` (a bare
|
||||
basename instead of a repo-relative path) scanned zero tools and exited 0,
|
||||
which reads exactly like a clean pass. Measured 2026-10-18 at 8932d06."""
|
||||
if not requested:
|
||||
return sorted(p for p in tree
|
||||
if p.startswith("tools/") and p.endswith(".py")), []
|
||||
return list(requested), [t for t in requested if t not in tree]
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
@@ -889,11 +908,16 @@ def main():
|
||||
|
||||
store = git(a.repo, "ls-tree", "-r", "--name-only", a.rev)
|
||||
tree = {p for p in store.decode("utf-8", "replace").split("\n") if p}
|
||||
tools = a.tools or sorted(p for p in tree
|
||||
if p.startswith("tools/") and p.endswith(".py"))
|
||||
tools, missing = resolve_tools(a.tools, tree)
|
||||
if not tools:
|
||||
print(f"no tools found at {a.rev}", file=sys.stderr)
|
||||
return 2
|
||||
if missing:
|
||||
print(f"cannot grade: --tools names nothing tracked at {a.rev}: "
|
||||
f"{', '.join(missing)}", file=sys.stderr)
|
||||
print(" names are repo-relative, e.g. --tools tools/checkin_check.py; "
|
||||
"a filter that matches nothing is not a clean scan", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
cache, reports = {}, []
|
||||
with tempfile.TemporaryDirectory(prefix="doccensus-") as tmpdir:
|
||||
|
||||
Reference in new issue
Block a user