feat: add light markdown candidate profile parser
This commit is contained in:
parent
0ce4ca0ee5
commit
17800a5f07
22
docs/profile-template.md
Normal file
22
docs/profile-template.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Candidate Profile
|
||||
|
||||
## Summary
|
||||
One short paragraph describing your target profile.
|
||||
|
||||
## Target Roles
|
||||
- Data Engineer
|
||||
|
||||
## Strengths
|
||||
- Python
|
||||
- SQL
|
||||
|
||||
## Skills To Emphasize
|
||||
- GCP
|
||||
- BigQuery
|
||||
|
||||
## Constraints
|
||||
- CDI only
|
||||
- France only
|
||||
|
||||
## Notes
|
||||
- Anything the CV parser might miss but future ranking should understand.
|
||||
1
src/job_research/profile/__init__.py
Normal file
1
src/job_research/profile/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__all__ = ["profile_parser"]
|
||||
68
src/job_research/profile/profile_parser.py
Normal file
68
src/job_research/profile/profile_parser.py
Normal file
@ -0,0 +1,68 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuthoredProfile:
|
||||
summary: str | None = None
|
||||
target_roles: list[str] = field(default_factory=list)
|
||||
strengths: list[str] = field(default_factory=list)
|
||||
skills_to_emphasize: list[str] = field(default_factory=list)
|
||||
constraints: list[str] = field(default_factory=list)
|
||||
notes: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
REQUIRED_SECTIONS = {
|
||||
"summary",
|
||||
"target roles",
|
||||
"strengths",
|
||||
"skills to emphasize",
|
||||
"constraints",
|
||||
"notes",
|
||||
}
|
||||
|
||||
|
||||
def parse_profile_markdown(markdown: str) -> AuthoredProfile:
|
||||
sections: dict[str, list[str]] = defaultdict(list)
|
||||
current_section: str | None = None
|
||||
|
||||
for raw_line in markdown.splitlines():
|
||||
line = raw_line.strip()
|
||||
if line.startswith("## "):
|
||||
current_section = line[3:].strip().lower()
|
||||
continue
|
||||
if not line or current_section is None:
|
||||
continue
|
||||
sections[current_section].append(line)
|
||||
|
||||
missing = REQUIRED_SECTIONS - set(sections)
|
||||
if missing:
|
||||
missing_text = ", ".join(sorted(missing))
|
||||
raise ValueError(f"Missing required markdown sections: {missing_text}")
|
||||
|
||||
return AuthoredProfile(
|
||||
summary=" ".join(sections["summary"]),
|
||||
target_roles=[
|
||||
line[2:].strip()
|
||||
for line in sections["target roles"]
|
||||
if line.startswith("- ")
|
||||
],
|
||||
strengths=[
|
||||
line[2:].strip()
|
||||
for line in sections["strengths"]
|
||||
if line.startswith("- ")
|
||||
],
|
||||
skills_to_emphasize=[
|
||||
line[2:].strip()
|
||||
for line in sections["skills to emphasize"]
|
||||
if line.startswith("- ")
|
||||
],
|
||||
constraints=[
|
||||
line[2:].strip()
|
||||
for line in sections["constraints"]
|
||||
if line.startswith("- ")
|
||||
],
|
||||
notes=[line[2:].strip() if line.startswith("- ") else line for line in sections["notes"]],
|
||||
)
|
||||
42
tests/profile/test_profile_parser.py
Normal file
42
tests/profile/test_profile_parser.py
Normal file
@ -0,0 +1,42 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from job_research.profile.profile_parser import parse_profile_markdown
|
||||
|
||||
|
||||
def test_parse_profile_markdown_reads_light_required_template() -> None:
|
||||
markdown = dedent(
|
||||
"""
|
||||
# Candidate Profile
|
||||
|
||||
## Summary
|
||||
Junior data engineer focused on Python and GCP.
|
||||
|
||||
## Target Roles
|
||||
- Data Engineer
|
||||
- Analytics Engineer
|
||||
|
||||
## Strengths
|
||||
- Python
|
||||
- SQL
|
||||
|
||||
## Skills To Emphasize
|
||||
- BigQuery
|
||||
- Terraform
|
||||
|
||||
## Constraints
|
||||
- CDI only
|
||||
- France only
|
||||
|
||||
## Notes
|
||||
- Slight preference for French listings.
|
||||
"""
|
||||
).strip()
|
||||
|
||||
profile = parse_profile_markdown(markdown)
|
||||
|
||||
assert profile.summary == "Junior data engineer focused on Python and GCP."
|
||||
assert profile.target_roles == ["Data Engineer", "Analytics Engineer"]
|
||||
assert profile.strengths == ["Python", "SQL"]
|
||||
assert profile.skills_to_emphasize == ["BigQuery", "Terraform"]
|
||||
assert profile.constraints == ["CDI only", "France only"]
|
||||
assert profile.notes == ["Slight preference for French listings."]
|
||||
Loading…
x
Reference in New Issue
Block a user