Skip to content

parse("Smith, PSM I") reads "PSM" as a given name — a suffix run breaks on a trailing I or V #430

Description

@derek73

A comma suffix run terminates early when its last word is I or V, the two roman numerals that are also initial-shaped. Only on the one-word-family path:

parse("John Smith, PSM I")   # -> given=John, family=Smith, suffix='PSM I'   correct
parse("Smith, PSM I")        # -> given='PSM', family=Smith, suffix='I'
parse("Smith, PSM I.")       # -> given='PSM', family=Smith, suffix='I.'
parse("Smith, PSM II")       # -> family=Smith, suffix='PSM, II'   (roles right; render is #429)

Two distinct wrong outcomes, depending on whether the run's first word is also in TITLES:

input today wanted
Smith, PSM I given=PSM, suffix=I family=Smith, suffix=PSM I
Smith, PhD I given=PhD, suffix=I family=Smith, suffix=PhD I
Smith, CBE I given=CBE, suffix=I family=Smith, suffix=CBE I
Smith, MD I title=MD, given=I family=Smith, suffix=MD I
Smith, Jr. I title=Jr., given=I family=Smith, suffix=Jr. I

The MD / Jr. rows reach the wrong answer through the leading-title peel instead (md is in TITLES by the deliberate #296 deviation; Jr. via _is_leading_title's period-abbreviation inference). A fix verified only on PSM would leave those shapes broken and still look green.

The rule this should follow

I and V are treated cautiously because they are the only suffix words that could equally be initials. But after a comma and after a suffix word, they are describing that suffixPSM I is Professional Scrum Master level I — not serving as a generational marker and not standing in for a name.

An initial in that position is not a supported name shape, so the period should be ignored there too: Smith, PSM I. reads as suffix PSM I., not as an initial.

This is already what the full-name path does — parse("John Smith, PSM I.") gives suffix 'PSM I.' — so the fix is to bring the one-word-family path into line with an existing correct reading, not to invent a new one.

Out of scope

The no-comma shapes are unchanged by this issue, where I / V genuinely can be name material:

parse("John Smith V")      # -> suffix='V'
parse("John Smith V.")     # -> middle=Smith, family='V.'
parse("John Smith MA V.")  # -> middle='Smith MA', family='V.'

Where a trailing dotted word lands on the no-comma path is the separate trailing-word question tracked by #316; this issue takes no position on it.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions