Skip to content

Commit 5c3c0db

Browse files
derek73claude
andauthored
Read a nickname, one name word and a suffix as the family name (#815) (#1107)
* Read a nickname, one name word and a suffix as the family name (#815) N3 (the lone-word nickname rule) now sets a suffix aside, as H1 (a title and one name word) and M4 (a maiden marker makes the lone name word the family) already did: "'Smitty' Jones Jr." reads family 'Jones' and no longer reports given-or-family. The early count is unchanged; the suffixed shape is decided at O5's site, after the trailing peel, so a word the vocabulary or its shape claimed keeps its claim ("'Smitty' J. Jr." stays given 'J.'). Rules N3, O5 and M4 amended; decisions/N3 records the measurement (one committed-corpus name, three nepal-candidates names taken as the cost) and closes the question decisions/H1's #410 entry left open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address the first review round on #815 - Gate the nickname scan on state.extracted, so a lone word with no delimited clause pays no frame (Madonna and Smith Jr. back to master's call counts). - rules/N3: the Except cites the rules whose reading a word keeps (T5, T4, P5, P4) and no longer claims M4 agrees on particles; a Precedence bullet gives a title word to H4; Accepted covers the dotted Nepal shape and the comma reach (a nickname in any part, an S1 clause, a nickname alone before a comma). - decisions/N3: capitalized headline, the 660-row grid, the reach the reviews found, and the population bounding each local-corpus zero; decisions/H1's #410 head marked. - Tests: the grid walks 660 rows in one test (quoted nicknames after the word, VI, Ph. D.), the claimed-word test adds bare and one-case initials and a particle, and case rows pin the comma, S1, acronym, gated-word, title-word, period-shape and given-abbreviation shapes. - shapes.py: a nickname-and-suffix arrangement under each order. - Release log: 2.0.0 through 2.8.2, the report since 2.3.0, and the full Except. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Simplify #815's tests and comments (/simplify pass) - The suffix grid parses each bare name once and drops FAMILY_FIRST_GIVEN_LAST, which reads every row as FAMILY_FIRST does (440 rows, all failing on master 90a9a86); it compares as_dict() whole, so a title or maiden name moving fails it too. - The claimed-word control stays as data in its comment; the test that only asserted a length is gone. - _assign.py: the N3 handoff is stated once, at the decision site. - test_cases.py: one dated step for #815's claim count. snapshot.jsonl unchanged; frame counts unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address the second review round on #815 - rules/N3: the Except lists exactly the three readings it keeps and says a given name written short is none of them; the Nepal Accepted bullet is the vocabulary reading again (D.C and जी.सी. are listed credentials, not dotted-shape reads), and decisions/N3 says so. - rules/O5: M4's exception names the given-name and initial claims only, since M4 flips a particle (de née Jones -> family 'de'). - cases.py: an empty-head boundary row; the Xyz. note states the mechanism the parser shows (bare it is taken whole as a title, beside a suffix the peel leaves it as the name word); three rows labelled parity get the change that moved them from 1.4.0 (suffix-routing, #296, #491). - test_parser.py: the grid's parse count is 480. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address the third review round on #815 - decisions/N3: जी.सी. is listed nowhere; it reads as a suffix because its chunk जी is a hi/mr honorific that period_joined_vocab takes as a suffix chunk (removing that honorific leaves it family). - rules/N3: the Nepal Accepted bullet covers a suffix read whole or by a period-joined chunk. - rules/O5: M4 keeps a bound given name and an initial; a given name written short (Chas. née Jones) is flipped like any other. - cases.py: 'Smitty' Pope Jr. moved from 1.4.0 with #489's title-peel floor, as its sibling Dr Jr is labelled; #491 added only the report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 90a9a86 commit 5c3c0db

17 files changed

Lines changed: 329 additions & 47 deletions

‎docs/design/decisions/H1-title-and-one-name-word.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
- H1 decides the field of the one name word before a comma with no given name after it, and of the one name word of a name read family-first: `Mary II, Dame` → given 'Mary' (`Elizabeth II, Queen` until 2026-10-27, when `queen` became a title only inside a title phrase, decisions/H9), `Smith, Sir` → given 'Smith' with the family empty, `Sir John` and `Pope Francis` given under every order — 2026-10-18 #720.
1111
- A particle surname keeps the family where something settled it, a comma (`van der Berg, Sir`, `Van, Sir`) or P1's fold asked of the leading name piece (`Sir de Mesnil`); an ambiguous particle no comma settled reads given (`Sir Abu Bakar`, `Sir Van` family-first; a lowercase one in a mixed-case name its writing settles, rules/P11's precedence, `Sir van Berg` family-first → family 'van Berg', decisions/P11's 2026-11-04 (Derek), #670 entry; `Sheik Abu Bakar` until 2026-10-27, decisions/H9, which under the family-first orders now reads the word as the family and the particle given by position), and so does a never-given one the fold does not take (`St Sir de Mesnil` under every order) — 2026-10-18 #720.
1212

13-
Elsewhere: the graf class, a title word borne as a name but rarely as its first word shipping as a title (`Greve Anna` → title 'Greve', family 'Anna'), is decisions/salutation-titles' 2026-10-04 #606 bundle; the renunciate class, the given-name titles of traditions that drop the surname (`Swami Vivekananda` → given 'Vivekananda'), is decisions/indic-honorifics' 2026-09-06 #346/#344/#343 bundle.
13+
Elsewhere: the nickname-led question the 2026-08-25 #410 entry left open, N3 setting a suffix aside as this rule does (`'Smitty' Jones Jr.` → family 'Jones'), is decisions/N3's 2026-11-05 #815 entry; the graf class, a title word borne as a name but rarely as its first word shipping as a title (`Greve Anna` → title 'Greve', family 'Anna'), is decisions/salutation-titles' 2026-10-04 #606 bundle; the renunciate class, the given-name titles of traditions that drop the surname (`Swami Vivekananda` → given 'Vivekananda'), is decisions/indic-honorifics' 2026-09-06 #346/#344/#343 bundle.
1414

15-
Open: [#815](https://github.com/derek73/python-nameparser/issues/815) (whether N3 sets a suffix aside as this rule does, the nickname-led question the 2026-08-25 #410 entry left open: `'Smitty' Jones Jr.` reads given 'Jones', family '').
15+
Open: none in this file.
1616

1717
## Log
1818

19-
- 2026-08-25 (#410) — H1's "and nothing else" counted a suffix, a nickname and a maiden name as further name words, so a title-plus-surname name reported no family the moment any of them stood beside it: `Dr. Smith` reads family 'Smith' and `Dr. Smith née Jones` read given 'Smith' with the family empty. #410 reports the maiden flavor; measured, all three roles suppress the rule identically and the fix is one term in one guard, so the term went rather than the maiden role being special-cased. What decided the width is H1's own rationale — a title addresses by surname — which says nothing about what stands BESIDE the name. The rationale is stated for H1 rather than as a doc-wide principle about what a suffix is, deliberately: N3 counts a suffix the other way (`'Smitty' Jones Jr.` reads given 'Jones', family ''), and which of the two readings is right for a nickname-led name is not decided here. #399 is what made this urgent rather than latent: stopping the particle chain at the marker routed the canonical title-and-particle shape (`Freiherr von Richthofen geb. Albrecht`) into H1 for the first time. N3 moves with it, without N3 changing: `'Smitty' Dr. Jones` declines N3's one-piece count as it always did, and H1 now names the family behind it, so it reads family 'Jones' where it read given 'Jones' through 2.1. Five corpus names change reading at every baseline (PR #444); one of them, `Freiherr von Richthofen V`, only narrowed a diff the `fix(#424)` ledger rule already classified, so no run named it. The v1 suite shipped the nickname reading as a strict xfail (`tests/test_nicknames.py::test_nickname_and_last_name_with_title`), which passes now. Known gap between the statement and the guard: H1 says "exactly one name word" and "that word", but the guard never counts units. It tests which ROLES are unoccupied — no middle, no family — and then retags every given token, so a name whose given run is two name WORDS (units, not tokens) reaches it and moves both: `Freiherr de V Jr` reads family 'de V'. The distinction matters for reading the claim that follows: a multi-token given run is ordinary — the rules.md example `Freiherr von Richthofen V` has one, its two tokens being a single particle unit — and it is a run of two UNITS that no real input produces. A 58,338-name sweep found no corpus name and no rules.md example with one — but it is recorded because decisions.md elsewhere leans on H1's "exactly one name word" as a settled scope when narrowing P5's licence, and that reading of H1 is stronger than the code behind it. Not fixed here: the widening this entry records is about which roles disqualify the rule, not about how it counts.
19+
- 2026-08-25 (#410) (its account of N3, a count not setting a suffix aside, superseded by #815, decisions/N3, which sets it aside as this rule does) — H1's "and nothing else" counted a suffix, a nickname and a maiden name as further name words, so a title-plus-surname name reported no family the moment any of them stood beside it: `Dr. Smith` reads family 'Smith' and `Dr. Smith née Jones` read given 'Smith' with the family empty. #410 reports the maiden flavor; measured, all three roles suppress the rule identically and the fix is one term in one guard, so the term went rather than the maiden role being special-cased. What decided the width is H1's own rationale — a title addresses by surname — which says nothing about what stands BESIDE the name. The rationale is stated for H1 rather than as a doc-wide principle about what a suffix is, deliberately: N3 counts a suffix the other way (`'Smitty' Jones Jr.` reads given 'Jones', family ''), and which of the two readings is right for a nickname-led name is not decided here. #399 is what made this urgent rather than latent: stopping the particle chain at the marker routed the canonical title-and-particle shape (`Freiherr von Richthofen geb. Albrecht`) into H1 for the first time. N3 moves with it, without N3 changing: `'Smitty' Dr. Jones` declines N3's one-piece count as it always did, and H1 now names the family behind it, so it reads family 'Jones' where it read given 'Jones' through 2.1. Five corpus names change reading at every baseline (PR #444); one of them, `Freiherr von Richthofen V`, only narrowed a diff the `fix(#424)` ledger rule already classified, so no run named it. The v1 suite shipped the nickname reading as a strict xfail (`tests/test_nicknames.py::test_nickname_and_last_name_with_title`), which passes now. Known gap between the statement and the guard: H1 says "exactly one name word" and "that word", but the guard never counts units. It tests which ROLES are unoccupied — no middle, no family — and then retags every given token, so a name whose given run is two name WORDS (units, not tokens) reaches it and moves both: `Freiherr de V Jr` reads family 'de V'. The distinction matters for reading the claim that follows: a multi-token given run is ordinary — the rules.md example `Freiherr von Richthofen V` has one, its two tokens being a single particle unit — and it is a run of two UNITS that no real input produces. A 58,338-name sweep found no corpus name and no rules.md example with one — but it is recorded because decisions.md elsewhere leans on H1's "exactly one name word" as a settled scope when narrowing P5's licence, and that reading of H1 is stronger than the code behind it. Not fixed here: the widening this entry records is about which roles disqualify the rule, not about how it counts.
2020

2121
- 2026-09-08 [#489](https://github.com/derek73/python-nameparser/issues/489) (the #316/#489 bundle) (its VOCABULARY SCOPE superseded in part by #519, below, and its TRAILING REACH's front slot by the 2026-09-09 review round 2 entry, below) — a title RUN addresses as its LAST title does. `Her Majesty Queen Elizabeth` read family `Elizabeth` because the `given_name_titles` lookup was keyed on the whole run, and `her majesty queen` is no shipped entry. A run is written as several titles and is addressed the way its final one is, so the run's folded key is now matched whole OR by its last word. **This AMENDS the 2026-08-22 #369 entry under #P5**, which keyed both sites on the whole run so they could never disagree; the amendment keys both on the LAST word and the invariant is untouched — H1's retag and P5's licence still cannot read one run two ways, through one predicate beside `_title_key`. What the amendment reopens is that entry's EXAMPLE and not its reasoning: `'mr sir'` was #369's own instance of a run neither site treats as a given-name title, and it now IS one to both, `sir` being the last word.
2222
The whole-run arm is kept for a caller's multi-word phrase entry — `lt col` is stored and matched as one key — and its order carries nothing: the `or` short-circuits but decides nothing, since for a ONE-WORD run the key IS its last word. Every shipped given-name title is a single word, asserted in tests/v2/test_lexicon.py rather than counted here, so under the default vocabulary that arm can only ever match a one-word run, which the last-word arm reads the same way. Recompute the single-word property with `L = Parser().lexicon; sorted(t for t in L.given_name_titles if " " in t)`, which gives `[]` on 2026-09-08; the set holds 47 entries that day, and the argument survives the digit moving.

0 commit comments

Comments
 (0)