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 to Parser().parse(text); build your own Parser (or use parser_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 a Policy (behavior), both defaulted when omitted. Build one when you need non-default configuration, build it once, and call parse() 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 through tokens / tokens_for(); correct a parse with replace() (returns a new value); produce output with render(), initials(), capitalized(), or str().

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().

tokens: tuple[Token, ...]

Every classified token, in document order.

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.tokens or ParsedName.tokens_for(); you only construct one directly when hand-building a ParsedName.

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.

role: Role

The field this token belongs to.

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 Token came from: a character range into ParsedName.original such that original[start:end] is the token’s source text (end exclusive). A plain two-int NamedTuple; None in Token.span marks 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 to ParsedName.tokens_for(); a member’s .value is 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.ambiguities instead 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).

tokens: tuple[Token, ...]

The tokens involved – always a value-equal subset of the owning ParsedName’s tokens (checked with ==, not identity: two distinct Token instances with identical text/span/role/tags satisfy this); may be empty (e.g. unbalanced-delimiter).

class nameparser.AmbiguityKind(*values)[source]

The stable vocabulary of Ambiguity kinds. A StrEnum: members ARE their string values, so kind == "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, so detail names 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) or empty(), derive variants with add() / remove() / | (union), and pass the result to Parser(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.

titles: frozenset[str]

Pre-nominal titles (“dr”, “sir”, “capt”, …). Full default list: TITLES.

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 to Parser(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 PolicyPatch field, distinguishable from every real value including None and False. 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_delimiters set: 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 to maiden, just list it in maiden_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 in nameparser.locales; building your own needs no registration – construct one and pass it to parser_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).

nameparser.locales.available() tuple[str, ...][source]

The registered locale codes, lowercase, sorted.

nameparser.locales.get(code: str) Locale[source]

Dynamic lookup by code (‘ru’); raises KeyError listing the available codes (spec §2).

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 HumanName facade: a mutable wrapper over a frozen ParsedName, delegating all parsing to the core Parser resolved from the bound Constants shim (dirty-tracked via its _generation). Keeps every v1 spelling (first/last over the core given/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): mutate name.C then call this to force a re-parse without reassigning full_name. The v1 parsing INTERNALS this name evokes live in the core Parser, 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.

comparison_key() tuple[str, ...][source]

One casefolded component per field in canonical order – the v1 replacement for ==/hash (#223); see ParsedName.comparison_key.

as_dict(include_empty: bool = True) dict[str, str][source]

The seven v1-named components as a dict; include_empty=False drops empty fields.

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 Constants shim: a mutable container whose state resolves to a frozen (Lexicon, Policy, _RenderDefaults) snapshot via _snapshot(). _generation increments 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 CONSTANTS singleton (below) has _shared flipped to True: any mutation reached through it emits DeprecationWarning pointing at Lexicon/Policy and HumanName(constants=...). A private Constants() never warns – only the shared instance is on the 3.0 removal path.

copy() Constants[source]

Independent copy (#260), subclass-preserving. Divergence from v1 (which deepcopied __dict__): attributes OUTSIDE the known field surface – e.g. ad-hoc names stashed on the instance – are not carried by copy() or pickling; only the enumerated fields survive.

class nameparser.config.RegexTupleManager(*args: object, _on_change: Callable[[], None] | None = None, **kwargs: object)[source]

Pickle-compat alias only: v1.4’s Constants.regexes field was a nameparser.config.RegexTupleManager instance (a TupleManager subclass whose __getattr__ fell back to EMPTY_REGEX for an unknown key). Unpickling a v1.4 blob resolves and constructs this class – via TupleManager.__reduce__’s (type(self), (), state) – before Constants.__setstate__ runs, so the name must exist here even though the shim’s Constants._snapshot() never reads it: regexes is a read-only _RegexesProxy in 2.0 (see above), and Constants.__setstate__ below deliberately ignores an incoming regexes key 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 SetManager surface over a plain set of lc()-normalized strings. Mutations call _on_change (the owning Constants’ generation bump, wired by a later task). __call__ and the missing-member-tolerant remove() are gone per the #243 schedule (warned 1.3.0, removed 2.0): remove() of a missing member raises KeyError, matching set.remove.

add(*strings: str) SetManager[source]

Add the normalized string arguments to the set. Returns self for chaining.

remove(*strings: str) SetManager[source]

Remove the normalized string arguments from the set. Raises KeyError if any argument is not a member. Returns self for chaining.

discard(*strings: str) SetManager[source]

Remove the normalized string arguments from the set if present; missing members are ignored, like set.discard. Returns self for chaining.

clear() SetManager[source]

Remove all entries from the set. Returns self for chaining.

class nameparser.config.TupleManager(*args: object, _on_change: Callable[[], None] | None = None, **kwargs: object)[source]

v1 TupleManager: a dict with dot-notation access. Backs capitalization_exceptions. Unknown-key attribute access raises AttributeError naming the key (#256, warned 1.4, enforced 2.0 – the v1 DeprecationWarning is 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.

clear() None.  Remove all items from D.[source]
update([E, ]**F) None.  Update D from mapping/iterable E and F.[source]

If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

setdefault(key: str, default: object = None) object[source]

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

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 PREFIXES that 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 of PREFIXES and disjoint from BOUND_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_PREFIXES member is guaranteed to also be a prefix (and still join forward), with no drift – mirroring TITLES = FIRST_NAME_TITLES | {...} in nameparser.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 PREFIXES for 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.