feat: issue/0020 — generacion de PDFs en Python y Go
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>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user