Europass import (old formats): UK and EL are stored as the country, which Postulo does not know #639

Closed
opened 2026-10-01 10:48:34 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the three Europass readers side by side and running the old ones on an address with each code.

The two SkillsPassport readers take an address's country as the first two characters of whatever the file's Code holds, and the import stores it in PostalAddress.country, which is an ISO 3166-1 alpha-2 code. Cedefop's Europass did not write ISO for two countries: it used the European Union's own codes, UK for the United Kingdom and EL for Greece. Neither is in Postulo's country table, so a British or Greek address arrives with a country Postulo cannot name, flag, check or show in its own form.

Checked again on 2026-10-01 against main at 0a5cad587: still present, at plugins/europass/reader.py:122-136.

  • Where:
    • plugins/europass/reader.py:168-177 (_country_code) and :180-182 (_json_country_code): .strip().upper()[:2], used at :484 and :780.
    • resume/importing.py:104 (_write_address): country=(parts.get("country") or "")[:2], with no check against the country table.
    • Compare plugins/europass/candidate.py:292-300 (_country), which takes a code only when it is exactly two ASCII letters, and whose docstring gives the reason: "cutting PRT to two letters would make it Puerto Rico".
  • What happens:
    1. A person imports an old Europass XML or JSON file whose address has <Country><Code>UK</Code><Label>United Kingdom</Label></Country>. Postulo's own JSON fixture writes a country this way (tests/data/europass.json:56).
    2. The reader returns 'country': 'UK' and the import saves the row with it.
    3. phones.country_name("UK") returns UK, so the address reads "…, London, UK" where every other one has the country's name; flag_url("UK") is empty; postal_rules.rule_for("UK") is the empty rule, so the parts get neutral labels and no notes.
    4. On Your details the country select has no UK option, so the row opens with no country chosen. The next save of that page stores an empty country without saying so.
    • The same happens with EL. A file that writes a three-letter code is cut to another country: PRT is stored as PR, which the table knows as Puerto Rico.
  • Why it matters: the import reports the address as filled, and it is filled with a country no part of Postulo recognises. The loss on the next save is silent.
  • Fix: give the old readers the Candidate reader's rule. Move candidate._country to a helper all three share; in it, map UK to GB and EL to GR, accept a code only when it is exactly two ASCII letters, and return an empty string otherwise (the country's label is still in location). Checking the code against the country table in importing._write_address belongs with the review's issue about import values stored without the profile forms' checks.

Done when

  • A test in tests/test_europass.py reads an XML file and a JSON file whose address has the code UK, and finds GB in record.person["address"]["country"]; the same for EL and GR. It fails today.
  • A test in tests/test_europass.py reads an address whose code is PRT and finds an empty country, not PR.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the three Europass readers side by side and running the old ones on an address with each code. The two SkillsPassport readers take an address's country as the first two characters of whatever the file's `Code` holds, and the import stores it in `PostalAddress.country`, which is an ISO 3166-1 alpha-2 code. Cedefop's Europass did not write ISO for two countries: it used the European Union's own codes, `UK` for the United Kingdom and `EL` for Greece. Neither is in Postulo's country table, so a British or Greek address arrives with a country Postulo cannot name, flag, check or show in its own form. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present, at `plugins/europass/reader.py:122-136`. - **Where:** - `plugins/europass/reader.py:168-177` (`_country_code`) and `:180-182` (`_json_country_code`): `.strip().upper()[:2]`, used at `:484` and `:780`. - `resume/importing.py:104` (`_write_address`): `country=(parts.get("country") or "")[:2]`, with no check against the country table. - Compare `plugins/europass/candidate.py:292-300` (`_country`), which takes a code only when it is exactly two ASCII letters, and whose docstring gives the reason: "cutting `PRT` to two letters would make it Puerto Rico". - **What happens:** 1. A person imports an old Europass XML or JSON file whose address has `<Country><Code>UK</Code><Label>United Kingdom</Label></Country>`. Postulo's own JSON fixture writes a country this way (`tests/data/europass.json:56`). 2. The reader returns `'country': 'UK'` and the import saves the row with it. 3. `phones.country_name("UK")` returns `UK`, so the address reads "…, London, UK" where every other one has the country's name; `flag_url("UK")` is empty; `postal_rules.rule_for("UK")` is the empty rule, so the parts get neutral labels and no notes. 4. On *Your details* the country select has no `UK` option, so the row opens with no country chosen. The next save of that page stores an empty country without saying so. - The same happens with `EL`. A file that writes a three-letter code is cut to another country: `PRT` is stored as `PR`, which the table knows as Puerto Rico. - **Why it matters:** the import reports the address as filled, and it is filled with a country no part of Postulo recognises. The loss on the next save is silent. - **Fix:** give the old readers the Candidate reader's rule. Move `candidate._country` to a helper all three share; in it, map `UK` to `GB` and `EL` to `GR`, accept a code only when it is exactly two ASCII letters, and return an empty string otherwise (the country's label is still in `location`). Checking the code against the country table in `importing._write_address` belongs with the review's issue about import values stored without the profile forms' checks. ## Done when - A test in `tests/test_europass.py` reads an XML file and a JSON file whose address has the code `UK`, and finds `GB` in `record.person["address"]["country"]`; the same for `EL` and `GR`. It fails today. - A test in `tests/test_europass.py` reads an address whose code is `PRT` and finds an empty country, not `PR`.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:34 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#639
No description provided.