TOXRA.AI / core /pdf_report.py
hchevva's picture
Upload 14 files
fc29964 verified
from __future__ import annotations
import json
import os
import tempfile
import textwrap
from datetime import datetime, timezone
from typing import Any, Dict, Tuple
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
def _safe_text(value: Any) -> str:
if value is None:
return ""
return str(value).encode("ascii", "replace").decode("ascii")
def _wrap_lines(text: str, width: int = 95) -> list[str]:
lines: list[str] = []
for raw in (text or "").splitlines():
if not raw:
lines.append("")
continue
lines.extend(textwrap.wrap(raw, width=width))
return lines
def build_pdf(cas: str, evidence: Dict[str, Any], ai_summary: str | None = None) -> Tuple[str, str]:
"""Generate a PDF + JSON evidence packet and return file paths."""
stamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
safe_cas = _safe_text(cas or "unknown").replace("/", "_").replace(" ", "_")
out_dir = os.path.join(tempfile.gettempdir(), "toxrai_reports")
os.makedirs(out_dir, exist_ok=True)
pdf_path = os.path.join(out_dir, f"toxrai_{safe_cas}_{stamp}.pdf")
json_path = os.path.join(out_dir, f"toxrai_{safe_cas}_{stamp}.json")
# JSON evidence
with open(json_path, "w", encoding="utf-8") as f:
json.dump(evidence, f, ensure_ascii=False, indent=2, default=str)
# PDF
c = canvas.Canvas(pdf_path, pagesize=letter)
width, height = letter
y = height - 40
def draw_line(line: str):
nonlocal y
if y < 50:
c.showPage()
y = height - 40
c.drawString(40, y, _safe_text(line))
y -= 14
draw_line("ToxRAI Evidence Report")
draw_line(f"CAS / Query: {safe_cas}")
draw_line(f"Generated: {datetime.now(timezone.utc).isoformat()} UTC")
draw_line("")
if ai_summary:
draw_line("AI Summary")
for line in _wrap_lines(ai_summary, width=90):
draw_line(line)
draw_line("")
# Include a compact evidence snapshot
evidence_text = json.dumps(evidence, ensure_ascii=False, indent=2, default=str)
if len(evidence_text) > 8000:
evidence_text = evidence_text[:8000] + "\n... (truncated)"
draw_line("Evidence JSON (truncated)")
for line in _wrap_lines(evidence_text, width=95):
draw_line(line)
c.save()
return pdf_path, json_path