Skip to content

Commit 2373240

Browse files
derek73claude
andauthored
fix: honor single-char symbol conjunctions regardless of name length (#173)
* fix: honor single-char symbol conjunctions regardless of name length (closes #151) The `join_on_conjunction` heuristic skipped single-character conjunctions when `total_length < 4` to avoid treating alphabetic initials like `e` or `y` as conjunctions. This inadvertently also skipped non-alphabetic symbols like `&`, which can never be initials. Fix: only apply the "treat as initial" fallback when the character is alphabetic. Non-alphabetic conjunctions (e.g. `&`) are now always joined regardless of name length, so `"Mr. & Mrs. John Smith"` correctly parses the title as `"Mr. & Mrs."`. * test: add boundary tests for single-char alpha vs symbol conjunction handling Documents the intentional asymmetry introduced in #151: non-alpha symbols like & are always honored as conjunctions, while single-char alpha conjunctions (e, y) still fall back to initial treatment in short names. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b488e97 commit 2373240

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

nameparser/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ def join_on_conjunctions(self, pieces: list[str], additional_parts_count: int =
870870
conj_index = [i for i, piece in enumerate(pieces) if self.is_conjunction(piece)]
871871

872872
for i in conj_index:
873-
if len(pieces[i]) == 1 and total_length < 4:
873+
if len(pieces[i]) == 1 and total_length < 4 and pieces[i].isalpha():
874874
# if there are only 3 total parts (minus known titles, suffixes
875875
# and prefixes) and this conjunction is a single letter, prefer
876876
# treating it as an initial rather than a conjunction.

tests/test_conjunctions.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,28 @@ def test_couple_titles(self) -> None:
111111
self.m(hn.first, "John and Jane", hn)
112112
self.m(hn.last, "Smith", hn)
113113

114+
def test_couple_titles_ampersand_conjunction(self) -> None:
115+
# issue 151: single-char conjunctions in the conjunctions list should
116+
# be honored even when total_length < 4
117+
hn = HumanName('Mr. & Mrs. John Smith')
118+
self.m(hn.title, "Mr. & Mrs.", hn)
119+
self.m(hn.first, "John", hn)
120+
self.m(hn.last, "Smith", hn)
121+
122+
def test_ampersand_conjunction_short_name_no_titles(self) -> None:
123+
# & is non-alpha so it should always be honored as a conjunction,
124+
# even when total_length < 4 (no titles to inflate the count)
125+
hn = HumanName('John & Jane')
126+
self.m(hn.first, "John & Jane", hn)
127+
128+
def test_single_char_alpha_conjunction_still_treated_as_initial_when_short(self) -> None:
129+
# single-char alpha conjunctions (e, y) are still treated as initials
130+
# when total_length < 4; only non-alpha symbols like & bypass this guard
131+
hn = HumanName('John y Jane')
132+
self.m(hn.first, "John", hn)
133+
self.m(hn.middle, "y", hn)
134+
self.m(hn.last, "Jane", hn)
135+
114136
def test_title_with_three_part_name_last_initial_is_suffix_uppercase_no_period(self) -> None:
115137
hn = HumanName("King John Alexander V")
116138
self.m(hn.title, "King", hn)

0 commit comments

Comments
 (0)