Skip to content

Commit 40e37c2

Browse files
committed
fix: address PR review feedback (docstrings, docs prose, test clarity)
1 parent d96fe42 commit 40e37c2

4 files changed

Lines changed: 35 additions & 18 deletions

File tree

docs/customize.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ Russian data in formal order (``Surname GivenName Patronymic``), enable
7979
('Ivan', 'Ivanovich', 'Ivanov')
8080

8181
Detection is anchored on a recognised East-Slavic patronymic suffix
82-
(``-ovich``, ``-ovna``, ``-evich``, ``-evna``, ``-ichna``, and several
83-
irregular forms; same patterns in Cyrillic). A comma in the input is treated as
84-
an explicit field-order declaration and suppresses reordering.
82+
(``-ovich``, ``-ovna``, ``-evich``, ``-evna``, ``-ichna``, and the irregular
83+
forms ``-ilyich``, ``-kuzmich``, ``-lukich``, ``-fomich``, ``-fokich``; same
84+
patterns in Cyrillic). A comma activates the parser's standard
85+
Last, First Middle path, which already handles Russian formal order —
86+
reordering is suppressed to avoid a double-transformation.
8587

8688
**Opt-in tradeoff:** when the flag is on, any name whose last token happens to
8789
end in a patronymic suffix is reordered — including Western names with

nameparser/config/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,18 @@ class Constants:
347347
If set, detects names in Russian formal order (``Surname GivenName Patronymic``)
348348
by recognizing a trailing East-Slavic patronymic suffix on the last token, and
349349
rotates the three name parts so that ``first``/``middle``/``last`` map to
350-
given name / patronymic / surname respectively.
350+
given name / patronymic / surname respectively. Detection requires exactly one
351+
token in each of first, middle, and last; names with multi-part given names or
352+
multiple middle names are left unchanged.
351353
352354
Opt-in because a Western person whose surname happens to end in a patronymic
353355
suffix (e.g. ``"David Michael Abramovich"``) will be reordered incorrectly
354356
when the flag is on. Enable only when your data is predominantly Russian
355357
formal-order names.
356358
359+
For per-instance control without a shared ``Constants``, pass a dedicated
360+
instance: ``HumanName("...", constants=Constants(patronymic_name_order=True))``.
361+
357362
.. doctest::
358363
359364
>>> from nameparser import HumanName

nameparser/parser.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,14 @@ def is_an_initial(self, value: str) -> bool:
648648
return bool(self.C.regexes.initial.match(value))
649649

650650
def is_patronymic(self, piece: str) -> bool:
651+
"""
652+
Return True if ``piece`` ends with a recognised East-Slavic patronymic
653+
suffix, checked against both Latin-script and Cyrillic patterns in
654+
``self.C.regexes``. Latin suffixes: ``-ovich``, ``-ovna``, ``-evich``,
655+
``-evna``, ``-ichna``, and the irregular forms ``-ilyich``, ``-kuzmich``,
656+
``-lukich``, ``-fomich``, ``-fokich``. Cyrillic equivalents are matched
657+
by a separate pattern.
658+
"""
651659
return bool(
652660
self.C.regexes.patronymic.search(piece)
653661
or self.C.regexes.patronymic_cyrillic.search(piece)
@@ -696,7 +704,9 @@ def handle_patronymic_name_order(self) -> None:
696704
When patronymic_name_order is enabled, detect Russian formal order
697705
(Surname GivenName Patronymic) and rotate to Western order.
698706
Fires only for no-comma, single-token first/middle/last where the last
699-
token is a patronymic and the middle token is not.
707+
token is a patronymic and the middle token is not. Title, suffix, and
708+
nickname parts do not affect this guard — reordering proceeds regardless
709+
of whether they are present.
700710
"""
701711
if (
702712
not self._had_comma

tests/test_patronymic_order.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ def test_suffix_preserved(self) -> None:
158158
assert n.last == "Ivanov"
159159
assert n.suffix == "Jr."
160160

161+
def test_western_patronymic_surname_reordered_when_flag_on(self) -> None:
162+
# Documented opt-in tradeoff: a Western name whose last token ends in a
163+
# patronymic suffix is reordered incorrectly. Not a bug to fix.
164+
n = self.hn("David Michael Abramovich")
165+
assert n.first == "Michael"
166+
assert n.middle == "Abramovich"
167+
assert n.last == "David"
168+
161169

162170
class PatronymicNameOrderGuardsTests(HumanNameTestBase):
163171
"""Names that must NOT be reordered even when the flag is on."""
@@ -189,10 +197,11 @@ def test_two_token_name(self) -> None:
189197
assert n.last == "Abramovich"
190198

191199
def test_no_patronymic(self) -> None:
192-
# No patronymic anchor → not reordered
193-
n = self.hn("Mogilny Alexander")
194-
assert n.first == "Mogilny"
195-
assert n.last == "Alexander"
200+
# Three tokens but no patronymic suffix on last → not reordered
201+
n = self.hn("Ivanov Ivan Petrov")
202+
assert n.first == "Ivanov"
203+
assert n.middle == "Ivan"
204+
assert n.last == "Petrov"
196205

197206
def test_western_name_unchanged(self) -> None:
198207
n = self.hn("John Michael Smith")
@@ -212,15 +221,6 @@ def test_comma_guard_patronymic_form_surname(self) -> None:
212221
n = self.hn("Sergeevich, Ivan Petrov")
213222
assert n.last == "Sergeevich"
214223

215-
def test_western_patronymic_surname_reordered_when_flag_on(self) -> None:
216-
# With the flag ON a western patronymic-form surname is reordered.
217-
# This is the documented opt-in tradeoff — not a bug to fix.
218-
n = self.hn("David Michael Abramovich")
219-
assert n.first == "Michael"
220-
assert n.middle == "Abramovich"
221-
assert n.last == "David"
222-
223-
224224
class PatronymicNameOrderFlagOffTests(HumanNameTestBase):
225225
"""With default Constants (flag=False) nothing changes."""
226226

0 commit comments

Comments
 (0)