Telephone numbers: Italian landlines lose their leading zero, and shared dialling codes show the wrong country #459

Closed
opened 2026-10-01 10:46:51 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading core/phones.py and running combine and country_of against numbers from the countries that share a dialling code.

Checked again on 2026-10-01 against main at 0a5cad587: still present.

Two mistakes in the country arithmetic. combine removes every leading zero from a national number, which is right for most of Europe and wrong for Italy, San Marino and the Vatican, whose zero is part of the international number: an Italian landline is stored as a different number that cannot be dialled. And country_of breaks ties between countries sharing a code alphabetically, so the telephone field shows Antigua and Barbuda for every North American number, the Åland Islands for every Finnish one, Kazakhstan for every Russian one and Western Sahara for every Moroccan one.

  • Where: core/phones.py:392 (combine, return f"+{row[1]}{digits.lstrip('0')}"); core/phones.py:286 (_BY_DIALLING = sorted(COUNTRIES, key=lambda row: (-len(row[1]), row[0]))), read by country_of at core/phones.py:395; core/phone_field.py:84 (PhoneWidget.decompress, which sets the chooser and the flag from country_of).
  • What happens:
    1. Somebody reading Postulo in Italian (default country IT) records a recruiter's Rome line as 06 6982 1234. combine("06 6982 1234", "IT") returns +39669821234; the right number is +390669821234. San Marino fails the same way (0549 882 555 becomes +378549882555). The docstring of combine says that where a country has no trunk prefix "nothing happens", but no such exception is coded.
    2. A stored +12125551234 or +14165551234 decompresses to AG, +358401234567 to AX, +74951234567 to KZ, +212612345678 to EH, +590590123456 to BL and +5999123456 to BQ. The edit form therefore shows that country and its flag beside every US, Canadian, Finnish, Russian, Moroccan, Guadeloupean and Curaçao number. Saving again keeps the same digits, so the second mistake is on screen only, but a Finnish reader meets it on every Finnish number.
  • Why it matters: the first mistake corrupts a contact's number silently at the moment it is typed, which is the one moment phones.py says a number can be fixed; the second puts a wrong, and for Western Sahara a politically loaded, flag beside ordinary numbers.
  • Fix: related to #304, which is replacing the arithmetic with the numbering plans (phonenumberslite). Parsing with the chosen region keeps the Italian leading zero, and region_code_for_number resolves a shared code by number range; #304's tests name "a country with no trunk prefix" but neither case here, so add them there. If combine survives #304 in any form, keep the zero for IT, SM and VA, and give each shared code a main country instead of the alphabetical first (US for 1, RU for 7, FI for 358, MA for 212, GP for 590, CW for 599).

Done when

  • tests/test_phones.py asserts that combine("06 6982 1234", "IT") is +390669821234, and that country_of answers US for +12125551234, FI for +358401234567, RU for +74951234567 and MA for +212612345678; all four fail today.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading `core/phones.py` and running `combine` and `country_of` against numbers from the countries that share a dialling code. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. Two mistakes in the country arithmetic. `combine` removes every leading zero from a national number, which is right for most of Europe and wrong for Italy, San Marino and the Vatican, whose zero is part of the international number: an Italian landline is stored as a different number that cannot be dialled. And `country_of` breaks ties between countries sharing a code alphabetically, so the telephone field shows Antigua and Barbuda for every North American number, the Åland Islands for every Finnish one, Kazakhstan for every Russian one and Western Sahara for every Moroccan one. - **Where:** `core/phones.py:392` (`combine`, `return f"+{row[1]}{digits.lstrip('0')}"`); `core/phones.py:286` (`_BY_DIALLING = sorted(COUNTRIES, key=lambda row: (-len(row[1]), row[0]))`), read by `country_of` at `core/phones.py:395`; `core/phone_field.py:84` (`PhoneWidget.decompress`, which sets the chooser and the flag from `country_of`). - **What happens:** 1. Somebody reading Postulo in Italian (default country `IT`) records a recruiter's Rome line as `06 6982 1234`. `combine("06 6982 1234", "IT")` returns `+39669821234`; the right number is `+390669821234`. San Marino fails the same way (`0549 882 555` becomes `+378549882555`). The docstring of `combine` says that where a country has no trunk prefix "nothing happens", but no such exception is coded. 2. A stored `+12125551234` or `+14165551234` decompresses to `AG`, `+358401234567` to `AX`, `+74951234567` to `KZ`, `+212612345678` to `EH`, `+590590123456` to `BL` and `+5999123456` to `BQ`. The edit form therefore shows that country and its flag beside every US, Canadian, Finnish, Russian, Moroccan, Guadeloupean and Curaçao number. Saving again keeps the same digits, so the second mistake is on screen only, but a Finnish reader meets it on every Finnish number. - **Why it matters:** the first mistake corrupts a contact's number silently at the moment it is typed, which is the one moment `phones.py` says a number can be fixed; the second puts a wrong, and for Western Sahara a politically loaded, flag beside ordinary numbers. - **Fix:** related to #304, which is replacing the arithmetic with the numbering plans (`phonenumberslite`). Parsing with the chosen region keeps the Italian leading zero, and `region_code_for_number` resolves a shared code by number range; #304's tests name "a country with no trunk prefix" but neither case here, so add them there. If `combine` survives #304 in any form, keep the zero for `IT`, `SM` and `VA`, and give each shared code a main country instead of the alphabetical first (`US` for 1, `RU` for 7, `FI` for 358, `MA` for 212, `GP` for 590, `CW` for 599). ## Done when - `tests/test_phones.py` asserts that `combine("06 6982 1234", "IT")` is `+390669821234`, and that `country_of` answers `US` for `+12125551234`, `FI` for `+358401234567`, `RU` for `+74951234567` and `MA` for `+212612345678`; all four fail today.
tiagoagueda added this to the 0.5.0 milestone 2026-10-01 10:46:51 +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#459
No description provided.