Skip to content

Commit b20e1cd

Browse files
derek73claude
andcommitted
docs: explain how roles get assigned, and what input shapes work
concepts.rst described the data model — string becomes tokens, tokens carry roles, fields are views — but never the decision procedure. v1's README did: a vocabulary layer claims words for what they are, wherever they sit, and a positional layer assigns whatever is left by where it sits. That framing is what customize.rst's Lexicon/Policy split rests on, so without it "which container does my setting go in?" is answerable only by consulting a table. It also carries three things v1 said and 2.0 had dropped: that an unrecognized word still gets a sensible role (the positional layer recognizes nothing), that title/suffix are really pre-nominal and post-nominal — "Dr." is a title before a name and a suffix after — and that parsing is deterministic, with no model and no training data, so a wrong parse is wrong reproducibly and can be fixed by configuration. usage.rst gains v1 README's "Supported Name Structures". Comma order was demonstrated once inside a matches() example and described once in a name_order table cell, so a reader could not learn that "Doe, John" works without stumbling onto it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent d0f887e commit b20e1cd

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

docs/concepts.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,36 @@ else — tokens, spans, the rest of the roles — carried over unchanged.
4141
``str()`` renders the default view; nothing about calling it mutates
4242
the value you called it on.
4343

44+
Two layers decide the roles
45+
----------------------------
46+
47+
Roles are not assigned in one pass. A vocabulary layer runs first and
48+
claims words for what they *are*, wherever they sit: titles, particles,
49+
conjunctions, recognized suffixes, and anything set off by nickname or
50+
maiden delimiters. Titles chain, so ``"Asst. Vice Chancellor"`` is one
51+
title; particles join forward, so ``de la`` attaches to ``Vega``.
52+
53+
Whatever the vocabulary layer has not claimed is left to a positional
54+
layer, which assigns purely by where a word sits: the first unclaimed
55+
word is the given name, the last is the family name, and anything
56+
between them is the middle name. ``name_order`` and an explicit comma
57+
change what "first" and "last" mean here; nothing else does.
58+
59+
This is the whole parser in two sentences, and it explains its
60+
character. A word nameparser has never seen still gets a sensible role,
61+
because the positional layer does not need to recognize anything. The
62+
same word can play different parts in different places — ``Dr.`` is a
63+
title before a name and a suffix after it, which is why the field names
64+
``title`` and ``suffix`` are really "pre-nominal" and "post-nominal".
65+
And nothing is statistical: there is no model and no training data, so
66+
the same input always parses the same way, and a parse that is wrong is
67+
wrong reproducibly, which is what makes it fixable by configuration.
68+
69+
The split also tells you which container a setting belongs in, before
70+
you look anything up: if you are teaching the parser a *word*, it goes
71+
in the :class:`~nameparser.Lexicon`; if you are changing how unclaimed
72+
words are *arranged*, it goes in the :class:`~nameparser.Policy`.
73+
4474
Three containers, three concerns
4575
--------------------------------
4676

docs/usage.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,28 @@ they exist). A name with no fields set is falsy, which is how you tell
2828
>>> bool(parse("")), bool(parse(" ")), bool(parse("John"))
2929
(False, False, True)
3030

31+
Input shapes
32+
-------------
33+
34+
Three arrangements are understood, and every piece of each is optional:
35+
36+
1. ``Title First Middle Middle Last Suffix``
37+
2. ``Last, Title First Middle Middle[,] Suffix [, Suffix]``
38+
3. ``Title First Middle Last [,] Suffix [, Suffix]``
39+
40+
A comma before the given name is the signal for family-first order, so
41+
the second form needs no configuration:
42+
43+
.. doctest::
44+
45+
>>> parse("de la Vega, Juan Q. Xavier III").family
46+
'de la Vega'
47+
>>> parse("Doe Jr., John").suffix
48+
'Jr.'
49+
50+
For family-first input *without* a comma — common outside Europe — set
51+
``name_order``; see :doc:`customize`.
52+
3153
Aggregate views
3254
----------------
3355

0 commit comments

Comments
 (0)