Spaces:
Sleeping
Sleeping
| import json | |
| import os | |
| import platform | |
| import re | |
| from datetime import datetime | |
| from pathlib import Path | |
| from models.config import AppSettings | |
| from models.cv import CVData | |
| from models.output import IndexRecord, OutputIndex | |
| from models.resume import HTMLResume | |
| TEMPLATE_DIR = Path(__file__).resolve().parent.parent / "templates" | |
| def render_pdf( | |
| html_resume: HTMLResume, | |
| cv_data: CVData, | |
| settings: AppSettings, | |
| input_filename: str = "", | |
| jd_text: str = "", | |
| iterations_used: int = 0, | |
| all_filters_passed: bool = False, | |
| duration_seconds: float = 0.0, | |
| ) -> Path: | |
| settings.output_dir.mkdir(parents=True, exist_ok=True) | |
| timestamp = datetime.now().strftime("%m%d_%H%M") | |
| name = _slugify(cv_data.name or "resume") | |
| filename = f"{timestamp}_{name}_{settings.language}.pdf" | |
| output_path = settings.output_dir / filename | |
| try: | |
| _ensure_homebrew_library_path() | |
| from weasyprint import HTML | |
| except OSError as exc: | |
| raise RuntimeError(f"WeasyPrint system dependencies are missing: {exc}") from exc | |
| html_document = _wrap_resume_html(html_resume.html) | |
| HTML(string=html_document).write_pdf(output_path) | |
| if settings.debug: | |
| debug_dir = settings.output_dir / "debug" | |
| debug_dir.mkdir(parents=True, exist_ok=True) | |
| (debug_dir / f"iter_{html_resume.iteration}.html").write_text(html_document, encoding="utf-8") | |
| record = IndexRecord( | |
| input_filename=input_filename, | |
| jd_snippet=jd_text[:300], | |
| output_pdf=str(output_path), | |
| iterations_used=iterations_used, | |
| model=settings.model.name, | |
| all_filters_passed=all_filters_passed, | |
| duration_seconds=duration_seconds, | |
| ) | |
| index_path = settings.output_dir / "index.json" | |
| index = _load_index(index_path) | |
| index.append_and_save(record, index_path) | |
| return output_path | |
| def _slugify(value: str) -> str: | |
| return re.sub(r"[^a-z0-9]+", "_", value.lower()).strip("_") or "resume" | |
| def _wrap_resume_html(html: str) -> str: | |
| if re.search(r"<\s*html[\s>]", html, re.IGNORECASE): | |
| return html | |
| wrapper_path = TEMPLATE_DIR / "resume_wrapper.html" | |
| if not wrapper_path.exists(): | |
| return f"<!doctype html><html><body>{html}</body></html>" | |
| wrapper = wrapper_path.read_text(encoding="utf-8") | |
| return wrapper.replace("{{HEADER}}", "").replace("{{BODY}}", html) | |
| def _ensure_homebrew_library_path() -> None: | |
| if platform.system() != "Darwin": | |
| return | |
| homebrew_lib = "/opt/homebrew/lib" | |
| if not Path(homebrew_lib).exists(): | |
| homebrew_lib = "/usr/local/lib" | |
| existing = os.environ.get("DYLD_FALLBACK_LIBRARY_PATH", "") | |
| paths = [path for path in existing.split(":") if path] | |
| if homebrew_lib not in paths: | |
| paths.insert(0, homebrew_lib) | |
| os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = ":".join(paths) | |
| def _load_index(path: Path) -> OutputIndex: | |
| if not path.exists() or not path.read_text(encoding="utf-8").strip(): | |
| return OutputIndex() | |
| return OutputIndex.model_validate(json.loads(path.read_text(encoding="utf-8"))) | |