2525
2626
2727class Role (Enum ):
28+ """The seven fields of a parsed name, one per :class:`Token`.
29+ Declaration order is the canonical field order everywhere
30+ (``as_dict()``, ``comparison_key()``, rendering). Pass a member to
31+ :meth:`ParsedName.tokens_for`; a member's ``.value`` is the field's
32+ string name (``Role.GIVEN.value == "given"``)."""
33+
2834 # Declaration order IS the canonical field order (conventions §3):
2935 # every listing of the seven fields anywhere derives from this.
3036 TITLE = "title"
@@ -37,9 +43,15 @@ class Role(Enum):
3743
3844
3945class Span (NamedTuple ):
40- """Provenance range into ParsedName.original. end is exclusive."""
46+ """Where a :class:`Token` came from: a character range into
47+ :attr:`ParsedName.original` such that ``original[start:end]`` is
48+ the token's source text (``end`` exclusive). A plain two-int
49+ NamedTuple; ``None`` in :attr:`Token.span` marks a synthetic token
50+ with no source position."""
4151
52+ #: First character index (0-based).
4253 start : int
54+ #: One past the last character index.
4355 end : int
4456
4557 def __add__ (self , other : object ) -> NoReturn : # type: ignore[override]
@@ -120,9 +132,23 @@ def _guarded_setstate(self: object, state: dict[str, object]) -> None:
120132
121133@dataclass (frozen = True , slots = True )
122134class Token :
135+ """One classified word of a parsed name: its text, where it came
136+ from, which field it belongs to, and how it was classified. Read
137+ tokens off :attr:`ParsedName.tokens` or
138+ :meth:`ParsedName.tokens_for`; you only construct one directly
139+ when hand-building a :class:`ParsedName`."""
140+
141+ #: The word exactly as written in the input (never empty).
123142 text : str
124- span : Span | None # None = synthetic (from replace())
143+ #: Position in ParsedName.original; None marks a synthetic token
144+ #: (e.g. introduced by replace()) with no source position.
145+ span : Span | None
146+ #: The field this token belongs to.
125147 role : Role
148+ #: Classification labels. Exactly the four in STABLE_TAGS
149+ #: ("particle", "conjunction", "initial", "joined") are API;
150+ #: namespaced tags like "vocab:..." are unstable debugging
151+ #: provenance -- never match against them.
126152 tags : frozenset [str ] = frozenset ()
127153
128154 # in the class body so @dataclass(slots=True) keeps them
@@ -187,7 +213,10 @@ def __repr__(self) -> str:
187213
188214
189215class AmbiguityKind (StrEnum ):
190- """Stable identifiers (API); members ARE their string values."""
216+ """The stable vocabulary of :class:`Ambiguity` kinds. A StrEnum:
217+ members ARE their string values, so ``kind == "particle-or-given"``
218+ compares directly. New kinds may be added in minor releases;
219+ existing values never change meaning."""
191220
192221 ORDER = "order"
193222 SUFFIX_OR_NICKNAME = "suffix-or-nickname"
@@ -198,8 +227,17 @@ class AmbiguityKind(StrEnum):
198227
199228@dataclass (frozen = True , slots = True )
200229class Ambiguity :
230+ """A call the parser made that could legitimately have gone the
231+ other way, surfaced on :attr:`ParsedName.ambiguities` instead of
232+ silently guessed away. The parse still commits to one reading --
233+ an Ambiguity is a flag for review, not an error."""
234+
235+ #: Which known ambiguity shape this is (stable API values).
201236 kind : AmbiguityKind
237+ #: Human-readable specifics of this occurrence (wording unstable).
202238 detail : str
239+ #: The tokens involved -- always a subset of the owning
240+ #: ParsedName's tokens; may be empty (e.g. unbalanced-delimiter).
203241 tokens : tuple [Token , ...]
204242
205243 # in the class body so @dataclass(slots=True) keeps them
@@ -232,15 +270,25 @@ def __repr__(self) -> str:
232270
233271@dataclass (frozen = True , slots = True )
234272class ParsedName :
235- """Immutable result of a parse. Constructor-enforced invariants:
236- spans ascending, non-overlapping, in bounds of `original`; every
237- Ambiguity's tokens are a subset of `tokens`. Provenance semantics
238- (text == original[span] for parser-produced names) are documented,
239- not enforced -- transforms like replace() legitimately break them.
273+ """The immutable result of parsing one name string. Read the seven
274+ fields as strings (``.given``, ``.family``, ...); inspect structure
275+ through :attr:`tokens` / :meth:`tokens_for`; correct a parse with
276+ :meth:`replace` (returns a new value); produce output with
277+ :meth:`render`, :meth:`initials`, :meth:`capitalized`, or ``str()``.
278+
279+ Constructor-enforced invariants: spans ascending, non-overlapping,
280+ in bounds of `original`; every Ambiguity's tokens are a subset of
281+ `tokens`. Provenance semantics (text == original[span] for
282+ parser-produced names) are documented, not enforced -- transforms
283+ like replace() legitimately break them.
240284 """
241285
286+ #: The input string exactly as passed to parse().
242287 original : str
288+ #: Every classified token, in document order.
243289 tokens : tuple [Token , ...]
290+ #: Judgment calls that could have gone the other way; empty for
291+ #: most names (see Ambiguity).
244292 ambiguities : tuple [Ambiguity , ...] = ()
245293
246294 # in the class body so @dataclass(slots=True) keeps them
0 commit comments