40-validation/measure-knowledge-coverage.py
#!/usr/bin/env python3
import argparse,json
from pathlib import Path
EXCLUDED=("99-berichte/","99-reports/","reports/","test/reports/")
def measure(root):
files=[]
for p in sorted(root.rglob("*.md")):
rel=p.relative_to(root).as_posix()
if any(rel.startswith(x) for x in EXCLUDED):continue
text=p.read_text(encoding="utf-8");files.append({"path":rel,"words":len(text.split()),"characters":len(text)})
return {"documents":len(files),"words":sum(x["words"] for x in files),"characters":sum(x["characters"] for x in files)}
def build(repositories,dashboard):
categories=dashboard.get("categories",[]);manual={c["id"]:{"coverage":c.get("coverage"),"maturity":c.get("maturity"),"reviewed":c.get("reviewed"),"approved":c.get("approved")} for c in categories}
return {"schemaVersion":"1.0","workItem":"SE-0031","status":"PASSED","method":{"encoding":"UTF-8","words":"Unicode whitespace tokens","characters":"Python len","generatedReportsExcluded":True},"repositories":{n:measure(p) for n,p in repositories.items()},"semanticUnits":{"categories":len(categories),"legacy":dashboard.get("totals",{}).get("legacy"),"coverage":dashboard.get("totals",{}).get("coverage")},"manualDecisionsPreserved":manual,"manualStatusOverwritten":False}
def main():
p=argparse.ArgumentParser();p.add_argument("--repository",action="append",required=True);p.add_argument("--dashboard",type=Path,required=True);p.add_argument("--output",type=Path);a=p.parse_args();repos={}
for v in a.repository:n,s,x=v.partition("=");repos[n]=Path(x)
r=build(repos,json.loads(a.dashboard.read_text()));text=json.dumps(r,ensure_ascii=False,indent=2)+"\n"
if a.output:a.output.parent.mkdir(parents=True,exist_ok=True);a.output.write_text(text)
else:print(text,end="")
if __name__=="__main__":main()