mirror of
https://github.com/fsecada01/Pygentic-AI.git
synced 2026-05-12 12:15:00 +00:00
fix: resolve critical PDF generation bugs
Fixed two critical errors preventing PDF downloads: 1. KeyError: "Style 'BodyText' already defined in stylesheet" - Renamed custom style from "BodyText" to "ReportBodyText" - BodyText is a reserved ReportLab built-in style name - Updated all references to use new name 2. AttributeError: 'int' object has no attribute 'encode' - StreamingResponse expected an iterator, not BytesIO directly - Added iterfile() generator function to yield BytesIO chunks - Properly resets buffer position with seek(0) before iteration Additional: - Removed unused hex_to_rgb_tuple() function (dead code cleanup) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -38,12 +38,6 @@ NEUTRAL_100 = colors.HexColor("#F3F4F6")
|
||||
WHITE = colors.white
|
||||
|
||||
|
||||
def hex_to_rgb_tuple(hex_color: str) -> tuple[float, float, float]:
|
||||
"""Convert hex color to RGB tuple (0-1 range)"""
|
||||
hex_color = hex_color.lstrip("#")
|
||||
return tuple(int(hex_color[i : i + 2], 16) / 255 for i in (0, 2, 4))
|
||||
|
||||
|
||||
def compute_content_hash(analysis: SwotAnalysis) -> str:
|
||||
"""
|
||||
Compute SHA-256 hash of SWOT analysis content for caching.
|
||||
@ -124,7 +118,7 @@ class SwotPDFGenerator:
|
||||
# Body text style
|
||||
self.styles.add(
|
||||
ParagraphStyle(
|
||||
name="BodyText",
|
||||
name="ReportBodyText",
|
||||
parent=self.styles["Normal"],
|
||||
fontSize=11,
|
||||
textColor=NEUTRAL_700,
|
||||
@ -243,7 +237,7 @@ class SwotPDFGenerator:
|
||||
|
||||
# Wrap summary in a table for better styling
|
||||
summary_para = Paragraph(
|
||||
self.analysis.analysis, self.styles["BodyText"]
|
||||
self.analysis.analysis, self.styles["ReportBodyText"]
|
||||
)
|
||||
summary_table = Table([[summary_para]], colWidths=[6.5 * inch])
|
||||
summary_table.setStyle(
|
||||
|
||||
@ -227,9 +227,13 @@ async def download_pdf(request: Request) -> StreamingResponse:
|
||||
# Prepare filename
|
||||
filename = f"swot-analysis-{session_id[:8]}.pdf"
|
||||
|
||||
# Return as streaming response
|
||||
# Return as streaming response (iterate over BytesIO in chunks)
|
||||
def iterfile():
|
||||
pdf_buffer.seek(0)
|
||||
yield from pdf_buffer
|
||||
|
||||
return StreamingResponse(
|
||||
content=pdf_buffer,
|
||||
content=iterfile(),
|
||||
media_type="application/pdf",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename={filename}",
|
||||
|
||||
Reference in New Issue
Block a user