Skip to content

Commit 85bee41

Browse files
committed
test: pin hand-duplicated regex/table copies to their config source
The layering rule forbids the pipeline/_render from importing nameparser.config directly, so several patterns are copied by hand with "keep in sync by hand" comments -- nothing previously checked that promise. Tests may legally import both sides (test_layering.py's own convention), so add sync tests for every duplicated pattern/table, including the documented "initial" trailing-"?" deviation between config and the pipeline copies (review finding on #288).
1 parent 64751b8 commit 85bee41

1 file changed

Lines changed: 73 additions & 0 deletions

File tree

tests/v2/test_regex_sync.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Pins the pipeline's hand-duplicated regex/table copies to their
2+
nameparser.config.regexes source of truth.
3+
4+
The 2.0 layering rule forbids nameparser._pipeline/_render importing
5+
nameparser.config directly, so several patterns and tables are copied
6+
by hand into the modules that need them, each with a "keep in sync by
7+
hand" comment. Nothing previously enforced that promise: if
8+
config/regexes.py changed, the copies would silently diverge with no
9+
CI signal. Tests may legally import both sides (test_layering.py's own
10+
convention), so this module is where the promise gets checked.
11+
"""
12+
from nameparser.config import regexes as _config
13+
from nameparser._pipeline import _assign, _post_rules, _tokenize, _vocab
14+
from nameparser import _render
15+
16+
17+
def test_emoji_ranges_match_config() -> None:
18+
assert _tokenize._EMOJI_RANGES == _config._EMOJI_RANGES
19+
20+
21+
def test_bidi_pattern_matches_config() -> None:
22+
assert _tokenize._BIDI.pattern == _config.re_bidi.pattern
23+
assert _tokenize._BIDI.flags == _config.re_bidi.flags
24+
25+
26+
def test_period_not_at_end_matches_config() -> None:
27+
source = _config.REGEXES["period_not_at_end"]
28+
assert _vocab._PERIOD_NOT_AT_END.pattern == source.pattern
29+
assert _vocab._PERIOD_NOT_AT_END.flags == source.flags
30+
31+
32+
def test_period_abbreviation_matches_config() -> None:
33+
source = _config.REGEXES["period_abbreviation"]
34+
assert _assign._PERIOD_ABBREV.pattern == source.pattern
35+
assert _assign._PERIOD_ABBREV.flags == source.flags
36+
37+
38+
def test_roman_numeral_matches_config() -> None:
39+
source = _config.REGEXES["roman_numeral"]
40+
assert _assign._ROMAN.pattern == source.pattern
41+
assert _assign._ROMAN.flags == source.flags
42+
43+
44+
def test_patronymic_patterns_match_config() -> None:
45+
pairs = (
46+
(_post_rules._EAST_SLAVIC, "east_slavic_patronymic"),
47+
(_post_rules._EAST_SLAVIC_CYR, "east_slavic_patronymic_cyrillic"),
48+
(_post_rules._TURKIC, "turkic_patronymic_marker"),
49+
(_post_rules._TURKIC_CYR, "turkic_patronymic_marker_cyrillic"),
50+
)
51+
for copy, key in pairs:
52+
source = _config.REGEXES[key]
53+
assert copy.pattern == source.pattern, key
54+
assert copy.flags == source.flags, key
55+
56+
57+
def test_initial_copies_agree_with_each_other_and_config() -> None:
58+
# _vocab._INITIAL and _render._INITIAL are both v1's "initial"
59+
# pattern minus its trailing "?" (documented at _render.py's
60+
# _INITIAL definition: the two call sites always fullmatch a
61+
# non-empty token, so the empty-string alternative is dropped on
62+
# purpose). Assert both the internal-copy agreement and the exact,
63+
# documented relationship to the config source, so a future edit to
64+
# either side that breaks the relationship fails loudly here
65+
# instead of silently drifting.
66+
assert _vocab._INITIAL.pattern == _render._INITIAL.pattern
67+
source = _config.REGEXES["initial"]
68+
# config's pattern is the pipeline copy with an extra "?" spliced in
69+
# just before the trailing "$", making the whole group optional.
70+
trimmed = _vocab._INITIAL.pattern
71+
reconstructed = trimmed[:-1] + "?" + trimmed[-1:]
72+
assert source.pattern == reconstructed
73+
assert source.flags == _vocab._INITIAL.flags

0 commit comments

Comments
 (0)