Skip to content

Commit 3edfe4e

Browse files
derek73claude
andcommitted
docs: move stranded recipes out of the release log
Actionable knowledge had accumulated in release_log.rst, which readers consult once at upgrade time and never search for how-to. Relocate it to the task-oriented pages. migrate.rst "Before you upgrade" gains: - The pre-1.3.0 pickle constraint, called out as an ordering hazard. A Constants blob written by 1.2.x must be re-pickled ON 1.3/1.4; after upgrading, the code that could rewrite it is gone. Every other migration step is fixable afterwards, which is why this one cannot live in a changelog. - A replacement table for the warned removals (decode() for bytes, set(manager), discard(), Constants()/CONSTANTS.copy(), plain attribute assignment, .get()). The section previously assumed a clean -W error::DeprecationWarning run and offered nothing to the readers who most need it -- those who didn't get one. - A pointer to tools/differential/ for diffing 1.4 vs 2.0 over the reader's own corpus, noting it is source-repo tooling, not installed. migrate.rst also inlines the casefold example (STRASSE/Straße) and the two behavior-diff shapes worth grepping fixtures for, both of which previously redirected to the release log. locales.rst gains "What works without a pack". The page listed two packs, so a reader with Arabic or Hebrew data concluded there was no support -- while the five-script default vocabulary from #269 handles it out of the box and was documented nowhere but the changelog. Also records which entries are deliberately held back and how to add them. Writing that last example surfaced the reason to document it: adding an honorific to given_name_titles ALONE silently does nothing, because the field is a marker over titles rather than its own vocabulary. The doctest caught it; the text now says so. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9be1df7 commit 3edfe4e

2 files changed

Lines changed: 115 additions & 7 deletions

File tree

docs/locales.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,54 @@ patronymics, Turkic patronymic markers, and so on. Packs apply only
77
when you ask for one by name, and every pack makes the same promise:
88
a pack never changes a name it doesn't declare.
99

10+
What works without a pack
11+
--------------------------
12+
13+
Most international names need no pack at all. The default vocabulary
14+
covers five scripts — Latin, Cyrillic, Greek, Arabic and Hebrew, plus
15+
Devanagari titles — so honorifics, conjunctions and name particles in
16+
those scripts are recognized out of the box:
17+
18+
.. doctest::
19+
20+
>>> from nameparser import parse
21+
>>> name = parse("الشيخ محمد بن سلمان")
22+
>>> name.title, name.given, name.family
23+
('الشيخ', 'محمد', 'بن سلمان')
24+
>>> parse("عبد الرحمن محمد").given
25+
'عبد الرحمن'
26+
27+
Native-script entries are safe to enable by default precisely because
28+
they cannot collide with Latin-script names. That rules out the
29+
reverse: transliterations like ``sri``/``shri`` are *not* in the
30+
default vocabulary, because they are also ordinary given names in
31+
Latin script. The same conservatism holds back a handful of native
32+
entries that collide within their own script — bare ``سيد`` and
33+
``شيخ`` (common given names), Hebrew ``רב`` (an ordinary word), the
34+
Arabic ``د.`` abbreviation (it would swallow initials).
35+
36+
If your data is homogeneous enough that a collision can't occur, the
37+
reasoning behind the default doesn't apply to you — add the entry:
38+
39+
.. doctest::
40+
41+
>>> from nameparser import Lexicon, Parser
42+
>>> lex = Lexicon.default().add(
43+
... titles={"سيد"}, given_name_titles={"سيد"})
44+
>>> name = Parser(lexicon=lex).parse("سيد محمد")
45+
>>> name.title, name.given
46+
('سيد', 'محمد')
47+
48+
Both fields, because ``given_name_titles`` is a marker over ``titles``
49+
rather than a separate vocabulary: ``titles`` makes the word a title at
50+
all, and listing it in ``given_name_titles`` says the honorific
51+
precedes the *given* name — as Arabic ones do — so the word after it
52+
isn't read as a family name. Adding it to ``given_name_titles`` alone
53+
has no effect.
54+
55+
A pack is for something different: a *structural* rule, like reordering
56+
a patronymic, that vocabulary alone can't express.
57+
1058
Using a pack
1159
------------
1260

docs/migrate.rst

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,46 @@ where 1.x returned ``True``. That one *did* warn on 1.4, but nothing
4646
will tell you on 2.0. If you compare names anywhere, grep for ``==``
4747
before upgrading and move to ``matches()`` — see `Comparison`_.
4848

