Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| from typing import List, Tuple, Optional | |
| import textwrap | |
| import re | |
| from .text import normalize_whitespace | |
| ACTION_VERBS = [ | |
| "Led", "Built", "Improved", "Optimized", "Delivered", "Designed", "Implemented", "Automated", | |
| "Reduced", "Increased", "Analyzed", "Developed", "Launched", "Managed", "Resolved", "Created", | |
| # Reed-recommended action words | |
| "Achieved", "Formulated", "Planned", "Generated", "Represented", "Completed", | |
| ] | |
| # Weak openers to avoid on bullets and suggested stronger replacements | |
| _WEAK_TO_STRONG = [ | |
| (re.compile(r"^\s*-\s*responsible for\s+", re.IGNORECASE), "- Led "), | |
| (re.compile(r"^\s*-\s*tasked with\s+", re.IGNORECASE), "- Executed "), | |
| (re.compile(r"^\s*-\s*worked on\s+", re.IGNORECASE), "- Delivered "), | |
| (re.compile(r"^\s*-\s*helped\s+", re.IGNORECASE), "- Supported "), | |
| (re.compile(r"^\s*-\s*assisted with\s+", re.IGNORECASE), "- Supported "), | |
| (re.compile(r"^\s*-\s*handled\s+", re.IGNORECASE), "- Managed "), | |
| ] | |
| def strengthen_action_verbs(text: str) -> str: | |
| """Promote weak bullet openers to stronger action verbs (The Muse guidance).""" | |
| if not text: | |
| return text | |
| lines = text.splitlines() | |
| out: List[str] = [] | |
| for line in lines: | |
| new_line = line | |
| for pattern, repl in _WEAK_TO_STRONG: | |
| if pattern.search(new_line): | |
| new_line = pattern.sub(repl, new_line) | |
| break | |
| out.append(new_line) | |
| return "\n".join(out) | |
| def make_bullets(lines: List[str]) -> str: | |
| clean_lines = [f"- {normalize_whitespace(l)}" for l in lines if l and l.strip()] | |
| return "\n".join(clean_lines) | |
| def ensure_keywords(text: str, keywords: List[str], max_new: int = 30, allowed_keywords: Optional[set] = None) -> Tuple[str, List[str]]: | |
| used = [] | |
| missing = [] | |
| lower_text = text.lower() | |
| for k in keywords: | |
| if k.lower() in lower_text: | |
| used.append(k) | |
| else: | |
| missing.append(k) | |
| if missing: | |
| additions = [] | |
| actually_added = [] | |
| for k in missing: | |
| if len(actually_added) >= max_new: | |
| break | |
| if allowed_keywords is not None and k.lower() not in allowed_keywords: | |
| continue | |
| additions.append(f"Experience with {k}.") | |
| actually_added.append(k) | |
| if additions: | |
| text = text.rstrip() + "\n\nKeywords: " + ", ".join(actually_added) + "\n" + make_bullets(additions) | |
| used.extend(actually_added) | |
| return text, used | |
| def format_resume_header(full_name: str, headline: str, email: str | None, phone: str | None, location: str | None, links: dict) -> str: | |
| contact_parts = [p for p in [email, phone, location] if p] | |
| links_str = " | ".join([f"{k}: {v}" for k, v in links.items()]) if links else "" | |
| top_line = f"{full_name} β {headline}" if headline else full_name | |
| contact_line = " | ".join(filter(None, [" | ".join(contact_parts), links_str])) | |
| return "\n".join([top_line, contact_line]).strip() + "\n" | |
| def format_experience_section(experiences: List[dict]) -> str: | |
| sections: List[str] = [] | |
| for exp in experiences: | |
| header = f"{exp.get('title','')} β {exp.get('company','')} ({exp.get('start_date','')} β {exp.get('end_date','Present')})" | |
| bullets = exp.get("achievements") or [] | |
| if not bullets: | |
| bullets = [ | |
| f"{ACTION_VERBS[0]} key outcomes relevant to the role.", | |
| "Collaborated cross-functionally to deliver results.", | |
| "Drove measurable impact with data-informed decisions.", | |
| ] | |
| sections.append("\n".join([header, make_bullets(bullets)])) | |
| return "\n\n".join(sections) | |
| def format_skills_section(skills: List[str]) -> str: | |
| if not skills: | |
| return "" | |
| return "Skills: " + ", ".join(skills) | |
| def basic_resume_template(header: str, summary: str | None, skills: str, experience: str, education: str | None) -> str: | |
| parts = [header] | |
| if summary: | |
| parts.append("\nSummary\n" + textwrap.fill(summary, width=100)) | |
| if skills: | |
| parts.append("\n" + skills) | |
| if experience: | |
| parts.append("\n\nExperience\n" + experience) | |
| if education: | |
| parts.append("\n\nEducation\n" + education) | |
| return "\n".join(parts).strip() + "\n" | |
| def basic_cover_letter_template(greeting: str, body_paragraphs: List[str], closing: str, signature: str) -> str: | |
| body = "\n\n".join(textwrap.fill(p, width=100) for p in body_paragraphs) | |
| return "\n".join([greeting, "", body, "", closing, "", signature]).strip() + "\n" |