83 lines
3.0 KiB
Python
83 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Write reports/inventory/DEPLOYED_CONTRACTS_UNIFIED_EXTENDED.md from
|
|
reports/inventory/deployed-contracts-by-network.csv.
|
|
|
|
The Markdown rows match the pipe format parsed by inventory_onchain.parse_table().
|
|
Re-run this if the CSV (repo evidence inventory) changes.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import csv
|
|
import re
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
CSV_IN = ROOT / "reports/inventory/deployed-contracts-by-network.csv"
|
|
OUT = ROOT / "reports/inventory/DEPLOYED_CONTRACTS_UNIFIED_EXTENDED.md"
|
|
SUMMARY_LINE_PREFIX = "- Current deduped closure state:"
|
|
|
|
PIPE = re.compile(r"\|")
|
|
|
|
|
|
def esc(s: str) -> str:
|
|
s = s.replace(" | ", " — ").strip()
|
|
s = PIPE.sub("/", s)
|
|
return s or "—"
|
|
|
|
|
|
def main() -> int:
|
|
if not CSV_IN.is_file():
|
|
print("Missing", CSV_IN, file=sys.stderr)
|
|
return 1
|
|
with CSV_IN.open(newline="", encoding="utf-8") as f:
|
|
r = csv.DictReader(f)
|
|
if not r.fieldnames:
|
|
print("Empty CSV", file=sys.stderr)
|
|
return 1
|
|
rows = list(r)
|
|
if not rows:
|
|
print("No data rows in", CSV_IN, file=sys.stderr)
|
|
return 1
|
|
|
|
now = datetime.now(timezone.utc).replace(microsecond=0)
|
|
out_lines: list[str] = [
|
|
"# DEPLOYED_CONTRACTS_UNIFIED (extended, repo evidence)",
|
|
"",
|
|
f"**Generated (UTC):** {now.isoformat().replace('+00:00', 'Z')}",
|
|
f"**Source table:** [`deployed-contracts-by-network.csv`]({CSV_IN.name}) (same contract set as the network report).",
|
|
"",
|
|
f"{SUMMARY_LINE_PREFIX} **pending** — run `build-inventory-completion-matrix.py` after the on-chain snapshot exists.",
|
|
"",
|
|
"Pipe rows below are the canonical set consumed by `inventory_onchain.parse_table()`.",
|
|
"",
|
|
"| # | Network | Ch | Name | Address | Status / provenance |",
|
|
"|--:|---|---:|---|---|",
|
|
]
|
|
for i, row in enumerate(rows, start=1):
|
|
network = esc(row.get("network", ""))
|
|
chain = esc(str(row.get("chain_id", "")).strip())
|
|
name = esc(row.get("contract_name", ""))
|
|
raw_addr = (row.get("address") or "").strip()
|
|
if not re.match(r"^0x[a-fA-F0-9]{40}$", raw_addr):
|
|
print("Bad address on CSV row", i, raw_addr, file=sys.stderr)
|
|
return 1
|
|
addr = "`" + "0x" + raw_addr[2:].lower() + "`"
|
|
cat = esc(row.get("category", ""))
|
|
stat = esc(row.get("status", ""))
|
|
notes = esc(row.get("notes", ""))
|
|
source = esc(row.get("source", ""))
|
|
tail = f"repo | {source} — {cat}, {stat}; {notes}" if notes else f"repo | {source} — {cat}, {stat}"
|
|
out_lines.append(f"| {i} | {network} | {chain} | {name} | {addr} | {tail} |")
|
|
|
|
OUT.parent.mkdir(parents=True, exist_ok=True)
|
|
OUT.write_text("\n".join(out_lines) + "\n", encoding="utf-8")
|
|
print(OUT, len(rows), "data rows", len(OUT.read_text(encoding="utf-8")), "bytes")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|