Implement PDF renderer with WeasyPrint
This commit is contained in:
83
src/py_dvt_ate/reporting/renderers/pdf.py
Normal file
83
src/py_dvt_ate/reporting/renderers/pdf.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""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()
|
||||
return HTML(string=html).write_pdf()
|
||||
except PDFConversionError:
|
||||
raise
|
||||
except Exception as e:
|
||||
msg = f"Failed to convert HTML to PDF: {e}"
|
||||
raise PDFConversionError(msg) from e
|
||||
Reference in New Issue
Block a user