df424f2de0
Añade 3 tipos Python (PDFDoc, PDFPage, PDFStyle) y 10 funciones Python para construir PDFs con fpdf2 (builder fluent), fusionar PDFs con pypdf y convertir HTML/Markdown a PDF via weasyprint (stub si no disponible). Añade pdf_simple_report en Go como stub hasta que go-pdf/fpdf se integre. - python/types/infra/: pdf_doc, pdf_page, pdf_style - python/functions/infra/: pdf_create, pdf_add_page, pdf_add_text, pdf_add_table, pdf_add_image, pdf_add_header_footer, pdf_from_html, pdf_from_markdown, pdf_merge, pdf_save - functions/infra/pdf_simple_report.go: stub Go con ReportSection/ReportTable - 17 tests Python pasando (pytest) - fpdf2 y pypdf añadidos via uv al venv Python Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
3.1 KiB
Python
95 lines
3.1 KiB
Python
"""pdf_create — inicializa un documento PDF nuevo con fpdf2."""
|
|
|
|
import sys
|
|
import os
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "python", "types"))
|
|
|
|
from fpdf import FPDF
|
|
|
|
# Import type from types directory
|
|
_types_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "python", "types", "infra")
|
|
sys.path.insert(0, _types_dir)
|
|
from pdf_doc import PDFDoc
|
|
|
|
|
|
class _PDFWithHeaderFooter(FPDF):
|
|
"""Subclase de FPDF con soporte para header/footer recurrente."""
|
|
|
|
def __init__(self, doc_ref: PDFDoc, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._doc_ref = doc_ref
|
|
|
|
def header(self):
|
|
if not self._doc_ref.header_text:
|
|
return
|
|
self.set_font(self._doc_ref.default_font, size=9)
|
|
self.set_text_color(100, 100, 100)
|
|
self.cell(0, 8, self._doc_ref.header_text, align="C", new_x="LMARGIN", new_y="NEXT")
|
|
self.ln(2)
|
|
|
|
def footer(self):
|
|
if not self._doc_ref.footer_text and not self._doc_ref.page_numbers:
|
|
return
|
|
self.set_y(-15)
|
|
self.set_font(self._doc_ref.default_font, size=9)
|
|
self.set_text_color(100, 100, 100)
|
|
text = self._doc_ref.footer_text
|
|
if self._doc_ref.page_numbers:
|
|
if "{n}" in text or "{total}" in text:
|
|
text = text.replace("{n}", str(self.page_no())).replace("{total}", "{nb}")
|
|
else:
|
|
text = f"Pagina {self.page_no()} de {{nb}}" if not text else text
|
|
self.cell(0, 10, text, align="C")
|
|
|
|
|
|
def pdf_create(
|
|
title: str = "",
|
|
author: str = "",
|
|
subject: str = "",
|
|
default_font: str = "Helvetica",
|
|
margin_left: float = 20.0,
|
|
margin_right: float = 20.0,
|
|
margin_top: float = 20.0,
|
|
margin_bottom: float = 20.0,
|
|
) -> PDFDoc:
|
|
"""Inicializa un documento PDF nuevo usando fpdf2.
|
|
|
|
Crea un objeto FPDF configurado con los margenes y metadatos especificados.
|
|
Retorna un PDFDoc listo para añadir paginas con pdf_add_page.
|
|
|
|
Args:
|
|
title: titulo del documento (aparece en metadata del PDF reader).
|
|
author: autor del documento (metadata).
|
|
subject: asunto del documento (metadata).
|
|
default_font: fuente por defecto. Built-ins: Helvetica, Times, Courier.
|
|
margin_left: margen izquierdo en mm. Por defecto 20.
|
|
margin_right: margen derecho en mm. Por defecto 20.
|
|
margin_top: margen superior en mm. Por defecto 20.
|
|
margin_bottom: margen inferior en mm. Por defecto 20.
|
|
|
|
Returns:
|
|
PDFDoc inicializado con el objeto fpdf2 configurado.
|
|
"""
|
|
doc = PDFDoc(
|
|
title=title,
|
|
author=author,
|
|
subject=subject,
|
|
default_font=default_font,
|
|
margin_left=margin_left,
|
|
margin_right=margin_right,
|
|
margin_top=margin_top,
|
|
margin_bottom=margin_bottom,
|
|
)
|
|
|
|
fpdf = _PDFWithHeaderFooter(doc_ref=doc)
|
|
fpdf.set_margins(margin_left, margin_top, margin_right)
|
|
fpdf.set_auto_page_break(auto=True, margin=margin_bottom)
|
|
fpdf.set_title(title)
|
|
fpdf.set_author(author)
|
|
fpdf.set_subject(subject)
|
|
fpdf.set_creator("fn-registry/pdf_create")
|
|
|
|
doc.fpdf = fpdf
|
|
return doc
|