Skip to content

Commit 257c235

Browse files
derek73claude
andcommitted
docs: bring concepts.rst up to date with 2.1-2.4 behavior
concepts.rst was last touched 2026-09-08. Read against the tree: - script_orders applies to kanji mixed with kana too (#272), not only to "a name written wholly in one East Asian script". - "nothing else does" (change what first and last mean) was false: a never-given particle opening the name opens the surname under every order, and the opt-in patronymic_rules reorder a name. Both named, the particle claim measured under all three orders ("de Mesnil Jean" under FAMILY_FIRST is family de Mesnil, given Jean -- the particle opens the surname, it does not swallow the name). - The two-layer model had no place for readings by written form: a period-final word opening the given part is a title with no list entry, and since 2.4 an unlisted dotted acronym, and by default an all-caps word after a comma, are credentials. A paragraph names them, each with the position it needs, and links usage.rst's and customize.rst's sections; "the whole parser in two sentences" becomes "in outline". - replace() tokens do carry a tag (vocab:unclassified), and revise() does not preserve tags, it classifies the value as a parse would. - "a name of one name word ... reported" was broader than rules.md's "one name word nothing else decided": "Dr. Smith" reports nothing, a listed boundary. - The paragraph on token tags sat at the end of "Honest ambiguity", which it is not about; it moves beside the spans paragraph, and "the four stable tags" loses its standing count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 495b2b3 commit 257c235

1 file changed

Lines changed: 39 additions & 22 deletions

File tree

‎docs/concepts.rst‎

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,26 @@ rewrite the wrong occurrence (`issue #100
3434
<https://github.com/derek73/python-nameparser/issues/100>`_ and its
3535
relatives); a position cannot be confused with a look-alike.
3636

37+
:class:`Tokens <nameparser.Token>` also carry tags — a second, independent label alongside their
38+
role, recording how a token was classified rather than what part of
39+
the name it belongs to — but only a handful of them are part of the
40+
stable API, collected in :data:`~nameparser.STABLE_TAGS`: ``particle``,
41+
``conjunction``, ``initial``, and ``joined``.
42+
Any tag written with a namespace prefix, like ``vocab:...``, is
43+
provenance information for debugging how a token got classified — it
44+
can change shape between releases and isn't something to match against
45+
in your own code. If you need to branch on how a token was
46+
classified, branch on role or on one of the stable tags above,
47+
not on a namespaced one.
48+
3749
:class:`~nameparser.ParsedName` is frozen: there is no attribute
3850
assignment, ever. If a parse is almost right and you want to fix one
3951
field, you call ``.replace()``, which returns a new
4052
:class:`~nameparser.ParsedName` with that field changed and everything
4153
else — tokens, spans, the rest of the roles — carried over unchanged
42-
(``replace()`` tokens carry no vocabulary tags; :meth:`Parser.revise
43-
<nameparser.Parser.revise>` is the tag-preserving form).
54+
(``replace()`` tokens carry no vocabulary classification;
55+
:meth:`Parser.revise <nameparser.Parser.revise>` classifies the new
56+
value the way a parse would).
4457
``str()`` renders the default view; nothing about calling it mutates
4558
the value you called it on.
4659

@@ -57,13 +70,28 @@ Whatever the vocabulary layer has not claimed is left to a positional
5770
layer, which assigns purely by where a word sits: the first unclaimed
5871
word is the given name, the last is the family name, and anything
5972
between them is the middle name. ``name_order``, an explicit comma,
60-
and — for a name written wholly in one East Asian script —
61-
``script_orders`` change what "first" and "last" mean here; the
62-
Chinese interpunct ``·`` dividing such a name walks the last of those
63-
back, marking a transcription that keeps its source order; nothing
64-
else does.
65-
66-
This is the whole parser in two sentences, and it explains its
73+
and — for a name in an East Asian script that settles its own order:
74+
wholly Han or hangul, or kanji mixed with kana — ``script_orders``
75+
change what "first" and "last" mean here; the Chinese interpunct ``·``
76+
dividing such a name walks the last of those back, marking a
77+
transcription that keeps its source order. Two rules can still
78+
override the arrangement: a particle that can never be a given name,
79+
opening the name, opens the surname under every order rather than
80+
becoming the given name (:ref:`order-vocabulary-first`), and the
81+
opt-in ``patronymic_rules``
82+
reorder a name whose patronymic marks its parts.
83+
84+
A few words are read by how they are written, which is neither a list
85+
lookup nor position alone: the writing proposes a reading, and where
86+
the word stands decides whether it lands. A word ending in a period at
87+
the front of the given-name part is a title though no list holds it
88+
(``"Insp. Jane Morse"``; see :ref:`abbreviated-titles`). Since 2.4, an
89+
unlisted acronym written in periods (``X.Y.Z.``) is a credential behind
90+
a name that can spare it, and one written in capitals (``XYZ``) is,
91+
by default, right after a comma behind a full name
92+
(:ref:`unlisted-credentials`).
93+
94+
That is the whole parser in outline, and it explains its
6795
character. A word nameparser has never seen still gets a sensible role,
6896
because the positional layer does not need to recognize anything. The
6997
same word can play different parts in different places — ``Lt.`` is a
@@ -177,7 +205,8 @@ readings — so nothing is recorded. A comma can settle the question
177205
before it arises, too: ``"Ma, Jack"`` fixes the family name, so the
178206
credential reading never comes up, while ``"John Smith MA"`` has to
179207
call it and says so. Some decisions are conventions rather than
180-
readings — a name of one name word has nothing to compare, and an
208+
readings — a name whose one name word nothing else decides (no
209+
title, family comma or vocabulary claim) has nothing to compare, and an
181210
input the title peel eats down to one last title word reads that word
182211
as the name for want of anything else — and since 2.3 those are
183212
reported too, so a field the library merely had to pick is a field you
@@ -195,15 +224,3 @@ much, but it leaves the rest of the name to be read as usual, so
195224
to call. Coverage grows over releases. Treat a non-empty
196225
``ambiguities`` as a signal to act on; do not read an empty one as a
197226
guarantee.
198-
199-
:class:`Tokens <nameparser.Token>` also carry tags — a second, independent label alongside their
200-
role, recording how a token was classified rather than what part of
201-
the name it belongs to — but only a handful of them are part of the
202-
stable API, collected in :data:`~nameparser.STABLE_TAGS`: ``particle``,
203-
``conjunction``, ``initial``, and ``joined``.
204-
Any tag written with a namespace prefix, like ``vocab:...``, is
205-
provenance information for debugging how a token got classified — it
206-
can change shape between releases and isn't something to match against
207-
in your own code. If you need to branch on how a token was
208-
classified, branch on role or on one of the four stable tags above,
209-
not on a namespaced one.

0 commit comments

Comments
 (0)