49+
One step has to happen *before* you upgrade, because the fix is only
50+
available on the version you're leaving: a ``Constants`` pickle written
51+
by nameparser 1.2.x or earlier must be re-pickled under 1.3 or 1.4.
52+
2.0 refuses to load one, and by then the code that could rewrite it is
53+
gone.
54+
55+
If your suite did *not* run clean, these are the replacements for the
56+
warned removals:
57+
58+
.. list-table::
59+
:header-rows: 1
60+
:widths: 45 55
61+
62+
* - 1.4 spelling
63+
- 2.0 replacement
64+
* - ``HumanName(b"...")``, ``manager.add(b"...")``
65+
- Decode first: ``HumanName(raw.decode("utf-8"))``
66+
* - ``SetManager.add_with_encoding(b"...")``
67+
- ``add()``, on already-decoded ``str``
68+
* - ``manager()`` (calling a set manager)
69+
- ``set(manager)``, or iterate it directly
70+
* - ``manager.remove(missing)`` (was tolerant)
71+
- ``discard()`` to ignore missing; ``remove()`` now raises
72+
``KeyError`` like ``set.remove``
73+
* - ``HumanName(..., constants=None)``
74+
- ``Constants()`` for library defaults, or ``CONSTANTS.copy()``
75+
for a private snapshot of the current shared config
76+
* - ``name['first'] = value``
77+
- ``name.first = value``
78+
* - ``CONSTANTS.regexes.typo`` (returned ``None``)
79+
- ``.get("typo")`` for intentional soft access; attribute access
80+
now raises ``AttributeError`` naming the known keys
81+
* - ``CONSTANTS.empty_attribute_default``
82+
- Gone; empty fields are always ``''``
83+
84+
Finally, if you want to see the difference on your own data rather than
85+
ours, ``tools/differential/`` in the source repository diffs 1.4 and
86+
2.0 parses over a corpus of names you supply. It is development
87+
tooling, not part of the installed package — see its README.
88+
4989
Attribute map
5090
-------------
5191

@@ -263,15 +303,35 @@ behavior:
263303

264304
One behavior changed underneath both methods: components now fold with
265305
``str.casefold()`` instead of ``str.lower()``, so more Unicode
266-
case-pairs compare equal than did under 1.4 (see the 2.0.0 section of
267-
:doc:`release_log` for the exact rule and examples).
306+
case-pairs compare equal than did under 1.4. The change is strictly
307+
more permissive — anything 1.4 matched still matches:
308+
309+
.. doctest::
310+
311+
>>> parse("Anna STRASSE").matches("Anna Straße")
312+
True
268313

269314
Behavior changes
270315
-----------------
271316

272317
Beyond the API surface mapped above, a handful of parse *outputs*
273-
differ between 1.4 and 2.0 for specific input shapes — comma-suffix
274-
routing, maiden-marker detection, an ambiguous-acronym data change, and
275-
one rendering difference under a custom suffix delimiter. These are
276-
listed with their reasoning and test coverage in the 2.0.0 section of
277-
:doc:`release_log`; they aren't repeated here.
318+
differ between 1.4 and 2.0 for specific input shapes. The full list,
319+
with reasoning, is in the 2.0.0 section of :doc:`release_log`. These
320+
are the shapes worth grepping your own fixtures for, because a
321+
recognized suffix or title now stays in its own field instead of
322+
landing in ``first``/``last``:
323+
324+
.. doctest::
325+
326+
>>> HumanName("Andrews, M.D.").last, HumanName("Andrews, M.D.").suffix
327+
('Andrews', 'M.D.')
328+
>>> HumanName("Johnson PhD").first, HumanName("Johnson PhD").suffix
329+
('Johnson', 'PhD')
330+
331+
Under 1.4 those read ``first="M.D."``/``last="Andrews"`` and
332+
``first="Johnson"``/``last="PhD"`` respectively. Two more to check for:
333+
a maiden marker now fills the ``maiden`` field rather than being folded
334+
into ``middle``/``last`` (``"Jane Smith née Jones"``), and with a
335+
custom suffix delimiter configured, a no-space delimiter group renders
336+
whole (``"RN/CRNA"``) where 1.x split it (``"RN, CRNA"``) — the role
337+
assignment is identical, only the rendered string differs.

0 commit comments

Comments
 (0)