mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-03 05:27:42 +00:00
fix(rank): handle UTF-8 BOM in tracker CSV headers (#485)
This commit is contained in:
1 parent
362ef6a522
commit
6a308c5cc8
3 files changed
+25
-1
No files matched your search
@@ -84,6 +84,14 @@ per-file diff commands.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`/rank` tracker exclusion handles UTF-8 BOMs on reordered CSV headers**
|
||||
(`tools/rank_state.py`, `tests/test_rank_state.py`) - when `company` or `role`
|
||||
is the first column, a leading BOM becomes part of the header name and an
|
||||
already-tracked application is selected for ranking again. Read with
|
||||
`utf-8-sig` so both BOM-prefixed and plain UTF-8 trackers match correctly.
|
||||
The standard `date`-first header already worked; regression coverage checks
|
||||
all three column orders with and without a BOM.
|
||||
|
||||
- **`/apply` Step 5b now actually runs the page-count check it claimed Step 5d ran**
|
||||
(`.claude/commands/apply.md`, `tests/test_apply_page_count.py`) - the 5b prose said
|
||||
"Page count is not checked here - that is `verify_pdf.py --pages`'s job, and Step 5d already
|
||||
|
||||
@@ -105,6 +105,22 @@ class Candidates(RankStateCase):
|
||||
self.assertEqual([row["key"] for row in out["selected"]], ["b"])
|
||||
self.assertEqual(out["excluded_by_tracker"], 1)
|
||||
|
||||
def test_tracker_exclusion_handles_utf8_bom_and_reordered_columns(self):
|
||||
self.write_state({"a": entry(company="Acme", title="SOC Analyst"), "b": entry(company="Other")})
|
||||
tracker = self.tmp / "tracker.csv"
|
||||
# A spreadsheet export can prepend a BOM to either matching column.
|
||||
for encoding in ("utf-8", "utf-8-sig"):
|
||||
for csv_text in (
|
||||
"date,company,role\r\n2026-08-01,ACME,soc analyst\r\n",
|
||||
"company,role,date\r\nACME,soc analyst,2026-08-01\r\n",
|
||||
"role,company,date\r\nsoc analyst,ACME,2026-08-01\r\n",
|
||||
):
|
||||
with self.subTest(encoding=encoding, header=csv_text.splitlines()[0]):
|
||||
tracker.write_bytes(csv_text.encode(encoding))
|
||||
out = self.run_tool("candidates", "--tracker", str(tracker))
|
||||
self.assertEqual([row["key"] for row in out["selected"]], ["b"])
|
||||
self.assertEqual(out["excluded_by_tracker"], 1)
|
||||
|
||||
def test_focus_filters_on_title_company_and_stored_fit_notes(self):
|
||||
self.write_state(
|
||||
{
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ def tracker_pairs(path: Path) -> set[tuple[str, str]]:
|
||||
import csv
|
||||
|
||||
pairs = set()
|
||||
with path.open(encoding="utf-8", newline="") as fh:
|
||||
with path.open(encoding="utf-8-sig", newline="") as fh:
|
||||
for row in csv.DictReader(fh):
|
||||
company, role = norm(row.get("company")), norm(row.get("role"))
|
||||
if company:
|
||||
|
||||
Reference in new issue
Block a user