Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -16,6 +16,12 @@ from datetime import datetime, timedelta
|
|
| 16 |
import urllib.request
|
| 17 |
import os
|
| 18 |
import base64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
# Streamlit page configuration
|
| 21 |
st.set_page_config(
|
|
@@ -517,36 +523,103 @@ if page == "CV Maker": # Assuming 'page' is defined elsewhere; use 'if' instead
|
|
| 517 |
return f"Error generating CV: {str(e)}"
|
| 518 |
|
| 519 |
def generate_cv_pdf(cv_content: str) -> BytesIO:
|
|
|
|
|
|
|
| 520 |
buffer = BytesIO()
|
|
|
|
|
|
|
| 521 |
doc = SimpleDocTemplate(buffer, pagesize=letter)
|
| 522 |
-
styles = getSampleStyleSheet()
|
| 523 |
-
heading_style = ParagraphStyle(name='Heading', fontSize=14, leading=16, spaceAfter=12,
|
| 524 |
-
fontName='Helvetica-Bold')
|
| 525 |
-
body_style = ParagraphStyle(name='Body', fontSize=11, leading=14, spaceAfter=8, fontName='Helvetica')
|
| 526 |
-
bullet_style = ParagraphStyle(name='Bullet', fontSize=11, leading=14, leftIndent=20, bulletIndent=10,
|
| 527 |
-
spaceAfter=8, fontName='Helvetica')
|
| 528 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 529 |
flowables = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
sections = cv_content.split('===')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 531 |
for i in range(0, len(sections), 2):
|
| 532 |
if i + 1 >= len(sections):
|
|
|
|
| 533 |
break
|
|
|
|
| 534 |
title = sections[i].strip()
|
| 535 |
content = sections[i + 1].strip().split('\n')
|
|
|
|
|
|
|
|
|
|
| 536 |
flowables.append(Paragraph(title, heading_style))
|
| 537 |
flowables.append(Spacer(1, 6))
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 541 |
else:
|
|
|
|
| 542 |
for line in content:
|
| 543 |
if line.strip():
|
| 544 |
-
|
|
|
|
|
|
|
|
|
|
| 545 |
flowables.append(Spacer(1, 12))
|
|
|
|
|
|
|
|
|
|
| 546 |
doc.build(flowables)
|
|
|
|
|
|
|
| 547 |
buffer.seek(0)
|
|
|
|
|
|
|
| 548 |
return buffer
|
| 549 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 550 |
with st.form("cv_form"):
|
| 551 |
col1, col2 = st.columns(2)
|
| 552 |
with col1:
|
|
|
|
| 16 |
import urllib.request
|
| 17 |
import os
|
| 18 |
import base64
|
| 19 |
+
import logging
|
| 20 |
+
|
| 21 |
+
# Set up logging for debugging
|
| 22 |
+
logging.basicConfig(level=logging.DEBUG)
|
| 23 |
+
logger = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
|
| 26 |
# Streamlit page configuration
|
| 27 |
st.set_page_config(
|
|
|
|
| 523 |
return f"Error generating CV: {str(e)}"
|
| 524 |
|
| 525 |
def generate_cv_pdf(cv_content: str) -> BytesIO:
|
| 526 |
+
try:
|
| 527 |
+
# Initialize BytesIO buffer
|
| 528 |
buffer = BytesIO()
|
| 529 |
+
|
| 530 |
+
# Create a SimpleDocTemplate for the PDF
|
| 531 |
doc = SimpleDocTemplate(buffer, pagesize=letter)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 532 |
|
| 533 |
+
# Define styles
|
| 534 |
+
styles = getSampleStyleSheet()
|
| 535 |
+
heading_style = ParagraphStyle(
|
| 536 |
+
name='Heading',
|
| 537 |
+
fontSize=14,
|
| 538 |
+
leading=16,
|
| 539 |
+
spaceAfter=12,
|
| 540 |
+
fontName='Helvetica-Bold'
|
| 541 |
+
)
|
| 542 |
+
body_style = ParagraphStyle(
|
| 543 |
+
name='Body',
|
| 544 |
+
fontSize=11,
|
| 545 |
+
leading=14,
|
| 546 |
+
spaceAfter=8,
|
| 547 |
+
fontName='Helvetica'
|
| 548 |
+
)
|
| 549 |
+
bullet_style = ParagraphStyle(
|
| 550 |
+
name='Bullet',
|
| 551 |
+
fontSize=11,
|
| 552 |
+
leading=14,
|
| 553 |
+
leftIndent=20,
|
| 554 |
+
bulletIndent=10,
|
| 555 |
+
spaceAfter=8,
|
| 556 |
+
fontName='Helvetica'
|
| 557 |
+
)
|
| 558 |
+
|
| 559 |
+
# Initialize flowables list
|
| 560 |
flowables = []
|
| 561 |
+
|
| 562 |
+
# Validate cv_content
|
| 563 |
+
if not cv_content or not isinstance(cv_content, str):
|
| 564 |
+
logger.error("Invalid or empty cv_content provided")
|
| 565 |
+
raise ValueError("CV content is empty or invalid")
|
| 566 |
+
|
| 567 |
+
# Split content into sections
|
| 568 |
sections = cv_content.split('===')
|
| 569 |
+
logger.debug(f"Number of sections: {len(sections)}")
|
| 570 |
+
logger.debug(f"Sections: {sections}")
|
| 571 |
+
|
| 572 |
+
# Process sections
|
| 573 |
for i in range(0, len(sections), 2):
|
| 574 |
if i + 1 >= len(sections):
|
| 575 |
+
logger.warning("Incomplete section pair detected, stopping processing")
|
| 576 |
break
|
| 577 |
+
|
| 578 |
title = sections[i].strip()
|
| 579 |
content = sections[i + 1].strip().split('\n')
|
| 580 |
+
logger.debug(f"Processing section: {title}")
|
| 581 |
+
|
| 582 |
+
# Add section title
|
| 583 |
flowables.append(Paragraph(title, heading_style))
|
| 584 |
flowables.append(Spacer(1, 6))
|
| 585 |
+
|
| 586 |
+
# Process section content
|
| 587 |
+
if title in ["Skills", "Certifications"]:
|
| 588 |
+
# Handle bullet points for Skills and Certifications
|
| 589 |
+
bullet_items = []
|
| 590 |
+
for line in content:
|
| 591 |
+
if line.strip():
|
| 592 |
+
# Sanitize text to avoid encoding issues
|
| 593 |
+
sanitized_line = line.strip().encode('ascii', 'ignore').decode('ascii')
|
| 594 |
+
bullet_items.append(ListItem(Paragraph(sanitized_line, bullet_style)))
|
| 595 |
+
if bullet_items:
|
| 596 |
+
flowables.append(ListFlowable(bullet_items, bulletType='bullet', start='circle'))
|
| 597 |
+
else:
|
| 598 |
+
logger.warning(f"No valid bullet items for section: {title}")
|
| 599 |
else:
|
| 600 |
+
# Handle regular paragraphs
|
| 601 |
for line in content:
|
| 602 |
if line.strip():
|
| 603 |
+
# Sanitize text to avoid encoding issues
|
| 604 |
+
sanitized_line = line.strip().encode('ascii', 'ignore').decode('ascii')
|
| 605 |
+
flowables.append(Paragraph(sanitized_line, body_style))
|
| 606 |
+
|
| 607 |
flowables.append(Spacer(1, 12))
|
| 608 |
+
|
| 609 |
+
# Build the PDF
|
| 610 |
+
logger.debug("Building PDF with flowables")
|
| 611 |
doc.build(flowables)
|
| 612 |
+
|
| 613 |
+
# Ensure buffer is ready to be read
|
| 614 |
buffer.seek(0)
|
| 615 |
+
logger.debug("PDF generation completed successfully")
|
| 616 |
+
|
| 617 |
return buffer
|
| 618 |
|
| 619 |
+
except Exception as e:
|
| 620 |
+
logger.error(f"Error generating PDF: {str(e)}")
|
| 621 |
+
raise Exception(f"Failed to generate PDF: {str(e)}")
|
| 622 |
+
|
| 623 |
with st.form("cv_form"):
|
| 624 |
col1, col2 = st.columns(2)
|
| 625 |
with col1:
|