API reference¶
The 2.0 API¶
Parsing¶
- nameparser.parse(text: str) ParsedName[source]¶
Parse a name with the default configuration and return a
ParsedName. Equivalent toParser().parse(text); build your ownParser(or useparser_for()) for custom vocabulary or behavior. Never raises on string content.
- class nameparser.Parser(lexicon: Lexicon = None, policy: Policy = None)[source]¶
A configured name parser: a
Lexicon(vocabulary) plus aPolicy(behavior), both defaulted when omitted. Build one when you need non-default configuration, build it once, and callparse()many times – it is immutable, thread-safe, and picklable by construction: all validity checking happens at construction, so a Parser that constructs successfully cannot fail at parse time on any str content.(The None field defaults resolve in __post_init__; after construction both fields are always non-None – the annotations state the steady-state truth, hence the assignment ignores on the defaults.)
- parse(text: str) ParsedName[source]¶
Parse one name string into a
ParsedName. Never raises on string content (unparseable input yields empty fields plus ambiguities); non-str raises TypeError eagerly, with a decode hint for bytes (bytes support ended with 1.x).
- nameparser.parser_for(*locales: Locale, base: Parser | None = None) Parser[source]¶
Lexicon fragments unioned left-to-right onto base’s; policy patches applied left-to-right (later wins; set-valued fields union per the patch metadata). Validation errors raised while applying a pack are wrapped with that pack’s identity (spec §4 amendment) – PolicyPatch validates lazily, so with stacked packs the raw error would otherwise point at nothing. Two packs setting the same SCALAR field is a declared conflict: UserWarning, later wins.
Results¶
- class nameparser.ParsedName(original: str, tokens: tuple[Token, ...], ambiguities: tuple[Ambiguity, ...] = ())[source]¶
The immutable result of parsing one name string. Read the seven fields as strings (
.given,.family, …); inspect structure throughtokens/tokens_for(); correct a parse withreplace()(returns a new value); produce output withrender(),initials(),capitalized(), orstr().Constructor-enforced invariants: spans ascending, non-overlapping, in bounds of original; every Ambiguity’s tokens are a value-equal subset of tokens (see Ambiguity.tokens). Provenance semantics (text == original[span] for parser-produced names) are documented, not enforced – transforms like replace() legitimately break them.
- original: str¶
The input string exactly as passed to parse().
- ambiguities: tuple[Ambiguity, ...]¶
Judgment calls that could have gone the other way; empty for most names (see Ambiguity).
- replace(**fields: str) ParsedName[source]¶
Return a new ParsedName with the named fields re-tokenized as synthetic tokens (span=None). Whitespace-splits each value; an empty value clears the field. original is unchanged (provenance). Ambiguities referencing replaced tokens are dropped.
- comparison_key() tuple[str, ...][source]¶
One casefolded component per Role, in canonical order, for dedup, dict keys, and sorting. The semantic layer; __eq__ stays strict.
- matches(other: str | ParsedName, *, parser: Parser | None = None) bool[source]¶
Component-wise case-insensitive comparison (the semantic layer; __eq__ stays strict). A str argument is parsed with parser, or the default parser when None.
- render(spec: str = '{title} {given} "{nickname}" {middle} {family} ({maiden}) {suffix}') str[source]¶
Fill the str.format spec from the seven role fields and the derived views; empty fields collapse (#254), including the default spec’s decorations (empty ‘””’ and ‘()’ wrappers). The default shows every non-empty field: the nickname quoted after the given name, the maiden name parenthesized after the family name. Unknown keys raise KeyError naming the valid fields.
- initials(spec: str = '{given} {middle} {family}', delimiter: str = '.', separator: str = ' ') str[source]¶
Initials per group; v1’s initials_format/_delimiter/_separator become call-site arguments instead of Config-wide settings. Valid spec keys: given, middle, family.
- capitalized(lexicon: Lexicon | None = None, *, force: bool = False) ParsedName[source]¶
Case-fixing transform -> new ParsedName, same spans, new token texts. Needs a lexicon for capitalization_exceptions and particle rules; None uses the default lexicon. force=False preserves mixed-case input (v1 parity). Idempotent.
- class nameparser.Token(text: str, span: Span | None, role: Role, tags: frozenset[str] = frozenset({}))[source]¶
One classified word of a parsed name: its text, where it came from, which field it belongs to, and how it was classified. Read tokens off
ParsedName.tokensorParsedName.tokens_for(); you only construct one directly when hand-building aParsedName.- text: str¶
The word exactly as written in the input (never empty).
- span: Span | None¶
Position in ParsedName.original; None marks a synthetic token (e.g. introduced by replace()) with no source position.
- tags: frozenset[str]¶
Classification labels. Exactly the four in STABLE_TAGS (“particle”, “conjunction”, “initial”, “joined”) are API; namespaced tags like “vocab:…” are unstable debugging provenance – never match against them.
- class nameparser.Span(start: int, end: int)[source]¶
Where a
Tokencame from: a character range intoParsedName.originalsuch thatoriginal[start:end]is the token’s source text (endexclusive). A plain two-int NamedTuple;NoneinToken.spanmarks a synthetic token with no source position.- start: int¶
First character index (0-based).
- end: int¶
One past the last character index.
- class nameparser.Role(*values)[source]¶
The seven fields of a parsed name, one per
Token. Declaration order is the canonical field order everywhere (as_dict(),comparison_key(), rendering). Pass a member toParsedName.tokens_for(); a member’s.valueis the field’s string name (Role.GIVEN.value == "given").- TITLE = 'title'¶
Pre-nominal titles and honorifics (“Dr.”, “Sir”, “Capt.”).
- GIVEN = 'given'¶
The given (first) name, or its initial.
- MIDDLE = 'middle'¶
Names between given and family – middle names or initials.
- FAMILY = 'family'¶
The family (last) name, including any particles (“de la Vega”).
- SUFFIX = 'suffix'¶
Post-nominal pieces (“III”, “Jr.”, “PhD”).
- NICKNAME = 'nickname'¶
Delimited nickname content (“Jonathan ‘Jack’ Kennedy” -> “Jack”).
- MAIDEN = 'maiden'¶
A birth surname, from a marker word (“Jane Smith née Jones” -> “Jones”) or a delimiter pair routed via Policy.maiden_delimiters.
- class nameparser.Ambiguity(kind: AmbiguityKind, detail: str, tokens: tuple[Token, ...])[source]¶
A call the parser made that could legitimately have gone the other way, surfaced on
ParsedName.ambiguitiesinstead of silently guessed away. The parse still commits to one reading – an Ambiguity is a flag for review, not an error.- kind: AmbiguityKind¶
Which known ambiguity shape this is (stable API values).
- detail: str¶
Human-readable specifics of this occurrence (wording unstable).
- class nameparser.AmbiguityKind(*values)[source]¶
The stable vocabulary of
Ambiguitykinds. A StrEnum: members ARE their string values, sokind == "particle-or-given"compares directly. New kinds may be added in minor releases; existing values never change meaning.A kind names a FORK THE PARSE HAD TO CALL, not a word that could be read two ways: the same token elsewhere in a name may present no choice at all and is then reported by nothing. Reporting is also partial – a kind listed here is not necessarily emitted everywhere its fork occurs (the comma paths stay quiet by design), and coverage grows over releases. A non-empty tuple is a signal to act on; an empty one is not a guarantee of certainty.
- ORDER = 'order'¶
Reserved: the name’s field order itself is uncertain (e.g. a two-word name under a non-default name_order). Not yet emitted; planned for 2.x.
- SUFFIX_OR_NICKNAME = 'suffix-or-nickname'¶
Delimited content is an ambiguous suffix acronym, so it reads plausibly as either a post-nominal or a nickname – “JEFFREY (JD) BRICKEN” keeps the nickname reading, where the unambiguous “(MBA)” escapes to suffix on vocabulary alone.
- SUFFIX_OR_NAME = 'suffix-or-name'¶
A trailing word reads plausibly as either a post-nominal or an ordinary name part. Covers an ambiguous acronym written without periods (“John Smith MA” takes MA as a credential because a family name remains; “Jack MA” keeps it as the name because none would) and a trailing roman numeral, which is a suffix where any other single letter would be a name (“John Smith V” vs “John Smith B”). Which name part was declined depends on position and
name_order, sodetailnames it rather than the kind.
- PARTICLE_OR_GIVEN = 'particle-or-given'¶
A leading ambiguous particle was read as a given name – “Van Johnson” parses given=”Van”, but “Van” is also a family-name particle in other names.
- UNBALANCED_DELIMITER = 'unbalanced-delimiter'¶
A nickname/maiden delimiter opened without closing (or closed without opening); the text was kept as literal name content, so the tokens are the one the stray character ended up inside. Two cases leave that tuple empty: a character that lands in no token at all (inside a masked region), and an input with no alphanumeric content anywhere, which parses to an empty name – the report survives because “was this malformed?” is the only question left, but there is no token for it to point at.
parse("(")is the second case, not an exotic one.
- COMMA_STRUCTURE = 'comma-structure'¶
More comma-separated segments than any recognized name shape; the parse is best-effort over the extra segments.
Configuration¶
- class nameparser.Lexicon(titles: frozenset[str] = frozenset({}), given_name_titles: frozenset[str] = frozenset({}), suffix_acronyms: frozenset[str] = frozenset({}), suffix_words: frozenset[str] = frozenset({}), suffix_acronyms_ambiguous: frozenset[str] = frozenset({}), particles: frozenset[str] = frozenset({}), particles_ambiguous: frozenset[str] = frozenset({}), conjunctions: frozenset[str] = frozenset({}), bound_given_names: frozenset[str] = frozenset({}), maiden_markers: frozenset[str] = frozenset({}), capitalization_exceptions: tuple[tuple[str, str], ...] = ())[source]¶
The vocabulary a parser matches against: which words are titles, particles, suffixes, and so on. Immutable and hashable. Start from
default()(the shipped vocabulary) orempty(), derive variants withadd()/remove()/|(union), and pass the result toParser(lexicon=...). Entries are normalized at construction – lowercased, edge periods stripped – so matching is case-insensitive. Field docs below show examples, not full contents; inspect any field’s shipped vocabulary directly, e.g.Lexicon.default().conjunctions.- given_name_titles: frozenset[str]¶
Titles whose single following name reads as a GIVEN name (“sheikh”, “sister”, …) rather than a family name. Full default list:
FIRST_NAME_TITLES.
- suffix_acronyms: frozenset[str]¶
Post-nominal acronym suffixes, matched with or without periods (“phd” matches “PhD” and “Ph.D.”). Full default list:
SUFFIX_ACRONYMS.
- suffix_words: frozenset[str]¶
Post-nominal word suffixes (“jr”, “esquire”, “iii”, …). Full default list:
SUFFIX_NOT_ACRONYMS.
- suffix_acronyms_ambiguous: frozenset[str]¶
Subset of suffix_acronyms counted as suffixes only when written WITH periods – their bare forms are common surnames (“ma”, “do”: “Jack Ma” keeps his family name). Full default list:
SUFFIX_ACRONYMS_AMBIGUOUS.
- particles: frozenset[str]¶
Family-name particles that chain onto the following piece (“van”, “de”, “bin”, …). Full default list:
PREFIXES.
- particles_ambiguous: frozenset[str]¶
Subset of particles that can also BE a given name: a leading one reads as given and records a particle-or-given ambiguity (“Van Johnson”). No constant of its own – the default derives as particles minus
NON_FIRST_NAME_PREFIXES(which marks the opposite, never-given subset).
- conjunctions: frozenset[str]¶
Words or characters that join surrounding pieces into one (“and”, “&”, “y”, “и”, …). Full default list:
CONJUNCTIONS.
- bound_given_names: frozenset[str]¶
Given-name prefixes that bind to the following word to form one given name (“abdul” -> “Abdul Salam”); never standalone names. Full default list:
BOUND_FIRST_NAMES.
- maiden_markers: frozenset[str]¶
Marker words introducing a birth surname, routed to the maiden field (“née”, “geb.”, “roz.”, …). Full default list:
MAIDEN_MARKERS.
- class nameparser.Policy(name_order: tuple[Role, Role, Role] = (Role.GIVEN, Role.MIDDLE, Role.FAMILY), patronymic_rules: frozenset[PatronymicRule] = frozenset({}), middle_as_family: bool = False, nickname_delimiters: frozenset[tuple[str, str]] = frozenset({('"', '"'), ("'", "'"), ('(', ')'), ('«', '»'), ('»', '«'), ('“', '”'), ('”', '”'), ('„', '“'), ('「', '」'), ('『', '』'), ('(', ')')}), maiden_delimiters: frozenset[tuple[str, str]] = frozenset({}), extra_suffix_delimiters: frozenset[str] = frozenset({}), lenient_comma_suffixes: bool = True, strip_emoji: bool = True, strip_bidi: bool = True)[source]¶
The behavior switches a parser runs with: name order, patronymic rules, delimiter routing, input scrubbing. Immutable and hashable; every field has a safe default, so construct with only what you change –
Policy(maiden_delimiters={("(", ")")})– and pass the result toParser(policy=...).- name_order: tuple[Role, Role, Role]¶
How positional (no-comma) input maps onto given/middle/family. Valid values are exactly the three exported name-order constants – GIVEN_FIRST (the default), FAMILY_FIRST, and FAMILY_FIRST_GIVEN_LAST; any other tuple of Roles raises ValueError. Ignored when a comma separates family from given: “Thomas, John” puts the family name first no matter which words could otherwise be either (“Thomas” and “John” both work as given or family names). A comma that only sets off suffixes (“John Smith, Jr.”) leaves name_order governing the name part.
- patronymic_rules: frozenset[PatronymicRule]¶
Opt-in detectors that reorder patronymic-shaped names (EAST_SLAVIC, TURKIC); usually set via a locale pack.
- middle_as_family: bool¶
Folds middle into family instead of splitting them (v1’s middle_name_as_last) – for data where unrecognized interior words are surname parts, not middle names: multi-part surnames like Spanish/Portuguese dual surnames (“Gabriel García Márquez” -> family “García Márquez” instead of middle “García”).
- nickname_delimiters: frozenset[tuple[str, str]]¶
(open, close) pairs whose enclosed content becomes the nickname field. Defaults to
DEFAULT_NICKNAME_DELIMITERS(#273).
- maiden_delimiters: frozenset[tuple[str, str]]¶
(open, close) pairs whose enclosed content becomes the maiden field instead; a pair listed here is dropped from the effective nickname set (maiden wins, see __post_init__), so maiden_delimiters={(“(”, “)”)} is the whole recipe (#274).
- extra_suffix_delimiters: frozenset[str]¶
Additional separators that split suffix groups (e.g. “ - “ for “Jane Smith, RN - CRNA”). Additive only: the comma always splits suffix groups and cannot be replaced – comma handling is structural (the same comma reading that parses “Family, Given” input), not a configurable delimiter.
- lenient_comma_suffixes: bool¶
Governs “Family, Suffix”-shaped input where the suffix word is also initial-shaped (a single letter, bare or period-written – of the default vocabulary that means the roman numerals “I” and “V”): “John Smith, V” reads as John Smith the fifth when True (the default, v1 behavior); False reads “V” as a given-name initial instead (family “John Smith”, given “V”). Multi-letter suffixes (“III”, “MD”) parse the same either way.
- strip_emoji: bool¶
Excludes emoji from tokenization: they appear in no token, field, or rendered view. The original string keeps them (input is never modified – spans stay true).
- strip_bidi: bool¶
Excludes bidirectional control characters from tokenization: they appear in no token, field, or rendered view; the original string keeps them.
- class nameparser.PolicyPatch(name_order: tuple[Role, Role, Role] | _Unset = _Unset.UNSET, patronymic_rules: frozenset[PatronymicRule] | _Unset = _Unset.UNSET, middle_as_family: bool | _Unset = _Unset.UNSET, nickname_delimiters: frozenset[tuple[str, str]] | _Unset = _Unset.UNSET, maiden_delimiters: frozenset[tuple[str, str]] | _Unset = _Unset.UNSET, extra_suffix_delimiters: frozenset[str] | _Unset = _Unset.UNSET, lenient_comma_suffixes: bool | _Unset = _Unset.UNSET, strip_emoji: bool | _Unset = _Unset.UNSET, strip_bidi: bool | _Unset = _Unset.UNSET)[source]¶
A partial Policy: one field per Policy field, all defaulting to UNSET. Composition per field is DECLARED via metadata – set-valued fields union, scalars override (later wins). Kept in lockstep with Policy by the parity test in tests/v2/test_policy.py.
Values are validated when the patch is applied (Policy’s constructor re-runs), not at patch construction.
- nameparser.UNSET¶
Sentinel meaning “this patch does not set this field” — the default of every
PolicyPatchfield, distinguishable from every real value includingNoneandFalse. You rarely need it: omit a field instead of passing it. Import it to test whether a patch sets a field (patch.name_order is UNSET) or to leave a field conditionally unset when building patches programmatically.
- class nameparser.PatronymicRule(*values)[source]¶
Stable rule names (API); implementations live in the pipeline. Enable via
Policy(patronymic_rules={...})or, more commonly, a locale pack (nameparser.locales).- EAST_SLAVIC = 'east-slavic'¶
East Slavic formal order: “Sidorov Ivan Petrovich” (family, given, patronymic) is detected by the patronymic ending and reordered. Enabled by locales.RU.
- TURKIC = 'turkic'¶
Turkic patronymic markers: a standalone “oglu”/”qizi”/”kyzy” (etc.) binds to the preceding name as a patronymic. Enabled by locales.TR_AZ.
Name-order constants¶
The three valid values for Policy(name_order=...). name_order
is deliberately restricted to these exported constants — an arbitrary
tuple of Role members raises ValueError,
because only these three orders have defined assignment semantics.
- nameparser.GIVEN_FIRST = (Role.GIVEN, Role.MIDDLE, Role.FAMILY)¶
Western order (the default): the first word of positional input is the given name, the last is the family name, everything between is middle.
- nameparser.FAMILY_FIRST = (Role.FAMILY, Role.GIVEN, Role.MIDDLE)¶
Family name first, given name second, remaining words middle — e.g. Hungarian, or East Asian order.
- nameparser.FAMILY_FIRST_GIVEN_LAST = (Role.FAMILY, Role.MIDDLE, Role.GIVEN)¶
Family name first, given name last, the words between middle — e.g. Vietnamese full-name order.
Delimiter defaults¶
- nameparser.DEFAULT_NICKNAME_DELIMITERS = frozenset({("'", "'"), ('"', '"'), ("(", ")"), ("“", "”"), ("„", "“"), ("”", "”"), ("«", "»"), ("»", "«"), ("「", "」"), ("『", "』"), ("(", ")")})¶
The default
nickname_delimitersset: straight quotes and parentheses plus the typographic conventions — smart quotes, German/Polish low-high quotes, Swedish right-right quotes, guillemets in both directions, CJK corner brackets, and fullwidth parentheses (#273). Curly single quotes are deliberately absent: U+2019 is the typographic apostrophe (“O’Connor”). Build on the constant for additive customizations, e.g.nickname_delimiters=DEFAULT_NICKNAME_DELIMITERS | {("⦅", "⦆")}; to reroute a pair tomaiden, just list it inmaiden_delimiters(it is dropped from the effective nickname set automatically).
Locales¶
- class nameparser.Locale(code: str, lexicon: Lexicon, policy: PolicyPatch = PolicyPatch(name_order=<_Unset.UNSET: 1>, patronymic_rules=<_Unset.UNSET: 1>, middle_as_family=<_Unset.UNSET: 1>, nickname_delimiters=<_Unset.UNSET: 1>, maiden_delimiters=<_Unset.UNSET: 1>, extra_suffix_delimiters=<_Unset.UNSET: 1>, lenient_comma_suffixes=<_Unset.UNSET: 1>, strip_emoji=<_Unset.UNSET: 1>, strip_bidi=<_Unset.UNSET: 1>))[source]¶
A named, shareable bundle of vocabulary and behavior for a naming tradition: a lexicon fragment plus a policy patch, applied together by
nameparser.parser_for(). The packs shipped with nameparser live innameparser.locales; building your own needs no registration – construct one and pass it toparser_for. See the locale packs guide for using, creating, and contributing packs.- code: str¶
Identifier, lowercase
[a-z0-9_]+(e.g. “ru”, “tr_az”).
- lexicon: Lexicon¶
Vocabulary ADDED to the base parser’s lexicon (unioned; a pack never removes base vocabulary).
- policy: PolicyPatch¶
Behavior changes folded onto the base policy (set-valued fields union; scalars override, later pack wins).
Locale packs: named (lexicon fragment, PolicyPatch) deltas folded in by parser_for (locales spec §2). Packs are pure data with no privileged capabilities; they dissolve at parser construction.
Loaded lazily (PEP 562): importing nameparser.locales never imports a
pack module; locales.RU triggers nameparser.locales.ru on
first access and caches the Locale here.
Layering: this package imports pack modules, which import _locale/ _lexicon/_policy only (enforced by tests/v2/test_layering.py).
1.x compatibility layer¶
Note
HumanName and nameparser.config are the 1.x API, kept
working through 2.x and removed in 3.0. New code should use the
2.0 API above; see Migrating from HumanName.
HumanName.parser¶
- class nameparser.parser.HumanName[source]
- class nameparser.parser.HumanName(full_name: str = '', constants: Constants | None = <Constants : [ prefixes: 67 suffix_acronyms: 620 suffix_not_acronyms: 20 titles: 709 first_name_titles: 35 conjunctions: 13 bound_first_names: 11 non_first_name_prefixes: 28 suffix_acronyms_ambiguous: 4 ]>, string_format: str | None = None, initials_format: str | None = None, initials_delimiter: str | None = None, initials_separator: str | None = None, suffix_delimiter: str | None = None, first: str | list[str] | None = None, middle: str | list[str] | None = None, last: str | list[str] | None = None, title: str | list[str] | None = None, suffix: str | list[str] | None = None, nickname: str | list[str] | None = None, maiden: str | list[str] | None = None)[source]¶
v1
HumanNamefacade: a mutable wrapper over a frozenParsedName, delegating all parsing to the coreParserresolved from the boundConstantsshim (dirty-tracked via its_generation). Keeps every v1 spelling (first/lastover the coregiven/family); the v1 parsing hooks are never called (#280). Deleted with the facade layer in 3.0.- __init__(full_name: str = '', constants: Constants | None = <Constants : [ prefixes: 67 suffix_acronyms: 620 suffix_not_acronyms: 20 titles: 709 first_name_titles: 35 conjunctions: 13 bound_first_names: 11 non_first_name_prefixes: 28 suffix_acronyms_ambiguous: 4 ]>, string_format: str | None = None, initials_format: str | None = None, initials_delimiter: str | None = None, initials_separator: str | None = None, suffix_delimiter: str | None = None, first: str | list[str] | None = None, middle: str | list[str] | None = None, last: str | list[str] | None = None, title: str | list[str] | None = None, suffix: str | list[str] | None = None, nickname: str | list[str] | None = None, maiden: str | list[str] | None = None) None[source]¶
- parse_full_name() None[source]¶
Re-parse the stored
full_name(v1’s documented re-parse trigger, docs/customize.rst): mutatename.Cthen call this to force a re-parse without reassigningfull_name. The v1 parsing INTERNALS this name evokes live in the coreParser, not here; a subclass overriding this method still triggers the #280 hook-override warning, and full_name assignment never consults it.
- capitalize(force: bool | None = None) None[source]¶
Re-capitalize the current parse against the bound lexicon. force=None reads the bound Constants’ render default (force_mixed_case_capitalization); the core’s capitalized() implements the single-case gate (v1 parity) – not re-implemented here.
- property has_own_config: bool¶
True when this instance is not using the shared module-level CONSTANTS.
- matches(other: str | HumanName) bool[source]¶
Component-wise case-insensitive comparison (v1 parity); a str argument is parsed with this instance’s resolved parser.
HumanName.config¶
v1 import-path preservation (migration spec §3): the Constants shim lives in nameparser._config_shim. The vocabulary data modules in this package (titles, suffixes, …) remain the single source through 2.x. This package is deleted in 3.0.
RegexTupleManager is re-exported unchanged from the shim purely for
pickle compatibility: a v1.4 Constants blob’s regexes field was
pickled as nameparser.config.RegexTupleManager(...), and unpickling
resolves and reconstructs that nested object before
Constants.__setstate__ ever runs. Without this name, loading such a
blob raises AttributeError looking up the class, not a clean
compatibility failure.
- class nameparser.config.Constants(*, prefixes: Iterable[str] | object = <object object>, suffix_acronyms: Iterable[str] | object = <object object>, suffix_not_acronyms: Iterable[str] | object = <object object>, suffix_acronyms_ambiguous: Iterable[str] | object = <object object>, titles: Iterable[str] | object = <object object>, first_name_titles: Iterable[str] | object = <object object>, conjunctions: Iterable[str] | object = <object object>, bound_first_names: Iterable[str] | object = <object object>, non_first_name_prefixes: Iterable[str] | object = <object object>, capitalization_exceptions: Mapping[str, str] | ~collections.abc.Iterable[tuple[str, str]] | object=<object object>, regexes: object = <object object>, patronymic_name_order: bool = False, middle_name_as_last: bool = False)[source]¶
v1
Constantsshim: a mutable container whose state resolves to a frozen(Lexicon, Policy, _RenderDefaults)snapshot via_snapshot()._generationincrements on every mutation; facades compare it against a cached value to decide whether their snapshot is stale (dirty-tracking, spec §3 – the facade itself is a later task).The module-level
CONSTANTSsingleton (below) has_sharedflipped toTrue: any mutation reached through it emitsDeprecationWarningpointing atLexicon/PolicyandHumanName(constants=...). A privateConstants()never warns – only the shared instance is on the 3.0 removal path.
- class nameparser.config.RegexTupleManager(*args: object, _on_change: Callable[[], None] | None = None, **kwargs: object)[source]¶
Pickle-compat alias only: v1.4’s
Constants.regexesfield was anameparser.config.RegexTupleManagerinstance (aTupleManagersubclass whose__getattr__fell back toEMPTY_REGEXfor an unknown key). Unpickling a v1.4 blob resolves and constructs this class – viaTupleManager.__reduce__’s(type(self), (), state)– beforeConstants.__setstate__runs, so the name must exist here even though the shim’sConstants._snapshot()never reads it:regexesis a read-only_RegexesProxyin 2.0 (see above), andConstants.__setstate__below deliberately ignores an incomingregexeskey rather than restoring it from this reconstructed (and otherwise unused) instance.
- class nameparser.config.SetManager(elements: Iterable[str] = (), _on_change: Callable[[], None] | None = None, _field: str | None = None)[source]¶
v1
SetManagersurface over a plain set oflc()-normalized strings. Mutations call_on_change(the owning Constants’ generation bump, wired by a later task).__call__and the missing-member-tolerantremove()are gone per the #243 schedule (warned 1.3.0, removed 2.0):remove()of a missing member raisesKeyError, matchingset.remove.- add(*strings: str) SetManager[source]¶
Add the normalized string arguments to the set. Returns
selffor chaining.
- remove(*strings: str) SetManager[source]¶
Remove the normalized string arguments from the set. Raises
KeyErrorif any argument is not a member. Returnsselffor chaining.
- discard(*strings: str) SetManager[source]¶
Remove the normalized string arguments from the set if present; missing members are ignored, like
set.discard. Returnsselffor chaining.
- clear() SetManager[source]¶
Remove all entries from the set. Returns
selffor chaining.
- class nameparser.config.TupleManager(*args: object, _on_change: Callable[[], None] | None = None, **kwargs: object)[source]¶
v1
TupleManager: a dict with dot-notation access. Backscapitalization_exceptions. Unknown-key attribute access raisesAttributeErrornaming the key (#256, warned 1.4, enforced 2.0 – the v1DeprecationWarningis gone, this shim only speaks 2.0). Mutations call_on_change(the owning Constants’ generation bump, wired by a later task).- pop(k[, d]) v, remove specified key and return the corresponding value.[source]¶
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem() tuple[str, object][source]¶
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
HumanName.config Defaults¶
- nameparser.config.titles.FIRST_NAME_TITLES = {'aunt', 'auntie', 'brother', 'cheikh', 'dame', 'father', 'king', 'maid', 'master', 'mother', 'pope', 'queen', 'shaik', 'shaikh', 'shayk', 'shaykh', 'sheik', 'sheikh', 'shekh', 'sir', 'sister', 'uncle', 'أستاذ', 'أستاذة', 'الأستاذ', 'الأستاذة', 'الحاج', 'الحاجة', 'الدكتور', 'الدكتورة', 'الشيخ', 'الشيخة', 'دكتور', 'دكتورة', 'مهندس'}¶
When these titles appear with a single other name, that name is a first name, e.g. “Sir John”, “Sister Mary”, “Queen Elizabeth”.
- nameparser.config.titles.TITLES = {'10th', '1lt', '1sgt', '1st', '1stlt', '1stsgt', '2lt', '2nd', '2ndlt', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', 'a1c', 'ab', 'abbess', 'abbot', 'abolitionist', 'academic', 'acolyte', 'activist', 'actor', 'actress', 'adept', 'adjutant', 'adm', 'admiral', 'advertising', 'adviser', 'advocate', 'air', 'akhoond', 'alderman', 'almoner', 'ambassador', 'amn', 'analytics', 'anarchist', 'animator', 'anthropologist', 'appellate', 'apprentice', 'arbitrator', 'archbishop', 'archdeacon', 'archdruid', 'archduchess', 'archduke', 'archeologist', 'architect', 'arhat', 'army', 'arranger', 'assistant', 'assoc', 'associate', 'asst', 'astronomer', 'attache', 'attaché', 'attorney', 'aunt', 'auntie', 'author', 'award-winning', 'ayatollah', 'baba', 'bailiff', 'ballet', 'bandleader', 'banker', 'banner', 'bard', 'baron', 'baroness', 'barrister', 'baseball', 'bearer', 'behavioral', 'bench', 'bg', 'bgen', 'biblical', 'bibliographer', 'biochemist', 'biographer', 'biologist', 'bishop', 'blessed', 'blogger', 'blues', 'bodhisattva', 'bookseller', 'botanist', 'bp', 'brigadier', 'briggen', 'british', 'broadcaster', 'brother', 'buddha', 'burgess', 'burlesque', 'business', 'businessman', 'businesswoman', 'bwana', 'canon', 'capt', 'captain', 'cardinal', 'cartographer', 'cartoonist', 'catholicos', 'ccmsgt', 'cdr', 'celebrity', 'ceo', 'cfo', 'chair', 'chairs', 'chancellor', 'chaplain', "chargé d'affaires", 'chef', 'cheikh', 'chemist', 'chief', 'chieftain', 'choreographer', 'civil', 'classical', 'clergyman', 'clerk', 'cmsaf', 'cmsgt', 'co-chair', 'co-chairs', 'co-founder', 'coach', 'col', 'collector', 'colonel', 'comedian', 'comedienne', 'comic', 'commander', 'commander-in-chief', 'commodore', 'composer', 'compositeur', 'comptroller', 'computer', 'comtesse', 'conductor', 'consultant', 'controller', 'corporal', 'corporate', 'correspondent', 'councillor', 'counselor', 'count', 'countess', 'courtier', 'cpl', 'cpo', 'cpt', 'credit', 'criminal', 'criminologist', 'critic', 'csm', 'curator', 'customs', 'cwo-2', 'cwo-3', 'cwo-4', 'cwo-5', 'cwo2', 'cwo3', 'cwo4', 'cwo5', 'cyclist', 'dame', 'dancer', 'dcn', 'deacon', 'delegate', 'deputy', 'designated', 'designer', 'detective', 'developer', 'dhr', 'dipl.-ing', 'diplomat', 'dir', 'director', 'discovery', 'dissident', 'district', 'division', 'do', 'docent', 'docket', 'doctor', 'doyen', 'dpty', 'dr', 'dra', 'dramatist', 'druid', 'drummer', 'duchesse', 'dutchess', 'ecologist', 'economist', 'editor', 'edler', 'edmi', 'edohen', 'educator', 'effendi', 'ekegbian', 'elerunwon', 'eminence', 'emperor', 'empress', 'engineer', 'english', 'ens', 'entertainer', 'entrepreneur', 'envoy', 'erzbischof', 'essayist', 'evangelist', 'excellency', 'excellent', 'exec', 'executive', 'expert', 'fadm', 'family', 'father', 'federal', 'fh-prof', 'field', 'film', 'financial', 'first', 'flag', 'flying', 'foreign', 'forester', 'founder', 'fr', 'frau', 'freifrau', 'freiherr', 'friar', 'frk', 'fru', 'fräulein', 'frøken', 'fürst', 'fürsterzbischof', 'gaf', 'gen', 'general', 'generalissimo', 'gentiluomo', 'giani', 'goodman', 'goodwife', 'governor', 'graf', 'grand', 'group', 'großfürst', 'gräfin', 'guitarist', 'guru', 'gyani', 'gysgt', 'hajji', 'headman', 'heir', 'heiress', 'her', 'hereditary', 'heren', 'herr', 'herren', 'herrn', 'herzog', 'high', 'highness', 'his', 'historian', 'historicus', 'historien', 'holiness', 'hon', 'honorable', 'honourable', 'host', 'hr', 'illustrator', 'imam', 'industrialist', 'information', 'instructor', 'intelligence', 'intendant', 'inventor', 'investigator', 'investor', 'journalist', 'journeyman', 'jr', 'judge', 'judicial', 'junior', 'jurist', 'keyboardist', 'king', "king's", 'kingdom', 'knowledge', 'lady', 'lama', 'lamido', 'law', 'lawyer', 'lcdr', 'lcpl', 'leader', 'lecturer', 'legal', 'librarian', 'lieutenant', 'linguist', 'literary', 'lord', 'lt', 'ltc', 'ltcol', 'ltg', 'ltgen', 'ltjg', 'lyricist', 'madam', 'madame', 'mademoiselle', 'mag', 'mag-judge', 'mag/judge', 'magistrate', 'magistrate-judge', 'magnate', 'maharajah', 'maharani', 'mahdi', 'maid', 'maj', 'majesty', 'majgen', 'manager', 'marcher', 'marchess', 'marchioness', 'marketing', 'marquess', 'marquis', 'marquise', 'master', 'mathematician', 'mathematics', 'matriarch', 'mayor', 'mcpo', 'mcpoc', 'mcpon', 'md', 'me', 'member', 'memoirist', 'merchant', 'met', 'metropolitan', 'mevr', 'mevrouw', 'mevrouwe', 'mg', 'mgr', 'mgysgt', 'military', 'minister', 'miss', 'misses', 'missionary', 'mister', 'mlle', 'mme', 'mobster', 'model', 'monk', 'monseigneur', 'monsieur', 'monsignor', 'most', 'mother', 'mountaineer', 'mpco-cg', 'mr', 'mrs', 'ms', 'msg', 'msgt', 'mufti', 'mullah', 'municipal', 'murshid', 'musician', 'musicologist', 'mx', 'mystery', 'nanny', 'narrator', 'national', 'naturalist', 'navy', 'neuroscientist', 'novelist', 'nurse', 'obstetritian', 'officer', 'opera', 'operating', 'ornithologist', 'painter', 'paleontologist', 'pastor', 'patriarch', 'pd', 'pediatrician', 'personality', 'petty', 'pfc', 'pharaoh', 'phd', 'philantropist', 'philosopher', 'photographer', 'physician', 'physicist', 'pianist', 'pilot', 'pioneer', 'pir', 'player', 'playwright', 'po1', 'po2', 'po3', 'poet', 'police', 'political', 'politician', 'pope', 'prefect', 'prelate', 'premier', 'pres', 'presbyter', 'president', 'presiding', 'priest', 'priestess', 'primate', 'prime', 'prin', 'prince', 'princess', 'principal', 'printer', 'printmaker', 'prinz', 'prior', 'priv.-doz', 'private', 'pro', 'producer', 'prof', 'professor', 'provost', 'pslc', 'psychiatrist', 'psychologist', 'publisher', 'pursuivant', 'pv2', 'pvt', 'queen', "queen's", 'ra', 'rabbi', 'radio', 'radm', 'rangatira', 'ranger', 'rdml', 'rear', 'rebbe', 'registrar', 'reichsgraf', 'rep', 'representative', 'researcher', 'resident', 'rev', 'revenue', 'reverend', 'right', 'risk', 'ritter', 'rock', 'royal', 'rt', 'sa', 'sailor', 'saint', 'sainte', 'saoshyant', 'satirist', 'scholar', 'schoolmaster', 'scientist', 'scpo', 'screenwriter', 'se', 'secretary', 'security', 'seigneur', 'senator', 'senhor', 'senhora', 'senhorita', 'senior', 'senior-judge', 'sergeant', 'servant', 'señor', 'señora', 'señores', 'señorita', 'señoritas', 'sfc', 'sgm', 'sgt', 'sgtmaj', 'sgtmajmc', 'shaik', 'shaikh', 'shayk', 'shaykh', 'shehu', 'sheik', 'sheikh', 'shekh', 'sheriff', 'siddha', 'signor', 'signora', 'signore', 'signorina', 'singer', 'singer-songwriter', 'sir', 'sister', 'sma', 'smsgt', 'sn', 'soccer', 'social', 'sociologist', 'software', 'soldier', 'solicitor', 'soprano', 'spc', 'speaker', 'special', 'sr', 'sra', 'sres', 'srta', 'srtas', 'ssg', 'ssgt', 'st', 'staff', 'state', 'states', 'strategy', 'subaltern', 'subedar', 'suffragist', 'sultan', 'sultana', 'superior', 'supreme', 'surgeon', 'swami', 'swordbearer', 'sysselmann', 'tax', 'teacher', 'technical', 'technologist', 'television', 'tenor', 'theater', 'theatre', 'theologian', 'theorist', 'timi', 'tirthankar', 'translator', 'travel', 'treasurer', 'tsar', 'tsarina', 'tsgt', 'uk', 'uncle', 'united', 'univ.prof', 'us', 'vadm', 'vardapet', 'vc', 'venerable', 'verderer', 'vicar', 'vice', 'viscount', 'vizier', 'vocalist', 'voice', 'vrouwe', 'warden', 'warrant', 'wing', 'wm', 'wo-1', 'wo1', 'wo2', 'wo3', 'wo4', 'wo5', 'woodman', 'wp', 'writer', 'zoologist', 'δρ', 'κα', 'καθ', 'κος', 'акад', 'г-жа', 'г-н', 'д-р', 'пан', 'пані', 'проф', "גב'", 'גברת', 'גב׳', 'ד"ר', 'ד״ר', 'הרב', 'מר', 'עו"ד', 'עו״ד', "פרופ'", 'פרופסור', 'פרופ׳', 'أستاذ', 'أستاذة', 'الأستاذ', 'الأستاذة', 'الحاج', 'الحاجة', 'الدكتور', 'الدكتورة', 'الشيخ', 'الشيخة', 'دكتور', 'دكتورة', 'مهندس', 'डॉ', 'श्री', 'श्रीमती'}¶
Cannot include things that could also be first names, e.g. “dean”. Many of these from wikipedia: https://en.wikipedia.org/wiki/Title. The parser recognizes chains of these including conjunctions allowing recognition titles like “Deputy Secretary of State”.
- nameparser.config.suffixes.SUFFIX_NOT_ACRONYMS = {'2', 'dr', 'esq', 'esquire', 'i', 'ii', 'iii', 'iv', 'jnr', 'jr', 'junior', 'ret', 'snr', 'sr', 'v', 'vet', 'ז"ל', 'ז״ל', 'שליט"א', 'שליט״א'}¶
Post-nominal pieces that are not acronyms. The parser does not remove periods when matching against these pieces.
- nameparser.config.suffixes.SUFFIX_ACRONYMS_AMBIGUOUS = {'do', 'ed', 'jd', 'ma'}¶
Acronym suffixes from SUFFIX_ACRONYMS that also plausibly collide with a common given-name nickname. Not a partition of SUFFIX_ACRONYMS – a small, standalone exception list consulted only by parse_nicknames().
- nameparser.config.suffixes.SUFFIX_ACRONYMS = {'8-vsb', 'aas', 'aba', 'abc', 'abd', 'abpp', 'abr', 'aca', 'acas', 'ace', 'acha', 'acp', 'ae', 'aem', 'afasma', 'afc', 'afm', 'agsf', 'aia', 'aicp', 'ala', 'alc', 'alp', 'am', 'amd', 'ame', 'amieee', 'ams', 'aphr', 'apn', 'apr', 'aprn', 'apss', 'aqp', 'arm', 'arrc', 'asa', 'asc', 'asid', 'asla', 'asp', 'atc', 'awb', 'ba', 'bca', 'bcl', 'bcss', 'bds', 'bem', 'bls-i', 'bn', 'bpe', 'bpi', 'bpt', 'bsc', 'bt', 'btcs', 'bts', 'cacts', 'cae', 'caha', 'caia', 'cams', 'cap', 'capa', 'capm', 'capp', 'caps', 'caro', 'cas', 'casp', 'cb', 'cbe', 'cbm', 'cbne', 'cbnt', 'cbp', 'cbrte', 'cbs', 'cbsp', 'cbt', 'cbte', 'cbv', 'cca', 'ccc', 'ccca', 'cccm', 'cce', 'cchp', 'ccie', 'ccim', 'cciso', 'ccm', 'ccmt', 'ccna', 'ccnp', 'ccp', 'ccp-c', 'ccpr', 'ccs', 'ccufc', 'cd', 'cdal', 'cdfm', 'cdmp', 'cds', 'cdt', 'cea', 'ceas', 'cebs', 'ceds', 'ceh', 'cela', 'cem', 'cep', 'cera', 'cet', 'cfa', 'cfc', 'cfcc', 'cfce', 'cfcm', 'cfe', 'cfeds', 'cfi', 'cfm', 'cfp', 'cfps', 'cfr', 'cfre', 'cga', 'cgap', 'cgb', 'cgc', 'cgfm', 'cgfo', 'cgm', 'cgma', 'cgp', 'cgr', 'cgsp', 'ch', 'cha', 'chba', 'chdm', 'che', 'ches', 'chfc', 'chi', 'chmc', 'chmm', 'chp', 'chpa', 'chpe', 'chpln', 'chpse', 'chrm', 'chsc', 'chse', 'chse-a', 'chsos', 'chss', 'cht', 'cia', 'cic', 'cie', 'cig', 'cip', 'cipm', 'cips', 'ciro', 'cisa', 'cism', 'cissp', 'cla', 'clsd', 'cltd', 'clu', 'cm', 'cma', 'cmas', 'cmc', 'cmfo', 'cmg', 'cmp', 'cms', 'cmsp', 'cmt', 'cna', 'cnm', 'cnp', 'cp', 'cp-c', 'cpa', 'cpacc', 'cpbe', 'cpcm', 'cpcu', 'cpe', 'cpfa', 'cpfo', 'cpg', 'cph', 'cpht', 'cpim', 'cpl', 'cplp', 'cpm', 'cpo', 'cpp', 'cppm', 'cprc', 'cpre', 'cprp', 'cpsc', 'cpsi', 'cpss', 'cpt', 'cpwa', 'crde', 'crisc', 'crma', 'crme', 'crna', 'cro', 'crp', 'crt', 'crtt', 'csa', 'csbe', 'csc', 'cscp', 'cscu', 'csep', 'csi', 'csm', 'csp', 'cspo', 'csre', 'csrte', 'csslp', 'cssm', 'cst', 'cste', 'ctbs', 'ctfa', 'cto', 'ctp', 'cts', 'cua', 'cusp', 'cva', 'cva[22]', 'cvo', 'cvp', 'cvrs', 'cwap', 'cwb', 'cwdp', 'cwep', 'cwna', 'cwne', 'cwp', 'cwsp', 'cxa', 'cyds', 'cysa', 'dabfm', 'dabvlm', 'dacvim', 'dbe', 'dc', 'dcb', 'dcm', 'dcmg', 'dcvo', 'dd', 'dds', 'ded', 'dep', 'dfc', 'dfm', 'diplac', 'diplom', 'djur', 'dma', 'dmd', 'dmin', 'dnp', 'do', 'dpm', 'dpt', 'drb', 'drmp', 'drph', 'dsc', 'dsm', 'dso', 'dss', 'dtr', 'dvep', 'dvm', 'ea', 'ed', 'edd', 'ei', 'eit', 'els', 'emd', 'emt-b', 'emt-i/85', 'emt-i/99', 'emt-p', 'enp', 'erd', 'esq', 'evp', 'faafp', 'faan', 'faap', 'fac-c', 'facc', 'facd', 'facem', 'facep', 'facha', 'facofp', 'facog', 'facp', 'facph', 'facs', 'faia', 'faicp', 'fala', 'fashp', 'fasid', 'fasla', 'fasma', 'faspen', 'fca', 'fcas', 'fcela', 'fd', 'fec', 'fhames', 'fic', 'ficf', 'fieee', 'fmp', 'fmva', 'fnss', 'fp&a', 'fp-c', 'fpc', 'frm', 'fsa', 'fsdp', 'fws', 'gaee[14]', 'gba', 'gbe', 'gc', 'gcb', 'gchs', 'gcie', 'gcmg', 'gcsi', 'gcvo', 'gisp', 'git', 'gm', 'gmb', 'gmr', 'gphr', 'gri', 'grp', 'gsmieee', 'hccp', 'hrs', 'iaccp', 'iaee', 'iccm-d', 'iccm-f', 'idsm', 'ifgict', 'iom', 'ipep', 'ipm', 'iso', 'issp-csp', 'issp-sa', 'itil', 'jd', 'jp', 'kbe', 'kcb', 'kchs/dchs', 'kcie', 'kcmg', 'kcsi', 'kcvo', 'kg', 'khs/dhs', 'kp', 'kt', 'lac', 'lcmt', 'lcpc', 'lcsw', 'leed ap', 'lg', 'litk', 'litl', 'litp', 'llm', 'lm', 'lmsw', 'lmt', 'lp', 'lpa', 'lpc', 'lpn', 'lpss', 'lsi', 'lsit', 'lt', 'lvn', 'lvo', 'lvt', 'ma', 'maaa', 'mai', 'mba', 'mbe', 'mbs', 'mc', 'mcct', 'mcdba', 'mches', 'mcm', 'mcp', 'mcpd', 'mcsa', 'mcsd', 'mcse', 'mct', 'md', 'mda', 'mdb', 'mdbb', 'mdep', 'mdhb', 'mdiv', 'mdl', 'mem', 'meng', 'mfa', 'micp', 'mieee', 'mirm', 'mle', 'mls', 'mlse', 'mlt', 'mm', 'mmad', 'mmas', 'mnaa', 'mnae', 'mp', 'mpa', 'mph', 'mpse', 'mra', 'ms', 'msa', 'msc', 'mscmsm', 'msm', 'mt', 'mts', 'mvo', 'nbc-his', 'nbcch', 'nbcch-ps', 'nbcdch', 'nbcdch-ps', 'nbcfch', 'nbcfch-ps', 'nbct', 'ncarb', 'nccp', 'ncidq', 'ncps', 'ncso', 'ncto', 'nd', 'ndtr', 'nicet i', 'nicet ii', 'nicet iii', 'nicet iv', 'nmd', 'np', 'np[18]', 'nraemt', 'nremr', 'nremt', 'nrp', 'obe', 'obi', 'oca', 'ocm', 'ocp', 'od', 'om', 'oscp', 'ot', 'pa-c', 'pcc', 'pci', 'pe', 'pfmp', 'pg', 'pgmp', 'ph', 'pharmd', 'phc', 'phd', 'phr', 'phrca', 'pla', 'pls', 'pmc', 'pmi-acp', 'pmp', 'pp', 'pps', 'prm', 'psm', 'psm i', 'psm ii', 'psp', 'psyd', 'pt', 'pta', 'qam', 'qc', 'qcsw', 'qfsm', 'qgm', 'qpm', 'qsd', 'qsp', 'ra', 'rai', 'rba', 'rci', 'rcp', 'rd', 'rdcs', 'rdh', 'rdms', 'rdn', 'res', 'rfp', 'rhca', 'rid', 'rls', 'rmsks', 'rn', 'rp', 'rpa', 'rph', 'rpl', 'rrc', 'rrt', 'rrt-accs', 'rrt-nps', 'rrt-sds', 'rtrp', 'rvm', 'rvt', 'sa', 'same', 'sasm', 'sccp', 'scmp', 'se', 'secb', 'sfp', 'sgm', 'shrm-cp', 'shrm-scp', 'si', 'siie', 'smieee', 'sphr', 'sra', 'sscp', 'stb', 'stmieee', 'tbr-ct', 'td', 'thd', 'thm', 'ud', 'usa', 'usaf', 'usar', 'uscg', 'usmc', 'usn', 'usnr', 'uxc', 'uxmc', 'vc', 'vcp', 'vd', 'vrd'}¶
Post-nominal acronyms. Titles, degrees and other things people stick after their name that may or may not have periods between the letters. The parser removes periods when matching against these pieces.
- nameparser.config.prefixes.NON_FIRST_NAME_PREFIXES = {"'t", 'af', 'auf', 'av', 'bint', 'de', "de'", 'degli', 'dei', 'delle', 'delli', 'dello', 'dem', 'der', 'dos', 'het', 'ibn', 'op', 'ter', 'vd', 'vom', 'zu', 'בן', 'בת', 'آل', 'ابن', 'بن', 'بنت'}¶
The sub-set of
PREFIXESthat are never a standalone first name. A name that starts with one of these has no first name – the whole thing is a surname (e.g. “de Mesnil” -> last name “de Mesnil”). Curated to exclude anything that can be a given name in some culture (al, van, von, della, di, del, da, vander, …) and anything that is also a first name prefix (abu). When unsure, leave a word out: a missing member just means that name is not auto-fixed, whereas a wrong member misparses a real person. Must stay a subset ofPREFIXESand disjoint fromBOUND_FIRST_NAMES.
- nameparser.config.prefixes.PREFIXES = {"'t", 'aan', 'abu', 'aen', 'af', 'al', 'auf', 'av', 'bar', 'bat', 'bin', 'bint', 'bon', 'da', 'dal', 'de', "de'", 'degli', 'dei', 'del', 'dela', 'della', 'delle', 'delli', 'dello', 'dem', 'den', 'der', 'di', 'do', 'dos', 'du', 'dí', 'freiherr', 'freiherrin', 'heer', 'het', 'ibn', 'la', 'le', 'mac', 'mc', 'op', 'san', 'santa', 'st', 'ste', 'te', 'ter', 'tho', 'thoe', 'van', 'vande', 'vander', 'vd', 'vel', 'vom', 'von', 'zu', 'בן', 'בת', 'آل', 'أبو', 'ابن', 'ابو', 'بن', 'بنت'}¶
Name pieces that appear before a last name. Prefixes join to the piece that follows them to make one new piece. They can be chained together, e.g “von der” and “de la”. Because they only appear in middle or last names, they also signify that all following name pieces should be in the same name part, for example, “von” will be joined to all following pieces that are not prefixes or suffixes, allowing recognition of double last names when they appear after a prefixes. So in “pennie von bergen wessels MD”, “von” will join with all following name pieces until the suffix “MD”, resulting in the correct parsing of the last name “von bergen wessels”.
Defined as a static union so every
NON_FIRST_NAME_PREFIXESmember is guaranteed to also be a prefix (and still join forward), with no drift – mirroringTITLES = FIRST_NAME_TITLES | {...}innameparser.config.titles.
- nameparser.config.bound_first_names.BOUND_FIRST_NAMES: set[str] = {'abdal', 'abdel', 'abdul', 'abou', 'abu', 'umm', 'أبو', 'أم', 'ابو', 'ام', 'عبد'}¶
Bound Arabic given-name prefixes that attach to the following word to form one first name (e.g. “abdul salam” → first name “abdul salam”). They are never standalone names. Join logic runs in the given-name region only, mirroring
PREFIXESfor last names.
- nameparser.config.conjunctions.CONJUNCTIONS = {'&', 'and', 'e', 'et', 'of', 'the', 'und', 'y', 'και', 'и', 'та', 'і', 'و'}¶
Pieces that should join to their neighboring pieces, e.g. “and”, “y” and “&”. “of” and “the” are also include to facilitate joining multiple titles, e.g. “President of the United States”.
- nameparser.config.maiden_markers.MAIDEN_MARKERS = {'född', 'fødd', 'født', 'geb', 'geboren', 'geborene', 'nee', 'né', 'née', 'roz', 'rozená', 'урожд', 'урожденная', 'урожденный', 'урождённая', 'урождённый'}¶
Marker words that introduce a birth surname, e.g. “Jane Smith née Jones” (#274). French née/né/nee, German geb./geborene, Dutch geboren, Czech/Slovak roz./rozená, Danish/Norwegian født (Nynorsk fødd), Swedish född, Russian урожд./урождённая/урождённый (both ё and е spellings — case normalization does not fold them, and running text routinely writes е). Both grammatical genders are listed where #274 or review attested them (née/né, урождённая/урождённый); Czech masculine rozený awaits the same vetting. Entries are stored normalized: lowercase, no periods.
Consumed by the 2.0 parser’s default lexicon. The 1.x parser does not read this module.
Deliberately absent: Polish “z domu” (a two-token marker; pending the 2.0 pipeline’s multi-token matching decision) and the Scandinavian abbreviation “f.” (collides with the initial “F.” — only the full participles are safe).
- nameparser.config.capitalization.CAPITALIZATION_EXCEPTIONS = {'ii': 'II', 'iii': 'III', 'iv': 'IV', 'md': 'M.D.', 'phd': 'Ph.D.'}¶
Any pieces that are not capitalized by capitalizing the first letter.
- nameparser.config.regexes.REGEXES = {'bidi': re.compile('[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]+'), 'commas': re.compile('[,،,]'), 'double_quotes': re.compile('\\"(.*?)\\"'), 'east_slavic_patronymic': re.compile('(ovich|ovna|evich|evna|ichna|ilyich|kuzmich|lukich|fomich|fokich)$', re.IGNORECASE), 'east_slavic_patronymic_cyrillic': re.compile('(ович|овна|евич|евна|ична|ильич|кузьмич|лукич|фомич|фокич)$', re.IGNORECASE), 'emoji': re.compile('[🌀-🙏🚀-\U0001f6ff☀-⛿✀-➿]+'), 'initial': re.compile('^(\\w\\.|[A-Z])?$'), 'mac': re.compile('^(ma?c)(\\w{2,})', re.IGNORECASE), 'parenthesis': re.compile('\\((.*?)\\)'), 'period_abbreviation': re.compile('^[^\\W\\d_]{2,}\\.$'), 'period_not_at_end': re.compile('.*\\..+$', re.IGNORECASE), 'phd': re.compile('\\s(ph\\.?\\s+d\\.?)', re.IGNORECASE), 'quoted_word': re.compile("(?<!\\w)\\'([^\\s]*?)\\'(?!\\w)"), 'roman_numeral': re.compile('^(X|IX|IV|V?I{0,3})$', re.IGNORECASE), 'space_before_comma': re.compile('\\s+,'), 'spaces': re.compile('\\s+'), 'turkic_patronymic_marker': re.compile("^(oglu|oğlu|ogly|ogli|o['’ʻ]g['’ʻ]li|qizi|qızı|kizi|kyzy|gyzy|uly|uulu)$", re.IGNORECASE), 'turkic_patronymic_marker_cyrillic': re.compile('^(оглу|оглы|оғлу|ўғли|угли|кызы|гызы|қызы|қизи|улы|ұлы|уулу)$', re.IGNORECASE), 'word': re.compile('(\\w|\\.)+')}¶
All regular expressions used by the parser are precompiled and stored in the config.