"""PDF renderer using WeasyPrint. This module provides PDF rendering from HTML content using WeasyPrint. """ from pathlib import Path from py_dvt_ate.reporting.exceptions import PDFConversionError class PDFRenderer: """Renders PDF documents from HTML content using WeasyPrint. WeasyPrint converts HTML/CSS to PDF with support for page layout, headers/footers, and professional typography. """ def __init__(self) -> None: """Initialise the PDF renderer.""" self._weasyprint: type | None = None def _get_weasyprint(self) -> type: """Lazy-load WeasyPrint to avoid import errors when not installed. Returns: The WeasyPrint HTML class. Raises: PDFConversionError: If WeasyPrint is not installed. """ if self._weasyprint is None: try: from weasyprint import HTML self._weasyprint = HTML except ImportError as e: msg = ( "WeasyPrint is required for PDF generation. " "Install it with: pip install py_dvt_ate[reports]" ) raise PDFConversionError(msg) from e return self._weasyprint def render_to_file(self, html: str, path: Path) -> None: """Render HTML content to a PDF file. Args: html: HTML content to convert. path: Output path for the PDF file. Raises: PDFConversionError: If PDF conversion fails. """ try: HTML = self._get_weasyprint() path.parent.mkdir(parents=True, exist_ok=True) HTML(string=html).write_pdf(path) except PDFConversionError: raise except Exception as e: msg = f"Failed to convert HTML to PDF: {e}" raise PDFConversionError(msg) from e def render_to_bytes(self, html: str) -> bytes: """Render HTML content to PDF bytes. Args: html: HTML content to convert. Returns: PDF document as bytes. Raises: PDFConversionError: If PDF conversion fails. """ try: HTML = self._get_weasyprint() result: bytes = HTML(string=html).write_pdf() return result except PDFConversionError: raise except Exception as e: msg = f"Failed to convert HTML to PDF: {e}" raise PDFConversionError(msg) from e