From 3b97c2954d847845bd089b17311890703a3204d8 Mon Sep 17 00:00:00 2001 From: Derek Gulbranson Date: Wed, 28 Oct 2026 01:07:31 -0700 Subject: [PATCH] Read Chancellor as a title only inside a title phrase, and Lord Justice as one title (#913) chancellor gains a dated given reading, so Chancellor Smith and Smith, Chancellor read the given name while Vice Chancellor, Chancellor of the Exchequer and Lord Chancellor keep the title. New attaches data keeps the phrases a modifier does not reach: lord to chancellor and justice, lady to justice, deputy to the office kind, pro to chancellor and magistrate to judge. Lord Justice and Lady Justice now read one title, which no release did. judge was measured in the same batch and stays a title; its counts are recorded in the note on its title reading. Co-Authored-By: Claude Opus 5.5 --- docs/design/decisions/H9-title-phrase.md | 7 ++ docs/design/decisions/vocabulary-model.md | 1 + docs/design/rules/H9-title-phrase.md | 3 + docs/migrate.rst | 11 +++ docs/release_log.rst | 1 + nameparser/config/_compiled.py | 81 ++++++++++++++++++++++- nameparser/vocab/en.toml | 16 +++-- tests/test_constants.py | 6 +- tests/test_python_api.py | 16 ++--- tests/v2/cases.py | 31 +++++++++ tests/v2/test_cases.py | 10 +-- tools/differential/corpus_rules.jsonl | 2 + tools/differential/snapshot.jsonl | 4 +- 13 files changed, 165 insertions(+), 24 deletions(-) diff --git a/docs/design/decisions/H9-title-phrase.md b/docs/design/decisions/H9-title-phrase.md index 11bfda8c8..406c80cbc 100644 --- a/docs/design/decisions/H9-title-phrase.md +++ b/docs/design/decisions/H9-title-phrase.md @@ -106,3 +106,10 @@ - THE COST, accepted by Derek on 2026-10-27: `FISH, ROYAL SR` reads given 'FISH' and no family, `sr` being a title as well as a suffix, so `ROYAL SR` is a title run with a head and H1 reads the word before the comma as the given name; one FEC name. A phrase with nothing behind it still names its last word (`Princess Royal` → title 'Princess', given 'Royal'), H4's reading of an input that is all vocabulary. - MEASURED (2026-10-27, against master `598167f4`, which holds the queen batch, py3.11, `uv run python tools/differential/measure.py --base `, 16 steps). Fields: fec-individuals 49, 47 fixes, nearly every one `AA, ROYAL…`, where the queen head read title 'ROYAL' and no given name, 1 broken (above) and 1 input that names one person twice; jrc-names 6 spellings, `Princess Royal Anne`'s and a `consort marquise of X`; PSC and orcid-researchers agreement no record moved (ORCID 1,831,533 scored). Reports only: orcid-researchers 548 (`prince` 329, `princess` 103, `king` 70, `queen` 24, `royal` 15, a few behind `Dr.` or `Prof.`), PSC 310 records (`prince` 119, `princess` 58, `king` 49, `queen` 13, the rest `royal` and salutation forms), jrc-names 154 spellings, ctgov-officials 17, nepal-candidates 3, the committed corpora 13; tse-donors, tw-donors and ukec-individuals none; spelling pairs jrc-names 0 now alike and 1 apart; CLDR and GND agreement do not move. A v1 `Constants().titles` keeps all four royal titles, and `royal` and `consort` reach it as titles with no edit. Recompute: `uv run python tools/differential/measure.py --base `. +- **2026-10-28 #913, `chancellor`, AND `judge` KEPT A TITLE (Derek) — THE LAST 2.8 TITLE BATCH: ONE TITLE BORNE AS A GIVEN NAME, AND THE PHRASES THAT KEEP JUDICIAL AND ACADEMIC TITLES WHOLE.** `judge` and `chancellor` were proposed together; Derek shipped `chancellor` alone and kept `judge` a title on 2026-10-28. `chancellor` gains a dated `given` reading and is a title only inside a title phrase: `Chancellor Smith`, `Mr Chancellor Smith` and `Smith, Chancellor` read given 'Chancellor', where 1.4.0 through 2.7.0 read the title. Before a family comma H6 no longer peels it (`Chancellor Case, Nancy` → family 'Chancellor Case', 1.4.0's reading). The phrases keep it: a modifier (`Vice Chancellor`, `Associate Chancellor`), `of` (`Chancellor of the Exchequer`), and `attaches` data added here for the phrases a modifier does not reach: `lord` attaches to `chancellor` and `justice` and `lady` to `justice` (`Lord Chancellor`, `Lord Justice`, `Lady Justice`), `deputy` to the office kind as `chief` does (`Deputy Chancellor`, `Deputy Judge`), `pro` to `chancellor` (`Pro Chancellor`), and `magistrate` to `judge` (`Magistrate Judge`, the US federal office, which with `judge` moved had lost its second word). `Lord Justice Leveson` and `Lady Justice Arden` now read the one title, where 1.4.0, which listed no `justice`, through 2.7.0, where it is contested (phase 2i), read title 'Lord', given 'Justice'. Since `Vice Chancellor` and `Lord Chancellor` are listed phrases, a bare `Chancellor` opening a name reports `title-or-name`, as `Dean Smith` does. Phrases that read the same on master and stay out of scope: `Circuit Judge`, `Probate Judge`, `His Honour Judge` and the hyphenated `Vice-Chancellor`. + - `judge` KEPT A TITLE, its evidence recorded in the note on its title reading so a later batch meets it: given US SSA 3,826 births (all male), Wikidata 7, nam_dict band 1 in the U.S.A.; family Census 10,453 (rank 3,414), Wikidata 133; in PSC 0 filers put it in the forename box and 0 in the title box. Measured as a contested title against master `f207e4f1`, it broke 13 FEC records, every one a judge filing `FAMILY, JUDGE GIVEN` (9) or `FAMILY, JUDGE` alone (4), and 2 jrc-names spellings of news text before a surname, against 2 fixes in all the local corpora (one ORCID and one PSC filer whose given name it is). The `TEST_NAMES` judges (`Judge James M. Moody`) and every example that uses `judge` as an ordinary surname in TITLES (the H section's Background, rules/H5, rules/H6 and rules/H7) keep it. + - THE COUNTS for `chancellor`, recorded on the word (`uv run python tools/name_usage.py chancellor`, 2026-10-28): given US SSA 2,648 births (2,643 male), Wikidata 13 (United States 3); family Census 4,147 (rank 7,974), Wikidata 77 (United Kingdom 11, United States 8). + - THE COST, accepted by Derek on 2026-10-28: a chancellor written with the bare title reads it as the given name (`Chancellor Merkel` → given 'Chancellor', family 'Merkel', where 1.4.0 through 2.7.0 read title 'Chancellor'), so does one alone after a full name and a comma (`John Smith, Chancellor` reverses to given 'Chancellor', family 'John Smith', the role-word class `John Smith, Dean` accepted), and a bare first-word `Chancellor` reports `title-or-name`. + - WORKED EXAMPLES MOVED. The v1 tests that add a custom title and parse it (`tests/test_constants.py`, `tests/test_python_api.py`) add `bursar`, in no default set, where they added `chancellor`, which v1's `Constants().titles` still holds; rules/H9 gains the `Lord Chancellor` and `Chancellor Smith` examples. + - MEASURED (2026-10-28, against master `f207e4f1`, py3.11, `uv run python tools/differential/measure.py --base `, 16 steps). fec-individuals 10, all fixes: 4 `AA, CHANCELLOR` alone, which had read no given name, 1 `AA, CHANCELLOR A.`, 2 `AA, CHANCELLOR MR.`, and 3 with a two-word surname opening with the word before the comma, which had read it as the title; jrc-names 5 spellings, 3 fixed (`Lord Justice` and `Lady Justice` before a surname) and 2 broken, spellings of one head of government written with the bare title, now reporting `title-or-name`; ctgov-officials 1 fix (a `Deputy` and an office title after a comma, now one title through `deputy`'s attaches); orcid-researchers, psc-individuals, nepal-candidates, tse-donors, tw-donors and ukec-individuals none; ORCID (1,831,533 scored) and PSC (1,039,145 scored) agreement do not move; spelling pairs jrc-names 0 now alike and 0 apart; CLDR and GND agreement do not move. The committed corpora move by `Chancellor Jane Smith` (given 'Chancellor') beside the batch's rule examples. A v1 `Constants().titles` keeps `chancellor` and `judge` with no edit, and `c.titles.remove('chancellor')` turns every title reading of it off (the v1 title list entry above). + Recompute: `uv run python tools/differential/measure.py --base `. diff --git a/docs/design/decisions/vocabulary-model.md b/docs/design/decisions/vocabulary-model.md index 33d705b2f..70a56b730 100644 --- a/docs/design/decisions/vocabulary-model.md +++ b/docs/design/decisions/vocabulary-model.md @@ -219,6 +219,7 @@ Open: #913 (the title words phase 2j left, read as titles though borne as names) - `dean`, `justice` and `major` gain an office or military reading beside a dated `given` one; `justice`'s exclusion (#606) is replaced by the reading. The batches of 2j declare the rest. Adding the four fields changes `Lexicon`'s pickle layout, as phase 2h did. - **2026-10-26 #752, phase 2i (Derek) — `attaches` MAY NAME A TITLE WORD AS WELL AS A KIND, AND `grace` AND `marshal` JOIN THE CONTESTED TITLES.** Amends the `attaches` bullet of the 2026-10-25 #752, phase 2i entry: a kind reaches every word that later joins it, and once `marshal` became a contested military word the military kind made `Sgt Marshal Smith` a title phrase. A list entry that is no kind must be a word with a title reading (a build check, its mutation in tests/v2/test_vocab.py). `major` attaches to `general` and `sergeant` and `sgt` to `major`. `grace` (style) and `marshal` (military, its #606 exclusion replaced) carry dated `given` readings. The measurement and Derek's answers are decisions/H9's entry of this date. +- **2026-10-28 #913, `chancellor`, and `judge` kept a title (Derek) — A #913 TITLE BATCH: `chancellor` has a dated `given` reading**, US SSA 2,648 births and Census rank 7,974 as a surname, so it is a title only inside a title phrase. `Chancellor Smith` and `Smith, Chancellor` read given 'Chancellor'; a chancellor written with the bare title does too (`Chancellor Merkel`), accepted by Derek on 2026-10-28. `Vice Chancellor`, `Chancellor of the Exchequer` and, through new `attaches` data, `Lord Chancellor`, `Deputy Chancellor` and `Pro Chancellor` keep the title; the same data makes `Lord Justice`, `Lady Justice` and `Magistrate Judge` one title. `judge` was proposed in the same batch and kept a title by Derek on 2026-10-28, the counts against moving it (13 FEC judges filing `FAMILY, JUDGE …` against 2 fixes) recorded in the note on its title reading. The measurement is decisions/H9's entry of this date. - **2026-10-27 #913, royal title phrases (Derek) — `king`, `queen`, `prince` and `princess` CARRY `attaches`, `consort` IS A NEW MODIFIER AND `royal` HAS A DATED `given` READING.** `king` and `prince` attach to `consort`, `queen` to `consort` and `mother`, `princess` to `consort` and `royal`; `consort` (no bearers found) and `royal` address by the given name, so `Queen Consort Camilla` and `Princess Royal Anne` read the phrase as the title and the given name behind it. `royal`'s given reading keeps `BALES, ROYAL` the listing form's given name. The bare royal words now report `title-or-name`, a listed phrase holding them, accepted by Derek on 2026-10-27. The measurement and the rule change are decisions/H9's entry of this date. - **2026-10-27 #913, `queen` (Derek) — A #913 TITLE BATCH: `queen` has a dated `given` reading**, US SSA 16,123 births and Census rank 1,945 as a surname, so it is a title only inside a title phrase. `Queen Latifah`, `Ms Queen Smith` and `Smith, Queen` read given 'Queen' and the word behind it as the family; a monarch written with the bare title does too (`Queen Elizabeth II`), the class accepted for `king`, accepted by Derek on 2026-10-27. `Her Majesty Queen Elizabeth` and `Queen of England` keep the title. `Mary II, Dame` replaces `Elizabeth II, Queen` as rules/H1's example. The measurement is decisions/H9's entry of this date. - **2026-10-27 #913, `deacon`, `burgess` and `ranger` (Derek) — A #913 TITLE BATCH: each has a dated `given` reading** on its en.toml entry, so each is a title only inside a title phrase. `Deacon Jones`, `Burgess Meredith` and `Ranger Smith` read the given name, and `Burgess Smith, John` keeps the surname whole; a cleric written with the bare title or behind `Rev.` does too (`The Rev. Deacon John Smith`), the religious class accepted for `buddha` and `gyani`, accepted by Derek on 2026-10-27. `Deacon of the Church Jane Smith` keeps the title. Derek chose the three, with `marquis` and `marquise` (#923), from #913's ranking on 2026-10-27. The measurement is decisions/H9's entry of this date. diff --git a/docs/design/rules/H9-title-phrase.md b/docs/design/rules/H9-title-phrase.md index f2c10c25d..e3820e9bb 100644 --- a/docs/design/rules/H9-title-phrase.md +++ b/docs/design/rules/H9-title-phrase.md @@ -14,6 +14,7 @@ "His Grace John Smith" → title="His Grace" "Field Marshal Bernard Montgomery" → title="Field Marshal" "Sergeant Major John Smith" → title="Sergeant Major" + "Lord Chancellor John Smith" → title="Lord Chancellor" "Mr Dean Smith" → given="Dean" "SMITH, DEAN MR." → given="DEAN" "General Major John Smith" → given="Major" @@ -28,6 +29,7 @@ "Marquis Johnson" → given="Marquis" "Mr Deacon Smith" → given="Deacon" "Ms Queen Smith" → given="Queen" + "Chancellor Smith" → given="Chancellor" "Cheikh Anta Diop" → given="Cheikh" "Queen Mother Elizabeth" → title="Queen Mother" ``` @@ -54,6 +56,7 @@ "Dean Smith, MD" → ambiguities=("title-or-name",) "Prince Fielder" → ambiguities=("title-or-name",) "Dr. King" → ambiguities=("title-or-name",) + "Chancellor Smith" → ambiguities=("title-or-name",) "Grace Smith" → ambiguities=() "Bard Larsen" → ambiguities=() "GRACE SMITH" → ambiguities=() diff --git a/docs/migrate.rst b/docs/migrate.rst index cc4947cca..a387b715b 100644 --- a/docs/migrate.rst +++ b/docs/migrate.rst @@ -901,6 +901,11 @@ grep your fixtures for, with what 1.4 read: after a family comma is the first name: 1.4 read title ``Prince``, first ``Consort``; title ``Princess Royal``, last ``Anne``; and title ``Royal``, first ``Bales``. +- ``"Chancellor Smith"`` and ``"Lord Justice Leveson"`` (2.8) — + ``Chancellor`` is a title only inside a title phrase (``"Lord + Chancellor John Smith"``), and ``Lord Justice`` and ``Lady Justice`` are + one title: 1.4 read title ``Chancellor``, and title ``Lord``, first + ``Justice``. .. doctest:: @@ -1058,3 +1063,9 @@ grep your fixtures for, with what 1.4 read: ('Prince Consort', 'Albert') >>> HumanName("Princess Royal Anne").first, HumanName("Bales, Royal").first ('Anne', 'Royal') + >>> HumanName("Chancellor Smith").first + 'Chancellor' + >>> HumanName("Lord Chancellor John Smith").title + 'Lord Chancellor' + >>> HumanName("Lord Justice Leveson").title + 'Lord Justice' diff --git a/docs/release_log.rst b/docs/release_log.rst index b0ae14f5d..8b087fbe2 100644 --- a/docs/release_log.rst +++ b/docs/release_log.rst @@ -10,6 +10,7 @@ Release Log **Behavior Changes** + - **Fix the given name Chancellor reading as a title, and read Lord Justice as one title.** ``Chancellor Smith`` gives first ``Chancellor``, where 1.4.0 through 2.7.0 gave title ``Chancellor``; ``Smith, Chancellor`` reads the same. A chancellor written with the bare title reads it as a first name too (``Chancellor Merkel``), where a modifier, ``of`` or ``Lord`` keeps it (``Vice Chancellor Jane Smith``, ``Chancellor of the Exchequer``, ``Lord Chancellor John Smith``), and so do ``Deputy`` and ``Pro``. Since a listed title phrase holds it, a bare ``Chancellor`` opening a name reports a ``title-or-name`` ambiguity. ``Lord Justice Leveson`` and ``Lady Justice Arden`` give title ``Lord Justice`` and ``Lady Justice``, where 1.4.0 through 2.7.0 gave title ``Lord``, first ``Justice``. :issue:`913` - **Read the royal title phrases Queen Mother, King Consort, Queen Consort, Prince Consort, Princess Consort and Princess Royal as one title.** ``Prince Consort Albert`` gives title ``Prince Consort``, first ``Albert``, where 2.7.0 gave first ``Prince``, middle ``Consort``, last ``Albert``, and 1.4.0 title ``Prince``, first ``Consort``; ``Princess Royal Anne`` gives first ``Anne``. ``Royal`` after a family comma is the first name (``Bales, Royal`` gives first ``Royal``, where 1.4.0 through 2.7.0 gave title ``Royal``). Since a listed title phrase holds them, a bare ``King``, ``Queen``, ``Prince``, ``Princess`` or ``Royal`` opening a name now reports a ``title-or-name`` ambiguity, as ``Dean Smith`` does (``Prince Fielder``, ``Dr. King``). :issue:`913` - **Fix the given name Queen reading as a title.** ``Queen Latifah`` and ``Ms Queen Smith`` give first ``Queen``, where 1.4.0 through 2.7.0 gave title ``Queen`` and ``Ms Queen``; ``Smith, Queen`` reads the same. A monarch written with the bare title reads it as a first name too (``Queen Elizabeth II`` and ``Elizabeth II, Queen`` give first ``Queen``, last ``Elizabeth``), where a style keeps it (``Her Majesty Queen Elizabeth``), and so does ``of`` (``Queen of England``). :issue:`913` - **Fix the given names Deacon, Burgess and Ranger reading as titles.** ``Deacon Jones``, ``Burgess Meredith`` and ``Ranger Smith`` give first ``Deacon``, ``Burgess`` and ``Ranger``, where 1.4.0 through 2.7.0 gave title ``Deacon``, ``Burgess`` and ``Ranger``; ``Smith, Deacon`` reads the same. A cleric written with the bare title, or behind a salutation or ``Rev.``, reads it as a first name too (``The Rev. Deacon John Smith`` gives first ``Deacon``), where ``of`` keeps it (``Deacon of the Church Jane Smith``). ``Burgess Meredith`` reports a ``title-or-name`` ambiguity, since ``Chief Burgess`` is a title phrase. :issue:`913` diff --git a/nameparser/config/_compiled.py b/nameparser/config/_compiled.py index e02f5adbb..7edec1de6 100644 --- a/nameparser/config/_compiled.py +++ b/nameparser/config/_compiled.py @@ -190,7 +190,6 @@ 'ch.mo', 'chair', 'chairs', - 'chancellor', 'chaplain', 'charge', 'chargé', @@ -946,6 +945,7 @@ 'bard', 'buddha', 'burgess', + 'chancellor', 'cheikh', 'deacon', 'dean', @@ -1316,11 +1316,90 @@ 'chief wo5', 'chief न्यायमूर्ति', 'chief বিচারপতি', + 'deputy administrator', + 'deputy alderman', + 'deputy almoner', + 'deputy ambassador', + 'deputy arbitrator', + 'deputy attache', + 'deputy attaché', + 'deputy bailiff', + 'deputy burgess', + 'deputy ceo', + 'deputy cfo', + 'deputy chair', + 'deputy chairs', + 'deputy chancellor', + 'deputy charge', + 'deputy chargé', + 'deputy clerk', + 'deputy cllr', + 'deputy co-chair', + 'deputy co-chairs', + 'deputy commissioner', + 'deputy comptroller', + 'deputy controller', + 'deputy councillor', + 'deputy counsel', + 'deputy courtier', + "deputy d'affaires", + 'deputy dean', + 'deputy delegate', + 'deputy dir', + 'deputy director', + 'deputy dpty', + 'deputy envoy', + 'deputy gov', + 'deputy governor', + 'deputy headman', + 'deputy intendant', + 'deputy judge', + 'deputy justice', + 'deputy leader', + 'deputy mag', + 'deputy mag-judge', + 'deputy mag/judge', + 'deputy magistrate', + 'deputy magistrate-judge', + 'deputy mayor', + 'deputy member', + 'deputy minister', + 'deputy prefect', + 'deputy premier', + 'deputy pres', + 'deputy president', + 'deputy prin', + 'deputy principal', + 'deputy provost', + 'deputy pslc', + 'deputy pursuivant', + 'deputy registrar', + 'deputy rep', + 'deputy representative', + 'deputy secretary', + 'deputy senator', + 'deputy senior-judge', + 'deputy sheriff', + 'deputy speaker', + 'deputy swordbearer', + 'deputy sysselmann', + 'deputy treasurer', + 'deputy vc', + 'deputy verderer', + 'deputy vizier', + 'deputy warden', + 'deputy न्यायमूर्ति', + 'deputy বিচারপতি', 'king consort', + 'lady justice', + 'lord chancellor', + 'lord justice', + 'magistrate judge', 'major general', 'prince consort', 'princess consort', 'princess royal', + 'pro chancellor', 'queen consort', 'queen mother', 'sergeant major', diff --git a/nameparser/vocab/en.toml b/nameparser/vocab/en.toml index 87975aea7..ac116e97f 100644 --- a/nameparser/vocab/en.toml +++ b/nameparser/vocab/en.toml @@ -119,7 +119,7 @@ academic = { expands = "the address of a nurse, 'Nurse Smith'" } [[word]] text = "pro" -academic = { issue = 9, expands = "Pro Se Law Clerk", note = "academic rather than modifier since 2026-10-25 (#752): a part after a comma written 'Pro' is the person's role, which decision 10's modifier rule would read out of the title (decisions/vocabulary-model)" } +academic = { issue = 9, attaches = ["chancellor"], expands = "Pro Se Law Clerk", note = "attaches: Pro Chancellor (rules/H9, #913); academic rather than modifier since 2026-10-25 (#752): a part after a comma written 'Pro' is the person's role, which decision 10's modifier rule would read out of the title (decisions/vocabulary-model)" } [[word]] text = "abbess" @@ -403,11 +403,11 @@ nobility = { gender = "m", expands = "the rank the post-nominal knt names", issu [[word]] text = "lady" -nobility = { gender = "f", note = "stays out of GIVEN_NAME_TITLES, decided: the given-name form ('Lady Diana') is a courtesy style for the daughters of the senior ranks alone, while every wife takes the title or surname ('Lady Thatcher'), and the text does not carry the rank (#519)" } +nobility = { gender = "f", attaches = ["justice"], note = "attaches: Lady Justice (rules/H9, #913); stays out of GIVEN_NAME_TITLES, decided: the given-name form ('Lady Diana') is a courtesy style for the daughters of the senior ranks alone, while every wife takes the title or surname ('Lady Thatcher'), and the text does not carry the rank (#519)" } [[word]] text = "lord" -nobility = { gender = "m", note = "stays out of GIVEN_NAME_TITLES, decided: the given-name form ('Lord Peter') is a courtesy style for the children of the senior ranks alone, while every peer takes the title or surname ('Lord Byron'), and the text does not carry the rank (#519)" } +nobility = { gender = "m", attaches = ["chancellor", "justice"], note = "attaches: Lord Chancellor, Lord Justice (rules/H9, #913); stays out of GIVEN_NAME_TITLES, decided: the given-name form ('Lord Peter') is a courtesy style for the children of the senior ranks alone, while every peer takes the title or surname ('Lord Byron'), and the text does not carry the rank (#519)" } [[word]] text = "marchess" @@ -939,7 +939,9 @@ office = { same_as = "chair" } [[word]] text = "chancellor" -office = {} +office = { issue = 913, decided = 2026-10-28, note = "a title only inside a title phrase, its given reading the clash (rules/H9): 'Lord Chancellor Smith' and 'Vice Chancellor Jones' read the title, 'Chancellor Smith' the given name" } +given = { us_ssa = 2648, wikidata = 13, as_of = 2026-10-28, note = "US SSA: male births 2,643, female 5; Wikidata is a lower bound (United States 3)" } +family = { us_census_2010 = 4147, wikidata = 77, as_of = 2026-10-28, note = "US Census rank 7,974; Wikidata United Kingdom 11, United States 8" } [[word]] text = "chargé" @@ -1005,7 +1007,7 @@ office = {} [[word]] text = "deputy" -office = {} +office = { attaches = ["office"], issue = 913, note = "attaches: Deputy Chancellor, Deputy Judge (rules/H9), as chief does" } [[word]] text = "dpty" @@ -1041,7 +1043,7 @@ office = {} [[word]] text = "judge" -office = {} +office = { issue = 913, note = "kept a title, decided 2026-10-28 (decisions/H9): US SSA 3,826 births (all male), Census 10,453 (rank 3,414), Wikidata 7 given and 133 family, but in PSC 0 filers put it in the forename box and 0 in the title box, and in FEC 13 judges file it before their given name (FAMILY, JUDGE GIVEN, or alone after the comma) and would lose the title, against 2 fixes in all the local corpora (one ORCID, one PSC forename). The given count stands here rather than as a given reading, which would make it a title only inside a title phrase (rules/H9)" } [[word]] text = "justice" @@ -1055,7 +1057,7 @@ office = {} [[word]] text = "magistrate" -office = {} +office = { attaches = ["judge"], issue = 913, note = "attaches: Magistrate Judge, the US federal office (rules/H9)" } [[word]] text = "mag" diff --git a/tests/test_constants.py b/tests/test_constants.py index 7c85f6185..3e3386c30 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -32,10 +32,10 @@ class CustomConstants(Constants): pass c = CustomConstants() - c.titles.add('chancellor') - hn = HumanName("Chancellor Jane Smith", constants=c) + c.titles.add('bursar') + hn = HumanName("Bursar Jane Smith", constants=c) self.assertIs(hn.C, c) - self.m(hn.title, "Chancellor", hn) + self.m(hn.title, "Bursar", hn) self.m(hn.first, "Jane", hn) self.m(hn.last, "Smith", hn) diff --git a/tests/test_python_api.py b/tests/test_python_api.py index 3aff9024f..66d576a18 100644 --- a/tests/test_python_api.py +++ b/tests/test_python_api.py @@ -126,15 +126,15 @@ def test_name_instance_pickle_preserves_instance_config(self) -> None: """ # Passing None as the second argument gives this name its own Constants. hn = HumanName("Smith, Dr. John", Constants()) - hn.C.titles.add('chancellor') + hn.C.titles.add('bursar') hn.parse_full_name() # Safe: round-tripping a HumanName the test just built, not untrusted data. restored = pickle.loads(pickle.dumps(hn)) - self.assertIn('chancellor', restored.C.titles) - restored.full_name = "Chancellor Jane Smith" - self.assertEqual(restored.title, "Chancellor") + self.assertIn('bursar', restored.C.titles) + restored.full_name = "Bursar Jane Smith" + self.assertEqual(restored.title, "Bursar") def test_name_instance_deepcopy(self) -> None: """copy.deepcopy of a HumanName must round-trip. @@ -153,12 +153,12 @@ def test_name_instance_deepcopy(self) -> None: def test_name_instance_deepcopy_isolates_instance_config(self) -> None: """A deep-copied HumanName with its own config must be independent.""" hn = HumanName("Smith, Dr. John", Constants()) - hn.C.titles.add('chancellor') + hn.C.titles.add('bursar') dup = copy.deepcopy(hn) dup.C.titles.add('marker') - self.assertIn('chancellor', dup.C.titles) + self.assertIn('bursar', dup.C.titles) self.assertNotIn('marker', hn.C.titles) def test_pickle_default_name_preserves_singleton_identity(self) -> None: @@ -184,7 +184,7 @@ def test_pickle_default_name_preserves_singleton_identity(self) -> None: def test_pickle_instance_config_name_preserves_own_config(self) -> None: """A HumanName with its own Constants must not be collapsed onto CONSTANTS after pickle.""" hn = HumanName("Smith, Dr. John", Constants()) - hn.C.titles.add('chancellor') + hn.C.titles.add('bursar') hn.parse_full_name() self.assertTrue(hn.has_own_config) self.assertIsNot(hn.C, CONSTANTS) @@ -194,7 +194,7 @@ def test_pickle_instance_config_name_preserves_own_config(self) -> None: self.assertTrue(restored.has_own_config) self.assertIsNot(restored.C, CONSTANTS) - self.assertIn('chancellor', restored.C.titles) + self.assertIn('bursar', restored.C.titles) def test_shallow_copy_default_name_preserves_singleton_identity(self) -> None: """copy.copy of a default HumanName shares the CONSTANTS reference without hooks.""" diff --git a/tests/v2/cases.py b/tests/v2/cases.py index 8552a821d..aa73d3c68 100644 --- a/tests/v2/cases.py +++ b/tests/v2/cases.py @@ -12990,6 +12990,37 @@ def _check_cjk_shape_purity(self) -> None: {"given": "Ranger", "family": "Smith"}, classification="fix(#913)", notes="H9; read title 'Ranger' 1.4.0 through 2.7.0"), + Case("given_name_title_chancellor_reports_title_or_name", + "Chancellor Smith", + {"given": "Chancellor", "family": "Smith"}, + ambiguities=("title-or-name",), classification="fix(#913)", + notes="H9: 'Vice Chancellor' and 'Lord Chancellor' hold it; read " + "title 'Chancellor' 1.4.0 through 2.7.0"), + Case("chancellor_keeps_the_title_behind_lord", + "Lord Chancellor John Smith", + {"title": "Lord Chancellor", "given": "John", "family": "Smith"}, + classification="parity", + notes="H9: 'lord' attaches to 'chancellor' (#913)"), + Case("chancellor_keeps_the_title_behind_deputy", + "Deputy Chancellor Ann Lee", + {"title": "Deputy Chancellor", "given": "Ann", "family": "Lee"}, + classification="parity", + notes="H9: 'deputy' attaches to the office kind, as 'chief' does " + "(#913)"), + Case("chancellor_keeps_the_title_behind_pro", "Pro Chancellor Ann Lee", + {"title": "Pro Chancellor", "given": "Ann", "family": "Lee"}, + classification="parity", + notes="H9: 'pro' attaches to 'chancellor' (#913)"), + Case("lord_justice_is_one_title", "Lord Justice Leveson", + {"title": "Lord Justice", "family": "Leveson"}, + classification="fix(#913)", + notes="H9: 'lord' attaches to 'justice'; 1.4.0 through 2.7.0 read " + "title 'Lord', given 'Justice'"), + Case("lady_justice_is_one_title", "Lady Justice Arden", + {"title": "Lady Justice", "family": "Arden"}, + classification="fix(#913)", + notes="H9: 'lady' attaches to 'justice'; 1.4.0 through 2.7.0 read " + "title 'Lady', given 'Justice'"), Case("given_name_modifier_after_a_style", "Hon. Wing Lau", {"title": "Hon.", "given": "Wing", "family": "Lau"}, notes="H9: the modifier's test, not a contested word's style " diff --git a/tests/v2/test_cases.py b/tests/v2/test_cases.py index b422293c4..d93d9c18d 100644 --- a/tests/v2/test_cases.py +++ b/tests/v2/test_cases.py @@ -302,10 +302,12 @@ def test_the_field_sweep_sees_the_claims_it_checks() -> None: # Meredith', reporting title-or-name under three orders; 1415 -> # 1448 the same day, #913's royal title phrases: ten rows of bare # King, Queen, Prince and Princess now reporting title-or-name, and - # 'Royal Smith', each under three orders. - assert claims == 1448, ( - f"the field sweep checks {claims} claims, recorded as 1448 on " - f"2026-10-27") + # 'Royal Smith', each under three orders; 1448 -> 1451 on 2026-10-28, + # #913's 'Chancellor Smith', reporting title-or-name under three + # orders. + assert claims == 1451, ( + f"the field sweep checks {claims} claims, recorded as 1451 on " + f"2026-10-28") #: The kinds that report a fork between two readings of a word, so carry diff --git a/tools/differential/corpus_rules.jsonl b/tools/differential/corpus_rules.jsonl index bd38e596e..15d121b9d 100644 --- a/tools/differential/corpus_rules.jsonl +++ b/tools/differential/corpus_rules.jsonl @@ -97,6 +97,7 @@ "Carod i" "Carod i Rovira, Josep" "Carod y de Rovira i" +"Chancellor Smith" "Chas. Smith" "Chas. Smith, Ed" "Cheikh Anta Diop" @@ -634,6 +635,7 @@ "Lloret Palol II, Josep Antoni" "Lord Buddha Tamang" "Lord Chancellor" +"Lord Chancellor John Smith" "López, Ana García" "MSc Dr. med. univ." "Ma." diff --git a/tools/differential/snapshot.jsonl b/tools/differential/snapshot.jsonl index 248b99e0b..1839b7cd6 100644 --- a/tools/differential/snapshot.jsonl +++ b/tools/differential/snapshot.jsonl @@ -517,7 +517,8 @@ {"name": "Cecilija Hemiš Šteber", "given": "Cecilija", "middle": "Hemiš", "family": "Šteber", "initials": "C. H. Š."} {"name": "Cerda y Aragón, Tomás Antonio de la", "given": "Tomás", "middle": "Antonio", "family": "de la Cerda y Aragón", "ambiguities": ["PARTICLE_OR_GIVEN"], "alternatives": ["PARTICLE_OR_GIVEN: name as middle (declared)"], "initials": "T. A. C. A."} {"name": "Cetto, August von", "given": "August", "family": "von Cetto", "ambiguities": ["PARTICLE_OR_GIVEN"], "alternatives": ["PARTICLE_OR_GIVEN: name as middle (declared)"], "initials": "A. C."} -{"name": "Chancellor Jane Smith", "title": "Chancellor", "given": "Jane", "family": "Smith", "initials": "J. S."} +{"name": "Chancellor Jane Smith", "given": "Chancellor", "middle": "Jane", "family": "Smith", "ambiguities": ["TITLE_OR_NAME"], "alternatives": ["TITLE_OR_NAME: title as title (vocabulary)"], "initials": "C. J. S."} +{"name": "Chancellor Smith", "given": "Chancellor", "family": "Smith", "ambiguities": ["TITLE_OR_NAME"], "alternatives": ["TITLE_OR_NAME: title as title (vocabulary)"], "initials": "C. S."} {"name": "Chang, Andy C I", "given": "Andy", "middle": "C", "family": "Chang", "suffix": "I", "initials": "A. C. C."} {"name": "Charles Claude de La Billarderie d'Angiviller", "given": "Charles", "middle": "Claude", "family": "de La Billarderie d'Angiviller", "initials": "C. C. B. d.", "capitalized_force": "Charles Claude de la Billarderie D'Angiviller"} {"name": "Charles Wilkins", "given": "Charles", "family": "Wilkins", "initials": "C. W."} @@ -2293,6 +2294,7 @@ {"name": "Lon (Jr.) Williams", "given": "Lon", "middle": "Jr.", "family": "Williams", "initials": "L. J. W."} {"name": "Lord Buddha Tamang", "title": "Lord", "given": "Buddha", "family": "Tamang", "initials": "B. T."} {"name": "Lord Chancellor", "title": "Lord", "family": "Chancellor", "ambiguities": ["TITLE_OR_NAME"], "alternatives": ["TITLE_OR_NAME: title as title (vocabulary)"], "initials": "C."} +{"name": "Lord Chancellor John Smith", "title": "Lord Chancellor", "given": "John", "family": "Smith", "initials": "J. S."} {"name": "Lord God Almighty", "title": "Lord", "given": "God", "family": "Almighty", "initials": "G. A."} {"name": "Lord and of the Universe", "title": "Lord and of the Universe"} {"name": "Lord of the Universe", "title": "Lord of the Universe"}