Files
ThothII/harness/tht/report.py
T
marcopan ea6412fafc feat(harness): port backend Onda 0 — vendor, lshindex, sqlcheck, execute, rest/exec, ctetest, report, datamart
8 moduli leaf portati verbatim da ChironeWp3 con rename psdwp3→tht:
- vendor/thoth_lsh (MinHash/LSH, leaf puro datasketch+tqdm) + VENDORED.md
- lshindex/ (build/save/load/query, dipende vendor + LshConfig)
- sqlcheck/ (validate_sql, leaf ExecutionConfig+mschema)
- execute/ + execute/warnings (run_controlled/explain, leaf sqlglot+sqlalchemy)
- rest/execute + rest/explain (REST variants, dipendono execute+rest.client)
- ctetest (CTE test records, leaf sqlglot+pydantic)
- report (validation report rendering, dipende execute+sqlcheck)
- datamart (stub NotImplementedError)

Verifica: import smoke catena completa OK, pytest 109 passed. Deps (datasketch, sqlglot,
sqlalchemy, pydantic, requests, tqdm) già in pyproject. VENDORED.md neutralizzato
(riferimenti PsdWp3→Thoth).
2026-06-27 10:34:23 +02:00

75 lines
2.2 KiB
Python

from tht.execute import ExecResult, PlanSummary
from tht.sqlcheck import CheckResult
NOTE_HEADING = "## Note del reviewer"
def _markdown_table(columns: list[str], rows: list[tuple]) -> str:
lines = [
"| " + " | ".join(columns) + " |",
"|" + "---|" * len(columns),
]
for row in rows:
lines.append("| " + " | ".join(str(v) for v in row) + " |")
return "\n".join(lines)
def render_validation_report(
*,
session_id: str,
check: CheckResult,
plan: PlanSummary,
plan_warnings: list[str],
result: ExecResult,
runtime_warnings: list[str],
static_warnings: list[str],
limit: int,
reviewer_notes: str = "",
) -> str:
"""Sezioni fattuali del validation report. La sezione note e' di Pi/reviewer:
se gia' scritta, va passata in reviewer_notes per preservarla."""
def warn(ws: list[str]) -> str:
return "\n".join(f"- warning: {w}" for w in ws) if ws else "- nessun warning"
parts = [
f"# Validation report — {session_id}",
"",
"> Avvertenza: questo report contiene sample di dati del database.",
"",
"## Parsing e read-only",
"",
"- parsing: OK" if check.ok else "- parsing: ERRORI",
"- statement read-only per struttura: OK" if check.ok else
"\n".join(f"- ERRORE: {e}" for e in check.errors),
warn(check.warnings + static_warnings),
"",
"## Piano di esecuzione",
"",
f"- costo totale stimato: {plan.total_cost}",
f"- righe stimate: {plan.plan_rows}",
f"- nodi: {', '.join(plan.node_types)}",
warn(plan_warnings),
"",
"## Preview / aggregato",
"",
f"- tempo di esecuzione: {result.execution_ms} ms (limit {limit})",
"",
_markdown_table(result.columns, result.rows),
"",
warn(runtime_warnings),
"",
NOTE_HEADING,
"",
reviewer_notes.strip(),
"",
]
return "\n".join(parts)
def extract_reviewer_notes(report_md: str) -> str:
"""Estrae il contenuto della sezione note da un report esistente."""
if NOTE_HEADING not in report_md:
return ""
return report_md.split(NOTE_HEADING, 1)[1].strip()