85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
"""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
|