diff --git a/AGENTS.md b/AGENTS.md index 6687a2ca..e74cc1cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -169,7 +169,7 @@ The library has two layers: `nameparser/config/` (data) and `nameparser/parser.p **A constant's membership is a question you may reopen.** Proposing that a word be ADDED, REMOVED or MOVED between vocabulary sets is ordinary design work — a shipped entry is not evidence that anyone judged it. `SUFFIX_ACRONYMS` arrived in `af5bdab` as a bulk Wikipedia import never reviewed against surname collisions: 572 of its 577 alphabetic entries leave `family` empty in `"John "` against five ambiguous-gated exceptions (recomputed 2026-09-07; the fifth is `ba`; 568 of 575 against seven, measured 2026-09-25 after #540), and `sa`, `se` and `om` are borne as surnames (measured 2026-08-23), as were `rai`, `cha`, `ba` and `mc` before `decisions.md#suffix-acronym-collisions` decided all four — `rai` and `cha` removed, `ba` marked ambiguous, `mc` left alone as no borne name at all. The same entry marked `meng` and `lac` ambiguous on 2026-09-25 (#540). When a fix starts to look like new machinery, check the vocabulary first. Criterion: `decisions.md#vocabulary-collisions`, with #360's positional qualifier. -**Sweep the forms a change can reach: comma shapes, then `name_order`.** No comma, a FULL name before the comma, a ONE-WORD name before the comma and NOTHING before the comma are four paths, and the last two are the misses — #429, #430 and #432 are all the one-word path disagreeing with the full-name path on inputs the full-name path reads correctly, and #613's PR review found `, PhD` and `, Jr.` (an empty surname field, as CSV data writes it) read as given and title by a decision that returned early on an empty head, after two review rounds whose every grid had a name before the comma. Put an empty head and a nickname-only head (`(Bob), PhD`) in every comma grid. Count the one-word path the way C1 counts, which is neither tokens nor pieces: a particle run and the one word it attaches to are one word (#575), a connective join and a bound given-name pair count as their words (#613, so `Ortega y Gasset, Dr.` is a whole name), and a suffix beside the surname counts as no name word at all. #603's review found the suffix half (`Vega y Lopez Jr., PhD Jones` lost its family where `Vega y Lopez, PhD Jones` kept it); #613 then reversed the connective half, and both now read given 'Vega', middle 'y', family 'Lopez' — so test a particle surname, a connective surname and a surname with a suffix, each before a comma. For orders the sweep already exists (`tests/v2/test_cases.py` runs every row under all three) but carries one assertion, R2's family partition, so it checks nothing a new change moves; coverage there has been vacuous before (PR #394's review found the suite passed with `name_order` discarded from grouping). Parse your change's names in each comma shape and each order, and read the ones you did not predict. And read a generated grid's moves by SHAPE, not by corpus membership: #614's first design passed the suite, the five gates and a fingerprint of every corpus name, because its grid moves were sorted into 'corpus name moved' and 'garbage', and the review found the moves that mattered among the 'garbage' -- a bare salutation (`Mr. and Mrs.` lost its connective to the family name) and a name with one trailing word (`Freiherr von Berg X.Y.Z.`). Pull out the head-plus-one-word slice of the grid and a salutation with nothing after it, and read every move there. Two more were the second review's (#614): no grid put TWO words that are both a title and a particle at the head (`Freiherr St van Berg MA`, where an index into the pieces was applied to a merged view of them -- `TITLES ∩ particles_ambiguous` is `{freiherr, st}`, so put both in every head list, each in its bare and its period-marked spelling -- #637's grid had `St` and `Freiherr` alone and missed that `St.` and `Freiherr.` are declined by the bound join and then attached by P6), and the grids compared ambiguity KINDS, so a report telling the caller the wrong field (`Freiherr von Berg Ma`, 'read as a given name' of a word in the family) passed every pin. Compare each report's `detail` against the field its tokens land in -- since #626 `test_a_report_names_the_field_its_word_lands_in` (tests/v2/test_cases.py) does it over every non-locale case row under all three orders (a row carrying its own policy only as declared), for the phrasings its `_FIELD_CLAIMS` lists -- so a row with the shape is the test only where the report's wording is listed: a new emitter's wording goes in that list, and segment's report on a part past the second comma names no field (#629). #626's own first grid then missed an emitter for want of one comma shape (`, Ma Dr.`: an empty head, an ambiguous word, a trailing title, which H1 moves to the family): a trailing title belongs in every empty-head comma grid too. And #620's: an exclusion list in code being replaced is a set of rules, not noise -- #614's merged copy excluded every word the trailing read weighs from its units, the first #620 prototype dropped the list as a symptom of the copy, and its review found the list had been keeping positional counting's rule that a member in front counts as a word (`Freiherr von Berg MA X.Y.Z.` lost its suffix). Before deleting one, mutate each entry out and read what moves. +**Sweep the forms a change can reach: comma shapes, then `name_order`.** No comma, a FULL name before the comma, a ONE-WORD name before the comma and NOTHING before the comma are four paths, and the last two are the misses — #429, #430 and #432 are all the one-word path disagreeing with the full-name path on inputs the full-name path reads correctly, and #613's PR review found `, PhD` and `, Jr.` (an empty surname field, as CSV data writes it) read as given and title by a decision that returned early on an empty head, after two review rounds whose every grid had a name before the comma. Put an empty head and a nickname-only head (`(Bob), PhD`) in every comma grid. Count the one-word path the way C1 counts, which is neither tokens nor pieces: a particle run and the one word it attaches to are one word (#575), a connective join and a bound given-name pair count as their words (#613, so `Ortega y Gasset, Dr.` is a whole name), and a suffix beside the surname counts as no name word at all. #603's review found the suffix half (`Vega y Lopez Jr., PhD Jones` lost its family where `Vega y Lopez, PhD Jones` kept it); #613 then reversed the connective half, and both now read given 'Vega', middle 'y', family 'Lopez' — so test a particle surname, a connective surname and a surname with a suffix, each before a comma. For orders the sweep already exists (`tests/v2/test_cases.py` runs every row under all three) but carries one assertion, R2's family partition, so it checks nothing a new change moves; coverage there has been vacuous before (PR #394's review found the suite passed with `name_order` discarded from grouping). Parse your change's names in each comma shape and each order, and read the ones you did not predict. And read a generated grid's moves by SHAPE, not by corpus membership: #614's first design passed the suite, the five gates and a fingerprint of every corpus name, because its grid moves were sorted into 'corpus name moved' and 'garbage', and the review found the moves that mattered among the 'garbage' -- a bare salutation (`Mr. and Mrs.` lost its connective to the family name) and a name with one trailing word (`Freiherr von Berg X.Y.Z.`). Pull out the head-plus-one-word slice of the grid and a salutation with nothing after it, and read every move there. Two more were the second review's (#614): no grid put TWO words that are both a title and a particle at the head (`Freiherr St van Berg MA`, where an index into the pieces was applied to a merged view of them -- `TITLES ∩ particles_ambiguous` is `{freiherr, st}`, so put both in every head list, each in its bare and its period-marked spelling -- #637's grid had `St` and `Freiherr` alone and missed that `St.` and `Freiherr.` are declined by the bound join and then attached by P6), and the grids compared ambiguity KINDS, so a report telling the caller the wrong field (`Freiherr von Berg Ma`, 'read as a given name' of a word in the family) passed every pin. #701's review added one: put a title/suffix dual (`Ms`, `Sr.`, `Cpl`) SECOND in a title run, behind an ordinary title. A stop that asks only "is this word suffix vocabulary" passes every row that opens with the dual and fails `Rev. Sr. Smith, Mary`; it was found by comparing `T Smith, John` against `T John Smith` over every title word, and a comma-versus-comma-less comparison is the cheap check for any rule that moves a word between the two slots. Compare each report's `detail` against the field its tokens land in -- since #626 `test_a_report_names_the_field_its_word_lands_in` (tests/v2/test_cases.py) does it over every non-locale case row under all three orders (a row carrying its own policy only as declared), for the phrasings its `_FIELD_CLAIMS` lists -- so a row with the shape is the test only where the report's wording is listed: a new emitter's wording goes in that list, and segment's report on a part past the second comma names no field (#629). #626's own first grid then missed an emitter for want of one comma shape (`, Ma Dr.`: an empty head, an ambiguous word, a trailing title, which H1 moves to the family): a trailing title belongs in every empty-head comma grid too. And #620's: an exclusion list in code being replaced is a set of rules, not noise -- #614's merged copy excluded every word the trailing read weighs from its units, the first #620 prototype dropped the list as a symptom of the copy, and its review found the list had been keeping positional counting's rule that a member in front counts as a word (`Freiherr von Berg MA X.Y.Z.` lost its suffix). Before deleting one, mutate each entry out and read what moves. **Then sweep the spellings: a class reached by vocabulary is also reached by SHAPE.** A test that uses only the listed spelling of a word class walks only the vocabulary path, and the shape path is a separate branch that can be missing while every test passes. Roman numerals are the sharpest case: `ii`, `iii` and `iv` are suffix vocabulary; `i` and `v` are vocabulary too but initial-shaped, so `is_suffix_piece` vetoes them and only the numeral fork reads them; and `vi` through `x` are in no list at all, read by the fork's shape test alone (checked 2026-10-04 against `Lexicon.default()`) -- which stops at `x`: `_vocab._ROMAN` matches I to X, so `John Smith XI` reads `XI` as a name word (re-checked 2026-10-07, #614's /simplify, which found a docstring claiming "any length"). So a change that handles `V` and `III` can still miss `VI` — #610 found exactly that, the maiden take's candidate loop admitting a shape-only numeral in one position where the peel reads it in two (`Jane Doe nee Smith VI Prof.` kept maiden `Smith VI` while `V` and `III` worked). The same split runs through the credentials (`MA` listed, `X.Y.Z.` by the dotted shape, `XYZ` by the caps shape, and `Ph. D.` merged by group into one flagged piece the peel's walk never holds -- #603 found #602's run-start predicate refusing it too, so `Smith, John Ph. D. Jones` kept middle 'Jones' where `Smith, John PhD Jones` read suffix 'PhD Jones') and the titles (`Prof.` period-marked and read at the end of a name, `Prof` bare and a name word there). When a change touches a word class, test one spelling from each path. The same holds for a separator's SPACING: a comma (or any punctuation) can stand alone, glue to the word before it or glue to the word after, and each is a different token stream. #653's first fix swept `(née, Jones)` and missed `(née , Jones)`, where the kept comma became a word after the marker and M3 read the clause as maiden ', Jones'; its review found it. Put all three spacings in any grid around a separator. @@ -275,7 +275,7 @@ Add a dedicated `copy.deepcopy()` round-trip test for it too (see `test_regexes_ **Titles permanently shadow first names — be conservative** — any word in `TITLES` is always consumed as a title and can never be parsed as a first name. `"Dean"` is the canonical example: it's a common academic title *and* a common given name, so it is intentionally absent from the default titles (see `docs/customize.rst` — users who need it add it via opt-in `Constants`). Before adding a word to `TITLES`, ask: "Could this plausibly be someone's given name in any culture?" If yes, don't add it globally; it belongs in caller-supplied `Constants` instead. This same caution applies to international honorifics — `Prince`, `Sheikh`, `Frau` are all first names in some contexts. It also applies to any prefix sub-set gated on "never a first name": obscure-looking foreign particles are surprisingly often real given names — `Von` (Von Miller), `Vander` (Brazilian, also the Arcane character). When unsure, exclude — a missing member just means that name isn't auto-handled, whereas a wrong member misparses a real person. The decided exception is a word borne as a name only RARELY in the leading position — mostly a surname written last (`graf`, `greve`, `knight`), a few with small given-name or surname-first counts (`herra`, `hrabia`): the title claim acts only in front, so it ships, and a name that begins with it (`Greve Anna`, `Herra Wijaya` → title) is the accepted cost. That is a judgment by incidence, made per word with the counts recorded in `decisions.md#salutation-titles` (rules.md#H1's Accepted clause states the cost), not a rule a sweep can apply: a word that commonly leads a real name (Vietnamese `Ông`, the given names `thiru`, `puan`, `marshal`) is still out. `tools/name_usage.py` produces the counts this judgment starts from (role counts, plus Wikidata citizenship to tell where a family name is written first); its Wikidata column is a lower bound (Shehu Shagari has no given-name statement), so a small count there proves little and a zero proves nothing. -**The period-abbreviation title inference runs at the head of the GIVEN-NAME part, not the head of the name** — an unrecognized multi-letter word ending in a single trailing period (`_pieces._PERIOD_ABBREV`, a hand copy of the `period_abbreviation` regex, `{2,}` letters — it was assign's until #424 and group's until #439) is treated as a title in the leading title run, e.g. `"Insp. Jane Morse"` → `title='Insp.'`. "Leading" is per SEGMENT: `_peel_leading_titles` is called for NO_COMMA segment 0, SUFFIX_COMMA segment 0, and FAMILY_COMMA **segment 1**, so `"Morse, Det. Insp. Jane"` → `title='Det. Insp.'` and a lone `"Smith, Xyz."` → `title='Xyz.'` — long-standing, verified against 1.4.0, and the mechanism behind #296 (`"Smith, Jr."` read title in 1.4.0; the comma's credential read takes it as suffix `Jr.` now). The docs said "leading word" until 2026-08-01 and were wrong for every comma path. It does not mutate `C.titles`, so the periodless form (`"Insp"`) is unaffected elsewhere. The `{2,}` length requirement — not a separate initials check — is what excludes single-letter initials like `"J."`; the same word after the given name is left as a middle name. **The inference OUTRANKS vocabulary where it runs**: `"Esq. Smith"` → `title='Esq.'` even though `esq` is suffix-only vocabulary, because the shape rule fires before anything consults the suffix sets. **The INFERENCE still runs in one direction only, and that is what the two slots share and where they part** (rewritten 2026-09-08, #316): a period-marked word is claimed by SHAPE at the front and by VOCABULARY at the back, so an unlisted abbreviation opening a name is a title while an unlisted abbreviation ending one is a NAME word (`"John Smith Xyz."` → `family='Xyz.'`). A trailing period-marked word the vocabulary knows as a title now IS one (`"John Smith Prof."` → `title='Prof.'`, `rules.md#H5`) — the comma path always read it that way and the two agree now — and a trailing period-marked word the SUFFIX vocabulary knows is still a suffix, the suffix run being peeled first (`"John Smith Esq."` → `suffix='Esq.'`). A BARE trailing title word stays a name word (`"John Smith Sir"`, `"Mary Jane King"`), which is the doctrine line below. Meanwhile `period_joined_vocab` resolves INTERIOR-period tokens (`Lt.Gov.`, `Msc.Ed.`) to title-or-suffix by vocabulary, and `_extract._suffix_shaped` treats any period-final delimited content as not-a-nickname. Four sites, and the trailing one now resolves by two vocabularies in order rather than one; unifying the rest is open design work, not settled. (#109; see `docs/usage.rst` "Titles you didn't configure") +**The period-abbreviation title inference runs at the head of the GIVEN-NAME part, not the head of the name** — an unrecognized multi-letter word ending in a single trailing period (`_pieces._PERIOD_ABBREV`, a hand copy of the `period_abbreviation` regex, `{2,}` letters — it was assign's until #424 and group's until #439) is treated as a title in the leading title run, e.g. `"Insp. Jane Morse"` → `title='Insp.'`. "Leading" is per SEGMENT: `_peel_leading_titles` is called for NO_COMMA segment 0, SUFFIX_COMMA segment 0, and FAMILY_COMMA **segment 1**, so `"Morse, Det. Insp. Jane"` → `title='Det. Insp.'` and a lone `"Smith, Xyz."` → `title='Xyz.'` — long-standing, verified against 1.4.0, and the mechanism behind #296 (`"Smith, Jr."` read title in 1.4.0; the comma's credential read takes it as suffix `Jr.` now). The docs said "leading word" until 2026-08-01 and were wrong for every comma path. FAMILY_COMMA **segment 0** peels too since #701, but by VOCABULARY only (rules.md#H6, in assign's family-comma branch rather than `_peel_leading_titles`): `Dr. Smith, John` → `title='Dr.'`, while `Xyz. Smith, John` keeps family `Xyz. Smith`, and a title-particle (`St`, `Freiherr`) stops the run, as does a title with nothing but post-nominals behind it (`Dr. Jr., John` keeps family `Dr.`); a title/suffix dual with a name word behind it still peels (`Rev. Sr. Smith, Mary`). It does not mutate `C.titles`, so the periodless form (`"Insp"`) is unaffected elsewhere. The `{2,}` length requirement — not a separate initials check — is what excludes single-letter initials like `"J."`; the same word after the given name is left as a middle name. **The inference OUTRANKS vocabulary where it runs**: `"Esq. Smith"` → `title='Esq.'` even though `esq` is suffix-only vocabulary, because the shape rule fires before anything consults the suffix sets. **The INFERENCE still runs in one direction only, and that is what the two slots share and where they part** (rewritten 2026-09-08, #316): a period-marked word is claimed by SHAPE at the front and by VOCABULARY at the back, so an unlisted abbreviation opening a name is a title while an unlisted abbreviation ending one is a NAME word (`"John Smith Xyz."` → `family='Xyz.'`). A trailing period-marked word the vocabulary knows as a title now IS one (`"John Smith Prof."` → `title='Prof.'`, `rules.md#H5`) — the comma path always read it that way and the two agree now — and a trailing period-marked word the SUFFIX vocabulary knows is still a suffix, the suffix run being peeled first (`"John Smith Esq."` → `suffix='Esq.'`). A BARE trailing title word stays a name word (`"John Smith Sir"`, `"Mary Jane King"`), which is the doctrine line below. Meanwhile `period_joined_vocab` resolves INTERIOR-period tokens (`Lt.Gov.`, `Msc.Ed.`) to title-or-suffix by vocabulary, and `_extract._suffix_shaped` treats any period-final delimited content as not-a-nickname. Four sites, and the trailing one now resolves by two vocabularies in order rather than one; unifying the rest is open design work, not settled. (#109; see `docs/usage.rst` "Titles you didn't configure") **Cyrillic suffix regexes need `re.I` even when the pattern is suffix-only** — a Latin title-cased word (`Ivanovich`) keeps its suffix lowercase, so `re.I` seemed skippable; but an irregular Cyrillic suffix can be nearly the whole word (`ильич`), so title-casing capitalizes into the suffix itself (`Ильич`). `east_slavic_patronymic_cyrillic` shipped without `re.I` on the Latin reasoning and silently failed on capitalized irregular forms — don't assume Latin's title-case safety transfers to Cyrillic. (#185) diff --git a/docs/design/decisions.md b/docs/design/decisions.md index 73027fed..6089a58f 100644 --- a/docs/design/decisions.md +++ b/docs/design/decisions.md @@ -620,6 +620,15 @@ Decided 2026-09-08 (was Open: [#316](https://github.com/derek73/python-nameparse MEASURED 2026-10-10 against 4d5631c2 (#634's merge), py3.11, `nameparser.__file__` asserted on each side. A given-part grid -- `{family}, {head} {middle} {tail}`, and the same with `, Jr.` appended, for family in `Smith`, `van der Berg`, `Ortega y Gasset`, (empty), `(Bob)`; head in `John`, `Dr. John`, `Freiherr`, `abdul`, `Freiherr St`, `J.`; middle in (none), `van`, `van der`, `de la`, `van Berg`, `van der Berg`, `Mc Mc`, `von und zu`, `Berg`, `Berg van`, `do`, `St`, `y Lopez`; tail in (none), `Prof.`, `Dr.`, `Prof. Dr.`, `Prof`, `Sir`, `Prof. PhD`, `PhD Prof.`, `Jr. Prof.`, `Prof. Jr.`, `MA`, `Ma`, `VI`, `V`, `X.Y.Z.`, `Ph. D.`, `Esq.`, `née Jones`, `Prof. Jones`, `Xyz.`, `King.`, `Prof. V`, `MA Prof.`, `Lt.Gov.` -- 18,480 texts under the three orders and `lenient_comma_suffixes=False`, comparing the seven fields and every report: 17,340 of the 73,920 parses move a role (4,335 texts under each configuration), and no parse moves a report alone. All but 500 parses (125 texts) put a trailing period-marked title into the title field. H5's transparency over the grid's default-order texts whose given part ends in `Prof.`, `Dr.`, `King.` or `Prof. Dr.` (5,390; the parse with the title against the parse without it, plus the title): broken on 392, against 3,048 on master, and on no text master kept. By cause, 352 of the 392 are H1's move of the name behind a title into an empty family (an empty or nickname-only head), and 40 are P5's lenient post-comma join taking the title into a bound given name -- 24 after a named family (`Smith, abdul Dr.` reads given 'abdul Dr.') and 16 behind an empty head (`, abdul Prof.`), the gap rules.md#H5's Accepted P5 paragraph records (fixed by #637, decisions.md#P5, 2026-10-11). The 500 put a title in front of a numeral with a third comma part (`(Bob), Freiherr Mc Mc Prof. V, Jr.`): the bound reads 'V' as a numeral and stops before 'Prof.', where the walk keeps 'V' a name word with a third part (#144), so 'Prof.' lands in the middle 'Prof. V' rather than the given 'Mc Mc Prof.' -- a name word either way, garbage. The S2 stress grid's comma half (#614's recipe): 56 moves, all a trailing title behind a particle after a family comma (`Smith, Jan Freiherr von Berg Prof.`); #624's title-particle grid: 24, the same class (`Smith, John Freiherr Dr.` → title 'Dr.', family 'Freiherr Smith'). #625's particle grid, every corpus name and case text, and #624's comma-tail grid: 0. The five gates exit 0 with the new `fix(#623)` rule in every ledger. Frames (3.11, warm): the reference rows do not move; a family-comma name with a particle pays 2 with no trailing run (`Smith, John van der Berg` 282 → 284), 4 with a suffix (`Smith, John van der Berg Jr.`), and the moved shapes 38 to 73 in a sample (`Smith, John van der Berg Prof. PhD` +38, `Smith, John van der Berg Prof.` 310 → 360, `Smith, Jan van Prof.` +73), with an unmoved particle name ending in a suffix and a title 20 to 22 (`Smith, John van der Berg PhD Prof.` 382 → 402, `Smith, John van der Berg Jr. Prof.` 382 → 404), rare shapes no guard sees; one without a particle pays less (`Smith, John Quincy` 221 → 213, `Doe, John MA` 254 → 227), which `test_a_given_part_with_no_particle_skips_the_chain_bound` holds (the bound skipped, 'Smith, John Prof.' 250 frames with it asked against 207). Recorded negative control: with the old bound, 8 tests fail -- the two `fix(#623)` rows on both surfaces, the three new rules.md#H5 examples and the field-sweep count. THE REVIEW (2026-10-10). The bound is `tail_reading`'s run, read as the comma-less name reads it, and the walk reads the given part by its own predicates, so where the two disagree on a word behind a title the chain stops for a title the walk does not take, or cannot cross one to reach a particle P6 takes: a title in front of a shape-only numeral (`Smith, John Mc Prof. VI` → suffix 'Mc', middle 'Prof. VI'; master middle 'Mc Prof. VI'; the walk never reads 'VI' as a suffix after a comma), in front of a numeral with a third comma part (the 500 above), in the middle of the given part in front of a particle (`Smith, John van Prof. Mc` → title 'Prof.', middle 'van', family 'Mc Smith'), and a period-marked title-particle ending it, which P6 attaches (`Smith, John van MA St.` → suffix 'MA', family 'St. Smith'). Every such shape is garbage, most read as master already reads the text without the title (`Smith, John Mc VI` suffix 'Mc'), and none is a reading a well-formed name loses: over about 1.6 million generated rows under every order, the opt-in policies, one-case writing and caller lexicons, and over a 134,720-pair transparency grid (`Smith, ` and `, ` heads; one to three words from `John`, `van`, `der`, `von und zu`, `Berg`, `Ma`, `MA`, `V`, `VI`, `Jr.`, `PhD`, `Ph. D.`, `Mc`, `St.`, `St`, `Freiherr`, `X.Y.Z.`, `Esq.`, `abdul`, `Prof.`; a trailing ` Prof.`, with and without `, Jr.` after it; the three orders and `lenient_comma_suffixes=False`; transparent where given, middle, family, nickname and maiden equal the title-less text's and the title gains exactly ` Prof.`; master broken on 53,384 pairs, the tree on 9,734), no text transparent to its title on master is broken now. (The first review named `Smith, John Ph. D. St. Prof.` as one, its oracle reading the direction backwards: master gives suffix 'Ph. D. St. Prof.' against the title-less 'family St. Smith', and the tree is transparent.) Recorded, not fixed (Derek): garbage, and narrowing the bound would add a condition for it. The review also found the bound's particle gate held by no test, two of its narrowings undoing readings master gives -- a scan from the name's start rather than the chain's lead (`Smith, Freiherr von Berg Prof.`) and a test of single-token particles alone (`Smith, John von und zu Berg Prof.`) -- now rows of their own, with an empty-head row (`, Jan van Prof.`, AGENTS.md's comma sweep), and the frame saving now held as above. Each of the three mutations fails a test. The re-ask after the chain (`left < tail`) still decides readings, though its documented case (`Freiherr von Berg Ma`) takes the read-once path since #614: removed, it moves 400 parses of the given-part grid on master and here alike, a title-particle head before a particle run and a dotted acronym (`Smith, Freiherr van Berg X.Y.Z.` → given 'van Berg X.Y.Z.', as 1.4.0 reads it; without it suffix 'X.Y.Z.'). It decides a main segment's run with a name piece inside it too (`Freiherr van Berg Dr. X.Y.Z.` → family 'van Berg Dr. X.Y.Z.', as master and 2.3.0 read it; without it given 'van Berg Dr.', family 'X.Y.Z.', 1.4.0's reading), a garbage shape no row holds. The first review reported it changing nothing over a grid with no such shape, and #638 was filed on that; the fix review found it live and held by no test, and the row `the_chain_runs_again_where_its_merges_free_the_acronym` (parity) holds it now. Left for follow-ups, two gaps outside this change: a part past the second comma reads a trailing title behind a particle into the suffix (`John Smith, Jr., van der Berg Prof.`, where `John Smith, Jr., Prof.` reads title 'Prof.'; #636), and P5's post-comma join taking a title (the 40 above; #637). +### H6 — a title before a family comma + +- 2026-10-17 (Derek), #701 — A TITLE OPENING THE PART BEFORE A FAMILY COMMA IS THE TITLE. `Dr. Smith, John` read family 'Dr. Smith', and every release did the same: 1.4.0 from PyPI gives last 'Dr. Smith' and 'Prof. Brühl' (suffix 'Dr.') for `Prof. Dr. Brühl, Ada Cornelia` (measured 2026-10-17, `PYTHONSAFEPATH=1`, wheel path asserted). The reading was written down on purpose as Accepted clauses of rules.md#H2 and #H3 ("before a family comma the pre-comma text is wholly the family name") and assumed by C1's Freiherr clause ('Prof. Cruz, Ed'); all three are rewritten here. The listing form moves the surname to the front and leaves the title where it was written, and CLDR's index renderings write exactly that in several locales (`prof. dr. von Selimović Hodžić, Izeta Amra`, `г-н Вернер, Иван Асен`). + DECIDED (Derek, the five points of the design proposal): (1) VOCABULARY ONLY. H2's shape does not fire before a family comma, so `Xyz. Smith, John` keeps family 'Xyz. Smith' — the slot is a surname's slot too, as the trailing slot is (#H5), and every CLDR case is a listed title. (2) The run leaves the family its last piece (`Dr., John`, `Greve, Anna`). (3) A word that is a particle too stops the run, bare or period-marked, so `St Pierre, Ed` and the 1919 legal-surname reading of `Freiherr von Berg, Ed` (C1's Accepted clause) stand, and a title in front of them still peels. (4) The peeled titles join the title field in input order, and the comma decision (`_comma.decide`) is untouched — the count before the comma already treated a title as no name word. (5) ACCEPTED COST: a bare surname-like title opening a two-word surname is the title, `King Smith, John` → title 'King', as `Greve Anna` already reads (#H1). + ADDED IN THE PROTOTYPE, not in the proposal: #H3's floor. The first version peeled `MD` from `MD PhD Jr., John`, leaving family 'PhD' — which a case row (`family_comma_segment_zero_is_not_the_run`) caught. A title addresses somebody, and a post-nominal is not somebody, so the run stops where nothing but post-nominals stands behind it: `Dr. Jr., John` keeps family 'Dr.'. The second version stopped in front of ANY piece of the suffix vocabulary, and the design-docs review found it too broad: a title/suffix dual standing SECOND in the run blocked it and then read as a suffix inside the family (`Rev. Sr. Smith, Mary` → family 'Rev. Smith', suffix 'Sr.', where the comma-less `Rev. Sr. Mary Smith` reads title 'Rev. Sr.'), and so did `Mc` and `vd`, which the family loop's own P2 clause reads as a surname's head (`Dr. Mc Donald, John`). Its check compared `T Smith, John` with `T John Smith` over every title word, bare and period-marked, alone, behind `Dr.` and ahead of it (4,788 pairs over the 798 title words before #705's merge): 36 disagreed, 12 the decided particle class and 24 the twelve duals in second position. The floor asks the H3 question instead — is everything behind this title post-nominal? — so the duals peel wherever a name word follows them, as they do in front of a name with no comma. + Declined: excluding the title/suffix duals from the run (it would keep `Ms Smith, Jane` whole); peeling by H2's shape too (the trailing doctrine, #H5, says only vocabulary claims a word in a surname's slot). + MEASURED 2026-10-17 against master `eb2c1fa5`, py3.11. Snapshot (`uv run python tools/differential/snapshot.py --since master`, before this change's own rows entered the corpora): 20 entries move, all one shape — a title leaves the family for the title field — and 18 of their names are held only by corpus_cldr.jsonl. Several of those are names C1 reads as a family comma though the part after it is a credential CLDR's vocabulary lacks (`hr. Hans Henrik Sven Åge Møller, MF`); the title still comes out right there, and the family stays as wrong as before. CLDR agreement: 29 fields now agree and 28 more get closer to CLDR's value, with none regressing. Merging master after #705 listed `bapak` adds one more of the same shape, `Bapak Adinata, Dwi Putro bin MP` (title 'Bapak' out of family 'bin Bapak Adinata'), two more CLDR fields agreeing and one closer. Cost (`sys.setprofile` call events, one warm-up): `Dr. Juan Q. Xavier de la Vega III` 366 → 366 (the benchmark's `_REFERENCE` row, 307, is unmoved too), `Smith, John` 161 → 161, `Smith Jones, John` 203 → 203 (an inline tag test ahead of `is_title_piece` keeps a part no title opens free of frames), `Dr. Smith, John` 200 → 201 (one `is_title_piece`; the floor's `is_suffix_piece` on 'Smith' replaces the family loop's, which no longer asks the first family piece), `Prof. Dr. Brühl, Ada` 279 → 280. The family loop does not re-ask a piece at or past the floor, so a long post-nominal run costs one frame more than on master, not one per member: `Dr. Smith Jr. PhD MD, John` 306 → 307 (310 before the /simplify round), `Dr. Smith` plus twenty `PhD`, `, John` 903 → 904 (924 before). Those two changes moved no reading on a grid of 88,740 family-comma heads (one to four words from `Dr.`, `Prof`, `St`, `Freiherr`, `Sr.`, `Ms`, `Smith`, `van`, `Vd`, `PhD`, `Jr.`, `MA`, `V`, `de`, `Rev.`, `Mc`, `née`, before `, John`) under the default and `FAMILY_FIRST` orders, comparing fields, ambiguity kinds and `initials()`. + THE PR REVIEW (2026-10-17), three decisions. (a) `gov` JOINS TITLES (Derek). `Lt. Gov. Smith, John` read title 'Lt.', family 'Gov. Smith' — a compound split across two fields, where master kept it whole in the family and the comma-less `Lt. Gov. John Smith` reads title 'Lt. Gov.' by H2's shape. The run is vocabulary-only, so the fix is the vocabulary: `gov` is the abbreviation of the listed `governor`. Counts (`uv run python tools/name_usage.py Gov`, 2026-10-17): 236 US Census 2010 surname bearers, rank 80,419, 91.53% Asian/Pacific Islander; SSA given names under 5 a year; Wikidata 3 family-name bearers, all Israeli. The claim acts only in front, so `John Gov` keeps family 'Gov', and a surname written first loses it (`Gov Sokha` → title 'Gov'), the graf-class trade (#salutation-titles) at a smaller incidence. No corpus name moved. The other unlisted second words the review found (`insp`, `sen`, `supt`, `cmdr`, `atty`, `msgr`) still split; each is a vocabulary question on its own. (b) `Dr. PhD Smith, John` KEEPS the branch reading, family 'PhD Smith' (Derek): the first piece the run leaves is family whatever it is, as piece 0 is with no title (`PhD Smith, John`, read that way by 1.4.0 too); master and 1.4.0 gave `Dr. PhD Smith, John` family 'Dr. Smith', suffix 'PhD'. Garbage input, so no row. (c) `Graf Lambsdorff, Otto` reads title 'Graf' while `Freiherr von Berg, Ed` keeps the rank, and the clause first written for it gave the 1919 legal-surname argument as the reason — which holds for every German rank alike. The reason is the particle stop: `freiherr` is the one rank in `particles`. rules.md#H6's Accepted clause now says so, and the vocabulary question (should `graf`, `fürst`, `prinz` and the rest read as `freiherr` does, with and without a comma) is [#709](https://github.com/derek73/python-nameparser/issues/709). + ### W1 — unspaced CJK division - 2026-07-27 #271 (decision; shipped in 2.1.0 via PR #294) — Korean division ships as a default: the census surname list is closed, hangul is self-selecting (a hangul entry can only match hangul text), and being unsplit is recoverable while a wrong split is not — which is also why an unrecognized name stays whole. The filed proposal (#271, 2026-07-07) asked for OPT-IN segmentation for Korean too, "like all localization"; default-on is the later refinement, and the census/self-selecting argument above is what justified promoting Korean past the blanket opt-in stance. @@ -1030,7 +1039,7 @@ Excluded (MAIDEN_MARKERS, per nameparser/config/maiden_markers.py): THE COMMA SETTLES P1's FORK, and that is the decision rather than a side effect. Standing alone, `Van Buren` is given 'Van', family 'Buren' with a `particle-or-given` report, so counting it as one surname makes the comma's reading disagree with the standalone one. Derek's call, after weighing the narrow alternative (count only a part P1 already reads as all surname, i.e. one led by a never-given particle like `de`): the listing form puts a surname before the comma, so the comma is evidence the standalone parse does not have, and the readings it gives are the ones a person takes — `Van Buren, Ed` given 'Ed', family 'Van Buren'; `van der Berg, MA` family 'van der Berg', suffix 'MA' (one name word, so C1 reads the case, and capitals in a mixed-case name make the credential). `Van Johnson, Dr.` moves with it, family 'Van Johnson', title 'Dr.', where 2.2.0 and 2.3.0 read given 'Van' and `tests/v2/pipeline/test_assign.py` had pinned the positional fork; that test now uses `Van Johnson Smith, Dr.`, which still has two name words. THE PARTICLE REACHES ONE WORD, as P1's fold does, not to the end of the part as P2's chain does: `de Mesnil Jean, Dr.` under a family-first order is family 'de Mesnil', given 'Jean', two name words. The cost, and it is real for an ambiguous particle: a `van`-led part with a word after the surname counts two and keeps the positional read with P1's fork, so `van Buren John, Ed` reads given 'van', middle 'Buren', family 'John' and `van der Berg Smith, PhD` given 'van', family 'der Berg Smith', both unchanged from master. Under the default order a never-given particle loses nothing (P1's fold makes `de Mesnil Jean` all surname anyway). `_vocab.unit_ends` carries both reaches behind a `chain` flag, post_rules' fold reading the full chain as before. ONLY PARTICLE CHAINS, not mechanisms.md#UNIT-PARTITION's full set — stated there as the Contract's one exception, and in P3's statement, whose "ONE name word wherever another rule counts them" now names C1's count as the exception. A bound given-name pair builds a GIVEN name, and P5 gives up a family word where the name has no other (`abdul Salam` alone is given 'abdul', family 'Salam'), so `abdul Salam, Ed` keeps the credential reading. Whether P3 joins a single-letter connective depends on the words of the whole name — `Carod i Rovira, Josep` joins as four words where `Ortega y Gasset` alone, three, does not — and the count is part of deciding what the whole name is, so segment could reach P3's answer only by copying P3; `Ortega y Gasset, Ed` keeps the credential reading. Approved as "particle chains and connective joins", narrowed to particles when P3's exception surfaced in implementation (the first draft joined `John e Smith, III` into one family name, caught by `tests/test_conjunctions.py`). - A WORD THAT IS ALSO A TITLE IS NO PARTICLE WHERE IT OPENS THE PART. `TITLES ∩ particles` is `{freiherr, st}` and `bound_given_names ∩ particles` is `{abu, أبو, ابو}` (recompute: `L = Parser().lexicon; L.particles & L.titles`, `L.particles & L.bound_given_names`). The first draft counted every particle, and the docs review found it reading `Freiherr von Berg, PhD` as family 'Freiherr von Berg' and `St John, PhD` as family 'St John', where every release reads the title. The first fix then excluded both overlaps in EVERY position, and the review of that fix found two errors in it. Position: inside a surname a title-particle chains as P1 and P2 chain it, and the blanket exclusion brought #575's own defect back for `de St Pierre, Ed`, `De St. Croix, Ed` and `de Abu Bakar, Ed` (family only, no given name, where 2.3.0 read given 'Ed'). And direction: 2.0 through 2.3 read `Abu Bakar, Ed` as given 'Ed', family 'Abu Bakar', so excluding the bound-given particle gave released behavior up rather than keeping it — and Abu Bakar is a common Malay surname. DECIDED: a title-particle is no particle only where it LEADS the part, and a bound given-name particle is a particle. So `Freiherr von Berg, PhD` and `St John, PhD` keep the title, `de St Pierre, Ed` reads given 'Ed', and `Abu Bakar, Ed` reads given 'Ed', family 'Abu Bakar' while `Abu Bakar, PhD` reads family 'Abu Bakar', suffix 'PhD' where 1.4.0 through 2.3.0 read given 'Abu'. The agreement test compares each token in both positions; it cannot see which position a caller passes, so case rows pin each count's flag: `de St Pierre, Ed` segment's, and `St John, Dr.` and `von St Johann, PhD` assign's, one per direction (the review of this round found assign's flag fixed to either constant passing every test, and both mutants now fail). `Freiherr von Berg, Ed` reads family 'Freiherr von Berg', given 'Ed' — 2.0.0's through 2.3.0's reading too, so no change against a release; only this cycle's count had read title 'Freiherr', family 'von Berg', suffix 'Ed'. The surname counts once and the title is no name word, so the count reads the listing form, which keeps a leading title in the family as it already did for `Prof. Cruz, Ed`. For `Prof.` that is a cost (rules.md#C1's Accepted line); for a German rank it is the right reading (Derek, 2026-10-01): since 1919 a former noble title is part of the legal surname, written between the given name and the particle (Karl-Theodor Freiherr von und zu Guttenberg), so `Freiherr von Berg` is the family name. That is also why `freiherr` is in PARTICLES at all — added with the German prefixes in 3e14ea20 (#18) without a stated reason, and the reason is this one. `Freiherr von Berg, PhD` keeps title 'Freiherr', the unambiguous credential's count taking the title as a word; both are readings of one name, and neither is changed here. A title in front is otherwise outside the fix: v1's count for an unambiguous credential counts the title as a word, so `Dr. van der Berg, PhD` reads as `Dr. van der Berg` does alone, given 'van'. + A WORD THAT IS ALSO A TITLE IS NO PARTICLE WHERE IT OPENS THE PART. `TITLES ∩ particles` is `{freiherr, st}` and `bound_given_names ∩ particles` is `{abu, أبو, ابو}` (recompute: `L = Parser().lexicon; L.particles & L.titles`, `L.particles & L.bound_given_names`). The first draft counted every particle, and the docs review found it reading `Freiherr von Berg, PhD` as family 'Freiherr von Berg' and `St John, PhD` as family 'St John', where every release reads the title. The first fix then excluded both overlaps in EVERY position, and the review of that fix found two errors in it. Position: inside a surname a title-particle chains as P1 and P2 chain it, and the blanket exclusion brought #575's own defect back for `de St Pierre, Ed`, `De St. Croix, Ed` and `de Abu Bakar, Ed` (family only, no given name, where 2.3.0 read given 'Ed'). And direction: 2.0 through 2.3 read `Abu Bakar, Ed` as given 'Ed', family 'Abu Bakar', so excluding the bound-given particle gave released behavior up rather than keeping it — and Abu Bakar is a common Malay surname. DECIDED: a title-particle is no particle only where it LEADS the part, and a bound given-name particle is a particle. So `Freiherr von Berg, PhD` and `St John, PhD` keep the title, `de St Pierre, Ed` reads given 'Ed', and `Abu Bakar, Ed` reads given 'Ed', family 'Abu Bakar' while `Abu Bakar, PhD` reads family 'Abu Bakar', suffix 'PhD' where 1.4.0 through 2.3.0 read given 'Abu'. The agreement test compares each token in both positions; it cannot see which position a caller passes, so case rows pin each count's flag: `de St Pierre, Ed` segment's, and `St John, Dr.` and `von St Johann, PhD` assign's, one per direction (the review of this round found assign's flag fixed to either constant passing every test, and both mutants now fail). `Freiherr von Berg, Ed` reads family 'Freiherr von Berg', given 'Ed' — 2.0.0's through 2.3.0's reading too, so no change against a release; only this cycle's count had read title 'Freiherr', family 'von Berg', suffix 'Ed'. The surname counts once and the title is no name word, so the count reads the listing form, which keeps a leading title in the family as it already did for `Prof. Cruz, Ed` (superseded for listed titles by #H6, 2026-10-17: the count is unchanged, and the listed title then peels). For `Prof.` that is a cost (rules.md#C1's Accepted line); for a German rank it is the right reading (Derek, 2026-10-01): since 1919 a former noble title is part of the legal surname, written between the given name and the particle (Karl-Theodor Freiherr von und zu Guttenberg), so `Freiherr von Berg` is the family name. That is also why `freiherr` is in PARTICLES at all — added with the German prefixes in 3e14ea20 (#18) without a stated reason, and the reason is this one. `Freiherr von Berg, PhD` keeps title 'Freiherr', the unambiguous credential's count taking the title as a word; both are readings of one name, and neither is changed here. A title in front is otherwise outside the fix: v1's count for an unambiguous credential counts the title as a word, so `Dr. van der Berg, PhD` reads as `Dr. van der Berg` does alone, given 'van'. `De La Cruz, M.J. K.L.` reads given 'M.J.', suffix 'K.L.', reporting twice, as `Cruz, M.J. K.L.` does (Derek, 2026-10-01): with one name word before the comma the paired-initials count no longer reaches it, and C1's two-dotted-groups sentence now says "behind two or more name words". #563 had read it as a flipped credential run with no given name. SEGMENT RUNS BEFORE CLASSIFY, so its count builds the two facts it reads (particle, suffix) from the vocabulary (`_vocab.surname_unit_tags`), while assign derives them from classify's tags (`_vocab.surname_unit_facts`) over every token of the part, so a suffix word stops a particle in both: the first draft's assign count dropped suffix pieces before walking and read `van Jr. Berg, Mr.` as family 'van Berg' (the code review). `test_classify.test_surname_unit_tags_agree_with_classify` sweeps every single-word vocabulary entry in three casings; its first run caught `JD.CPA` and `Msc.Ed.`, which classify tags as suffixes through the period-joined derivation, now mirrored, and that pair is the recorded negative control (`_SURNAME_UNIT_CONTROL`, asserted with the mirror patched out). BLAST RADIUS, measured 2026-10-01: the gate exits 0 at all five baselines, and of the 1459 names in master's corpora exactly one moves, `De La Cruz, M.J. K.L.` (above, decided). Comparator: `parse(n).as_dict()`, the ambiguity kinds and `initials()` for every name in every `tools/differential/corpus*.jsonl` at `git archive origin/master`, under all three name orders, on master's tree against this one. The population that could move is small and the corpus is evidence about itself, not the rule: two corpus names have a part before the comma that is one particle surname of several words, with the part after the comma holding a credential — that one and `De La Cruz, M.J. PhD`, which keeps given 'M.J.'. Recompute: corpus names whose part before the first comma has more than one token and `_vocab.surname_unit_count` 1 (24 at master, nearly all `de la Vega, Juan`-type listings), then keep those whose second segment holds a word `_vocab.ambiguous_class_candidate` admits (a listed or dotted member of the credential class) — 2 at master. A filter on any suffix word keeps 17, the `de la Vega, Juan … III` listings among them. Against 2.3.0, `fix(#575)` classifies one name, `van der Berg, PhD`; the other particle-surname example names diff there only by this cycle's #289 count and report. Outside the corpora the move against 2.3.0 is a class, not a list: a leading ambiguous particle and one word, before a comma followed by an unambiguous credential or a title alone, now reads as one surname (`Abu Bakar, PhD`, `bin Laden, PhD`, `Mac Donald, PhD`, `van Gogh, Jr.`, `Van Johnson, Dr.`), where 2.3.0 read the particle as the given name; `Freiherr von Berg, Ed` and `Abu Bakar, Ed` move only against this cycle's master. The boundary case rows added in review carry no shape tag on purpose: their diffs against the older baselines come from earlier changes (#296's positional read, #289's count), so admitting them to the contract corpus would have stretched unrelated ledger rules over them; the case table asserts them either way. diff --git a/docs/design/rules.md b/docs/design/rules.md index 02f972e4..b6420f1c 100644 --- a/docs/design/rules.md +++ b/docs/design/rules.md @@ -90,13 +90,15 @@ H1. Rationale: a title normally addresses by surname, so a title the title in front of a name, so a name that BEGINS with it -- a surname written first without a comma, or a given name -- gives that word to the title, under a declared family-first order too. - Written last without a period, or before a family comma, it is - the name; a period behind it makes it the title by H5, as for - `Mary Jane King.` (#606). + Written last without a period, or alone before a family comma, + it is the name; a period behind it makes it the title by H5, as + for `Mary Jane King.` (#606), and a name word behind it before + a family comma makes it the title by H6. + "Greve Smith, Anna" → title="Greve" "Greve Anna" → family="Anna" "Anna Greve" → family="Greve" "Greve, Anna" → family="Greve" - history: decisions.md#H1 · interacts: H3, H5, P2, P3, P5, M2, S1, S2, N1, N3 · implemented: nameparser/_pipeline/_post_rules.py + history: decisions.md#H1 · interacts: H3, H5, H6, P2, P3, P5, M2, S1, S2, N1, N3 · implemented: nameparser/_pipeline/_post_rules.py H2. Rationale: before a name, an abbreviation is almost always a title — "Rev.", "Ing.", "Mag." — and no vocabulary can list @@ -144,16 +146,16 @@ H2. Rationale: before a name, an abbreviation is almost always a second line below is typed that way. "Smith. John" → title="Smith." "김. 민준" → title="" - Accepted: before a family comma the pre-comma text is wholly the - family name (C1), so no shape or vocabulary reading makes a - title there. + Accepted: before a family comma the shape does not fire: the + titles there are the vocabulary's alone (H6), so an unlisted + abbreviation opening that part stays in the family. "Xyz. Smith, John" → family="Xyz. Smith" Accepted: after a family comma a part that is nothing but suffix words is the credential run (C1), which the abbreviation does not open: the vocabulary decides, and "Esq." is the postnominal it is. "Smith, Esq." → suffix="Esq." - history: decisions.md#H2 · interacts: C1, S2, S3, P4, H5, W3, W4 · implemented: nameparser/_pipeline/_assign.py, nameparser/_pipeline/_pieces.py, nameparser/_pipeline/_vocab.py + history: decisions.md#H2 · interacts: C1, S2, S3, P4, H5, H6, W3, W4 · implemented: nameparser/_pipeline/_assign.py, nameparser/_pipeline/_pieces.py, nameparser/_pipeline/_vocab.py H3. Rationale: compound titles are written as a run of title words, connectives included; a title word standing inside the name is @@ -175,9 +177,11 @@ H3. Rationale: compound titles are written as a run of title words, "Dr King Jr" → suffix="Jr" "MD DDS" → family="DDS" "John Doctor Smith" → middle="Doctor" · boundary - Accepted: before a family comma the pre-comma text is wholly the - family name (C1), title words included. - "Dr. Smith, John" → family="Dr. Smith" + Accepted: before a family comma the run is H6's, which stops + where nothing but post-nominals follows for the reason this one + gives a word back, and always leaves the family one word, + whatever that word is. + "Dr. Jr., John" → family="Dr." Accepted: the word given back must stand alone, so a title written as one joined unit stays whole and the post-nominal behind it is the name — turning the unit into a name and leaving @@ -188,7 +192,7 @@ H3. Rationale: compound titles are written as a run of title words, the name and the parse reports the doubt (H4). "Dr Jr" → given="Dr" "Dr Jr" → ambiguities=("title-or-name",) - history: decisions.md#H3 · interacts: C1, H1, H4, H5, S2 · implemented: nameparser/_pipeline/_pieces.py + history: decisions.md#H3 · interacts: C1, H1, H4, H5, H6, S2 · implemented: nameparser/_pipeline/_pieces.py H4. Rationale: this is a name parser, not a title parser. Handed a string the title peel eats down to one last word which is itself @@ -370,6 +374,55 @@ H5. Rationale: a word abbreviated with a period at the END of a name "Berg, abdul Prof." → title="Prof." history: decisions.md#H5 · interacts: H1, H2, H3, H4, M2, P2, P5, P6, S2, C1 · implemented: nameparser/_pipeline/_assign.py, nameparser/_pipeline/_group.py, nameparser/_pipeline/_pieces.py +H6. Rationale: the listing form moves the surname to the front and + leaves everything else where it was written, so a title written + ahead of the name ends up ahead of the surname — `Dr. Smith, + John` is `Dr. John Smith` indexed. The comma names the family, + and a title is no part of it. But the slot in front of a family + comma is a surname's slot as well, so only the vocabulary claims + a word there, never H2's shape, and a word that is a particle as + well as a title opens a surname rather than ranking a person. + A run of title words opening the part before a family comma is + the title, joining the title field in input order with any title + after the comma. The run admits a title word only as vocabulary + knows it, stops at a word that is also a particle, or where + nothing but post-nominals stands behind it (H3), and always + leaves the family at least one word. The comma decides the + family whatever + the order declared, so the reading is the same under every + name_order. + "Dr. Smith, John" → title="Dr." + "Dr. Smith, John" → family="Smith" + "Prof. Dr. Brühl, Ada" → title="Prof. Dr." + "Dr. de la Vega, Juan" → family="de la Vega" + "Sir Smith, John" → given="John" + "Prof. Smith, Dr. John" → title="Prof. Dr." + "Rev. Sr. Smith, Mary" → title="Rev. Sr." + "Dr. Mc Donald, John" → family="Mc Donald" + "Prof. Smith, John, PhD" → family="Smith" + "Dr., John" → family="Dr." · boundary + "Dr. King, John" → family="King" · boundary + "MD PhD Jr., John" → family="MD" · boundary + "St Pierre, Ed" → family="St Pierre" · boundary + "Dr. St. Pierre, Ed" → family="St. Pierre" · boundary + Accepted: a title word that is also an ordinary surname (king, + judge, bishop, greve) opening a surname of two words is read as + the title, as it is in front of a name with no comma (H1). A + double-barrelled surname that begins with such a word loses it. + "King Smith, John" → title="King" + Accepted: what keeps a word in the family is the particle stop + and nothing else. 'Freiherr' and 'St' are particles as well as + titles, so they stay in either spelling, keeping 'St Pierre' + whole and 'Freiherr von Berg' as C1 reads it. The other German + ranks are titles only, so they peel, though since 1919 a rank + is part of the legal surname for all of them alike; that is the + vocabulary's distinction, not this rule's. A title in front of + a particle still peels. + "Graf Lambsdorff, Otto" → title="Graf" + "Freiherr von Berg, Ed" → family="Freiherr von Berg" + "Dr. Freiherr von Berg, Ed" → title="Dr." + history: decisions.md#H6 · interacts: C1, H1, H2, H3, M2, P1, P2, P4, S2, W3 · implemented: nameparser/_pipeline/_assign.py + ## Particles & surname prefixes (P) Background: particles ("de", "la", "van", "von", "bin") link forward to a surname and are written as part of it. Some are never anyone's given name; others ("Van", "Bin") are ordinary given names in some cultures, so the vocabulary distinguishes never-given particles from ambiguous ones, and only the never-given ones license special treatment. A separate small vocabulary binds forward to a GIVEN name instead: words like "abdul" that are not complete given names alone (P5). Which particles fall on which side of the never-given line is its own open question (#360). @@ -1062,7 +1115,8 @@ S2. Rationale: generational suffixes and credentials are recognized says "opening" and does not mean what P4 and the H Background mean by it. A family comma is the other boundary: the comma has already named the family, so a credential run may open the part - after it (C1), and the part before it is that family. + after it (C1), and the part before it is that family, less a + title run opening it (H6). A trailing word of the suffix vocabulary reads as a suffix — generational forms and credential acronyms alike, and an ambiguous acronym written with its periods, one after each @@ -1756,8 +1810,9 @@ C1. Rationale: a credential run after the comma means the name is in With a comma present, the name reads as trailing suffixes when the part after the first comma is entirely suffix words and more than one word precedes the comma; otherwise it reads as the - listing form, the part before the comma being the family name - unless the part after it fixes no family boundary (below). Only + listing form, the part before the comma being the family name, + less a title run opening it (H6), unless the part after it fixes + no family boundary (below). Only the part after the first comma decides. Wherever this rule counts the words before the comma, a particle run and the one name word it attaches to are one word, the reach @@ -2034,11 +2089,11 @@ C1. Rationale: a credential run after the comma means the name is in "Smith, John, Puig - i Soler" extra_suffix_delimiters-dash → suffix="Puig, i Soler" "Smith, John, PhD - and MD" extra_suffix_delimiters-dash → suffix="PhD, and MD" Accepted: a title in front of a particle surname, before the - credential class's word, is read into the family. The surname + credential class's word, reads the listing form. The surname counts once and the title is no name word, so the count reads the - listing form, and the listing form keeps a title before the comma - in the family, as it already did for any one-word surname ('Prof. - Cruz, Ed'). For a German rank that reading is the right one: + listing form, and the listing form peels a title before the comma + (H6) unless the word is a particle too, as 'Freiherr' is, which + stays in the family. For a German rank that reading is the right one: since 1919 a former noble title is part of the legal surname, written between the given name and the particle, so 'Freiherr von Berg' is the family name in 'Freiherr von Berg, Ed', as 2.0 @@ -2097,7 +2152,7 @@ C1. Rationale: a credential run after the comma means the name is in V` reads the suffix and `Smith, John PhD I.` continues the run, while adding a suffix comma after either turns that same letter into the middle initial. - history: decisions.md#C1 · interacts: H1, H2, P1, P2, P3, P5, P6, W3, S2, S3, M2 · implemented: nameparser/_pipeline/_comma.py, nameparser/_pipeline/_assign.py, nameparser/_pipeline/_group.py + history: decisions.md#C1 · interacts: H1, H2, H6, P1, P2, P3, P5, P6, W3, S2, S3, M2 · implemented: nameparser/_pipeline/_comma.py, nameparser/_pipeline/_assign.py, nameparser/_pipeline/_group.py C2. Rationale: text beyond the recognized comma parts should be taken in without silent guessing. @@ -2375,7 +2430,9 @@ W3. Rationale: a family name declared by a comma is the writer's it does not promise it. Under a family comma the pre-comma text is the family by declaration and never divides, and the post-comma side is given - text with no family to find; only the honorific split-off (W2) + text with no family to find. A title run opening the pre-comma + text is H6's title, not family text. Only the honorific + split-off (W2) crosses the comma, an honorific being no part of the name on either side — the crossing is stated here rather than in W2 because it is a claim about the comma, and the comma is the part @@ -2430,7 +2487,7 @@ W3. Rationale: a family name declared by a comma is the writer's "김민준씨." → suffix="씨." "田中. 太郎" → family="田中." tolerated: native CJK writing has neither a family-comma convention nor an edge full stop of any width on a name word, so the five comma lines above and the three period lines under them illustrate current behavior — changeable without notice — rather than promise it; the line carrying neither, beside them, is W1's claim, which is normative. All eight stay watched by the snapshot (tools/differential/snapshot.jsonl, over corpus_rules.jsonl and corpus_cjk.jsonl), and the `tolerated` rows of tests/v2/cases.py pin them at HEAD. - history: decisions.md#W3 · interacts: W1, W2, C1, H2 · implemented: nameparser/_pipeline/_script_segment.py + history: decisions.md#W3 · interacts: W1, W2, C1, H2, H6 · implemented: nameparser/_pipeline/_script_segment.py W4. Rationale: Chinese, Japanese and Korean all write the family name first in native script — the script settles the order diff --git a/docs/release_log.rst b/docs/release_log.rst index 98f2344e..a0c9f040 100644 --- a/docs/release_log.rst +++ b/docs/release_log.rst @@ -9,6 +9,8 @@ Release Log - **Add junior and senior in other languages as suffixes.** ``Antonio Pavlović mlađi`` gives last ``Pavlović``, suffix ``mlađi``, where 1.4.0 through 2.4.2 gave middle ``Pavlović``, last ``mlađi``. The words come from 45 languages and are read when written as a separate word after the name. :issue:`661`, :issue:`679` - **Remove mai from the default post-nominal acronyms, so a trailing Mai keeps the name.** ``Tran Thi Mai`` read in Vietnamese order (``FAMILY_FIRST_GIVEN_LAST``) gives given ``Mai``, middle ``Thi``, family ``Tran``, where 2.0.0 through 2.4.2 gave suffix ``Mai`` and no given name; ``Nguyen Mai`` gives family ``Mai``, as 1.4.0 did. The cost is that ``John Smith MAI`` gives last ``MAI`` instead of suffix; ``Smith, John, MAI`` and ``John Smith M.A.I.`` still read as credentials. A caller who needs it back adds it: ``Lexicon.default().add(suffix_acronyms={"mai"})``. See the ``suffix-acronym-collisions`` entry of ``docs/design/decisions.md`` (:issue:`687`) - **Add the Akan and Indonesian salutations owura and bapak as titles.** ``Bapak Dwi Putro`` gives title ``Bapak``, first ``Dwi``, last ``Putro``, where 1.4.0 through 2.4.2 gave first ``Bapak``, middle ``Dwi``. :issue:`662` + - **Fix a title written before a family comma reading as part of the family name.** ``Dr. Smith, John`` gives title ``Dr.``, last ``Smith``, where 1.4.0 through 2.4.2 gave last ``Dr. Smith``. Only listed titles are read there, so ``Xyz. Smith, John`` keeps its family, and a title that is also a surname particle, such as ``St`` or ``Freiherr``, stays in the surname. :issue:`701` + - **Add Gov as a title.** ``Gov Smith`` gives title ``Gov``, last ``Smith``, where 1.4.0 through 2.4.2 gave first ``Gov``, and ``Lt. Gov. Smith, John`` gives title ``Lt. Gov.`` with the change above. :issue:`701` * 2.4.2 - October 13, 2026 diff --git a/docs/usage.rst b/docs/usage.rst index 760cc59e..bea4c30f 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -858,7 +858,7 @@ rule applies there in exactly the same way: Where the inference stops ~~~~~~~~~~~~~~~~~~~~~~~~~ -The rule is bounded in four ways, so it doesn't swallow ordinary +The rule is bounded in five ways, so it doesn't swallow ordinary names: - **Single initials** are left alone (``J.``). @@ -869,6 +869,10 @@ names: even with a period, since those scripts write no abbreviation with one (``"田中. 太郎"`` has family ``田中.``). +- **Before a family comma** the inference does not run, since that + slot holds a surname too: ``Xyz. Smith, John`` keeps family + ``Xyz. Smith``. A listed title is still read there, so + ``Dr. Smith, John`` gives title ``Dr.``. .. doctest:: @@ -878,6 +882,8 @@ names: 'E.T.' >>> parse("Jane Insp. Morse").middle 'Insp.' + >>> parse("Xyz. Smith, John").family + 'Xyz. Smith' Because this is structural rather than vocabulary-driven, emptying ``titles`` does not switch it off; see :ref:`title-detection-off`. diff --git a/nameparser/_pipeline/_assign.py b/nameparser/_pipeline/_assign.py index 04b90f88..613a4fab 100644 --- a/nameparser/_pipeline/_assign.py +++ b/nameparser/_pipeline/_assign.py @@ -35,7 +35,9 @@ The v1 single-name+nickname rule lives here (decisions.md#N3): a nonempty nickname beside exactly one piece in total puts that piece in FAMILY. -FAMILY_COMMA: segment 0 wholly FAMILY (v1 parity). A part after the +FAMILY_COMMA: segment 0 FAMILY but for a leading run of listed titles +(rules.md#H6, #701; v1 kept them in the family) and the post-nominals +behind its first family piece (SUFFIX, 'Smith Jr., John'). A part after the comma that holds no name word, or that a credential opens (#603), is not read here: group's head binds its SUFFIX and TITLE roles before any join (`_comma.decide`, #613), making the comma a suffix comma @@ -857,7 +859,7 @@ def assign(state: ParseState) -> ParseState: AmbiguityKind.SUFFIX_OR_NAME, f"{tokens[i].text!r} after the comma is also an " f"ordinary name word; read as ", (i,), field_tail="")) - # Segment 1 is read before segment 0's wholly-family pass. It + # Segment 1 is read before segment 0's family pass. It # consumes piece tags and text only -- nothing segment 0's # read writes. (A title standing after the comma behind a whole # name, 'John V, Dr.', is bound at group's head since #613 and @@ -1412,6 +1414,41 @@ def reads_as_a_suffix(m: int, titled: frozenset[int]) -> bool: tokens)): _attach_particle_tail(pieces, tokens, n, k6, end6, ambiguities) + # rules.md#H6: "A run of title words opening the part before a + # family comma is the title" -- by vocabulary only, never H2's + # shape, leaving one piece for the family, and stopping at a + # word that is a particle too ('St Pierre', 'Freiherr von + # Berg'), or where everything behind it is post-nominal, which + # leaves no family word to address -- H3's concern, by a + # stricter test than H3's one-word give-back, so this is not + # `leading_titles` ('MD PhD Jr., John' keeps family 'MD', where + # 'MD PhD Jr. John' reads title 'MD'). A dual is a title wherever + # a name word follows it ('Rev. Sr. Smith, Mary'). + # `is_title_piece` is H5's vocabulary read, so the two slots that + # refuse the shape agree on what a title word is. + lead = 0 + floor = len(fam_pieces) + # the length test and the tag test first, both C-level: a part + # no title opens ('Smith, John', 'Smith Jones, John') pays no + # frame. The tags are the two arms `is_title_piece` answers yes + # from, so the predicate stays the one that answers + if (floor > 1 + and ("title" in fam_tags[0] + or "vocab:title" in tokens[fam_pieces[0][0]].tags) + and is_title_piece(fam_pieces[0], fam_tags[0], tokens)): + # where the trailing post-nominal run starts: walked once, + # and only for a part a title opens + while floor > 1 and is_suffix_piece(fam_pieces[floor - 1], + fam_tags[floor - 1], + tokens): + floor -= 1 + # the first piece is a title, asked above + while (lead + 1 < floor + and (lead == 0 or is_title_piece( + fam_pieces[lead], fam_tags[lead], tokens)) + and "particle" not in tokens[fam_pieces[lead][0]].tags): + _set_roles(tokens, fam_pieces[lead], Role.TITLE) + lead += 1 # rules.md#P2: a particle "joins the words after it into one # name part" -- so a particle that is suffix vocabulary too # (vd, mc) with a name piece behind it in this part heads @@ -1419,12 +1456,19 @@ def reads_as_a_suffix(m: int, titled: frozenset[int]) -> bool: # (#573: 'SMITH VD MA, JOHN', where the uniform case left the # chain stopped before VD; 'SMITH VD JR, JOHN', a suffix word # behind it, keeps suffix 'VD JR'). Read here because only - # this wholly-family pass needs it: a comma followed by no name + # this family pass needs it: a comma followed by no name # word behind a whole name is group's suffix comma since #613, # and the NO_COMMA read takes segment 0, trailing run and all - # ('Berg de MA, Prof.'). - for k, piece in enumerate(fam_pieces): - if (k > 0 and is_suffix_piece(piece, fam_tags[k], tokens) + # ('Berg de MA, Prof.'). The first piece the title run leaves + # is the family's first and is family whatever it is, as piece + # 0 is with no title ('Dr. PhD Smith, John' as 'PhD Smith, John'). + # A piece at or past the floor is already known to be a suffix + # with nothing but suffixes behind it, so it is not asked again. + for k in range(lead, len(fam_pieces)): + piece = fam_pieces[k] + if k >= floor: + _set_roles(tokens, piece, Role.SUFFIX) + elif (k > lead and is_suffix_piece(piece, fam_tags[k], tokens) and not (k + 1 < len(fam_pieces) and "particle" in tokens[piece[0]].tags and not is_suffix_piece( diff --git a/nameparser/_pipeline/_pieces.py b/nameparser/_pipeline/_pieces.py index 1be5733e..8fd953f4 100644 --- a/nameparser/_pipeline/_pieces.py +++ b/nameparser/_pipeline/_pieces.py @@ -802,7 +802,7 @@ def segment_suffix_reading(pieces: Sequence[Sequence[int]], run ends where it always did. Reading no policy here silently overrode the one knob a caller sets to prevent exactly this. - The FAMILY_COMMA rule "segment 0 is wholly the family name" rests + The FAMILY_COMMA rule that segment 0 is the family name rests on the writer having said where the family name ends. A comma followed by no name word said no such thing -- 'John Smith, Dr.' is 'Dr. John Smith' with the honorific moved -- so the pre-comma name diff --git a/nameparser/_pipeline/_vocab.py b/nameparser/_pipeline/_vocab.py index b20c1551..3a477b82 100644 --- a/nameparser/_pipeline/_vocab.py +++ b/nameparser/_pipeline/_vocab.py @@ -163,7 +163,8 @@ def in_initialless_script(text: str) -> bool: # ask the SAME question _pieces.is_leading_title asks -- measured # divergence before the move: 'Dr. Smith, Ed' (LISTED title 'Dr.') and # 'Xyz. Smith, Ed' (UNLISTED, H2-shaped) both read family 'Dr. -# Smith'/'Xyz. Smith', given 'Ed' at the peel, because is_leading_title +# Smith'/'Xyz. Smith', given 'Ed' at the peel (since #701 the listed +# 'Dr.' then peels into the title, rules.md#H6), because is_leading_title # reads H2's shape and a bare `folded in lexicon.titles` lookup does # not -- but name_word_count's OWN count disagreed: 'Xyz.' counted as # a name word where 'Dr.' did not, so 'Xyz. Smith, Ed' alone flipped diff --git a/nameparser/config/titles.py b/nameparser/config/titles.py index b137cd15..13e0be7b 100644 --- a/nameparser/config/titles.py +++ b/nameparser/config/titles.py @@ -404,6 +404,7 @@ 'giani', 'goodman', 'goodwife', + 'gov', 'governor', 'graf', 'gräfin', diff --git a/tests/v2/cases.py b/tests/v2/cases.py index f2312084..c4461ca2 100644 --- a/tests/v2/cases.py +++ b/tests/v2/cases.py @@ -3390,13 +3390,14 @@ def _check_cjk_shape_purity(self) -> None: "read suffix 'ANDREW PhD'"), Case("a_title_supplies_no_contrast_for_the_caps_shape", "Mr LLOYD WEBBER, ANDREW PhD", - {"given": "ANDREW", "family": "Mr LLOYD WEBBER", "suffix": "PhD"}, + {"title": "Mr", "given": "ANDREW", "family": "LLOYD WEBBER", + "suffix": "PhD"}, + classification="fix(#701)", notes="#564 boundary: titles and particles are written in " "lowercase in a record that capitalizes its surname, so " "neither counts as the name's contrast and the given name " - "stays. The title in the family is the listing form's " - "long-standing reading of a title before the comma " - "('Prof. Cruz, Ed'), master's too"), + "stays. Until #701 the title read into the family, the " + "listing form keeping the text before the comma whole"), Case("a_generation_supplies_no_contrast_for_the_caps_shape", "LLOYD WEBBER Jr., ANDREW", {"given": "ANDREW", "family": "LLOYD WEBBER", "suffix": "Jr."}, @@ -3748,13 +3749,110 @@ def _check_cjk_shape_purity(self) -> None: "credential produced a name reading"), Case("the_comma_count_counts_names_not_words_behind_a_title", "Mr Smith, Ma", - {"given": "Ma", "family": "Mr Smith"}, + {"title": "Mr", "given": "Ma", "family": "Smith"}, ambiguities=("suffix-or-name",), + classification="fix(#701)", notes="MEASURED. name_word_count's TITLE arm: 'Mr' is title " "vocabulary, so the part before the comma holds ONE " "name word and the count declines the flip. Without " "that arm two tokens would read as two names and hand " "the family to `given`"), + # rules.md#H6 (#701): a title opening the part before a family + # comma. The rows sweep the spellings and comma neighbours the rule + # reads; its own examples carry the plain shapes. + Case("a_title_before_a_family_comma_peels_beside_a_nickname", + "Dr. (Bob) Smith, John", + {"title": "Dr.", "given": "John", "family": "Smith", + "nickname": "Bob"}, + classification="fix(#701)", + notes="the nickname is extracted before the run is read, so " + "it does not stand between the title and the family"), + Case("a_title_before_a_family_comma_peels_ahead_of_a_maiden_clause", + "Dr. Smith née Jones, Mary", + {"title": "Dr.", "given": "Mary", "family": "Smith", + "maiden": "Jones"}, + classification="fix(#701)"), + Case("a_title_before_a_family_comma_peels_ahead_of_a_shape_numeral", + "Dr. Smith VI, John", + {"title": "Dr.", "given": "John", "family": "Smith VI"}, + classification="fix(#701)", + notes="VI is read by shape alone, and the part before a " + "family comma keeps it as it does without the title"), + Case("a_title_before_a_family_comma_stops_at_a_period_marked_dual", + "Dr. Freiherr. von Berg, Ed", + {"title": "Dr.", "given": "Ed", "family": "Freiherr. von Berg"}, + ambiguities=("suffix-or-name",), + classification="fix(#701)", + notes="'Freiherr' is a particle as well as a title in either " + "spelling, so the run stops at it; the bare spelling is " + "rules.md#H6's example"), + Case("a_period_marked_dual_opening_a_family_comma_stays_family", + "Freiherr. von Berg, Ed", + {"given": "Ed", "family": "Freiherr. von Berg"}, + ambiguities=("suffix-or-name",)), + Case("a_dual_second_in_a_title_run_before_a_family_comma_peels", + "Hon. Ms Smith, Jane", + {"title": "Hon. Ms", "given": "Jane", "family": "Smith"}, + classification="fix(#701)", + notes="'Ms' is suffix vocabulary too, and a name word follows " + "it, so it is a title as in 'Hon. Ms Jane Smith'. The " + "second #701 draft stopped in front of any suffix word " + "and read family 'Hon. Smith', suffix 'Ms' (rules.md#H6's " + "'Rev. Sr.' example; the design-docs review)"), + Case("a_title_before_a_family_comma_stops_at_a_bare_saint", + "Dr. St Pierre, Ed", + {"title": "Dr.", "given": "Ed", "family": "St Pierre"}, + ambiguities=("suffix-or-name",), + classification="fix(#701)"), + Case("a_listed_title_before_a_family_comma_peels_in_cyrillic", + "г-н Вернер, Иван Асен", + {"title": "г-н", "given": "Иван", "middle": "Асен", + "family": "Вернер"}, + classification="fix(#701)", + notes="CLDR's bg index rendering: a listed title with no " + "period, which H2's shape could never have read"), + Case("a_title_before_a_family_comma_reads_the_same_family_first", + "Dr. de Mesnil, Jean", + {"title": "Dr.", "given": "Jean", "family": "de Mesnil"}, + policy=Policy(name_order=FAMILY_FIRST), + classification="fix(#701)", + notes="the comma names the family, so no declared order moves " + "the title or the particle surname behind it"), + Case("a_joined_title_unit_before_a_family_comma_peels_whole", + "Secretary of State Smith, John", + {"title": "Secretary of State", "given": "John", + "family": "Smith"}, + classification="fix(#701)", + notes="a connective join makes one title piece, which the run " + "reads by its piece tag rather than its first word"), + Case("a_joined_salutation_before_a_family_comma_peels_whole", + "Mr. and Mrs. Smith, John", + {"title": "Mr. and Mrs.", "given": "John", "family": "Smith"}, + classification="fix(#701)"), + Case("a_two_word_abbreviated_title_before_a_family_comma_peels_whole", + "Lt. Gov. Smith, John", + {"title": "Lt. Gov.", "given": "John", "family": "Smith"}, + classification="fix(#701)", + notes="the run is vocabulary-only, so before 'gov' was listed " + "it stopped after 'Lt.' and read family 'Gov. Smith', " + "where the comma-less name reads title 'Lt. Gov.' by " + "H2's shape (the PR review of #701)"), + Case("a_title_before_a_family_comma_reads_the_same_given_last", + "Prof. Dr. Brühl, Ada", + {"title": "Prof. Dr.", "given": "Ada", "family": "Brühl"}, + policy=Policy(name_order=FAMILY_FIRST_GIVEN_LAST), + classification="fix(#701)", + notes="the second family-first order, beside the FAMILY_FIRST " + "row: test_cases' three-order sweep checks R2's family " + "partition only, so it would not see the title move"), + Case("bare_gov_opening_a_name_is_a_title", + "Gov Smith", + {"title": "Gov", "family": "Smith"}, + classification="fix(#701)", + notes="'gov' joined TITLES in the #701 review, as the listed " + "'governor' abbreviated; 1.4.0 through 2.4.2 read given " + "'Gov'. 236 US Census surname bearers, so a surname " + "written first loses it (decisions.md#H6)"), Case("the_comma_count_counts_names_not_words_behind_a_suffix", "Smith Jr, Ma", {"given": "Ma", "family": "Smith", "suffix": "Jr"}, @@ -8887,7 +8985,8 @@ def _check_cjk_shape_purity(self) -> None: # is_leading_title's H2 shape test -- so an UNLISTED period-marked # opener counted as a NAME word where a LISTED one did not, and # this pair split on that alone: 'Dr. Smith, Ed' (LISTED 'Dr.') - # read family 'Dr. Smith' unflipped, but 'Xyz. Smith, Ed' + # read family 'Dr. Smith' unflipped (the count is unchanged; since + # #701 the listed 'Dr.' then peels, rules.md#H6), but 'Xyz. Smith, Ed' # (UNLISTED, H2-shaped) flipped the comma structure and read title # 'Xyz.', family 'Smith', suffix 'Ed' -- a different STRUCTURE for # the same shape, from a title-vocabulary difference the count had @@ -9341,7 +9440,10 @@ def _check_cjk_shape_purity(self) -> None: notes="segment 0 is the family segment even when it is wholly " "credential-shaped, so 'MD' is the FAMILY and not the " "head of a credential run, and that is what this row " - "still guards. The SEPARATOR is no longer the row's " + "still guards. Since #701 it guards rules.md#H6's stop " + "too: 'MD' is title vocabulary, and a title before the " + "comma peels only in front of a family word, which 'PhD' " + "is not. The SEPARATOR is no longer the row's " "subject. Until #436 it was: the join was asked of " "segment 1 alone, and dropping that conjunct left the " "whole suite green while this shape's suffix silently " diff --git a/tests/v2/test_cases.py b/tests/v2/test_cases.py index a17b02b9..b8fa1ee1 100644 --- a/tests/v2/test_cases.py +++ b/tests/v2/test_cases.py @@ -180,10 +180,12 @@ def test_the_field_sweep_sees_the_claims_it_checks() -> None: # 1156 -> 1159 on 2026-10-11: the JOHN PROF. MA row (one # suffix-or-name claim under each of the three orders); 1159 -> # 1162 on 2026-10-14: the Агриппина Младшая row (#661, one - # given-or-family claim under each order). - assert claims == 1162, ( - f"the field sweep checks {claims} claims, recorded as 1162 on " - f"2026-10-14") + # given-or-family claim under each order); 1162 -> 1171 on + # 2026-10-17: three #701 rows reporting suffix-or-name, under each + # order. + assert claims == 1171, ( + f"the field sweep checks {claims} claims, recorded as 1171 on " + f"2026-10-17") #: Case.__post_init__'s shape checks, each probed for the message that diff --git a/tests/v2/test_facade_cases.py b/tests/v2/test_facade_cases.py index a9f12a79..f4294e7c 100644 --- a/tests/v2/test_facade_cases.py +++ b/tests/v2/test_facade_cases.py @@ -73,6 +73,10 @@ #: to the unsubtracted default pushes every parenthesis-maiden row #: into this set and turns nothing red. _CORE_ONLY_IDS = frozenset({ + # #701: H6's peel under a declared family-first order, which v1 + # cannot express + "a_title_before_a_family_comma_reads_the_same_family_first", + "a_title_before_a_family_comma_reads_the_same_given_last", # #296's bundle: the positional read of the pre-comma name under a # declared family-first order -- v1 has no name order to declare "family_comma_no_name_word_family_first", diff --git a/tools/differential/cldr_agreement.json b/tools/differential/cldr_agreement.json index b88680d7..a18c7f1f 100644 --- a/tools/differential/cldr_agreement.json +++ b/tools/differential/cldr_agreement.json @@ -2,11 +2,11 @@ "af/foreignFull/givenFirst": { "family": { "expected": "van den Berg", - "got": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg" + "got": "Cornelia Margarita Sofia Aletta van den Berg" }, "family_base": { "expected": "Berg", - "got": "Prof. dr. Cornelia Margarita Sofia Aletta Berg" + "got": "Cornelia Margarita Sofia Aletta Berg" }, "given_names": { "expected": "Cornelia Margarita Sofia Aletta", @@ -16,11 +16,7 @@ "expected": "jnr. MBChB PhD", "got": "jnr., PhD" }, - "text": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg jnr., MBChB PhD", - "title": { - "expected": "Prof. dr.", - "got": "" - } + "text": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg jnr., MBChB PhD" }, "af/foreignFull/surnameFirst": { "family": { @@ -366,11 +362,11 @@ "ar/foreignFull/givenFirst": { "family": { "expected": "فون برول", - "got": "الدكتور عايدة كورنيليا سيزار مارتن فون برول" + "got": "عايدة كورنيليا سيزار مارتن فون برول" }, "family_base": { "expected": "برول", - "got": "الدكتور عايدة كورنيليا سيزار مارتن فون برول" + "got": "عايدة كورنيليا سيزار مارتن فون برول" }, "family_particles": { "expected": "فون", @@ -384,11 +380,7 @@ "expected": "الإبن طبيب وجراح", "got": "الإبن" }, - "text": "الدكتور عايدة كورنيليا سيزار مارتن فون برول الإبن، طبيب وجراح", - "title": { - "expected": "الدكتور", - "got": "" - } + "text": "الدكتور عايدة كورنيليا سيزار مارتن فون برول الإبن، طبيب وجراح" }, "ar/foreignFull/sorting": { "family_base": { @@ -1036,11 +1028,11 @@ "bg/foreignFull/givenFirst": { "family": { "expected": "Брюл", - "got": "проф. д-р Ада Корнелия Цезар Мартин Брюл" + "got": "Ада Корнелия Цезар Мартин Брюл" }, "family_base": { "expected": "Брюл", - "got": "проф. д-р Ада Корнелия Цезар Мартин Брюл" + "got": "Ада Корнелия Цезар Мартин Брюл" }, "given_names": { "expected": "Ада Корнелия Цезар Мартин", @@ -1050,11 +1042,7 @@ "expected": "доктор", "got": "" }, - "text": "проф. д-р Ада Корнелия Цезар Мартин Брюл, доктор", - "title": { - "expected": "проф. д-р", - "got": "" - } + "text": "проф. д-р Ада Корнелия Цезар Мартин Брюл, доктор" }, "bg/foreignFull/sorting": { "family": { @@ -1071,21 +1059,6 @@ }, "text": "Брюл, Ада Корнелия Цезар Мартин фон" }, - "bg/foreignFull/surnameFirst": { - "family": { - "expected": "Брюл", - "got": "проф. д-р Брюл" - }, - "family_base": { - "expected": "Брюл", - "got": "проф. д-р Брюл" - }, - "text": "проф. д-р Брюл, Ада Корнелия Цезар Мартин, доктор", - "title": { - "expected": "проф. д-р", - "got": "" - } - }, "bg/foreignG/sorting": { "family": { "expected": "", @@ -1135,14 +1108,6 @@ "text": "Вернер, Иван Асен фон" }, "bg/nativeFull/surnameFirst": { - "family": { - "expected": "Вернер", - "got": "г-н Вернер" - }, - "family_base": { - "expected": "Вернер", - "got": "г-н Вернер" - }, "suffix": { "expected": "проф. д-р", "got": "" @@ -1150,7 +1115,7 @@ "text": "г-н Вернер, Иван Асен, проф. д-р", "title": { "expected": "г-н", - "got": "проф. д-р" + "got": "г-н проф. д-р" } }, "bg/nativeG/sorting": { @@ -1533,36 +1498,6 @@ "got": "prof. dr. dipl. stom." } }, - "bs/foreignFull/sorting": { - "family": { - "expected": "von Selimović Hodžić", - "got": "prof. dr. von Selimović Hodžić" - }, - "family_base": { - "expected": "Selimović Hodžić", - "got": "prof. dr. Selimović Hodžić" - }, - "text": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", - "title": { - "expected": "prof. dr.", - "got": "" - } - }, - "bs/foreignFull/surnameFirst": { - "family": { - "expected": "von Selimović Hodžić", - "got": "prof. dr. von Selimović Hodžić" - }, - "family_base": { - "expected": "Selimović Hodžić", - "got": "prof. dr. Selimović Hodžić" - }, - "text": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", - "title": { - "expected": "prof. dr.", - "got": "" - } - }, "bs/foreignG/sorting": { "family": { "expected": "", @@ -2300,11 +2235,11 @@ "da/nativeFull/givenFirst": { "family": { "expected": "Møller", - "got": "hr. Hans Henrik Sven Åge Møller" + "got": "Hans Henrik Sven Åge Møller" }, "family_base": { "expected": "Møller", - "got": "hr. Hans Henrik Sven Åge Møller" + "got": "Hans Henrik Sven Åge Møller" }, "given_names": { "expected": "Hans Henrik Sven Åge", @@ -2314,11 +2249,7 @@ "expected": "MF", "got": "" }, - "text": "hr. Hans Henrik Sven Åge Møller, MF", - "title": { - "expected": "hr.", - "got": "" - } + "text": "hr. Hans Henrik Sven Åge Møller, MF" }, "da/nativeG/sorting": { "family": { @@ -4157,11 +4088,11 @@ "hi/nativeFull/surnameFirst": { "family": { "expected": "शर्मा", - "got": "श्री शर्मा ललित कुमार" + "got": "शर्मा ललित कुमार" }, "family_base": { "expected": "शर्मा", - "got": "श्री शर्मा ललित कुमार" + "got": "शर्मा ललित कुमार" }, "given_names": { "expected": "ललित कुमार", @@ -4171,11 +4102,7 @@ "expected": "एम॰डी॰", "got": "" }, - "text": "श्री शर्मा ललित कुमार, एम॰डी॰", - "title": { - "expected": "श्री", - "got": "" - } + "text": "श्री शर्मा ललित कुमार, एम॰डी॰" }, "hi/nativeG/sorting": { "family": { @@ -4291,11 +4218,11 @@ "hr/foreignFull/givenFirst": { "family": { "expected": "von Brühl", - "got": "prof. dr. Ada Cornelia César Martín von Brühl" + "got": "Ada Cornelia César Martín von Brühl" }, "family_base": { "expected": "Brühl", - "got": "prof. dr. Ada Cornelia César Martín Brühl" + "got": "Ada Cornelia César Martín Brühl" }, "given_names": { "expected": "Ada Cornelia César Martín", @@ -4308,7 +4235,7 @@ "text": "prof. dr. Ada Cornelia César Martín von Brühl Jr, univ. bacc", "title": { "expected": "prof. dr.", - "got": "univ." + "got": "prof. dr. univ." } }, "hr/foreignG/sorting": { @@ -4608,21 +4535,6 @@ }, "text": "Արթուր" }, - "id/foreignFull/surnameFirst": { - "family": { - "expected": "von Bruhl", - "got": "Prof. Dr. von Bruhl" - }, - "family_base": { - "expected": "Bruhl", - "got": "Prof. Dr. Bruhl" - }, - "text": "Prof. Dr. von Bruhl, Ada Cornelia Cesar Martín Jr, M.D., Ph.D.", - "title": { - "expected": "Prof. Dr.", - "got": "" - } - }, "id/foreignG/sorting": { "family": { "expected": "", @@ -4678,11 +4590,7 @@ "id/nativeFull/surnameFirst": { "family": { "expected": "Adinata", - "got": "bin Bapak Adinata" - }, - "family_base": { - "expected": "Adinata", - "got": "Bapak Adinata" + "got": "bin Adinata" }, "family_particles": { "expected": "", @@ -4692,11 +4600,7 @@ "expected": "Dwi Putro bin", "got": "Dwi Putro" }, - "text": "Bapak Adinata, Dwi Putro bin MP", - "title": { - "expected": "Bapak", - "got": "" - } + "text": "Bapak Adinata, Dwi Putro bin MP" }, "id/nativeG/sorting": { "family": { @@ -6258,11 +6162,11 @@ "kok/foreignFull/givenFirst": { "family": { "expected": "वॉन ब्रूह्ल गॉन्जालेज डोमिंगो", - "got": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर" + "got": "आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर" }, "family_base": { "expected": "ब्रूह्ल गॉन्जालेज डोमिंगो", - "got": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर" + "got": "आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर" }, "family_particles": { "expected": "वॉन", @@ -6276,11 +6180,7 @@ "expected": "जेआर बी.ए. एल.एल.बी", "got": "" }, - "text": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर, बी.ए. एल.एल.बी", - "title": { - "expected": "प्रो. डॉ.", - "got": "" - } + "text": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर, बी.ए. एल.एल.बी" }, "kok/foreignFull/sorting": { "family": { @@ -6349,11 +6249,11 @@ "kok/nativeFull/givenFirst": { "family": { "expected": "दे सोजा ए मेनेजेस", - "got": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा." + "got": "फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा." }, "family_base": { "expected": "सोजा ए मेनेजेस", - "got": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा." + "got": "फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा." }, "family_particles": { "expected": "दे", @@ -6367,11 +6267,7 @@ "expected": "धा. एमपी", "got": "" }, - "text": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा., एमपी", - "title": { - "expected": "श्री", - "got": "" - } + "text": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा., एमपी" }, "kok/nativeFull/sorting": { "family": { @@ -6890,21 +6786,6 @@ "got": "med." } }, - "lt/foreignFull/surnameFirst": { - "family": { - "expected": "von Vilkas Jankauskas-Baranauskas", - "got": "prof. dr. von Vilkas Jankauskas-Baranauskas" - }, - "family_base": { - "expected": "Vilkas Jankauskas-Baranauskas", - "got": "prof. dr. Vilkas Jankauskas-Baranauskas" - }, - "text": "prof. dr. von Vilkas Jankauskas-Baranauskas, Ada Kornelija Eva Sofija", - "title": { - "expected": "prof. dr.", - "got": "" - } - }, "lt/foreignG/sorting": { "family": { "expected": "", @@ -7334,11 +7215,11 @@ "mn/foreignFull/givenFirst": { "family": { "expected": "вон Брюхл", - "got": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр" + "got": "Др. Ада Корнелиа Эва Софиа вон Брюхл Жр" }, "family_base": { "expected": "Брюхл", - "got": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр" + "got": "Др. Ада Корнелиа Эва Софиа вон Брюхл Жр" }, "family_particles": { "expected": "вон", @@ -7355,7 +7236,7 @@ "text": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр, Анагаах ухааны доктор", "title": { "expected": "Проф. Др.", - "got": "" + "got": "Проф." } }, "mn/foreignFull/sorting": { @@ -7469,11 +7350,11 @@ "mr/foreignFull/givenFirst": { "family": { "expected": "व्हॉन ब्र्यूल", - "got": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु." + "got": "अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु." }, "family_base": { "expected": "ब्र्यूल", - "got": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु." + "got": "अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु." }, "family_particles": { "expected": "व्हॉन", @@ -7490,7 +7371,7 @@ "text": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु., एम. डी. डी. डी. एस.", "title": { "expected": "प्रोफे.डॉ.", - "got": "एम." + "got": "प्रोफे.डॉ. एम." } }, "mr/foreignFull/sorting": { @@ -7560,11 +7441,11 @@ "mr/nativeFull/givenFirst": { "family": { "expected": "देशपांडे", - "got": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क." + "got": "धिरज देशपांडे विजय देशपांडे देशपांडे क." }, "family_base": { "expected": "देशपांडे", - "got": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क." + "got": "धिरज देशपांडे विजय देशपांडे देशपांडे क." }, "given_names": { "expected": "धिरज देशपांडे विजय देशपांडे", @@ -7577,7 +7458,7 @@ "text": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क., एम. पी.", "title": { "expected": "श्री.", - "got": "एम." + "got": "श्री. एम." } }, "mr/nativeFull/surnameFirst": { @@ -10579,30 +10460,7 @@ "got": "prof. dr. dr. shk. mjek." } }, - "sq/foreignFull/sorting": { - "family": { - "expected": "Popa van den", - "got": "van den prof. dr. Popa" - }, - "family_base": { - "expected": "Popa", - "got": "prof. dr. Popa" - }, - "text": "prof. dr. Popa, Gentiana van den", - "title": { - "expected": "prof. dr.", - "got": "" - } - }, "sq/foreignFull/surnameFirst": { - "family": { - "expected": "van den Popa", - "got": "prof. dr. van den Popa" - }, - "family_base": { - "expected": "Popa", - "got": "prof. dr. Popa" - }, "given_names": { "expected": "Gentiana", "got": "Gentiana M." @@ -10614,7 +10472,7 @@ "text": "prof. dr. van den Popa, Gentiana M., dr. shk. mjek.", "title": { "expected": "prof. dr.", - "got": "dr." + "got": "prof. dr. dr." } }, "sq/foreignG/sorting": { diff --git a/tools/differential/corpus_rules.jsonl b/tools/differential/corpus_rules.jsonl index a6150dd2..ac778986 100644 --- a/tools/differential/corpus_rules.jsonl +++ b/tools/differential/corpus_rules.jsonl @@ -69,21 +69,28 @@ "Dr Jr" "Dr King Jr" "Dr." +"Dr. Freiherr von Berg, Ed" "Dr. John Smith Prof." "Dr. John van der Berg" +"Dr. Jr., John" "Dr. Juan Q. Xavier de la Vega III" "Dr. King" "Dr. King MD" +"Dr. King, John" +"Dr. Mc Donald, John" "Dr. Sir John" "Dr. Smith" "Dr. Smith Sir." "Dr. Smith née Jones" "Dr. Smith, John" +"Dr. St. Pierre, Ed" "Dr. abdul salam" +"Dr. de la Vega, Juan" "Dr. inž. Janez Novak" "Dr. juan garcia" "Dr. med. univ. Margit Popp, MSc" "Dr. nee Smith PhD Prof." +"Dr., John" "Duke of Edinburgh" "Eric H. Holder Jr. Attorney General" "Eric H. Holder, Jr., Attorney General" @@ -105,7 +112,9 @@ "García Márquez, MJ JK" "García Márquez, MJ PhD" "García Márquez, Ms G.J." +"Graf Lambsdorff, Otto" "Greve Anna" +"Greve Smith, Anna" "Greve, Anna" "Hans „Erster“ und “Zweiter” Müller" "Hassan Mohamad Ali" @@ -299,8 +308,10 @@ "Juan Ó Pérez" "Juan Ó. Pérez" "Kim김민준씨, MA" +"King Smith, John" "Lord Chancellor" "MD DDS" +"MD PhD Jr., John" "MSc Dr. med. univ." "Mai Le née Nguyen" "Mari' Aube'" @@ -343,9 +354,13 @@ "Ph. D., John" "Pieter Bruegel stariji Jones" "Prince of Wales Jr" +"Prof. Dr. Brühl, Ada" +"Prof. Smith, Dr. John" +"Prof. Smith, John, PhD" "Pérez, Juan Ó." "QC MP" "Rev. John Smith" +"Rev. Sr. Smith, Mary" "Rinpoche" "Royce, Ed" "SEÁN Ó MURCHÚ" @@ -367,6 +382,7 @@ "Sir John" "Sir John Prof." "Sir Ph. D. Van Johnson" +"Sir Smith, John" "Sir abdul van der Berg" "Sir de Mesnil" "Smith" @@ -423,6 +439,7 @@ "Smith, XYZ" "Smith, de Mesnil Jean" "Smith. John" +"St Pierre, Ed" "Stariji Bruegel" "Steven Hardman, MD, DO, DDS" "Steven Hardman, RN - CRNA" diff --git a/tools/differential/snapshot.jsonl b/tools/differential/snapshot.jsonl index 3da32f91..ab450e02 100644 --- a/tools/differential/snapshot.jsonl +++ b/tools/differential/snapshot.jsonl @@ -282,7 +282,7 @@ {"name": "Balóch Karima", "order": "FAMILY_FIRST", "given": "Karima", "family": "Balóch", "initials": "K. B."} {"name": "Balóch Karima Mehráb", "order": "FAMILY_FIRST", "given": "Karima", "middle": "Mehráb", "family": "Balóch", "initials": "K. M. B."} {"name": "Balóch Wj. Monir Mómen Monir Mómen", "order": "FAMILY_FIRST", "given": "Wj.", "middle": "Monir Mómen Monir Mómen", "family": "Balóch", "initials": "W. M. M. M. M. B."} -{"name": "Bapak Adinata, Dwi Putro bin MP", "order": "FAMILY_FIRST", "given": "Dwi", "middle": "Putro", "family": "bin Bapak Adinata", "suffix": "MP", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "D. P. B. A."} +{"name": "Bapak Adinata, Dwi Putro bin MP", "order": "FAMILY_FIRST", "title": "Bapak", "given": "Dwi", "middle": "Putro", "family": "bin Adinata", "suffix": "MP", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "D. P. A."} {"name": "Bapak Dwi Putro bin Adinata MP", "title": "Bapak", "given": "Dwi", "middle": "Putro", "family": "bin Adinata", "suffix": "MP", "initials": "D. P. A."} {"name": "Barbara Brukalska", "given": "Barbara", "family": "Brukalska", "initials": "B. B."} {"name": "Barbara Scharf", "given": "Barbara", "family": "Scharf", "initials": "B. S."} @@ -687,6 +687,7 @@ {"name": "Dr. Abdul Salam Hassan, MD", "title": "Dr.", "given": "Abdul Salam", "family": "Hassan", "suffix": "MD", "initials": "A. S. H."} {"name": "Dr. Ardelean Dl Daniel Ionescu Dragoș Ioan Jr.", "order": "FAMILY_FIRST", "title": "Dr.", "given": "Dl", "middle": "Daniel Ionescu Dragoș Ioan", "family": "Ardelean", "suffix": "Jr.", "initials": "D. D. I. D. I. A."} {"name": "Dr. Do Van Johnson, MD", "title": "Dr.", "given": "Do", "family": "Van Johnson", "suffix": "MD", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "D. J."} +{"name": "Dr. Freiherr von Berg, Ed", "title": "Dr.", "given": "Ed", "family": "Freiherr von Berg", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "E. B."} {"name": "Dr. Jason", "title": "Dr.", "family": "Jason", "initials": "J."} {"name": "Dr. Jason Ross Jay", "title": "Dr.", "given": "Jason", "middle": "Ross", "family": "Jay", "initials": "J. R. J."} {"name": "Dr. John A. Doe", "title": "Dr.", "given": "John", "middle": "A.", "family": "Doe", "initials": "J. A. D."} @@ -703,6 +704,7 @@ {"name": "Dr. John Smith", "title": "Dr.", "given": "John", "family": "Smith", "initials": "J. S."} {"name": "Dr. John Smith Prof.", "title": "Dr. Prof.", "given": "John", "family": "Smith", "initials": "J. S."} {"name": "Dr. John van der Berg", "title": "Dr.", "given": "John", "family": "van der Berg", "initials": "J. B."} +{"name": "Dr. Jr., John", "given": "John", "family": "Dr.", "suffix": "Jr.", "initials": "J. D."} {"name": "Dr. Juan Q. Velasquez y Garcia", "title": "Dr.", "given": "Juan", "middle": "Q.", "family": "Velasquez y Garcia", "initials": "J. Q. V. G."} {"name": "Dr. Juan Q. Velasquez y Garcia III", "title": "Dr.", "given": "Juan", "middle": "Q.", "family": "Velasquez y Garcia", "suffix": "III", "initials": "J. Q. V. G."} {"name": "Dr. Juan Q. Velasquez y Garcia, Jr.", "title": "Dr.", "given": "Juan", "middle": "Q.", "family": "Velasquez y Garcia", "suffix": "Jr.", "initials": "J. Q. V. G."} @@ -725,18 +727,22 @@ {"name": "Dr. Juan de la Vega, Jr.", "title": "Dr.", "given": "Juan", "family": "de la Vega", "suffix": "Jr.", "initials": "J. V."} {"name": "Dr. King", "title": "Dr.", "family": "King", "ambiguities": ["TITLE_OR_NAME"], "initials": "K."} {"name": "Dr. King MD", "title": "Dr.", "family": "King", "suffix": "MD", "ambiguities": ["TITLE_OR_NAME"], "initials": "K."} +{"name": "Dr. King, John", "title": "Dr.", "given": "John", "family": "King", "initials": "J. K."} {"name": "Dr. Martin Luther King Jr.", "title": "Dr.", "given": "Martin", "middle": "Luther", "family": "King", "suffix": "Jr.", "initials": "M. L. K."} {"name": "Dr. Mazen Elrouqi", "title": "Dr.", "given": "Mazen", "family": "Elrouqi", "initials": "M. E."} +{"name": "Dr. Mc Donald, John", "title": "Dr.", "given": "John", "family": "Mc Donald", "initials": "J. D."} {"name": "Dr. Paul Vinzent von Fischer jr. MdB", "title": "Dr.", "given": "Paul", "middle": "Vinzent", "family": "von Fischer", "suffix": "jr. MdB", "initials": "P. V. F."} {"name": "Dr. Sir John", "title": "Dr. Sir", "given": "John", "initials": "J."} {"name": "Dr. Smith", "title": "Dr.", "family": "Smith", "initials": "S."} {"name": "Dr. Smith Sir.", "title": "Dr. Sir.", "family": "Smith", "initials": "S."} {"name": "Dr. Smith née Jones", "title": "Dr.", "family": "Smith", "maiden": "Jones", "initials": "S."} -{"name": "Dr. Smith, John", "given": "John", "family": "Dr. Smith", "initials": "J. D. S."} +{"name": "Dr. Smith, John", "title": "Dr.", "given": "John", "family": "Smith", "initials": "J. S."} +{"name": "Dr. St. Pierre, Ed", "title": "Dr.", "given": "Ed", "family": "St. Pierre", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "E. P."} {"name": "Dr. Van Johnson", "title": "Dr.", "given": "Van", "family": "Johnson", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "V. J."} {"name": "Dr. Williams", "title": "Dr.", "family": "Williams", "initials": "W."} {"name": "Dr. abdul salam", "title": "Dr.", "given": "abdul", "family": "salam", "initials": "a. s."} {"name": "Dr. abdul salam ahmed salem", "title": "Dr.", "given": "abdul salam", "middle": "ahmed", "family": "salem", "initials": "a. s. a. s."} +{"name": "Dr. de la Vega, Juan", "title": "Dr.", "given": "Juan", "family": "de la Vega", "initials": "J. V."} {"name": "Dr. inž. Janez Novak", "title": "Dr. inž.", "given": "Janez", "family": "Novak", "initials": "J. N."} {"name": "Dr. juan garcia", "title": "Dr.", "given": "juan", "family": "garcia", "initials": "j. g."} {"name": "Dr. med. univ.", "title": "Dr. med.", "family": "univ.", "initials": "u."} @@ -744,6 +750,7 @@ {"name": "Dr. med. univ. Margit Popp, MSc", "title": "Dr. med. univ.", "given": "Margit", "family": "Popp", "suffix": "MSc", "initials": "M. P."} {"name": "Dr. nee Smith PhD Prof.", "title": "Dr. Prof.", "given": "nee", "family": "Smith", "suffix": "PhD", "initials": "n. S."} {"name": "Dr. 김민준씨, MA", "title": "Dr.", "given": "민준", "family": "김", "suffix": "씨, MA", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "민. 김."} +{"name": "Dr., John", "given": "John", "family": "Dr.", "initials": "J. D."} {"name": "Dr.philol. Laima Kristīne Eva Sofija van den Volfa Bērziņa-Kalniņa", "title": "Dr.philol.", "given": "Laima", "middle": "Kristīne Eva Sofija", "family": "van den Volfa Bērziņa-Kalniņa", "initials": "L. K. E. S. V. B."} {"name": "Dra. Andréia da Silva", "title": "Dra.", "given": "Andréia", "family": "da Silva", "initials": "A. S."} {"name": "Dra. Erika Cornelia Anna Isabelle von Brül Cabral de Melo II", "title": "Dra.", "given": "Erika", "middle": "Cornelia Anna Isabelle von Brül Cabral", "family": "de Melo", "suffix": "II", "initials": "E. C. A. I. B. C. M."} @@ -1017,6 +1024,7 @@ {"name": "Gottfried Huyn von Geleen und Amsterad", "given": "Gottfried", "middle": "Huyn", "family": "von Geleen und Amsterad", "initials": "G. H. G. A."} {"name": "Gottfried IV.", "given": "Gottfried", "suffix": "IV.", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "G."} {"name": "Goëß, Johann von", "given": "Johann", "family": "von Goëß", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "J. G."} +{"name": "Graf Lambsdorff, Otto", "title": "Graf", "given": "Otto", "family": "Lambsdorff", "initials": "O. L."} {"name": "Gragger, Robert", "given": "Robert", "family": "Gragger", "initials": "R. G."} {"name": "Gramont, Antoine de", "given": "Antoine", "family": "de Gramont", "initials": "A. G."} {"name": "Grand Rounds", "title": "Grand", "family": "Rounds", "initials": "R."} @@ -1027,6 +1035,7 @@ {"name": "Gregorio Modrego Casaus", "given": "Gregorio", "middle": "Modrego", "family": "Casaus", "initials": "G. M. C."} {"name": "Grettir Björnsson", "given": "Grettir", "family": "Björnsson", "initials": "G. B."} {"name": "Greve Anna", "title": "Greve", "family": "Anna", "initials": "A."} +{"name": "Greve Smith, Anna", "title": "Greve", "given": "Anna", "family": "Smith", "initials": "A. S."} {"name": "Greve, Anna", "given": "Anna", "family": "Greve", "initials": "A. G."} {"name": "Grouchy, Emmanuel de", "given": "Emmanuel", "family": "de Grouchy", "initials": "E. G."} {"name": "Guardia Neyra, Jaime", "given": "Jaime", "family": "Guardia Neyra", "initials": "J. G. N."} @@ -1862,6 +1871,7 @@ {"name": "King Henry", "title": "King", "given": "Henry", "initials": "H."} {"name": "King John Alexander V", "title": "King", "given": "John", "family": "Alexander", "suffix": "V", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "J. A."} {"name": "King John V.", "title": "King", "given": "John", "family": "V.", "initials": "J. V."} +{"name": "King Smith, John", "title": "King", "given": "John", "family": "Smith", "initials": "J. S."} {"name": "Kishi, Kōichi", "given": "Kōichi", "family": "Kishi", "initials": "K. K."} {"name": "Kjetil Bjørn Løseth", "given": "Kjetil", "middle": "Bjørn", "family": "Løseth", "initials": "K. B. L."} {"name": "Klaus Poeck", "given": "Klaus", "family": "Poeck", "initials": "K. P."} @@ -2022,6 +2032,7 @@ {"name": "MD DDS", "title": "MD", "family": "DDS", "initials": "D."} {"name": "MD DDS Dut.ra Prof.ra von Brühl González Domingo Maria Giusepa Juana Teresa", "order": "FAMILY_FIRST", "title": "MD", "given": "Dut.ra", "middle": "Prof.ra von Brühl González Domingo Maria Giusepa Juana Teresa", "family": "DDS", "initials": "D. P. B. G. D. M. G. J. T. D."} {"name": "MD DDS von Brühl César Martín Ada Cornelia", "order": "FAMILY_FIRST", "title": "MD", "given": "von Brühl César Martín Ada Cornelia", "family": "DDS", "initials": "v. B. C. M. A. C. D."} +{"name": "MD PhD Jr., John", "given": "John", "family": "MD", "suffix": "PhD Jr.", "initials": "J. M."} {"name": "MD, DO, DDS", "given": "DO", "family": "MD", "suffix": "DDS", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "D. M."} {"name": "MD, PHD", "family": "MD", "suffix": "PHD", "initials": "M."} {"name": "MP Pēteris Kārlis Ozoliņš", "given": "MP", "middle": "Pēteris Kārlis", "family": "Ozoliņš", "initials": "M. P. K. O."} @@ -2493,16 +2504,19 @@ {"name": "Prof. Dr. Ada Kornelia Sezar Martin van den Volf Becker Schmidt M.D. Ph.D.", "title": "Prof. Dr.", "given": "Ada", "middle": "Kornelia Sezar Martin", "family": "van den Volf Becker Schmidt", "suffix": "M.D. Ph.D.", "initials": "A. K. S. M. V. B. S."} {"name": "Prof. Dr. Adama Coulibaly Camara Massamba won Baar Dominique Goudiaby MD DDS", "title": "Prof. Dr.", "given": "Adama", "middle": "Coulibaly Camara Massamba won Baar Dominique", "family": "Goudiaby", "suffix": "MD DDS", "initials": "A. C. C. M. w. B. D. G."} {"name": "Prof. Dr. Anna Cornelia Eva Sophia van den Wolf jr. M.D. Ph.D.", "title": "Prof. Dr.", "given": "Anna", "middle": "Cornelia Eva Sophia", "family": "van den Wolf", "suffix": "jr. M.D. Ph.D.", "initials": "A. C. E. S. W."} +{"name": "Prof. Dr. Brühl, Ada", "title": "Prof. Dr.", "given": "Ada", "family": "Brühl", "initials": "A. B."} {"name": "Prof. Dr. MD DDS Ada Cornelia César Martín von Brühl Jr", "title": "Prof. Dr. MD", "given": "DDS", "middle": "Ada Cornelia César Martín", "family": "von Brühl", "suffix": "Jr", "initials": "D. A. C. C. M. B."} {"name": "Prof. Dr. Mary Lou Cesare Martín von Brühl Jr., Dr. Ph.D", "title": "Prof. Dr. Dr.", "given": "Mary", "middle": "Lou Cesare Martín", "family": "von Brühl", "suffix": "Jr., Ph.D", "initials": "M. L. C. M. B."} {"name": "Prof. Dr. Mary Sue Marie von Miller II, MD DDS", "title": "Prof. Dr.", "given": "Mary", "middle": "Sue Marie", "family": "von Miller", "suffix": "II, MD DDS", "initials": "M. S. M. M."} {"name": "Prof. Dr. María Florencia Martina Cristina von Brühl Jr., MD DDS", "title": "Prof. Dr.", "given": "María", "middle": "Florencia Martina Cristina", "family": "von Brühl", "suffix": "Jr., MD DDS", "initials": "M. F. M. C. B."} -{"name": "Prof. Dr. von Bruhl, Ada Cornelia Cesar Martín Jr, M.D., Ph.D.", "order": "FAMILY_FIRST", "given": "Ada", "middle": "Cornelia Cesar Martín", "family": "Prof. Dr. von Bruhl", "suffix": "Jr, M.D., Ph.D.", "initials": "A. C. C. M. P. D. B."} +{"name": "Prof. Dr. von Bruhl, Ada Cornelia Cesar Martín Jr, M.D., Ph.D.", "order": "FAMILY_FIRST", "title": "Prof. Dr.", "given": "Ada", "middle": "Cornelia Cesar Martín", "family": "von Bruhl", "suffix": "Jr, M.D., Ph.D.", "initials": "A. C. C. M. B."} {"name": "Prof. Dr. von Brühl Ada Cornelia César Martín Jr, MD DDS", "order": "FAMILY_FIRST", "title": "Prof. Dr.", "given": "Brühl", "middle": "Ada Cornelia César Martín", "family": "von", "suffix": "Jr, MD DDS", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "B. A. C. C. M. v."} {"name": "Prof. Dr. von Brühl González Domingo Ada Cornelia César Martín, M.D. DDS.", "order": "FAMILY_FIRST", "title": "Prof. Dr.", "given": "Brühl", "middle": "González Domingo Ada Cornelia César Martín", "family": "von", "suffix": "M.D. DDS.", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "B. G. D. A. C. C. M. v."} {"name": "Prof. Dr. von Brühl María Florencia Martina Cristina Jr., MD DDS", "order": "FAMILY_FIRST", "title": "Prof. Dr.", "given": "Brühl", "middle": "María Florencia Martina Cristina", "family": "von", "suffix": "Jr., MD DDS", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "B. M. F. M. C. v."} {"name": "Prof. Dr. von Brühl Plácido Domingo Ada Cornelia César Martín, MD DDS", "order": "FAMILY_FIRST", "title": "Prof. Dr.", "given": "Brühl", "middle": "Plácido Domingo Ada Cornelia César Martín", "family": "von", "suffix": "MD DDS", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "B. P. D. A. C. C. M. v."} -{"name": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg jnr., MBChB PhD", "given": "MBChB", "family": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg", "suffix": "jnr., PhD", "initials": "M. P. d. C. M. S. A. B."} +{"name": "Prof. Smith, Dr. John", "title": "Prof. Dr.", "given": "John", "family": "Smith", "initials": "J. S."} +{"name": "Prof. Smith, John, PhD", "title": "Prof.", "given": "John", "family": "Smith", "suffix": "PhD", "initials": "J. S."} +{"name": "Prof. dr. Cornelia Margarita Sofia Aletta van den Berg jnr., MBChB PhD", "title": "Prof. dr.", "given": "MBChB", "family": "Cornelia Margarita Sofia Aletta van den Berg", "suffix": "jnr., PhD", "initials": "M. C. M. S. A. B."} {"name": "Prof. dr. MD Chirurgie dentară Eva-Eleonora Karl Hans von der Ruhr Jr.", "title": "Prof. dr. MD", "given": "Chirurgie", "middle": "dentară Eva-Eleonora Karl Hans", "family": "von der Ruhr", "suffix": "Jr.", "initials": "C. d. E. K. H. R."} {"name": "Prof. Ɖr. MƉ Samʊwɛl fan ƉAM Fostɛɛŋ", "title": "Prof. Ɖr.", "given": "MƉ", "middle": "Samʊwɛl fan ƉAM", "family": "Fostɛɛŋ", "initials": "M. S. f. Ɖ. F."} {"name": "Prof. Ɖr. MƉ fan ƉAM ƉOMIŊGO Fostɛɛŋ Samʊwɛl", "order": "FAMILY_FIRST", "title": "Prof. Ɖr.", "given": "fan", "middle": "ƉAM ƉOMIŊGO Fostɛɛŋ Samʊwɛl", "family": "MƉ", "initials": "f. Ɖ. Ɖ. F. S. M."} @@ -2556,6 +2570,7 @@ {"name": "Rev John A. Kenneth Doe III (Kenny)", "title": "Rev", "given": "John", "middle": "A. Kenneth", "family": "Doe", "suffix": "III", "nickname": "Kenny", "initials": "J. A. K. D."} {"name": "Rev. John A. Kenneth Doe", "title": "Rev.", "given": "John", "middle": "A. Kenneth", "family": "Doe", "initials": "J. A. K. D."} {"name": "Rev. John Smith", "title": "Rev.", "given": "John", "family": "Smith", "initials": "J. S."} +{"name": "Rev. Sr. Smith, Mary", "title": "Rev. Sr.", "given": "Mary", "family": "Smith", "initials": "M. S."} {"name": "Reza Hossein Zadeh", "given": "Reza", "middle": "Hossein", "family": "Zadeh", "initials": "R. H. Z."} {"name": "Ricardo Bodenlle Corral", "given": "Ricardo", "middle": "Bodenlle", "family": "Corral", "initials": "R. B. C."} {"name": "Ricardo Legorreta Vilchis", "given": "Ricardo", "middle": "Legorreta", "family": "Vilchis", "initials": "R. L. V."} @@ -2752,6 +2767,7 @@ {"name": "Sir John", "title": "Sir", "given": "John", "initials": "J."} {"name": "Sir John Prof.", "title": "Sir Prof.", "given": "John", "initials": "J."} {"name": "Sir Ph. D. Van Johnson", "title": "Sir", "given": "Van Johnson", "suffix": "Ph. D.", "initials": "V. J."} +{"name": "Sir Smith, John", "title": "Sir", "given": "John", "family": "Smith", "initials": "J. S."} {"name": "Sir Van Johnson", "title": "Sir", "given": "Van", "family": "Johnson", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "V. J."} {"name": "Sir abdul van der Berg", "title": "Sir", "given": "abdul", "family": "van der Berg", "initials": "a. B."} {"name": "Sir de Mesnil", "title": "Sir", "family": "de Mesnil", "initials": "M."} @@ -2882,6 +2898,7 @@ {"name": "Sr. Xosé Carlos Francisco Xavier de Castro Sáez", "title": "Sr.", "given": "Xosé", "middle": "Carlos Francisco Xavier", "family": "de Castro Sáez", "initials": "X. C. F. X. C. S."} {"name": "Srta. Andréia da Silva", "title": "Srta.", "given": "Andréia", "family": "da Silva", "initials": "A. S."} {"name": "St Clair", "title": "St", "family": "Clair", "initials": "C."} +{"name": "St Pierre, Ed", "given": "Ed", "family": "St Pierre", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "E. P."} {"name": "Stander Zelda Herman", "order": "FAMILY_FIRST", "given": "Zelda", "middle": "Herman", "family": "Stander", "initials": "Z. H. S."} {"name": "Stander, Zelda Herman", "given": "Zelda", "middle": "Herman", "family": "Stander", "initials": "Z. H. S."} {"name": "Stariji Bruegel", "given": "Stariji", "family": "Bruegel", "initials": "S. B."} @@ -3332,7 +3349,7 @@ {"name": "g. Hodžić Adnan Mirza, zastupnik u parlamentu", "order": "FAMILY_FIRST", "given": "zastupnik", "middle": "u parlamentu", "family": "g. Hodžić Adnan Mirza", "initials": "z. u. p. g. H. A. M."} {"name": "g. Janez Peter Novak ml., univ. dipl. inž.", "title": "univ. dipl. inž.", "given": "g.", "middle": "Janez Peter Novak", "family": "ml.", "initials": "g. J. P. N. m."} {"name": "g. Novak Janez Peter, univ. dipl. inž.", "order": "FAMILY_FIRST", "title": "univ. dipl. inž.", "given": "Novak", "middle": "Janez Peter", "family": "g.", "initials": "N. J. P. g."} -{"name": "hr. Hans Henrik Sven Åge Møller, MF", "given": "MF", "family": "hr. Hans Henrik Sven Åge Møller", "initials": "M. h. H. H. S. Å. M."} +{"name": "hr. Hans Henrik Sven Åge Møller, MF", "title": "hr.", "given": "MF", "family": "Hans Henrik Sven Åge Møller", "initials": "M. H. H. S. Å. M."} {"name": "ibn Awf abdul Rahman", "family": "ibn Awf abdul Rahman", "initials": "A. a. R."} {"name": "ina binti navalamar", "given": "ina", "family": "binti navalamar", "initials": "i. n."} {"name": "j.-e.-p. dupont", "given": "j.-e.-p.", "family": "dupont", "initials": "j. d."} @@ -3425,17 +3442,17 @@ {"name": "prof. dr Ada Cornelia von Brühl", "title": "prof. dr", "given": "Ada", "middle": "Cornelia", "family": "von Brühl", "initials": "A. C. B."} {"name": "prof. dr Aleksandra Eva Sara van den Volf Petrović Jugović dipl. inž.", "title": "prof. dr", "given": "Aleksandra", "middle": "Eva Sara", "family": "van den Volf Petrović Jugović dipl. inž.", "initials": "A. E. S. V. P. J. d. i."} {"name": "prof. dr von Brühl Ada Cornelia César Martín", "order": "FAMILY_FIRST", "title": "prof. dr", "given": "Brühl", "middle": "Ada Cornelia César Martín", "family": "von", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "B. A. C. C. M. v."} -{"name": "prof. dr. Ada Cornelia César Martín von Brühl Jr, univ. bacc", "title": "univ.", "given": "bacc", "family": "prof. dr. Ada Cornelia César Martín von Brühl", "suffix": "Jr", "initials": "b. p. d. A. C. C. M. B."} +{"name": "prof. dr. Ada Cornelia César Martín von Brühl Jr, univ. bacc", "title": "prof. dr. univ.", "given": "bacc", "family": "Ada Cornelia César Martín von Brühl", "suffix": "Jr", "initials": "b. A. C. C. M. B."} {"name": "prof. dr. Ada Cornelia César Martín von Brühl ml., dr. med., dr. dent. med.", "title": "prof. dr. dr. med. dr.", "given": "Ada", "middle": "Cornelia César Martín", "family": "von Brühl ml.", "suffix": "dent. med.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "A. C. C. M. B. m."} {"name": "prof. dr. Anna Cornelia Eva Sophia van den Wolf jr. m.d. ph.d.", "title": "prof. dr.", "given": "Anna", "middle": "Cornelia Eva Sophia", "family": "van den Wolf", "suffix": "jr. m.d. ph.d.", "initials": "A. C. E. S. W."} {"name": "prof. dr. Gentiana van den Popa, dr. shk. mjek.", "title": "prof. dr. dr. shk. mjek.", "given": "Gentiana", "family": "van den Popa", "initials": "G. P."} {"name": "prof. dr. Izeta Amra von Selimović Hodžić, dipl. stom.", "title": "prof. dr. dipl. stom.", "given": "Izeta", "middle": "Amra", "family": "von Selimović Hodžić", "initials": "I. A. S. H."} -{"name": "prof. dr. Popa, Gentiana van den", "given": "Gentiana", "family": "van den prof. dr. Popa", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "G. p. d. P."} -{"name": "prof. dr. van den Popa, Gentiana M., dr. shk. mjek.", "order": "FAMILY_FIRST", "title": "dr.", "given": "Gentiana", "middle": "M.", "family": "prof. dr. van den Popa", "suffix": "shk. mjek.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "G. M. p. d. P."} +{"name": "prof. dr. Popa, Gentiana van den", "title": "prof. dr.", "given": "Gentiana", "family": "van den Popa", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "G. P."} +{"name": "prof. dr. van den Popa, Gentiana M., dr. shk. mjek.", "order": "FAMILY_FIRST", "title": "prof. dr. dr.", "given": "Gentiana", "middle": "M.", "family": "van den Popa", "suffix": "shk. mjek.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "G. M. P."} {"name": "prof. dr. von Brühl Ada Cornelia César Martín, dr. med., dr. dent. med.", "order": "FAMILY_FIRST", "title": "prof. dr. dr. med. dr.", "given": "Brühl", "middle": "Ada Cornelia César Martín", "family": "von", "suffix": "dent. med.", "ambiguities": ["COMMA_STRUCTURE", "PARTICLE_OR_GIVEN"], "initials": "B. A. C. C. M. v."} -{"name": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", "given": "Izeta", "middle": "Amra", "family": "prof. dr. von Selimović Hodžić", "suffix": "dipl. stom.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "I. A. p. d. S. H."} -{"name": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", "order": "FAMILY_FIRST", "given": "Izeta", "middle": "Amra", "family": "prof. dr. von Selimović Hodžić", "suffix": "dipl. stom.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "I. A. p. d. S. H."} -{"name": "prof. dr. von Vilkas Jankauskas-Baranauskas, Ada Kornelija Eva Sofija", "order": "FAMILY_FIRST", "given": "Ada", "middle": "Kornelija Eva Sofija", "family": "prof. dr. von Vilkas Jankauskas-Baranauskas", "initials": "A. K. E. S. p. d. V. J."} +{"name": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", "title": "prof. dr.", "given": "Izeta", "middle": "Amra", "family": "von Selimović Hodžić", "suffix": "dipl. stom.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "I. A. S. H."} +{"name": "prof. dr. von Selimović Hodžić, Izeta Amra, dipl. stom.", "order": "FAMILY_FIRST", "title": "prof. dr.", "given": "Izeta", "middle": "Amra", "family": "von Selimović Hodžić", "suffix": "dipl. stom.", "ambiguities": ["COMMA_STRUCTURE"], "initials": "I. A. S. H."} +{"name": "prof. dr. von Vilkas Jankauskas-Baranauskas, Ada Kornelija Eva Sofija", "order": "FAMILY_FIRST", "title": "prof. dr.", "given": "Ada", "middle": "Kornelija Eva Sofija", "family": "von Vilkas Jankauskas-Baranauskas", "initials": "A. K. E. S. V. J."} {"name": "professori Ana Christina Lëja von Wright González Domingo, MD DDS", "given": "professori", "middle": "Ana Christina Lëja", "family": "von Wright González Domingo", "suffix": "MD DDS", "initials": "p. A. C. L. W. G. D."} {"name": "qc mp", "given": "qc", "suffix": "mp", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "q."} {"name": "salem, abdul", "given": "abdul", "family": "salem", "initials": "a. s."} @@ -4102,7 +4119,7 @@ {"name": "Преображенский, Василий Алексеевич", "given": "Василий", "middle": "Алексеевич", "family": "Преображенский", "initials": "В. А. П."} {"name": "Проф. Док. Ада Корнелиа Сезар Мартин вон Брухи Гонзалес Доминго", "title": "Проф. Док.", "given": "Ада", "middle": "Корнелиа Сезар Мартин вон Брухи Гонзалес", "family": "Доминго", "initials": "А. К. С. М. в. Б. Г. Д."} {"name": "Проф. Доктор. Алтынай Сулайманова Асель Сартбаева ван ден Вольф Бекер Шмидт Илимдин кандидаты", "title": "Проф. Доктор.", "given": "Алтынай", "middle": "Сулайманова Асель Сартбаева ван ден Вольф Бекер Шмидт Илимдин", "family": "кандидаты", "initials": "А. С. А. С. в. д. В. Б. Ш. И. к."} -{"name": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр, Анагаах ухааны доктор", "given": "Анагаах", "middle": "ухааны доктор", "family": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр", "initials": "А. у. д. П. Д. А. К. Э. С. в. Б. Ж."} +{"name": "Проф. Др. Ада Корнелиа Эва Софиа вон Брюхл Жр, Анагаах ухааны доктор", "title": "Проф.", "given": "Анагаах", "middle": "ухааны доктор", "family": "Др. Ада Корнелиа Эва Софиа вон Брюхл Жр", "initials": "А. у. д. Д. А. К. Э. С. в. Б. Ж."} {"name": "Пётр Васильевич Быков", "given": "Пётр", "middle": "Васильевич", "family": "Быков", "initials": "П. В. Б."} {"name": "Пётр Иванович Почивалов", "given": "Пётр", "middle": "Иванович", "family": "Почивалов", "initials": "П. И. П."} {"name": "Пётр Николаевич Краснов", "given": "Пётр", "middle": "Николаевич", "family": "Краснов", "initials": "П. Н. К."} @@ -4243,16 +4260,16 @@ {"name": "вон Брухи Гонзалес Доминго Проф. Док. Ада Корнелиа Сезар Мартин", "order": "FAMILY_FIRST", "given": "Брухи", "middle": "Гонзалес Доминго Проф. Док. Ада Корнелиа Сезар Мартин", "family": "вон", "initials": "Б. Г. Д. П. Д. А. К. С. М. в."} {"name": "вон Брухи Гонзалес Доминго, Проф. Док. Ада Корнелиа Сезар Мартин", "title": "Проф. Док.", "given": "Ада", "middle": "Корнелиа Сезар Мартин", "family": "вон Брухи Гонзалес Доминго", "initials": "А. К. С. М. в. Б. Г. Д."} {"name": "вон Брюхл Гонзалес Доминго Проф. Др. Ада Корнелиа Эва Софиа Анагаах ухааны доктор", "order": "FAMILY_FIRST", "given": "Брюхл", "middle": "Гонзалес Доминго Проф. Др. Ада Корнелиа Эва Софиа Анагаах ухааны доктор", "family": "вон", "initials": "Б. Г. Д. П. Д. А. К. Э. С. А. у. д. в."} -{"name": "г-н Вернер, Иван Асен, проф. д-р", "order": "FAMILY_FIRST", "title": "проф. д-р", "given": "Иван", "middle": "Асен", "family": "г-н Вернер", "initials": "И. А. г. В."} +{"name": "г-н Вернер, Иван Асен, проф. д-р", "order": "FAMILY_FIRST", "title": "г-н проф. д-р", "given": "Иван", "middle": "Асен", "family": "Вернер", "initials": "И. А. В."} {"name": "г-н Иван Асен Вернер, проф. д-р", "title": "г-н проф. д-р", "given": "Иван", "middle": "Асен", "family": "Вернер", "initials": "И. А. В."} {"name": "г-н Иван Петров", "title": "г-н", "given": "Иван", "family": "Петров", "initials": "И. П."} {"name": "др Слађана Вера Миленковић дипл. инж.", "given": "др", "middle": "Слађана Вера Миленковић дипл.", "family": "инж.", "initials": "д. С. В. М. д. и."} {"name": "проф. Анастасія Єва Софія фон Вольф Гонзалес Домінго, д-р", "title": "проф. д-р", "given": "Анастасія", "middle": "Єва Софія фон Вольф Гонзалес", "family": "Домінго", "initials": "А. Є. С. ф. В. Г. Д."} {"name": "проф. Анна Марія Богдан-Зиновій Петренко доц.", "title": "проф.", "given": "Анна", "middle": "Марія Богдан-Зиновій Петренко", "family": "доц.", "initials": "А. М. Б. П. д."} {"name": "проф. Петренко Анна Марія Богдан-Зиновій доц.", "order": "FAMILY_FIRST", "title": "проф.", "given": "Анна", "middle": "Марія Богдан-Зиновій доц.", "family": "Петренко", "initials": "А. М. Б. д. П."} -{"name": "проф. д-р Ада Корнелия Цезар Мартин Брюл, доктор", "given": "доктор", "family": "проф. д-р Ада Корнелия Цезар Мартин Брюл", "initials": "д. п. д. А. К. Ц. М. Б."} +{"name": "проф. д-р Ада Корнелия Цезар Мартин Брюл, доктор", "title": "проф. д-р", "given": "доктор", "family": "Ада Корнелия Цезар Мартин Брюл", "initials": "д. А. К. Ц. М. Б."} {"name": "проф. д-р Ана Марија Цезар Мартин ван ден Волф", "title": "проф. д-р", "given": "Ана", "middle": "Марија Цезар Мартин ван ден", "family": "Волф", "initials": "А. М. Ц. М. в. д. В."} -{"name": "проф. д-р Брюл, Ада Корнелия Цезар Мартин, доктор", "order": "FAMILY_FIRST", "given": "Ада", "middle": "Корнелия Цезар Мартин", "family": "проф. д-р Брюл", "suffix": "доктор", "ambiguities": ["COMMA_STRUCTURE"], "initials": "А. К. Ц. М. п. д. Б."} +{"name": "проф. д-р Брюл, Ада Корнелия Цезар Мартин, доктор", "order": "FAMILY_FIRST", "title": "проф. д-р", "given": "Ада", "middle": "Корнелия Цезар Мартин", "family": "Брюл", "suffix": "доктор", "ambiguities": ["COMMA_STRUCTURE"], "initials": "А. К. Ц. М. Б."} {"name": "проф. д-р Крсте Петков Мисирков", "title": "проф. д-р", "given": "Крсте", "middle": "Петков", "family": "Мисирков", "initials": "К. П. М."} {"name": "проф. д-р Мисирков Крсте Петков", "order": "FAMILY_FIRST", "title": "проф. д-р", "given": "Крсте", "middle": "Петков", "family": "Мисирков", "initials": "К. П. М."} {"name": "проф. д-р ван ден Волф Ана Марија Цезар Мартин", "order": "FAMILY_FIRST", "title": "проф. д-р", "given": "ден", "middle": "Волф Ана Марија Цезар Мартин", "family": "ван", "initials": "д. В. А. М. Ц. М. в."} @@ -4473,7 +4490,7 @@ {"name": "اسەم", "order": "FAMILY_FIRST", "family": "اسەم", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "ا."} {"name": "اصغر شازیہ", "order": "FAMILY_FIRST", "given": "شازیہ", "family": "اصغر", "initials": "ش. ا."} {"name": "اصغر، شازیہ", "order": "FAMILY_FIRST", "given": "شازیہ", "family": "اصغر", "initials": "ش. ا."} -{"name": "الدكتور عايدة كورنيليا سيزار مارتن فون برول الإبن، طبيب وجراح", "given": "طبيب", "middle": "وجراح", "family": "الدكتور عايدة كورنيليا سيزار مارتن فون برول", "suffix": "الإبن", "initials": "ط. و. ا. ع. ك. س. م. ف. ب."} +{"name": "الدكتور عايدة كورنيليا سيزار مارتن فون برول الإبن، طبيب وجراح", "title": "الدكتور", "given": "طبيب", "middle": "وجراح", "family": "عايدة كورنيليا سيزار مارتن فون برول", "suffix": "الإبن", "initials": "ط. و. ع. ك. س. م. ف. ب."} {"name": "السيد أحمد رامي نجيب محفوظ أبو الأغا الابن، النائب", "given": "النائب", "family": "السيد أحمد رامي نجيب محفوظ أبو الأغا", "suffix": "الابن", "initials": "ا. ا. أ. ر. ن. م. ا."} {"name": "العامر، كمال مجدي", "order": "FAMILY_FIRST", "given": "كمال", "middle": "مجدي", "family": "العامر", "initials": "ك. م. ا."} {"name": "النجار، سميرة", "order": "FAMILY_FIRST", "given": "سميرة", "family": "النجار", "initials": "س. ا."} @@ -4750,8 +4767,8 @@ {"name": "पोख्रेल रमिता", "order": "FAMILY_FIRST", "given": "रमिता", "family": "पोख्रेल", "initials": "र. प."} {"name": "पोख्रेल, रमिता", "given": "रमिता", "family": "पोख्रेल", "initials": "र. प."} {"name": "प्रेमप्रसाद हिमलाल वास्तोला", "given": "प्रेमप्रसाद", "middle": "हिमलाल", "family": "वास्तोला", "initials": "प. ह. व."} -{"name": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर, बी.ए. एल.एल.बी", "given": "बी.ए.", "middle": "एल.एल.बी", "family": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर", "initials": "ब. ए. प. ड. आ. क. स. म. व. ब. ग. ड. ज."} -{"name": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु., एम. डी. डी. डी. एस.", "title": "एम.", "given": "डी.", "middle": "डी. डी. एस.", "family": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु.", "initials": "ड. ड. ड. ए. प. अ. श. स. म. व. ब. ज."} +{"name": "प्रो. डॉ. आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर, बी.ए. एल.एल.बी", "title": "प्रो. डॉ.", "given": "बी.ए.", "middle": "एल.एल.बी", "family": "आडा कोर्नेलिया सेजार मार्टिन वॉन ब्रूह्ल गॉन्जालेज डोमिंगो जेआर", "initials": "ब. ए. आ. क. स. म. व. ब. ग. ड. ज."} +{"name": "प्रोफे.डॉ. अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु., एम. डी. डी. डी. एस.", "title": "प्रोफे.डॉ. एम.", "given": "डी.", "middle": "डी. डी. एस.", "family": "अदा शर्मा सीझर मार्टिन व्हॉन ब्र्यूल ज्यु.", "initials": "ड. ड. ड. ए. अ. श. स. म. व. ब. ज."} {"name": "प्रो॰ डॉ॰ माइकल जॉन वॉन वॉटसन चेस्टर, एम॰डी॰, पी॰एच॰डी॰", "given": "एम॰डी॰", "family": "प्रो॰ डॉ॰ माइकल जॉन वॉन वॉटसन चेस्टर", "suffix": "पी॰एच॰डी॰", "ambiguities": ["COMMA_STRUCTURE"], "initials": "ए. प. ड. म. ज. व. व. च."} {"name": "प्रो॰ डॉ॰ वॉन वॉटसन माइकल जॉन, एम॰डी॰, पी॰एच॰डी॰", "order": "FAMILY_FIRST", "given": "एम॰डी॰", "family": "प्रो॰ डॉ॰ वॉन वॉटसन माइकल जॉन", "suffix": "पी॰एच॰डी॰", "ambiguities": ["COMMA_STRUCTURE"], "initials": "ए. प. ड. व. व. म. ज."} {"name": "फडके रिधान समीर", "order": "FAMILY_FIRST", "given": "रिधान", "middle": "समीर", "family": "फडके", "initials": "र. स. फ."} @@ -4804,10 +4821,10 @@ {"name": "शर्मा, ललित कुमार एम॰डी॰", "given": "ललित", "middle": "कुमार एम॰डी॰", "family": "शर्मा", "initials": "ल. क. ए. श."} {"name": "शर्मा, ललित मोहन", "given": "ललित", "middle": "मोहन", "family": "शर्मा", "initials": "ल. म. श."} {"name": "शांति गांवकर", "given": "शांति", "family": "गांवकर", "initials": "श. ग."} -{"name": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा., एमपी", "given": "एमपी", "family": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा.", "initials": "ए. श. फ. श. ज. आ. द. स. ए. म. ध."} +{"name": "श्री फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा., एमपी", "title": "श्री", "given": "एमपी", "family": "फ्रांसिस शावियेर जुआंव आंतोन दे सोजा ए मेनेजेस धा.", "initials": "ए. फ. श. ज. आ. द. स. ए. म. ध."} {"name": "श्री ललित कुमार शर्मा एम॰डी॰", "title": "श्री", "given": "ललित", "middle": "कुमार शर्मा", "family": "एम॰डी॰", "initials": "ल. क. श. ए."} -{"name": "श्री शर्मा ललित कुमार, एम॰डी॰", "order": "FAMILY_FIRST", "given": "एम॰डी॰", "family": "श्री शर्मा ललित कुमार", "initials": "ए. श. श. ल. क."} -{"name": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क., एम. पी.", "title": "एम.", "given": "पी.", "family": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क.", "initials": "प. श. ध. द. व. द. द. क."} +{"name": "श्री शर्मा ललित कुमार, एम॰डी॰", "order": "FAMILY_FIRST", "title": "श्री", "given": "एम॰डी॰", "family": "शर्मा ललित कुमार", "initials": "ए. श. ल. क."} +{"name": "श्री. धिरज देशपांडे विजय देशपांडे देशपांडे क., एम. पी.", "title": "श्री. एम.", "given": "पी.", "family": "धिरज देशपांडे विजय देशपांडे देशपांडे क.", "initials": "प. ध. द. व. द. द. क."} {"name": "संजय ख़ान", "given": "संजय", "family": "ख़ान", "initials": "स. ख."} {"name": "सिंदबाद", "given": "सिंदबाद", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "स."} {"name": "सिंदबाद", "order": "FAMILY_FIRST", "family": "सिंदबाद", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "स."}