Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
273 commits
Select commit Hold shift + click to select a range
b88d3ac
Drop exception keys that normalize to empty
derek73 Jul 12, 2026
0838e98
Add bounded deviation-only reprs to all v2 types
derek73 Jul 12, 2026
af6a01a
Export v2 core types; enforce layering and mypy strictness
derek73 Jul 12, 2026
30ef763
Make Lexicon picklable despite its mappingproxy slot
derek73 Jul 12, 2026
401535c
Drop Python 3.10 from the CI matrix (#257, partial)
derek73 Jul 12, 2026
f2b42c8
Drop the pre-3.11 typing_extensions shim (#257)
derek73 Jul 12, 2026
4c171fc
Annotate v2 test returns for ruff ANN compliance
derek73 Jul 12, 2026
353d10a
Tighten the layering test to exact-module matching
derek73 Jul 12, 2026
09cc85d
Pin the derived views' particle tag to STABLE_TAGS
derek73 Jul 12, 2026
473c0b9
Reject mappings passed to plain Lexicon vocab fields
derek73 Jul 12, 2026
ce7b36b
Diff Lexicon reprs against the nearer named baseline
derek73 Jul 12, 2026
334c617
Order Lexicon sections per conventions doc §4
derek73 Jul 12, 2026
5a5bf80
Adopt the stdlib exception taxonomy across v2 validation
derek73 Jul 12, 2026
974aec2
Source maiden markers from a config data module (#274)
derek73 Jul 12, 2026
5d78933
Add Scandinavian participle maiden markers (#274)
derek73 Jul 12, 2026
a16364e
Distill 2.0 implementation conventions into AGENTS.md
derek73 Jul 12, 2026
339a3ed
Guard Token.tags and coerce Token.role
derek73 Jul 12, 2026
9d7493c
Close the fail-loud gaps in Policy.__post_init__
derek73 Jul 12, 2026
cff23ff
Canonicalize PolicyPatch's scalar name_order to a tuple
derek73 Jul 12, 2026
d4cb1b2
Validate capitalization_exceptions entry shapes
derek73 Jul 12, 2026
af3aad0
Fail at unpickle time on Lexicon field-layout skew
derek73 Jul 12, 2026
c5090d1
Fix vacuous removal assertion in the add/remove test
derek73 Jul 12, 2026
2310fb1
Pin four stated-but-untested v2 contracts
derek73 Jul 12, 2026
cbd8cdf
Fix stale and inaccurate comments found in review
derek73 Jul 12, 2026
358ce80
Raise on entries that normalize to empty
derek73 Jul 12, 2026
22fe2ea
Block Span concatenation and bool span coordinates
derek73 Jul 12, 2026
f07082b
Pin Locale.code to the registry-key charset [a-z0-9_]+
derek73 Jul 12, 2026
22ea503
Extract _coerce_enum for the duplicated enum coercion blocks
derek73 Jul 12, 2026
eaba92f
Extract _normpairs as _normset's sibling
derek73 Jul 12, 2026
cac4231
Drop the whitespace check the charset pin subsumed
derek73 Jul 12, 2026
a2d88ea
Test the real matrix interpreter, and add 3.15 pre-release (#259)
derek73 Jul 12, 2026
73e816e
Add _render with the #254-normative collapse; extend layering for it
derek73 Jul 12, 2026
a6750dc
Add render(): spec formatting over role fields and derived views
derek73 Jul 12, 2026
bbca365
Add ParsedName.render() and __str__ via call-time _render delegation
derek73 Jul 12, 2026
445571d
Add initials() with call-site delimiter/separator arguments
derek73 Jul 12, 2026
da94eb5
Add capitalized(): lexicon-driven case fixing, same spans
derek73 Jul 12, 2026
936d347
True up module docstrings to the rendering delegation
derek73 Jul 12, 2026
27616dc
Guard all frozen types against pickle layout skew
derek73 Jul 12, 2026
35e1836
Validate rendering arguments eagerly
derek73 Jul 13, 2026
7e8b6fb
Reject bare-string name_order with the taxonomy TypeError
derek73 Jul 13, 2026
4db87b7
Pin two documented rendering contracts
derek73 Jul 13, 2026
96b9166
Fix three stale doc claims from the PR review
derek73 Jul 13, 2026
79277de
Simplify the rendering module
derek73 Jul 13, 2026
60802f1
Single-source the bare-string name_order guard
derek73 Jul 13, 2026
bc56bd2
Enforce the pickle guards mechanically; flatten test imports
derek73 Jul 13, 2026
bf68147
Add the pipeline package skeleton: ParseState and layering wiring
derek73 Jul 13, 2026
24c5191
Add extract_delimited: delimiter pairs to nickname/maiden spans
derek73 Jul 13, 2026
7e341a9
Add tokenize: char-classification tokenizer with exact spans
derek73 Jul 13, 2026
29ceb18
Add segment: comma-structure decision over token index runs
derek73 Jul 13, 2026
a91e465
Add classify: vocabulary tags from the lexicon
derek73 Jul 13, 2026
20e6bf6
Add group: piece boundaries by index; joins ported from v1
derek73 Jul 13, 2026
5e22e78
Add assign: positional roles per name_order over pieces
derek73 Jul 13, 2026
4f3a707
Add post_rules: firstname swap and opt-in patronymic rotations
derek73 Jul 13, 2026
bb80c8d
Add assemble: final ParseState to validated ParsedName
derek73 Jul 13, 2026
9bcd007
Add Parser and parse(): the 2.0 pipeline goes end to end
derek73 Jul 13, 2026
8ad0247
Add parser_for() with locale-identified errors and matches()
derek73 Jul 13, 2026
c7e3fb0
Fix the shared case-table format and seed it with the pinned corpus
derek73 Jul 13, 2026
9347848
Add property, contract, and benchmark test layers
derek73 Jul 13, 2026
bacb42b
Apply type-design review fixes to the pipeline state contract
derek73 Jul 13, 2026
f65bd7c
Exclude the ambiguous subset from the plain suffix-acronym test
derek73 Jul 13, 2026
c66be14
Heal the split Ph. D. credential across the pipeline (I2/I3)
derek73 Jul 13, 2026
ec9e3a2
Fold a leading never-given particle into the family name (I4)
derek73 Jul 13, 2026
481f27a
Wire the three dead Policy fields (I5)
derek73 Jul 13, 2026
e7ccd67
Restrict name_order to the exported orders; drop dangled ambiguities
derek73 Jul 13, 2026
ddd0416
Add the review's test-coverage batch (T1-T4, T6)
derek73 Jul 13, 2026
d64cb6a
Single-source the suffix-as-written rule and the comma set
derek73 Jul 16, 2026
222b079
Factor the shared piece machinery in group and assign
derek73 Jul 16, 2026
2d5d8c2
Trim constant-factor waste on the tokenize hot path
derek73 Jul 16, 2026
12298df
Add the shim SetManager (migration spec §3)
derek73 Jul 16, 2026
95de007
Add shim TupleManager, delimiter managers, and the read-only regexes …
derek73 Jul 16, 2026
e2979f6
Add the shim Constants with generation tracking and pickle acceptance
derek73 Jul 16, 2026
8b22f1d
Resolve shim Constants to (Lexicon, Policy, defaults) snapshots with …
derek73 Jul 16, 2026
273e373
Wire Policy.extra_suffix_delimiters through segment and group (v1 suf…
derek73 Jul 17, 2026
3db907e
Add the HumanName facade skeleton: construction, config binding, dirt…
derek73 Jul 17, 2026
0719ae0
Add facade field properties, list snapshots, and derived views
derek73 Jul 17, 2026
ea49778
Add facade dunders: v1 str/repr/iteration, #258 item semantics, ident…
derek73 Jul 17, 2026
bd2abc7
Port v1 initials to the facade and validate render-default assignment
derek73 Jul 17, 2026
0cdd787
Add facade capitalize/matches/comparison_key and v1-compatible pickling
derek73 Jul 17, 2026
75e3219
Swap parser.py and config to the 2.0 facade and shim (v1 suite reconc…
derek73 Jul 17, 2026
2d3fb93
M12 batch 1: drop the dead empty_attribute_default dual-run fixture (…
derek73 Jul 17, 2026
a689e1d
M12 batch 1: delete test_config_attribute_docstrings.py (bucket A)
derek73 Jul 17, 2026
b959112
Preserve empty comma segments' structural position (v1 parity)
derek73 Jul 17, 2026
2e64c48
Close four v1-compat gaps: Constants kwargs, parse_full_name, C sette…
derek73 Jul 17, 2026
81f2109
Reconcile test_python_api against the facade (buckets A, B, E)
derek73 Jul 17, 2026
7bf53f3
Port v1's parts[1]-only suffix-comma decision and period-joined vocab…
derek73 Jul 17, 2026
7e81187
Restore v1.3/1.4 manager hardening in the shim (#221/#238/#241/#242/#…
derek73 Jul 17, 2026
7da89ee
Reconcile test_constants against the shim (buckets A, B, C)
derek73 Jul 17, 2026
c1b5730
Add the two v1.4 bool constructor kwargs to the shim Constants
derek73 Jul 17, 2026
eb4b362
Lift test_constants from the skip lists (bool kwargs landed)
derek73 Jul 17, 2026
be4e106
Reconcile test_output_format against the facade (buckets B, C)
derek73 Jul 17, 2026
0368081
Reconcile test_initials against the facade (buckets B, C, E)
derek73 Jul 17, 2026
91dad40
Hold test_capitalization on a confirmed _cap_word conjunction/initial…
derek73 Jul 17, 2026
e8dd59f
Hold test_first_name on a family-segment trailing-suffix pipeline bug
derek73 Jul 17, 2026
dac3f22
Reconcile test_titles; hold on two comma/nickname parity bugs (bucket D)
derek73 Jul 17, 2026
2c45150
Fix four v1-parity bugs from the M12 batch-2 queue
derek73 Jul 17, 2026
8ea1b36
Lift capitalization, first_name, and titles from the skip list
derek73 Jul 17, 2026
8784070
Hold test_suffixes on six suspected pipeline gaps (bucket D, reported)
derek73 Jul 17, 2026
35f6280
Route suffix-shaped delimited content past nickname extraction (v1 pa…
derek73 Jul 17, 2026
21795cc
Reconcile test_prefixes (bucket C); hold on the B1 trailing-suffix gap
derek73 Jul 17, 2026
20c2829
Hold test_conjunctions on the join-stage conjunction/initial bug
derek73 Jul 17, 2026
2c17454
Reconcile test_nicknames (buckets A, B); hold on a bucket-precedence …
derek73 Jul 17, 2026
7e044dd
Reconcile test_comma_variants against the facade (bucket B)
derek73 Jul 17, 2026
c131dde
Fix the M12 batch-3 bug queue: walk order, chunk rules, tail entries
derek73 Jul 17, 2026
95b148a
Lift suffixes, prefixes, conjunctions, nicknames from the skip list
derek73 Jul 17, 2026
bf06045
Reconcile patronymic + bound-given files; hold two on parity bugs
derek73 Jul 17, 2026
d8e3042
Delete test_parser_util.py (bucket A)
derek73 Jul 17, 2026
11d9e37
Reconcile test_variations against the facade (buckets A, B)
derek73 Jul 17, 2026
fb524d8
Reconcile test_brute_force (no edits needed); drop the mypy exclude
derek73 Jul 17, 2026
06bab72
Fix the last two M12 bugs and lift the reconciliation skip list
derek73 Jul 17, 2026
785c3e5
Add the facade runner over the shared case table
derek73 Jul 17, 2026
1748493
Add the v1-vs-2.0 differential harness with a classified allowlist
derek73 Jul 17, 2026
cd94143
Reimplement the CLI over the new API with --json
derek73 Jul 17, 2026
fa95cd1
Record the migration layer in AGENTS.md
derek73 Jul 17, 2026
912e608
Harden shim notification/validation paths and facade failure ordering
derek73 Jul 18, 2026
c39ef49
Harden the differential comparator against silent false confidence
derek73 Jul 18, 2026
b0099a9
Type polish and coverage from the toolkit review
derek73 Jul 18, 2026
05329f8
Fix comment rot and citation precision from the toolkit review
derek73 Jul 18, 2026
43969ad
Document the ma/do ambiguous-acronym data change
derek73 Jul 18, 2026
1eca44b
Apply the /simplify findings: snapshot caching, shared collapse, one …
derek73 Jul 18, 2026
9673f00
Lift _vocab's regex constants to the module top
derek73 Jul 18, 2026
2776fa2
Record the facade layer's concern-grouped class organization
derek73 Jul 18, 2026
6ee4681
Anchor the emoji-range CodeQL suppression on the flagged line
derek73 Jul 18, 2026
697dbe3
Eliminate the py/overly-large-range false positive at the source
derek73 Jul 18, 2026
ac43dc9
Add the locales package with lazy loading and the RU pack
derek73 Jul 18, 2026
e68db58
Add the TR_AZ pack
derek73 Jul 18, 2026
be3f25e
Scan ru.DEVIATES per token (whole-string search under-declared)
derek73 Jul 18, 2026
6fc7031
Add pack case-table segments through parser_for
derek73 Jul 18, 2026
822170a
Prove the RU+TR_AZ composition example with the shipped packs
derek73 Jul 18, 2026
be28a9b
Add the non-interference gate over the default corpus
derek73 Jul 18, 2026
6028ab4
Add non-Latin default vocabulary (#269): Cyrillic, Greek, Arabic, Hebrew
derek73 Jul 18, 2026
a053e8a
Drop bare Greek κ and tighten the #269 allowlist rule
derek73 Jul 18, 2026
759b217
Add --locale to the CLI (closes the deferred migration deviation)
derek73 Jul 18, 2026
b2ce60a
Record the locales package in AGENTS.md and the release-log draft
derek73 Jul 18, 2026
b49239d
Make the SetManager doctest reprs addition-proof
derek73 Jul 18, 2026
3e6e08d
fix: normalize vocabulary with lower(), not casefold()
derek73 Jul 18, 2026
81f8fa3
test: give the non-interference gate teeth; close locale coverage gaps
derek73 Jul 18, 2026
affdd5b
fix: --locale '' errors instead of silently using the default parser
derek73 Jul 18, 2026
7d6071c
docs: comment accuracy pass from the locale review
derek73 Jul 18, 2026
cf46e3c
test: simplify locale test scaffolding (/simplify review)
derek73 Jul 18, 2026
d4aaafa
test: make the pack registry the gate contract (design note, option C)
derek73 Jul 18, 2026
0fd386c
fix: point patronymic_rules=True at the v1 migration path
derek73 Jul 18, 2026
17efbbe
docs+test: record the comparison_key casefold deviation from 1.4
derek73 Jul 18, 2026
38b8dcb
style: ParsedName repr indents with 4 spaces, matching HumanName's
derek73 Jul 18, 2026
bcd58b7
docs: add concepts page — the 2.0 model in four essays
derek73 Jul 18, 2026
684f854
docs: rewrite usage.rst as the 2.0 getting-started tour
derek73 Jul 18, 2026
e954825
docs: rewrite customize.rst principle-first for the 2.0 API
derek73 Jul 18, 2026
f817d22
docs: add locales page — using, creating, contributing packs
derek73 Jul 18, 2026
26e0dea
docs: add Migrating from HumanName page (#262 successor)
derek73 Jul 18, 2026
6b68fda
fix: migration hint names both rules v1's patronymic flag enabled
derek73 Jul 18, 2026
7306724
docs: correct two migrate-table facts from the table audit
derek73 Jul 18, 2026
b29861c
docs: regroup reference into 2.0 API + compat layer; new front page
derek73 Jul 18, 2026
432e39e
docs: rewrite README new-API-first (doubles as the PyPI page)
derek73 Jul 18, 2026
5063056
docs: drop the nonexistent _static path so -W builds run clean
derek73 Jul 18, 2026
b809ccd
docs: show the CLI example's JSON output in usage.rst
derek73 Jul 18, 2026
cc7063f
feat: maiden_delimiters wins on overlap; export DEFAULT_NICKNAME_DELI…
derek73 Jul 18, 2026
0ab19fd
docs: use dean, not chancellor, as the add-a-title example
derek73 Jul 18, 2026
f609d40
docs: user-facing docstrings across the public API surface
derek73 Jul 18, 2026
76e85dc
docs: introduce and properly describe the module-level constants
derek73 Jul 18, 2026
4531538
docs: say when UNSET is actually needed
derek73 Jul 18, 2026
d7df3ce
docs: strip flags exclude characters from tokenization, not the input
derek73 Jul 18, 2026
4e657a8
docs: name_order states its valid values and comma-input scope
derek73 Jul 18, 2026
79ff5f5
docs: reference lists members in source order; strip_bidi self-contained
derek73 Jul 18, 2026
b746792
docs: extra_suffix_delimiters is additive; the comma is not replaceable
derek73 Jul 18, 2026
28078c7
docs: name_order links to the Name-order constants reference section
derek73 Jul 18, 2026
f37cc48
docs: list the AmbiguityKind and PatronymicRule members in the reference
derek73 Jul 18, 2026
8c87959
docs: explain lenient_comma_suffixes by its observable behavior
derek73 Jul 18, 2026
c8313a0
docs: define initial-shaped in the lenient_comma_suffixes doc
derek73 Jul 18, 2026
0a5e93b
docs: comma-order example a reader can verify without cultural context
derek73 Jul 18, 2026
d1f2749
docs: conjunctions are words or characters; show and/& examples
derek73 Jul 18, 2026
7716e9b
docs: Lexicon example lists read as examples, not full contents
derek73 Jul 18, 2026
d2cc767
docs: every Lexicon field links to its full default list
derek73 Jul 18, 2026
f0bd837
docs: Role members document the seven fields in the reference
derek73 Jul 18, 2026
bdc4cfd
docs: middle_as_family use case; nickname default links to its constant
derek73 Jul 18, 2026
895ecb3
docs: Locale docstring links to the locale packs guide
derek73 Jul 18, 2026
717101e
docs: concepts page reads plainly — accurate title, concrete walkthrough
derek73 Jul 18, 2026
5b21b97
docs: rendering-arguments bullet links to the customize section
derek73 Jul 18, 2026
7ee6e3a
feat: typographic nickname delimiters as defaults (closes #273)
derek73 Jul 18, 2026
9dc7e13
feat: Arabic-script bound given names (#269 follow-up)
derek73 Jul 18, 2026
00b73b8
feat: Arabic honorific titles and the conjunction و (#269 follow-up)
derek73 Jul 18, 2026
f0fbf65
feat: Hebrew honorifics + post-nominals, Devanagari titles (#269 foll…
derek73 Jul 18, 2026
05fe693
fix: extraction scans by position, not pair order (review critical)
derek73 Jul 18, 2026
ed9938a
docs: review accuracy corrections; hoist the migration hint
derek73 Jul 18, 2026
59cb4cb
test: regression guards from the review
derek73 Jul 18, 2026
cb3e5b5
docs: inline unresolvable docs/superpowers spec citations
derek73 Jul 19, 2026
e5e83e7
fix: name the field in non-iterable TypeErrors for Policy/Lexicon
derek73 Jul 19, 2026
64751b8
test: pin the assemble() unassigned-role fallback as an invariant
derek73 Jul 19, 2026
85bee41
test: pin hand-duplicated regex/table copies to their config source
derek73 Jul 19, 2026
26dd5da
test: isolate pipeline-stage branches only hit via the full corpus
derek73 Jul 19, 2026
3ae385e
docs: clarify Ambiguity/ParsedName subset check is value-equality-based
derek73 Jul 19, 2026
4cc75db
docs: signpost PolicyPatch's scalar-field validation asymmetry
derek73 Jul 19, 2026
66a4963
docs: drop stale v1 parser.py line-number citations
derek73 Jul 19, 2026
371b093
docs: cross-link token/span mentions in concepts.rst to API reference
derek73 Jul 19, 2026
d238e86
docs: sharpen Lexicon/Policy split and rendering-arguments examples
derek73 Jul 19, 2026
e7a5c4d
feat: default str()/render() shows nickname and maiden
derek73 Jul 19, 2026
bf1141c
feat: default spec is Derek's chosen format — quoted nickname, parent…
derek73 Jul 19, 2026
020e5ad
fix: .get() on the regexes proxy is no longer swallowed by __getattr__
derek73 Jul 19, 2026
d8f0664
Remove the dead regexes.no_vowels config (#268)
derek73 Jul 19, 2026
08cfeb5
docs: rewrite the 2.0 release log new-API-first and complete the audit
derek73 Jul 19, 2026
24aa787
fix: pickled HumanName keeps multi-word suffix entries intact
derek73 Jul 19, 2026
26d261a
docs: replace "Nothing breaks." with a check the reader can run
derek73 Jul 19, 2026
599c5e0
docs: map capitalize() by its method signature, not its config constant
derek73 Jul 19, 2026
521076c
docs: warn that the default render spec loses the maiden name
derek73 Jul 19, 2026
08dcc51
docs: add worked examples for ambiguities, tokens/spans, and name_order
derek73 Jul 19, 2026
9be1df7
docs: show what the Lexicon fields actually do
derek73 Jul 19, 2026
3edfe4e
docs: move stranded recipes out of the release log
derek73 Jul 19, 2026
d8feb3e
Reject given_name_titles entries that are not titles
derek73 Jul 19, 2026
418a210
Tell the caller how to fix a subset violation
derek73 Jul 19, 2026
182249a
Enforce the bound-given/never-given-particle invariant on Lexicon
derek73 Jul 19, 2026
022fd07
Guard the remaining config data invariants at import time
derek73 Jul 19, 2026
081a17c
docs: record the vocabulary data corrections in the release log
derek73 Jul 19, 2026
d0f887e
docs: restore two warnings and three behaviors the v1 docs carried
derek73 Jul 19, 2026
b20e1cd
docs: explain how roles get assigned, and what input shapes work
derek73 Jul 19, 2026
b20059b
docs: show the customizations that only had table rows
derek73 Jul 19, 2026
4dd99c1
docs: name the customize sections after the reader's problem
derek73 Jul 19, 2026
a6bd04c
docs: input shapes use the 2.0 field names
derek73 Jul 19, 2026
b23b08f
docs: explain which words attach to their neighbors
derek73 Jul 19, 2026
1e76761
Label the CLI output sections; document the tussenvoegsel sort
derek73 Jul 19, 2026
261c9c9
docs: retitle usage.rst "Using the parser"
derek73 Jul 19, 2026
5f1f6ac
docs: name the subject in the configuration heading
derek73 Jul 19, 2026
d4dd8a1
Restore 'esq' to SUFFIX_ACRONYMS; it was never a duplicate
derek73 Jul 19, 2026
0c642dc
Check given_name_titles per word, not per entry
derek73 Jul 19, 2026
bd87bb9
Re-validate Lexicon on unpickle
derek73 Jul 19, 2026
d69cb59
Complete the read surface on the regexes proxy
derek73 Jul 19, 2026
53c6442
Pin the two-piece deviation in the bound-particle translation
derek73 Jul 19, 2026
42b3ad6
docs: correct five factual errors found in review
derek73 Jul 19, 2026
02e9726
Close the remaining review findings
derek73 Jul 19, 2026
23ee08e
Drop the given_name_titles invariant; translate instead of filtering
derek73 Jul 19, 2026
59040a2
Translate only the first_name_titles entries v1 could match
derek73 Jul 19, 2026
dcb102f
Ignore, don't ungate, an ambiguous acronym added as a suffix word
derek73 Jul 19, 2026
234b35f
Record this session's hard-won conventions in AGENTS.md
derek73 Jul 19, 2026
8147ac6
An ambiguous acronym is a suffix when the name can spare it
derek73 Jul 19, 2026
ed71eb4
Report the ambiguous-suffix readings instead of guessing silently
derek73 Jul 19, 2026
49c67a2
Document that an ambiguity records a decision, not a word
derek73 Jul 19, 2026
d993db0
Report unmatched closing delimiters too
derek73 Jul 19, 2026
3f0b754
A word-final apostrophe is not an unbalanced delimiter
derek73 Jul 19, 2026
cc7c6a8
Point UNBALANCED_DELIMITER at the token it landed in
derek73 Jul 19, 2026
81ea9c1
Fix three defects in the new ambiguity emitters
derek73 Jul 20, 2026
2ff9189
Report both branches of every fork the parser reports on
derek73 Jul 20, 2026
de264af
Only report the particle fork when the chain actually claims something
derek73 Jul 20, 2026
30eb338
Give each SUFFIX_OR_NAME branch its own detail, and stop over-claiming
derek73 Jul 20, 2026
e8c3a46
AGENTS.md: what makes a fork worth reporting, and three sharper rules
derek73 Jul 20, 2026
4e02fa4
Bisect the mask overlap test; the close sweep made it quadratic
derek73 Jul 20, 2026
d13bf5c
Fold given_name_titles per word, so abbreviated entries match
derek73 Jul 20, 2026
8b91742
Report each fork where it is decided
derek73 Jul 20, 2026
cea2a28
Collapse seven copies of the config normalization assert
derek73 Jul 20, 2026
d9a07f7
Small cleanups from the review sweep
derek73 Jul 20, 2026
7fbcd9e
Pin the two-emitter invariant for PARTICLE_OR_GIVEN
derek73 Jul 20, 2026
6e53b56
Parse content-free input to an empty name
derek73 Jul 21, 2026
7747cef
docs: reorganize the attaching-words table by word type
derek73 Jul 21, 2026
8e77693
docs: link the attaching-words rows to their vocabulary sets
derek73 Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.11", "3.12", "3.13", "3.14", "3.15"]
# 3.15 is pre-release until 2026-10-01 (#259): surface breakage
# without blocking the branch; flip to blocking when it goes final.
continue-on-error: ${{ matrix.python-version == '3.15' }}
env:
# Without this, uv sync honors .python-version (3.11) over the
# matrix interpreter and every job silently tests 3.11.
UV_PYTHON: ${{ matrix.python-version }}

steps:
- uses: actions/checkout@v7
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
3.11
34 changes: 32 additions & 2 deletions AGENTS.md

Large diffs are not rendered by default.

198 changes: 50 additions & 148 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,9 @@ Name Parser

|Build Status| |PyPI| |PyPI version| |Documentation| |License| |Downloads| |Codecov|

📣 **nameparser 2.0 is in design** — a new immutable core API, with full
compatibility for existing code through 2.x. Read the `design RFC
<https://github.com/derek73/python-nameparser/pull/285>`__ and share
feedback on `the discussion issue
<https://github.com/derek73/python-nameparser/issues/284>`__.

A simple Python (3.10+) module for parsing human names into their
individual components.

* hn.title
* hn.first
* hn.middle
* hn.last
* hn.suffix
* hn.nickname
* hn.maiden
* hn.surnames *(middle + last)*
* hn.given_names *(first + middle)*
* hn.initials *(first initial of each name part)*
* hn.last_base *(last, minus any prefixes)*
* hn.last_prefixes *(leading last-name particles, e.g. "van der")*

Supported Name Structures
~~~~~~~~~~~~~~~~~~~~~~~~~

The supported name structure is generally "Title First Middle Last Suffix", where all pieces
are optional. Comma-separated format like "Last, First" is also supported.

1. Title Firstname "Nickname" Middle Middle Lastname Suffix
2. Lastname [Suffix], Title Firstname (Nickname) Middle Middle[,] Suffix [, Suffix]
3. Title Firstname M Lastname [Suffix], Suffix [Suffix] [, Suffix]

How It Works
~~~~~~~~~~~~

The parser works in two layers.

A **vocabulary layer** recognizes name pieces by what they are, using
configurable sets of known words: titles ("Dr."), suffixes ("III", "PhD"),
last-name prefixes ("de la"), conjunctions ("y", "&"), and delimited
nicknames ("Doc"). Titles and conjunctions chain together to handle complex
titles like "Asst Secretary of State"; prefixes join forward so "de la Vega"
stays one last name. This layer doesn't care where in the string a word
appears — and it's the layer you customize, by adding or removing entries
in the sets to fit your dataset.

A **positional layer** then assigns everything the vocabulary layer didn't
claim, based purely on where it sits: the first unclaimed word is the first
name, the last one is the last name, and anything between them is a middle
name. There is no semantic understanding — "Dr" is a title when it comes
before a name and a suffix when it comes after ("pre-nominal" and
"post-nominal" would probably be better names) — and no attempt to correct
mistakes in the input.

It attempts the best guess that can be made with a simple, deterministic,
rule-based approach — no statistical models or machine learning; the same
input always parses the same way. The positional layer assumes Western name
order (given name first), so the main use case is English and other
languages that share that structure. It can also try to correct the
capitalization of names that are all upper- or lowercase. It's not perfect,
but it gets you pretty far.
nameparser parses human names into seven fields — title, given, middle,
family, suffix, nickname, maiden. Results are immutable, configuration is
composable, and locale packs are opt-in.

Installation
------------
Expand All @@ -72,95 +14,55 @@ Installation

pip install nameparser

If you want to try out the latest code from GitHub you can
install with pip using the command below.

``pip install -e git+https://github.com/derek73/python-nameparser.git``

If you need to handle lists of names, check out
`namesparser <https://github.com/gwu-libraries/namesparser>`_, a
compliment to this module that handles multiple names in a string.

Requires Python 3.11+.

Quick Start Example
-------------------

::

>>> from nameparser import HumanName
>>> name = HumanName("Dr. Juan Q. Xavier de la Vega III (Doc Vega)")
>>> name
<HumanName : [
title: 'Dr.'
first: 'Juan'
middle: 'Q. Xavier'
last: 'de la Vega'
suffix: 'III'
nickname: 'Doc Vega'
maiden: ''
]>
>>> name.last
'de la Vega'
>>> name.as_dict()
{'title': 'Dr.', 'first': 'Juan', 'middle': 'Q. Xavier', 'last': 'de la Vega', 'suffix': 'III', 'nickname': 'Doc Vega', 'maiden': ''}
>>> str(name)
'Dr. Juan Q. Xavier de la Vega III (Doc Vega)'
>>> name.string_format = "{first} {last}"
>>> str(name)
'Juan de la Vega'


Because the positional layer has no semantic understanding, position is
everything:

::

>>> name = HumanName("1 & 2, 3 4 5, Mr.")
>>> name
<HumanName : [
title: ''
first: '3'
middle: '4 5'
last: '1 & 2'
suffix: 'Mr.'
nickname: ''
maiden: ''
]>

Customization
-------------

Your project may need some adjustment for your dataset. Most customization
is vocabulary — `customizing the configured pre-defined sets`_ of titles,
prefixes, etc. that the vocabulary layer matches against. You can also do
your own pre- or post-processing, or subclass the `HumanName` class for
deeper changes. See the `full documentation`_ for more information.


`Full documentation`_
~~~~~~~~~~~~~~~~~~~~~

.. _customizing the configured pre-defined sets: http://nameparser.readthedocs.org/en/latest/customize.html
.. _Full documentation: http://nameparser.readthedocs.org/en/latest/


Contributing
------------

If you come across name piece that you think should be in the default config, you're
probably right. `Start a New Issue`_ and we can get them added.

Please let me know if there are ways this library could be structured to make
it easier for you to use in your projects. Read CONTRIBUTING.md_ for more info
on running the tests and contributing to the project.

**GitHub Project**

https://github.com/derek73/python-nameparser

.. _CONTRIBUTING.md: https://github.com/derek73/python-nameparser/tree/master/CONTRIBUTING.md
.. _Start a New Issue: https://github.com/derek73/python-nameparser/issues
.. _click here to propose changes to the titles: https://github.com/derek73/python-nameparser/edit/master/nameparser/config/titles.py
--------------------

.. code-block:: python

>>> from nameparser import parse
>>> name = parse("Dr. Juan Q. Xavier de la Vega III")
>>> name.given, name.family
('Juan', 'de la Vega')
>>> name.render("{family}, {given}")
'de la Vega, Juan'

Those seven fields are ``title``, ``given``, ``middle``, ``family``,
``suffix``, ``nickname``, and ``maiden`` — plus aggregate views like
``given_names``, ``surnames``, ``family_base``, and ``family_particles``
for combining or splitting them further.

Learn more
----------

* `Using the parser <https://nameparser.readthedocs.io/en/latest/usage.html>`__ — the full tour: input shapes, aggregates, rendering, comparison, ambiguities, tokens
* `Customizing the parser <https://nameparser.readthedocs.io/en/latest/customize.html>`__ — vocabulary, behavior, and presentation
* `Locale packs <https://nameparser.readthedocs.io/en/latest/locales.html>`__ — opt-in bundles for East Slavic patronymics, Turkic markers, and more
* There's also a CLI: ``python -m nameparser --json "Doe, John"``

Coming from 1.x
----------------

``HumanName`` and ``CONSTANTS`` keep working in 2.0 — same imports, same
attributes, same mutation API. What 2.0 removes is the batch of
deprecations 1.3 and 1.4 announced, so if your test suite runs clean on
1.4 under ``python -W error::DeprecationWarning``, you are nearly done.
Two things that check will not catch: four removals 1.4 never warned
about (three raise on contact, the fourth only warns), and one that
changes results silently — ``name == "John Smith"`` is now ``False``.
`Migrating from HumanName <https://nameparser.readthedocs.io/en/latest/migrate.html>`__
covers both, and translates a v1 customization into the new API whenever
that's convenient for you.

See the `release log <https://nameparser.readthedocs.io/en/latest/release_log.html>`__
for the full list of changes in the 2.0 series.

License
-------

LGPL licensed. See `LICENSE <https://github.com/derek73/python-nameparser/blob/master/LICENSE>`__
for details.

.. |Build Status| image:: https://github.com/derek73/python-nameparser/actions/workflows/python-package.yml/badge.svg
:target: https://github.com/derek73/python-nameparser/actions/workflows/python-package.yml
Expand Down
Loading
Loading