fix(tests): replace importlib.reload with monkeypatch.setattr for DB_PATH isolation

importlib.reload(dev_api) reset all module-level globals (RESUME_PATH,
SEARCH_PREFS_PATH, etc.) on every digest/interviews test, causing
subsequent monkeypatch.setattr calls in test_dev_api_settings.py to
silently fail — the patched attribute was reset between fixture setup
and the actual HTTP request.

Fix: patch dev_api.DB_PATH directly via monkeypatch, which pytest reverts
cleanly after each test without touching any other module state.

Also sync resume optimizer endpoints to dev-api.py (hyphen variant).
This commit is contained in:
pyr0ball 2026-04-01 06:58:28 -07:00
parent 931a07d4e0
commit dfac0f3d7a
3 changed files with 63 additions and 5 deletions

View file

@ -364,6 +364,67 @@ def research_task_status(job_id: int):
return {"status": row["status"], "stage": row["stage"], "message": row["error"]} return {"status": row["status"], "stage": row["stage"], "message": row["error"]}
# ── ATS Resume Optimizer endpoints ───────────────────────────────────────────
@app.get("/api/jobs/{job_id}/resume_optimizer")
def get_optimized_resume(job_id: int):
"""Return the current optimized resume and ATS gap report for a job."""
from scripts.db import get_optimized_resume as _get
import json
result = _get(db_path=Path(DB_PATH), job_id=job_id)
gap_report = result.get("ats_gap_report", "")
try:
gap_report_parsed = json.loads(gap_report) if gap_report else []
except Exception:
gap_report_parsed = []
return {
"optimized_resume": result.get("optimized_resume", ""),
"ats_gap_report": gap_report_parsed,
}
class ResumeOptimizeBody(BaseModel):
full_rewrite: bool = False
@app.post("/api/jobs/{job_id}/resume_optimizer/generate")
def generate_optimized_resume(job_id: int, body: ResumeOptimizeBody):
"""Queue an ATS resume optimization task for this job.
full_rewrite=False (default) free tier: gap report only, no LLM rewrite.
full_rewrite=True paid tier: per-section LLM rewrite + hallucination check.
"""
import json
try:
from scripts.task_runner import submit_task
params = json.dumps({"full_rewrite": body.full_rewrite})
task_id, is_new = submit_task(
db_path=Path(DB_PATH),
task_type="resume_optimize",
job_id=job_id,
params=params,
)
return {"task_id": task_id, "is_new": is_new}
except Exception as e:
raise HTTPException(500, str(e))
@app.get("/api/jobs/{job_id}/resume_optimizer/task")
def resume_optimizer_task_status(job_id: int):
"""Poll the latest resume_optimize task status for this job."""
db = _get_db()
row = db.execute(
"SELECT status, stage, error FROM background_tasks "
"WHERE task_type = 'resume_optimize' AND job_id = ? "
"ORDER BY id DESC LIMIT 1",
(job_id,),
).fetchone()
db.close()
if not row:
return {"status": "none", "stage": None, "message": None}
return {"status": row["status"], "stage": row["stage"], "message": row["error"]}
@app.get("/api/jobs/{job_id}/contacts") @app.get("/api/jobs/{job_id}/contacts")
def get_job_contacts(job_id: int): def get_job_contacts(job_id: int):
db = _get_db() db = _get_db()

View file

@ -50,9 +50,8 @@ def tmp_db(tmp_path):
@pytest.fixture() @pytest.fixture()
def client(tmp_db, monkeypatch): def client(tmp_db, monkeypatch):
monkeypatch.setenv("STAGING_DB", tmp_db) monkeypatch.setenv("STAGING_DB", tmp_db)
import importlib
import dev_api import dev_api
importlib.reload(dev_api) monkeypatch.setattr(dev_api, "DB_PATH", tmp_db)
return TestClient(dev_api.app) return TestClient(dev_api.app)

View file

@ -54,10 +54,8 @@ def tmp_db(tmp_path):
@pytest.fixture() @pytest.fixture()
def client(tmp_db, monkeypatch): def client(tmp_db, monkeypatch):
monkeypatch.setenv("STAGING_DB", tmp_db) monkeypatch.setenv("STAGING_DB", tmp_db)
# Re-import after env var is set so DB_PATH picks it up
import importlib
import dev_api import dev_api
importlib.reload(dev_api) monkeypatch.setattr(dev_api, "DB_PATH", tmp_db)
return TestClient(dev_api.app) return TestClient(dev_api.app)