Skip to content

A title displaces a particle out of leading position, so Dr. Van Johnson reads as one surname #367

Description

@derek73

A leading particle deliberately does not chain — that is what makes Van Johnson read as given Van, family Johnson rather than as one surname. But the exception is keyed on piece index 0, so a title displaces the particle out of leading position and the chain fires. Identical name text then parses differently depending on whether a title precedes it:

Van Johnson         given='Van'          family='Johnson'
Dr. Van Johnson     given=''             family='Van Johnson'
Sir Van Johnson     given='Van Johnson'  family=''            (no surname at all)

The last row compounds it: with a given-name title, post_rules rule 1's carve-out then hands the whole chain to given, so the name ends with no surname.

Decision: titles are transparent to the leading-particle exception

A title is not part of the name, so it should not change whether the name begins with a particle. Dr. Van Johnson and Sir Van Johnson should read as Van Johnson does.

The change is one line in nameparser/_pipeline/_group.py — the chain loop's if k == 0 becomes "the first piece that is not a title".

Measured: prototype vs current

Changes — every one is a titled name whose first name-piece is a particle:

                        current                              prototype
Dr. Van Johnson         family='Van Johnson'                 given='Van'  family='Johnson'
Dr. Van Johnson Smith   family='Van Johnson Smith'           given='Van'  middle='Johnson' family='Smith'
Mr. Van Nguyen          family='Van Nguyen'                  given='Van'  family='Nguyen'
Sir Van Johnson         given='Van Johnson'  family=''       given='Van'  family='Johnson'
Sir Van Johnson Smith   given='Van Johnson Smith'            given='Van'  middle='Johnson' family='Smith'
Sir de Mesnil           given='de Mesnil'    family=''       given=''     family='de Mesnil'
Sheik Abu Bakar         given='Abu Bakar'    family=''       given='Abu'  family='Bakar'

Unchanged, including the exact shapes v1 worried about:

Mr. Smith / Mrs. Smith / Mr. Nguyen / Mr. John Smith
Sir Ian / Sir Ian McKellen / King Henry
Van Johnson / de Mesnil / de Mesnil Garcia   (no title)
Dr. de Mesnil
Sheik abdul salam

This fixes a v1-era xfail that says it cannot be fixed

tests/test_first_name.py:

@pytest.mark.xfail
def test_first_name_is_prefix_if_three_parts(self) -> None:
    """Not sure how to fix this without breaking Mr and Mrs"""
    hn = HumanName("Mr. Van Nguyen")
    self.m(hn.first, "Van", hn)
    self.m(hn.last, "Nguyen", hn)

The prototype makes it pass. And it does not break Mr and Mrs — every bare Mr./Mrs. Surname shape is byte-identical, because those have no particle to displace. v1's concern was about the fix it had in mind, not about this one.

And it reverses a case row that pins the opposite

tests/v2/cases.py:

Case("titled_ambiguous_particle_chains", "Dr. Van Johnson",
     {"title": "Dr.", "family": "Van Johnson"},
     ambiguities=("particle-or-given",),
     notes="... a leading title shifts Van off the given position, the prefix
            chain fires, and the fork is reported from group rather than
            assign (v1 parity on the fields)")

Mr. Van Nguyen and Dr. Van Johnson are the same shape. The repository currently pins one as broken-and-unfixable and the other as correct-by-v1-parity. This resolves the contradiction in favour of the xfail. The row must be rewritten to given='Van', family='Johnson'.

Note "v1 parity on the fields" is accurate — 1.4.0 does give last='Van Johnson' — but v1 also ships the xfail calling the same shape wrong, so parity is not the tiebreaker it appears to be.

The fork is still reported either way: under the change Dr. Van Johnson emits particle-or-given from _assign instead of from _group, i.e. from the same place the untitled Van Johnson reports it.

Blast radius

Nine test failures on the prototype, all coherent:

test why
test_first_name_is_prefix_if_three_parts the xfail now passes — this is the fix
titled_ambiguous_particle_chains + its facade twin the case row above; rewrite
4 × test_chained_particle_detail_* _group's PARTICLE_OR_GIVEN emitter loses its only reachable case, since titles were what displaced the particle
test_ambiguous_particle_reports_both_branches_of_its_fork same cause
test_add_title fallout; investigate

Whether _group's emitter becomes dead code needs checking — if a non-title piece can never precede a chaining particle, the emitter and its tests should go.

Scope and verification

Changes default-order output — the first change in this sequence to move the default-order corpus, byte-identical through #354, #358 and #361. Needs a tools/differential pass at all three baselines with ledger entries.

Related

Metadata

Metadata

Assignees

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions