Skip to content

fix: keep all digits when formatting 13-digit SP/MG voter ids#742

Open
gaoflow wants to merge 2 commits into
brazilian-utils:mainfrom
gaoflow:fix-format-voter-id-13-digit
Open

fix: keep all digits when formatting 13-digit SP/MG voter ids#742
gaoflow wants to merge 2 commits into
brazilian-utils:mainfrom
gaoflow:fix-format-voter-id-13-digit

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 17, 2026

Copy link
Copy Markdown

What this fixes

format_voter_id silently corrupts valid 13-digit voter IDs (the SP/MG edge case, where the sequential number has 9 digits instead of 8).

>>> from brutils import is_valid_voter_id, format_voter_id
>>> is_valid_voter_id("3244567800167")
True
>>> format_voter_id("3244567800167")
'3244 5678 00 16'   # last digit dropped; UF "00"/vd "16" are wrong (real UF=01, vd=67)

is_valid already accepts 13-digit IDs (_is_length_valid allows len == 13 for UF 01/02), and the parsing helpers _get_federative_union / _get_verifying_digits index backwards specifically because "the sequential_number can have eight or nine digits". Only format_voter_id used hardcoded 12-digit forward slices (voter_id[:4], [4:8], [8:10], [10:12]), so it dropped the 13th digit and misplaced the trailing fields.

The change

Make the slicing length-aware, reusing the existing helpers: the federative union and verifying digits are always the last four characters, and the sequential number is everything before them.

  • 12-digit IDs format exactly as before (2776 2712 28 52).
  • 13-digit IDs now format losslessly (32445 6780 01 67), so the output minus spaces round-trips back to the input.

Tests

Added test_format_voter_id_special_case using the official 13-digit fixture (3244567800167, already asserted valid by test_valid_special_case): it checks validity, the formatted output, and that the result round-trips losslessly. It fails before the change (the last digit is dropped) and passes after. Full suite: 172 tests pass; ruff format --check and ruff check clean.

I used an AI assistant to help investigate this under my direction, and I have reviewed and verified the change myself.

format_voter_id used hardcoded 12-digit forward slices, so a valid 13-digit
voter id (the SP/MG edge case with a 9-digit sequential number) lost its last
digit and showed the wrong federative union and verifying digits, even though
is_valid accepts it.

Slice length-aware: the federative union and verifying digits are always the
last four characters (via the existing backward-indexing helpers), and the
sequential number is everything before them. 12-digit output is unchanged;
13-digit ids now format losslessly.
@gaoflow gaoflow requested review from a team as code owners June 17, 2026 09:37
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.08%. Comparing base (e1ce34a) to head (d38500b).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #742   +/-   ##
=======================================
  Coverage   99.08%   99.08%           
=======================================
  Files          26       26           
  Lines         765      769    +4     
=======================================
+ Hits          758      762    +4     
  Misses          7        7           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant