nameparser 2.0 implementation#288
Draft
derek73 wants to merge 136 commits into
Draft
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The v2 core design uses enum.StrEnum (3.11+). Full #257 (dropping typing_extensions, CI matrix) remains tracked on the issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Validate that all replace() field values are str (user error if None) - Append missing-role synthetics in canonical Role order, not kwargs order - Unquote return type annotation (postponed annotations in effect) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Casefolded seven-component tuple in canonical Role order for dedup, dict keys, and sorting. Semantic layer comparison; __eq__ remains strict. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds tests/v2/test_layering.py to mechanically enforce the conventions
doc's import layering and the public v2 export surface. Appends the v2
core types (Span, Role, Token, Ambiguity, AmbiguityKind, ParsedName,
Lexicon, Policy, PolicyPatch, PatronymicRule, UNSET, GIVEN_FIRST,
FAMILY_FIRST, FAMILY_FIRST_GIVEN_LAST, Locale) to nameparser/__init__.py
alongside the existing v1 HumanName export.
Turns on component-flag mypy strictness for the four v2 modules and
check_untyped_defs for tests/v2, then fixes the resulting test-only
type mismatches by using the precise constructed types (Span(...),
frozenset({...}), tuple-of-pairs) where the literal type didn't matter
to the test, and adding narrow # type: ignore[arg-type] comments only
where a test deliberately exercises runtime coercion/validation of an
intentionally mismatched static type (e.g. Token span/Ambiguity kind
coercion tests, PatronymicRule string coercion, dict aliasing test).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pickle.dumps(Lexicon.default()) raised TypeError because the default slots-dataclass pickle path serializes the _cap_map MappingProxyType. Ship every other slot and rebuild the proxy from the canonical capitalization_exceptions tuple on load. Parser (Plan 3) is picklable by construction per the core spec, and a Parser holds a Lexicon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
requires-python is >=3.11 on this branch, so the 3.10 job can no longer install the package (uv sync either fails or silently substitutes a managed 3.11). The rest of #257 (typing_extensions, classifiers) stays tracked on the issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With requires-python at >=3.11, Self imports directly from typing and the conditional dependency can never activate; ruff (UP035/UP036) flags the dead version block once the floor is raised. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The v1 suite is fully annotated (since #250 put tests/ under mypy), so pyproject carries no per-file ANN ignores; the new tests/v2 modules must be annotated too or 'ruff check' fails in CI. Also drops an unused import ruff flagged (F401). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
158 dual-run cases -> 67 tests (the empty_attribute_default dual-run parametrization died in the previous batch commit; per-run count 79 -> 67). Bucket A (deleted machinery): - test_unpickle_legacy_state_without_derived_sets: pinned __setstate__ backfill of the v1 per-parse _derived_* sets and the is_title predicate, both gone with the v1 parser. - the six is_prefix/is_conjunction/is_suffix list-fallthrough tests: the v1 predicate methods are not part of the facade (#280 hook list). - test_get_full_name_attribute_references_internal_lists: pinned the v1 full_name getter re-rendering from the live *_list state; 2.0 deliberately returns the stored input string (spec section 2 mutation semantics, pinned in tests/v2/test_facade.py::test_field_assignment_str_list_none) and the *_list attributes are snapshots without setters (spec section 2 exc. 1). Bucket B (scheduled removals now raising / silently changed): - #245 bytes: both HumanName(bytes) and the full_name setter now pytest.raises(TypeError, match="decode"). - #223 ==/hash: rewritten to assert the identity semantics (distinct instances unequal, strings never match, hash == object default, no warnings), with matches()/comparison_key() shown as the replacements. - #258 slices/__setitem__: slice access raises TypeError naming the issue; item assignment raises TypeError for every key; str-key reads stay silent. - #255: given_names empty expectation is '' outright. - Constants(regexes=...) raises TypeError pointing at Policy (deliberate 2.0 divergence, migration spec section 3 uniform rule). 3 of 67 tests still fail on one confirmed pipeline bug (SUFFIX_COMMA detection tests all post-comma segments where v1 tested only parts[1]; repro 'Dr. John P. Doe-Ray, CLU, CFP, LUTC'), so the file stays in collect_ignore_glob with a pointer comment; it is mypy-clean and leaves the mypy exclude. test_constants.py stays ignored, blocked on a wider shim-regression inventory (see conftest comment). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ulary
M12 reconciliation surfaced two more Plan-3 misports, both pinned
live against v1.4 (2026-07-16):
- the suffix-comma structure is decided by parts[1] ALONE
(parser.py:1318); v2 wrongly required every post-first segment to
be suffix-shaped, so one unrecognized credential ('LUTC') collapsed
the whole parse into FAMILY_COMMA. Non-suffix tails now ride along
as suffixes with the COMMA_STRUCTURE flag (v1 consumed them
silently; the flag is the v2 value-add).
- v1's period-joined derivation (parse_pieces): a token with an
interior period whose chunks include ANY title is a title
('Lt.Gov.', 'Mr.Smith'), else ANY suffix chunk makes it a suffix
('JD.CPA'). Title wins. Ported into classify with the ANY rule
kept deliberately.
Six case rows pin the matrix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Also lifts test_python_api.py's collect_ignore_glob entry: its 3 held tests pass after the suffix-comma and period-joined-vocabulary pipeline fixes (7bf53f3), making the file fully green (67/67). test_constants.py: 240 dual-run cases -> 94 tests (the dual-run parametrization died with #255; per-run 120 -> 94). Bucket A (deleted machinery): - the suffixes_prefixes_titles cached-union property block (~13 tests of cache priming/invalidation incl. the timeit performance guard and the is_rootname consistency pair); change tracking is the shim generation counter, covered in tests/v2/test_config_shim.py. Two contracts survived and are re-pinned on parsing surface: post-unpickle mutations are honored, and wholesale manager replacement re-wires tracking. - .elements raw-set accessor uses rewritten to set(...) (operators also return plain set now); _repr_collection_attrs/_repr_scalar_attrs class internals replaced by test-owned name lists. - __setstate__ missing-field validation test (the shim deliberately accepts partial state to load v1.4 blobs). - the legacy-unpickle warn-once pair (#279's warning machinery is gone). Bucket B (scheduled removals now raising): - #255 empty_attribute_default: assignment raises AttributeError; the six None-mode behavior tests collapse to one removal test (scalar pickle/copy round-trip intent re-pinned on string_format). - #243: SetManager() call -> TypeError not callable; missing-member remove() -> KeyError (mixed-args call still applies the present removal). - #245/#263: add_with_encoding -> AttributeError; bytes add() -> TypeError with decode hint. - #256: unknown tuple-manager keys -> AttributeError naming known keys; regexes proxy raises naming the missing key; sunder probes now report absent (AttributeError) instead of returning manager defaults. - #261: constants=None raises TypeError at constructor, positional, and C-setter entry points (class renamed ConstantsNoneRemovalTests). - deliberate 2.0 divergences pinned: custom nickname delimiters raise pointing at Policy (spec section 3); plain-iterable set-field assignment auto-wraps in a validated SetManager where v1 demanded a pre-built one (bare strings still raise, #241 stays impossible); class-not-instance constants message no longer carries the "did you mean Constants()" hint. Bucket C (shared-CONSTANTS mutation): - test_can_change_global_constants wraps its shared mutation in pytest.deprecated_call (it exercises exactly that deprecation). 2 of 94 tests still fail on one remaining v1.4-parity gap -- the shim Constants.__init__ lacks the patronymic_name_order/middle_name_as_last bool kwargs -- so the file stays in collect_ignore_glob and the mypy exclude with a pointer comment; remove both once the kwargs land. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
patronymic_name_order and middle_name_as_last were v1.4 constructor kwargs (docs/customize.rst doctests use them); the M12 reconciliation of test_constants.py caught the gap. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Constants(patronymic_name_order=True) / Constants(middle_name_as_last= True) work again (c1b5730), so the two held ConstantsReprTests pass: 94/94 green. Removes the file's collect_ignore_glob and mypy-exclude entries and settles the three mypy items its un-excluding surfaced (|= re-wrap annotations, a dict[str, object] state annotation, and a note that the 2.0 TupleManager subscripts via dict's __class_getitem__ rather than v1's Generic). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
23 tests -> 22, all green. Bucket B (scheduled removals / deliberate divergences): - the two #254 None-mode scrubbing regressions merge into one residual test: the None display mode is gone (#255), but literal 'None'/'Nonez' name text must still survive formatting unscathed. - regexes.emoji/.bidi = False opt-outs raise TypeError in 2.0 (migration spec section 3 uniform rule); the tests now pin the error naming the Policy(strip_emoji/strip_bidi=False) replacements. Bucket C (shared-CONSTANTS mutation): - the four *_constants_attribute tests (string_format, capitalize_name, force_mixed_case_capitalization, both) move onto a private Constants passed as constants= -- the migration-guide idiom -- instead of mutating the shared singleton. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
33 tests -> 31, all green. Bucket B: the two #255 None-mode regressions (literal-"None" interpolation, all-empty fallback) collapse to one test pinning the 2.0 invariant -- a fully-empty initials() renders ''. Bucket C: the three *_constants tests (initials_format, initials_delimiter, delimiter+separator+format combo) move onto a private Constants passed as constants= instead of mutating the shared singleton; the fixture-restore sentinel test keeps asserting the shared default is ' '. Bucket E: the #232 doubled-space test's direct middle_list assignment becomes field assignment; the v1 hole it pinned (unnormalized *_list elements crashing initials) is unreachable in 2.0 -- list snapshots plus setter whitespace normalization -- so it now pins the normalized result. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… bug
The file needs no reconciliation edits (20 pass, 1 pre-existing v1
xfail), but one test fails on a render-layer parity bug: _render.py's
_cap_word lowercases every conjunction-set word, missing v1
is_conjunction's is_an_initial exclusion, so an initial that doubles as
a conjunction stays lowercase:
HumanName('scott e. werner').capitalize() -> 'Scott e. Werner'
(v1: 'Scott E. Werner'; 'e' is in CONJUNCTIONS)
The file stays in collect_ignore_glob with a pointer comment; it is
mypy-clean and leaves the mypy exclude.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The file needs no reconciliation edits (8 pass, 2 pre-existing v1
xfails), but one test fails on a confirmed pipeline parity bug: in the
family-comma format, a trailing suffix inside the family segment is not
split out of it.
Parser().parse('Smith Jr., John') -> family='Smith Jr.', suffix=''
(v1: last='Smith', first='John', suffix='Jr.')
Stays in collect_ignore_glob with a pointer comment; mypy-clean, so it
leaves the mypy exclude.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57 tests: the stale 'U.S. District Judge' xfail is removed -- the 2.0
period-joined title derivation makes the long-desired expectation hold
(logged in docs/superpowers/plans/notes-m12-diffs.md for the M14
expected-changes list). 54 pass, 1 pre-existing v1 xfail remains.
2 tests fail on confirmed pipeline parity bugs, so the file stays in
collect_ignore_glob (mypy-clean, leaves the mypy exclude):
1. _lexicon._normalize strips INTERIOR periods, so 'J.R.' normalizes to
'jr' -- a TITLES vocabulary entry; v1's lc() kept 'j.r' unmatched.
HumanName('Smith, J.R.') -> title='J.R.'
(v1: first='J.R.', last='Smith')
2. _assign's nickname rule (plan deviation #2) counts name pieces AFTER
title peeling; v1's p_len==1 counted the whole segment before it.
HumanName('Xyz. (Bud) Smith') -> last='Smith'
(v1: title='Xyz.', first='Smith', nickname='Bud')
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All pinned live against v1.4 (2026-07-17):
- _normalize now matches v1's lc(): casefold + EDGE periods only.
'J.R.' no longer collapses to 'jr' and hits the periodless titles
vocabulary. Suffix-ACRONYM membership alone uses the period-free
form ('M.D.' -> 'md'), mirroring v1's is_suffix, which removed
periods only for the acronym test. The capitalization-exception
lookup tries both forms (v1 cap_word parity), keeping
'phd' -> 'Ph.D.' idempotent.
- _cap_word's conjunction lowering excludes initial-shaped words
(v1 is_conjunction): 'scott e. werner' capitalizes to
'Scott E. Werner'; an uppercase lone 'Y' stays 'Y'.
- FAMILY_COMMA's family segment peels per-piece suffixes after the
first piece ('Smith Jr., John' -> family=Smith, suffix=Jr.).
- the lone-piece nickname rule counts the segment BEFORE title
peeling ('Xyz. (Bud) Smith' -> title, given, nickname).
Six case rows pin the matrix; the three stale v2 unit tests that
pinned the pre-fix semantics are updated with v1 citations.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All four queued parity bugs are fixed (2c45150); the three held files run green (85 pass, 5 xfail). Two xfail flips settled in the process: - 'Andrews, M.D.': the family-comma suffix peel makes the v1 xfail's long-desired expectation hold (last='Andrews', suffix='M.D.'; v1 parsed first='M.D.') -- marker removed, diff logged in docs/superpowers/plans/notes-m12-diffs.md as fix(comma-family/suffix-routing). - 'U.S. District Judge ...': the interim interior-period normalization that briefly made this chain was itself the 'Smith, J.R.' bug; with v1's lc() restored the name matches v1 again, so the xfail marker is restored with a comment recording why. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The file needs no bucket A/B/C edits (30 pass, 2 pre-existing v1 xfails); all 24 failures are component-value diffs traced to six root causes, each reproduced on the core -- reported for fixing, not classified: B1 two-word trailing suffix: 'Jack Ma' -> given='Jack', suffix='Ma', family='' (v1: last='Ma'). Same shape the fix(suffix-routing) case row pins intentionally for 'Johnson PhD'; needs a decision on suffix-shaped words that are also common surnames. B2 suffix-comma segments split per word: 'John Smith, V MD' -> suffix='V, MD' (v1 kept the whole segment: 'V MD'); also 'Jr. MD', 'Q.C. M.P.'. B3 split/period-joined suffix segments fail SUFFIX_COMMA detection: 'John Smith, Ph. D.' and 'John Doe, Msc.Ed.' -> family swallows the whole head, given='' (v1: first/last split + suffix). B4 #144 family-comma trailing suffix_not_acronyms rule missing: 'Smith, John V' -> middle='V'; 'Maier, Amy Lauren I' -> middle='Lauren I' (v1: suffix). B5 suffix-in-parens/quotes routing (#111, shipped 1.3) absent: 'Andrew Perkins (MBA)' / 'MBA' / "MBA" -> nickname (v1: suffix); 'Lon (Jr.) Williams', 'Col. (Ret.) Smith', '(Mgr.)', and the suffix_acronyms_ambiguous customization all diverge with it. B6 suffix_delimiter edges: a trailing delimiter ('John Doe, MD-PhD-', delimiter '-') kills detection entirely; a multi-word side leaks the delimiter token into suffix ('MD, PhD, -, FACS, Fellow' vs the pinned drop rule); the delimiter-unset degenerate 'Steven Hardman, RN - CRNA' diverges from v1's documented limitation (first='-' vs first='RN'). Stays in collect_ignore_glob with a summary comment; mypy-clean, so it leaves the mypy exclude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rity)
CI's sphinx doctests caught this unported v1 rule: parse_nicknames
leaves suffix-shaped delimited content -- an unambiguous suffix word,
an unambiguous period-free acronym, or anything ending in a period --
in place for normal parsing ('Andrew Perkins (MBA)' -> suffix=MBA,
not nickname). The v2 spelling masks only the two delimiter spans so
the inner content joins the main token stream (spans keep indexing
the original, anti-#100). Two case rows pin it.
The three customize.rst doctest blocks that taught the removed
regexes.emoji/bidi and custom-delimiter-pattern idioms now teach the
2.0 replacements (Policy strip flags; Policy delimiter pairs).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
58 tests: one bucket-C rewrite (the custom-title fold test moves its
'gunny' title onto a private Constants instead of mutating the shared
singleton); 57 pass.
1 test fails on the same B1 root cause already reported for
test_suffixes -- two-word trailing-suffix routing:
HumanName('Anh Do') -> suffix='Do', family=''
(v1: first='Anh', last='Do'; 'do' is the D.O. suffix acronym)
Stays in collect_ignore_glob next to test_suffixes' entry; mypy-clean,
so it leaves the mypy exclude.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The file needs no bucket edits (37 pass, 2 pre-existing v1 xfails); one test fails on the join-stage sibling of the already-fixed _cap_word bug: the classify-stage "conjunction" tag lacks v1 is_conjunction's is_an_initial exclusion, so an initial that doubles as a conjunction is joined into its neighbors. The group-stage #11 carve-out only exempts the bare single letter ('e'), not the initial form ('e.'). HumanName('john e. smith') -> first='john e. smith' (v1: first='john', middle='e.', last='smith') Stays in collect_ignore_glob with a pointer comment; mypy-clean, so it leaves the mypy exclude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flip 39 tests -> 35; 33 pass, 1 v1 xfail. Bucket A/B (custom-delimiter mechanism removed, spec section 3): - test_add_custom_nickname_delimiter becomes the raises pin (TypeError naming Policy); the remove/multiple/ambiguous-through-custom variants die with the mechanism they exercised. - the regexes-override live-resolution test becomes a raises pin too (regexes item assignment raises, same uniform rule). - the unresolvable-string-sentinel ValueError-at-parse test becomes a TypeError-at-assignment pin (2.0 enforces the invariant earlier). - as_dict()['maiden'] empty expectation is '' outright (#255). Held (bucket D, reported): the documented both-buckets misuse case flipped precedence -- with 'parenthesis' in BOTH delimiter buckets, v1 processed nickname first (nickname='Johnson'); 2.0 gives maiden='Johnson'. The v1 test exists precisely to catch this silent change; needs fix-or-classify. File stays in collect_ignore_glob; mypy-clean, leaves the mypy exclude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5 tests -> 4, all green; lifted from both skip lists. Bucket B: the custom-regexes-without-commas shatter guard died with its mechanism -- Constants(regexes=...) raises TypeError in 2.0 (migration spec section 3 uniform rule), already pinned in test_python_api.py's test_override_regex_raises. The four non-ASCII comma tests (#265) pass unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All pinned live against v1.4 (2026-07-17) unless classified:
- 'ma'/'do' join suffix_acronyms_ambiguous (data): common surnames
need periods to read as credentials -- 'Jack Ma' keeps its family
name while the approved fix(suffix-routing) rows keep theirs. The
set's doc comment gains the surname criterion and the 2.0 gating
note. Release-log item.
- classify's conjunction tag excludes initial-shaped tokens (v1
is_conjunction): 'john e. smith' keeps its middle initial.
- the period-joined derivation moves to _vocab.period_joined_vocab,
shared by classify AND segment's suffix-comma detection
('John Doe, Msc.Ed.'); chunk-level membership is v1's is_suffix
(bare ambiguous acronyms count within period-joined tokens).
- segment's detection collapses an adjacent Ph./D. pair into one
suffix unit (v1 extracted the credential pre-parse via fix_phd).
- extract iterates the nickname bucket first: when one delimiter
pair sits in both buckets, the nickname reading wins (v1 order).
- the FAMILY_COMMA walk restores v1's order -- the first post-comma
piece is the given BEFORE any suffix check ('Hardman, RN - CRNA')
-- with one classified fix(comma-family) deviation: a LONE
unambiguous suffix piece routes to suffix ('Andrews, M.D.').
The trailing piece of a two-part name takes the lenient test
(v1 #144: 'Smith, John V' -> suffix=V).
- tail comma segments render as ONE suffix entry each: continuation
tokens take the 'joined' tag (space-join), a delimiter core inside
a segment separates entries and is dropped, and a lone-core
segment stays whole (v1 expand semantics).
Ten case rows pin the matrix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The batch-3 bug queue is fixed (c131dde): all four held files run green (184 pass, 5 xfail). Two last touches in test_suffixes: - Bucket D with classification: 'John Doe, MD-PhD-' (delimiter '-') keeps the no-space delimiter-core token whole, suffix='MD-PhD-' -- fix(suffix-delimiter-rendering), same rule as the pinned 'RN/CRNA' case row; logged in docs/superpowers/plans/notes-m12-diffs.md. - Bucket C: the constants-level suffix_delimiter test moves onto a private Constants instead of mutating the shared singleton. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test_east_slavic_patronymic_order (26) and test_turkic_patronymic_order (39): all green; the only edits are typing -- the regex-inspection tests read patterns through the 2.0 regexes proxy (typed object), now cast once at module level. Lifted from both skip lists. - test_bound_first_names: bucket A -- the two is_bound_first_name predicate tests died with the v1 parsing hooks (#280); vocabulary behavior stays pinned through the parsing tests. 1 test held on a join-guard bug: the FAMILY_COMMA bound-given join does not fire when it would consume the whole post-comma segment ('salem, abdul salam' -> first='abdul'; v1: 'abdul salam'). - test_middle_name_as_last: no bucket edits; 4 tests held on a fold-order bug -- v1 PREPENDED middle_list to last_list so comma and rotated forms converge ('Hassan, Mohamad Ahmad Ali' -> last='Ahmad Ali Hassan'); v2 renders the folded family in token order ('Hassan Ahmad Ali'). Both held files stay in collect_ignore_glob with repro comments; mypy-clean, so they leave the mypy exclude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its sole subject, nameparser.parser.group_contiguous_integers, was a v1 join_on_conjunctions helper; the 2.0 pipeline's group stage merges by piece index with no such utility, and the swap left no export. Nothing survives to port. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The three-code-paths variation bank (180+ names, cross-checked across no-comma / lastname-comma / suffix-comma spellings) passes wholesale; only two v1-internals touches were needed: - Bucket B (#255): the forced empty_attribute_default='' step is gone -- empty attributes are always '' in 2.0, which is exactly what the format strings needed. - Bucket A: the private hn._members iteration becomes the public as_dict() key set (same seven fields). Lifted from both skip lists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 117-case brute-force bank passes wholesale against the facade with zero edits. With it, every v1 test file is reconciled and mypy-clean, so the TEMPORARY [tool.mypy] exclude is deleted entirely; the conftest collect_ignore_glob shrinks to its final remnant -- the two files each held on one confirmed parity bug (bound-given whole-segment join; middle_name_as_last fold order), to be deleted when those land. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- bound given names join freely in FAMILY_COMMA's post-comma segment (v1 reserve_last=False, parser.py:1366): 'salem, abdul salam' -> given 'abdul salam'. _group_segment takes the per-segment bound_required (3 main / 2 post-comma / 0 family segment, which v1 never bound-joined). - middle_as_family renders in v1's prepend order: folded tokens carry vocab:folded-middle and the family view orders them before the original family tokens (spans cannot reorder, anti-#100) -- 'Hassan, Mohamad Ahmad Ali' -> family 'Ahmad Ali Hassan', matching the no-comma and rotated forms. The stage-ownership contract gains tags for post_rules accordingly. With these, every v1 test file is reconciled: the conftest collect_ignore_glob is GONE (the mypy exclude went earlier). The full v1 suite runs against the facade: 1160 passed, 12 xfailed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 2.0 modules section gains the facade layer: the re-export swap of nameparser.parser/config, the _facade/_config_shim mechanisms (dirty-tracking, v1-shaped pickle, #280 hook warning), the layering rule, and the differential-harness pointer. The v1 #256 extension-pattern paragraph is marked historical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implementation branch for the 2.0 design — see the RFC in #285 and the umbrella issue #284 for the design discussion and feedback questions. Implementation learnings that change the design will land as amendment commits on #285, per the plan described there.
Progress
Span,Role,Token,Ambiguity/AmbiguityKind,ParsedName;Lexicon,Policy/PolicyPatch/apply_patch,Locale. Frozen, slotted, hashable, picklable dataclasses with eager fail-loud validation; ~110 dedicated tests undertests/v2/.render()/initials()/capitalized()/__str__)Parser/parse()/parser_for()/matches()+ shared case tableHumanNamefacade +CONSTANTSshim (existing test corpus as regression harness)ru,tr_az) + differential-parse harnessNotes on what's here so far
TypeError, well-typed bad value →ValueError, enum lookups stayValueErrorper stdlib precedent.tests/v2/test_layering.py), and the seven-field canonical order derives fromRoledeclaration order everywhere — no ordering is ever stated twice.nameparser/configdata modules through 2.x, including the newmaiden_markers.py(Recognize maiden-name markers like "née" and "geb." (Jane Smith née Jones) #274 — marker words like "née"/"geb."; decisions recorded on the issue).🤖 Generated with Claude Code