Skip to content

fix(domains): read an integral float code column as integer text - #488

Merged
kevincostner17 merged 1 commit into
mainfrom
fix/domain-regex-float-text
Sep 20, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
fix/domain-regex-float-text

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Summary

A numeric code column with one blank cell loads from CSV as float64, so Series.astype("string") renders 10000266 as "10000266.0" and the trailing 0 reads as an extra digit. Every row of a perfectly valid column then fails a digit-only pattern.

GS1-008  gpc_brick_code, int64    -> passed,  0 violations, trust 0.25
GS1-008  gpc_brick_code, float64  -> FAILED,  3 violations, trust 0.0625

Same codes, same rule, four-fold trust drop, decided by whether one cell happened to be blank. Both regex rules in the repo were affected: GS1-008 ([0-9]{8}) and FIN-008 ([A-Za-z0-9]{4,12}).

Found by the Phase 8 domain lane (#482) and reproduced independently before fixing.

The intended behaviour was already settled

retail/validator.py carried _integral_float_text for exactly this case on the GTIN checks, and its docstring describes this same CSV-blank-cell scenario. The shared rule engine simply never used it.

The helper now lives in domains/base.py as integral_float_text, _check_regex applies it, and retail imports it rather than keeping a second copy.

Deliberately narrow

Only an integral, finite float is rewritten:

input output
10000266.0 "10000266"
12.5 12.5 — a real decimal keeps its fraction
nan, ±inf unchanged — int(nan) would raise
"0250" "0250" — text untouched, padding survives
7, None unchanged

So a real violation is still reported: verified that a frame of genuinely invalid codes still fails with all four rows flagged.

A note for reviewers

This also updates test_domain_validation_lane.py, which pinned this defect as current behaviour when #482 found it. That test was a tripwire for the fix, and the fix duly tripped it — it now asserts the repaired behaviour, with the history kept in its docstring.

This is the second time a pinned-defect test has had to be flipped by the fix that resolved it (see #485). Worth grepping for DEFECT / FINDING (S before landing any behaviour change.

Verification

  • 14 new tests; 3 assertions fail on main, across both affected rules.
  • Full suite py3.12: 7107 passed, 20 skipped, 0 failed, coverage 94.94%.
  • python -m benchmarks.gauntlet run --check: all gates passed.
  • ruff check . clean repo-wide.

A numeric code column with one blank cell loads from CSV as float64, so
Series.astype("string") renders 10000266 as "10000266.0" and the trailing 0
reads as an extra digit. Every row of a perfectly valid column then fails a
digit-only pattern:

    GS1-008  gpc_brick_code, int64   -> passed,  0 violations, trust 0.25
    GS1-008  gpc_brick_code, float64 -> FAILED,  3 violations, trust 0.0625

Same codes, same rule, four-fold trust drop, decided by whether one cell
happened to be blank. Both regex rules in the repo were affected: GS1-008
([0-9]{8}) and FIN-008 ([A-Za-z0-9]{4,12}).

The repository had already settled the intended behaviour. retail/validator.py
carried _integral_float_text for exactly this case on the GTIN checks, and its
docstring describes this same CSV-blank-cell scenario -- the shared rule engine
simply never used it. The helper now lives in domains/base.py as
integral_float_text, _check_regex applies it, and retail imports it rather than
keeping a second copy.

Deliberately narrow: only an integral, finite float is rewritten. A genuine
decimal keeps its fraction, NaN and ±inf pass through (int(nan) would raise),
and text, integers and None are untouched -- so zero-padded strings keep their
padding and a real violation is still reported. Verified: a frame of genuinely
invalid codes still fails with all four rows flagged.

Three assertions in the new test file fail on main, across both affected rules.

Also updates test_domain_validation_lane.py, which pinned this defect as
current behaviour when #482 found it. That test is a tripwire for the fix and
the fix duly tripped it, so it now asserts the repaired behaviour with the
history kept in its docstring. This is the second time a pinned-defect test has
had to be flipped by the fix that resolved it (see #485); worth checking for
others before landing a behaviour change.

Full suite 7107 passed / 0 failed, coverage 94.94%; gauntlet gates all pass;
ruff clean repo-wide.
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f6166bb2-0e7c-4ad2-9200-f9a58529e0de


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

FreshData benchmark report — performance

  • freshdata: ?
  • python: ?
  • platform: ?
fixture n_rows n_cols p50 s p95 s peak MB repair % false-repair % preserve % trust monotonic export %

Authored-code reduction (Metric 6)

@kevincostner17
kevincostner17 merged commit b363c39 into main Sep 20, 2026
22 checks passed
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