| """Regenerate the task status table in README.md from the run logs. |
| |
| Reads outputs/tasks/v3_<task>.log for every registered task and reports pass / fail / not-run, |
| with the failure reason the solver or the condition printed. Nothing here is hand-maintained, so |
| the table cannot drift from what the runs actually did. |
| |
| python scripts/status.py # print |
| python scripts/status.py --write # replace the table in README.md |
| """ |
| import argparse |
| import glob |
| import os |
| import re |
|
|
| ap = argparse.ArgumentParser() |
| ap.add_argument("--logs", default="outputs/tasks") |
| ap.add_argument("--tasks", default="source/bimanual/yam/tasks") |
| ap.add_argument("--readme", default="doc/tasks.md") |
| ap.add_argument("--write", action="store_true") |
| a = ap.parse_args() |
|
|
| MARK_A = "<!-- STATUS TABLE -->" |
| MARK_B = "<!-- END STATUS TABLE -->" |
|
|
|
|
| def reason(text): |
| for pat in (r'reason": "([^"]{0,80})', |
| r'\[cond\] ([^\n]{0,80})', |
| r'(OUTSIDE its limits[^\n]{0,40})'): |
| m = re.findall(pat, text) |
| if m: |
| return m[-1].strip().rstrip(",") |
| return "" |
|
|
|
|
| rows = [] |
| for p in sorted(glob.glob(os.path.join(a.tasks, "*.py"))): |
| name = os.path.basename(p)[:-3] |
| if name == "__init__": |
| continue |
| log = os.path.join(a.logs, f"v3_{name}.log") |
| if not os.path.exists(log): |
| rows.append((name, "not run", "")); continue |
| t = open(log, errors="ignore").read() |
| if "EPISODE_RESULT: SUCCESS" in t: |
| rows.append((name, "pass", "")) |
| else: |
| rows.append((name, "fail", reason(t))) |
|
|
| npass = sum(1 for _, s, _ in rows if s == "pass") |
| table = [f"**{npass} of {len(rows)} passing.**", "", |
| "| task | status | last failure |", "|---|---|---|"] |
| for n, s, r in rows: |
| mark = {"pass": "**pass**", "fail": "fail", "not run": "not run"}[s] |
| table.append(f"| `{n}` | {mark} | {r.replace('|', '/')} |") |
| out = "\n".join(table) |
| print(out) |
|
|
| if a.write: |
| src = open(a.readme).read() |
| block = f"{MARK_A}\n{out}\n{MARK_B}" |
| if MARK_A in src and MARK_B in src: |
| src = re.sub(re.escape(MARK_A)+r".*?"+re.escape(MARK_B), block, src, flags=re.S) |
| else: |
| src = src.rstrip()+"\n\n"+block+"\n" |
| open(a.readme, "w").write(src) |
| print(f"\n[status] wrote the table into {a.readme}") |
|
|