Skip to content

Commit e1447f2

Browse files
derek73claude
andcommitted
Fix what the review of #597 found
- The release log and a case note blamed the bracket for every release's given-first reading of 山田 「タロー」 タロウ; in released versions the unclassified halfwidth kana did that, and the bracket became the blocker only after #594. The order moves with #594 and #597 together, and the prose says so. - "Kept as a middle" holds for the spaced rows only: 山田「タロー」太郎 was one given word. decisions.md#N1 and the five ledger comments now say which. - A v1 Constants restored from a pickle keeps its saved keys and does not gain the pair, the policy #273's pairs followed; decisions.md and the release bullet now say so. - Two _config_shim comments called every non-v1 pair #273's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 0b02c46 commit e1447f2

9 files changed

Lines changed: 36 additions & 24 deletions

File tree

‎docs/design/decisions.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ the fullwidth-colon marker (旧姓:佐藤 arrives as one word; the head-peel q
234234

235235
### N1 — the default delimiter pairs
236236

237-
- 2026-10-03 #597 — THE HALFWIDTH CORNER BRACKETS ARE A DEFAULT NICKNAME PAIR. `「」` (U+FF62/U+FF63) join `DEFAULT_NICKNAME_DELIMITERS` beside `「」`, and the v1 facade gains the matching `halfwidth_corner_brackets` key, so `HumanName` reads them as `parse()` does. They are the same punctuation as `「」` in JIS X 0201's narrower encoding, the legacy data halfwidth katakana comes from (#594), where they were the only corner brackets available, and they appear in no non-CJK text. Before this every release kept the clause in the name as a middle, brackets and all, and since #594 that cost the name its order too: the unclassified bracket kept `山田 「タロー」 タロウ` from being wholly East Asian script, so it read given 山田. A pair is not script-gated, so `John 「Jack」 Smith` reads nickname Jack as `John 「Jack」 Smith` does. Nothing else needs a halfwidth twin: Unicode has no halfwidth form of `『』` or of the fullwidth parentheses. MEASURED 2026-10-03: no corpus line held a halfwidth bracket before this change, so the three `fix(#597)` case rows are the whole population, and they move at every baseline. RECOMPUTE: parse `山田 「タロー」 タロウ`, `山田「タロー」太郎` and `John 「Jack」 Smith` here and on each baseline from PyPI and read `nickname` beside the name fields.
237+
- 2026-10-03 #597 — THE HALFWIDTH CORNER BRACKETS ARE A DEFAULT NICKNAME PAIR. `「」` (U+FF62/U+FF63) join `DEFAULT_NICKNAME_DELIMITERS` beside `「」`, and the v1 facade gains the matching `halfwidth_corner_brackets` key, so `HumanName` reads them as `parse()` does. They are the same punctuation as `「」` in JIS X 0201's narrower encoding, the legacy data halfwidth katakana comes from (#594), where they were the only corner brackets available, and they appear in no non-CJK text. Before this every release kept the clause in the name, brackets and all — a middle where it stood spaced (`山田 「タロー」 タロウ`), part of one given word where it was glued (`山田「タロー」太郎`) — and since #594 the bracket also cost the spaced name its order: the halfwidth kana now classify, but the unclassified bracket kept `山田 「タロー」 タロウ` from being wholly East Asian script, so it read given 山田 (in released versions the unclassified kana did that on their own). A v1 `Constants` restored from a pickle keeps the keys it was saved with and so does not gain the pair, the same policy #273's pairs followed: restored configuration is never widened behind the caller's back. A pair is not script-gated, so `John 「Jack」 Smith` reads nickname Jack as `John 「Jack」 Smith` does. Nothing else needs a halfwidth twin: Unicode has no halfwidth form of `『』` or of the fullwidth parentheses. MEASURED 2026-10-03: no corpus line held a halfwidth bracket before this change, so the three `fix(#597)` case rows are the whole population, and they move at every baseline. RECOMPUTE: parse `山田 「タロー」 タロウ`, `山田「タロー」太郎` and `John 「Jack」 Smith` here and on each baseline from PyPI and read `nickname` beside the name fields.
238238

239239
### N3 — the lone-word nickname rule
240240

‎docs/release_log.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Release Log
7070

7171
- **Fix a katakana name typed with a separate voicing mark being read family-first.** ``HumanName("ア゙イ タロウ")`` gives first ``ア゙イ``, last ``タロウ``, as ``アイ タロウ`` does, where 2.1 through 2.3 gave last ``ア゙イ``, first ``タロウ``. A dakuten or handakuten after a kana that has no precomposed voiced form (``ア゙``, ``ン゙``), or the spacing ``゛`` and ``゜``, was read as hiragana, which made the name Japanese by script and turned it around; the mark now belongs to the kana it follows. It flipped the rest of the name too: ``マイケル ア゙イ`` gives first ``マイケル`` where it gave last ``マイケル``. Hiragana names and kanji-and-kana names with such a mark read as before. See the ``W4`` entry of ``docs/design/decisions.md`` (closes #596)
7272

73-
- **Fix halfwidth corner brackets not being read as a nickname.** ``HumanName("山田 「タロー」 タロウ")`` gives nickname ``タロー``, last ``山田``, first ``タロウ``, where every release gave middle ``「タロー」`` and, the bracket keeping the name from reading as Japanese, first ``山田``. The halfwidth ``「」`` are the corner brackets of legacy JIS X 0201 data, the same punctuation as ``「」``, and are now a default nickname pair in both APIs: ``DEFAULT_NICKNAME_DELIMITERS`` gains ``("「", "」")`` and the 1.x ``nickname_delimiters`` gains the key ``halfwidth_corner_brackets``. They are not limited to Japanese text: ``John 「Jack」 Smith`` gives nickname ``Jack`` where it gave middle ``「Jack」``. See the ``N1`` entry of ``docs/design/decisions.md`` (closes #597)
73+
- **Fix halfwidth corner brackets not being read as a nickname.** ``HumanName("山田 「タロー」 タロウ")`` gives nickname ``タロー``, last ``山田``, first ``タロウ``, where every release gave middle ``「タロー」`` and first ``山田`` (the order moves with the halfwidth katakana change above; the bracket would otherwise have blocked it). The halfwidth ``「」`` are the corner brackets of legacy JIS X 0201 data, the same punctuation as ``「」``, and are now a default nickname pair in both APIs: ``DEFAULT_NICKNAME_DELIMITERS`` gains ``("「", "」")`` and the 1.x ``nickname_delimiters`` gains the key ``halfwidth_corner_brackets``. They are not limited to Japanese text: ``John 「Jack」 Smith`` gives nickname ``Jack`` where it gave middle ``「Jack」``. A ``Constants`` restored from a pickle keeps the keys it was saved with, as it did when 2.0 added the other typographic pairs. See the ``N1`` entry of ``docs/design/decisions.md`` (closes #597)
7474

7575
**Additions**
7676

‎nameparser/_config_shim.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,9 @@ def __setstate__(self, state: dict[str, object]) -> None:
435435

436436
#: The named delimiter buckets, translated to the ``Policy``
437437
#: (open, close) pairs they stand for. The first three are
438-
#: v1's; the rest are the #273 typographic conventions, named so the
439-
#: v1 keyed idioms (pop/move/del) work on them like the originals.
438+
#: v1's; the rest are the #273 typographic conventions plus #597's
439+
#: halfwidth corner brackets, named so the v1 keyed idioms
440+
#: (pop/move/del) work on them like the originals.
440441
#: Keep in sync with DEFAULT_NICKNAME_DELIMITERS in _policy.py (pinned
441442
#: by the default-Constants equality test).
442443
_SENTINEL_PAIRS = {
@@ -477,7 +478,7 @@ class -- via ``TupleManager.__reduce__``'s ``(type(self), (), state)``
477478
class _DelimiterManager(TupleManager):
478479
"""v1 ``nickname_delimiters``/``maiden_delimiters`` bucket. In 2.0
479480
only the named sentinels in ``_DELIMITER_SENTINELS`` exist (the v1
480-
trio plus the #273 typographic pairs) -- assigning any
481+
trio plus the typographic pairs, #273 and #597) -- assigning any
481482
other key raises so a caller reaches for a custom-delimiter Policy
482483
kwarg instead of a dict entry that silently does nothing. ``pop()``/
483484
``__setitem__``/``__delitem__`` stay open (inherited) for the

‎tests/v2/cases.py‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5995,10 +5995,11 @@ def _check_cjk_shape_purity(self) -> None:
59955995
"same punctuation as 「」 in JIS X 0201's narrower "
59965996
"encoding, the data halfwidth katakana comes from (#594). "
59975997
"2.3.0 and every earlier release left the clause in the "
5998-
"name as a middle 「タロー」, and the unclassified bracket "
5999-
"kept the name from being wholly East Asian script, so "
6000-
"it read given 山田 too. Extracted, the rest is kanji "
6001-
"plus katakana and takes the kana license"),
5998+
"name as a middle 「タロー」 and read given 山田, the "
5999+
"halfwidth kana being unclassified until #594. Since "
6000+
"#594 the bracket alone kept the name from being wholly "
6001+
"East Asian script; extracted, the rest is kanji plus "
6002+
"katakana and takes the kana license"),
60026003
Case("cjk_halfwidth_corner_bracket_unspaced_nickname", '山田「タロー」太郎',
60036004
{"family": "山田", "given": "太郎", "nickname": "タロー"},
60046005
classification="fix(#597)",

‎tools/differential/expected_since_1.4.0.toml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4968,7 +4968,8 @@ fields = ["title", "given"]
49684968
# 「」 (U+FF62/U+FF63) join DEFAULT_NICKNAME_DELIMITERS beside 「」, and
49694969
# the v1 facade's nickname_delimiters gains halfwidth_corner_brackets,
49704970
# so a clause they enclose is lifted out as the nickname (rules.md#N1)
4971-
# where every release left it in the name as a middle. With the
4971+
# where every release left it in the name -- a middle where spaced,
4972+
# part of one given word where glued. With the
49724973
# unclassified bracket gone, '山田 「タロー」 タロウ' is kanji plus katakana and
49734974
# takes the kana license; the unspaced '山田「タロー」太郎' divides at the
49744975
# extracted clause; 'John 「Jack」 Smith' shows the pair is not
@@ -4982,7 +4983,8 @@ fields = ["title", "given"]
49824983

49834984
[[change]]
49844985
issue = "fix(#597) halfwidth corner brackets enclose a nickname"
4985-
# The clause leaves middle for nickname in all three; the two Japanese
4986-
# names also take their script order, family 山田.
4986+
# The clause moves to nickname in all three, out of middle in the two
4987+
# spaced names and out of the one given word in '山田「タロー」太郎'; the
4988+
# two Japanese names also take their script order, family 山田.
49874989
name_regex = "^(?:山田 「タロー」 タロウ|山田「タロー」太郎|John 「Jack」 Smith)$"
49884990
fields = ["given", "middle", "family", "nickname"]

‎tools/differential/expected_since_2.0.0.toml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4041,7 +4041,8 @@ fields = ["title", "given", "_ambiguities"]
40414041
# 「」 (U+FF62/U+FF63) join DEFAULT_NICKNAME_DELIMITERS beside 「」, and
40424042
# the v1 facade's nickname_delimiters gains halfwidth_corner_brackets,
40434043
# so a clause they enclose is lifted out as the nickname (rules.md#N1)
4044-
# where every release left it in the name as a middle. With the
4044+
# where every release left it in the name -- a middle where spaced,
4045+
# part of one given word where glued. With the
40454046
# unclassified bracket gone, '山田 「タロー」 タロウ' is kanji plus katakana and
40464047
# takes the kana license; the unspaced '山田「タロー」太郎' divides at the
40474048
# extracted clause; 'John 「Jack」 Smith' shows the pair is not
@@ -4055,7 +4056,8 @@ fields = ["title", "given", "_ambiguities"]
40554056

40564057
[[change]]
40574058
issue = "fix(#597) halfwidth corner brackets enclose a nickname"
4058-
# The clause leaves middle for nickname in all three; the two Japanese
4059-
# names also take their script order, family 山田.
4059+
# The clause moves to nickname in all three, out of middle in the two
4060+
# spaced names and out of the one given word in '山田「タロー」太郎'; the
4061+
# two Japanese names also take their script order, family 山田.
40604062
name_regex = "^(?:山田 「タロー」 タロウ|山田「タロー」太郎|John 「Jack」 Smith)$"
40614063
fields = ["given", "middle", "family", "nickname"]

‎tools/differential/expected_since_2.1.0.toml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3986,7 +3986,8 @@ fields = ["given", "family"]
39863986
# 「」 (U+FF62/U+FF63) join DEFAULT_NICKNAME_DELIMITERS beside 「」, and
39873987
# the v1 facade's nickname_delimiters gains halfwidth_corner_brackets,
39883988
# so a clause they enclose is lifted out as the nickname (rules.md#N1)
3989-
# where every release left it in the name as a middle. With the
3989+
# where every release left it in the name -- a middle where spaced,
3990+
# part of one given word where glued. With the
39903991
# unclassified bracket gone, '山田 「タロー」 タロウ' is kanji plus katakana and
39913992
# takes the kana license; the unspaced '山田「タロー」太郎' divides at the
39923993
# extracted clause; 'John 「Jack」 Smith' shows the pair is not
@@ -4000,7 +4001,8 @@ fields = ["given", "family"]
40004001

40014002
[[change]]
40024003
issue = "fix(#597) halfwidth corner brackets enclose a nickname"
4003-
# The clause leaves middle for nickname in all three; the two Japanese
4004-
# names also take their script order, family 山田.
4004+
# The clause moves to nickname in all three, out of middle in the two
4005+
# spaced names and out of the one given word in '山田「タロー」太郎'; the
4006+
# two Japanese names also take their script order, family 山田.
40054007
name_regex = "^(?:山田 「タロー」 タロウ|山田「タロー」太郎|John 「Jack」 Smith)$"
40064008
fields = ["given", "middle", "family", "nickname"]

‎tools/differential/expected_since_2.2.0.toml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,7 +2382,8 @@ fields = ["given", "family"]
23822382
# 「」 (U+FF62/U+FF63) join DEFAULT_NICKNAME_DELIMITERS beside 「」, and
23832383
# the v1 facade's nickname_delimiters gains halfwidth_corner_brackets,
23842384
# so a clause they enclose is lifted out as the nickname (rules.md#N1)
2385-
# where every release left it in the name as a middle. With the
2385+
# where every release left it in the name -- a middle where spaced,
2386+
# part of one given word where glued. With the
23862387
# unclassified bracket gone, '山田 「タロー」 タロウ' is kanji plus katakana and
23872388
# takes the kana license; the unspaced '山田「タロー」太郎' divides at the
23882389
# extracted clause; 'John 「Jack」 Smith' shows the pair is not
@@ -2396,7 +2397,8 @@ fields = ["given", "family"]
23962397

23972398
[[change]]
23982399
issue = "fix(#597) halfwidth corner brackets enclose a nickname"
2399-
# The clause leaves middle for nickname in all three; the two Japanese
2400-
# names also take their script order, family 山田.
2400+
# The clause moves to nickname in all three, out of middle in the two
2401+
# spaced names and out of the one given word in '山田「タロー」太郎'; the
2402+
# two Japanese names also take their script order, family 山田.
24012403
name_regex = "^(?:山田 「タロー」 タロウ|山田「タロー」太郎|John 「Jack」 Smith)$"
24022404
fields = ["given", "middle", "family", "nickname"]

‎tools/differential/expected_since_2.3.0.toml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,8 @@ fields = ["given", "family"]
16281628
# 「」 (U+FF62/U+FF63) join DEFAULT_NICKNAME_DELIMITERS beside 「」, and
16291629
# the v1 facade's nickname_delimiters gains halfwidth_corner_brackets,
16301630
# so a clause they enclose is lifted out as the nickname (rules.md#N1)
1631-
# where every release left it in the name as a middle. With the
1631+
# where every release left it in the name -- a middle where spaced,
1632+
# part of one given word where glued. With the
16321633
# unclassified bracket gone, '山田 「タロー」 タロウ' is kanji plus katakana and
16331634
# takes the kana license; the unspaced '山田「タロー」太郎' divides at the
16341635
# extracted clause; 'John 「Jack」 Smith' shows the pair is not
@@ -1642,8 +1643,9 @@ fields = ["given", "family"]
16421643

16431644
[[change]]
16441645
issue = "fix(#597) halfwidth corner brackets enclose a nickname"
1645-
# The clause leaves middle for nickname in all three; the two Japanese
1646-
# names also take their script order, family 山田.
1646+
# The clause moves to nickname in all three, out of middle in the two
1647+
# spaced names and out of the one given word in '山田「タロー」太郎'; the
1648+
# two Japanese names also take their script order, family 山田.
16471649
# `_ambiguities` moves on '山田「タロー」太郎', which 2.3 read as one name
16481650
# word and reported given-or-family (#449); extracted, the Han
16491651
# script order decides the two pieces and nothing is reported.

0 commit comments

Comments
 (0)