v2.0.0rc1
Pre-releaseThis is a release candidate. A plain
pip install nameparserwill not pick it up — pre-releases are opt-in:pip install --pre nameparser==2.0.0rc1Please try it against your real code and report anything the migration missed on #284. The final 2.0.0 follows once the RC settles.
nameparser 2.0 adds a new parsing API alongside HumanName. HumanName keeps working unchanged as a compatibility facade over the same pipeline, and stays through the 2.x series — if your code runs warning-free on 1.4.0, most of 2.0 will not affect you.
What's new: the 2.0 API
parse(text) returns an immutable ParsedName whose seven fields are named for what they are — given, family — rather than where they sit in a Western name:
from nameparser import parse
name = parse("Dr. Juan Q. Xavier de la Vega III")
name.given # 'Juan'
name.family # 'de la Vega'
name.family_base # 'Vega' (particles split off)
name.suffix # 'III'- Frozen, explicit configuration. A
Lexiconof vocabulary and aPolicyof behavior replace the mutable globalConstants. Both are immutable, hashable value objects; parsing is a pure function of the text, a lexicon, and a policy — nothing global is read or mutated. Build a reusableParser(lexicon=..., policy=...). - Family-first name order, as written rather than reordered by hand —
Policy(name_order=FAMILY_FIRST)andFAMILY_FIRST_GIVEN_LAST(#270). - Locale packs.
parser_for(locales.RU)folds in East Slavic patronymic order;locales.TR_AZcovers Turkic markers. Packs are pure data, they compose, and they're never auto-detected. - New recognition: maiden markers (
née,geb.→ amaidenfield, #274), typographic nickname delimiters (smart quotes, guillemets, CJK brackets, #273), and non-Latin vocabulary — Cyrillic, Greek, Arabic, Hebrew titles and particles (#269). - Honest ambiguity. When a parse has to guess, it says so on
ParsedName.ambiguitiesinstead of guessing silently — e.g."John Smith MA"reports thatMAwas read as a credential rather than a surname. A reading the vocabulary settles on its own reports nothing. - Exact provenance. Every field is backed by
Tokens carrying(start, end)offsets into the original string, reachable viatokens_for(Role.GIVEN)— so you can highlight or re-slice the input a parse came from. - Fully typed (PEP 561), checked under strict mypy, with no runtime dependencies.
Breaking changes — read before upgrading
The removals are the deprecations announced in 1.3.0 and 1.4.0 coming due. The one that matters most:
⚠️ HumanName.__eq__and__hash__are removed (#223). Instances now compare and hash by identity, soHumanName("John Smith") == "John Smith"is nowFalsewhere 1.x returnedTrue. This changes results silently rather than raising — it's the one removal that can slip into production unnoticed. Usematches()to compare names andcomparison_key()as a dict/sort key.
Also: minimum Python is now 3.11 (#257); bytes input is gone (decode first, #245); regex configuration, subclass parsing hooks, HumanName slicing, and empty_attribute_default are removed. Each raises with a migration hint (except the __eq__ case above).
Migrating
HumanName is unchanged, so most users need to do nothing yet. If you customized Constants, subclassed HumanName, or compared names with ==, see the migration guide for the field-by-field and attribute-by-attribute map.
- 📖 Full 2.0 documentation · Using the parser · Customizing
- 📝 Complete release notes
- 💬 Feedback → #284