nameparser 2.7.0__tar.gz → 2.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nameparser-2.7.0/nameparser.egg-info → nameparser-2.8.0}/PKG-INFO +22 -17
- {nameparser-2.7.0 → nameparser-2.8.0}/README.rst +21 -16
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_config_shim.py +153 -22
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_facade.py +48 -3
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_post_rules.py +1 -1
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_vocab.py +6 -2
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_version.py +4 -4
- nameparser-2.8.0/nameparser/config/__init__.py +76 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/_compiled.py +97 -8
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/titles.py +1 -1
- nameparser-2.8.0/nameparser/util.py +46 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/en.toml +37 -17
- {nameparser-2.7.0 → nameparser-2.8.0/nameparser.egg-info}/PKG-INFO +22 -17
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser.egg-info/SOURCES.txt +4 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/pyproject.toml +9 -0
- nameparser-2.8.0/tests/removals.py +26 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_constants.py +9 -3
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_first_name.py +7 -3
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_python_api.py +11 -8
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/cases.py +182 -7
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_cases.py +10 -4
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_config_shim.py +6 -1
- nameparser-2.8.0/tests/v2/test_deprecations.py +457 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_facade.py +3 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_local_agreement.py +82 -6
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_local_corpora.py +147 -7
- nameparser-2.8.0/tests/v2/test_local_orcid.py +561 -0
- nameparser-2.8.0/tests/v2/test_local_patentsview.py +366 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_measure.py +5 -2
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_name_usage_tool.py +100 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_properties.py +1 -1
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_render.py +4 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_word_report.py +65 -65
- nameparser-2.7.0/nameparser/config/__init__.py +0 -43
- nameparser-2.7.0/nameparser/util.py +0 -14
- {nameparser-2.7.0 → nameparser-2.8.0}/AUTHORS +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/LICENSE +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/MANIFEST.in +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/__main__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_lexicon.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_locale.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_assemble.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_assign.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_classify.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_comma.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_extract.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_group.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_pieces.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_script_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_state.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_pipeline/_tokenize.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_policy.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_render.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/_types.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/_deprecated.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/_invariants.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/_titles_2_6_0.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/bound_first_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/bound_given_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/capitalization.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/conjunctions.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/given_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/maiden_markers.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/particles.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/prefixes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/regexes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/suffixes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/config/surnames.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/locales/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/locales/ja.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/locales/ru.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/locales/tr_az.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/locales/zh.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/py.typed +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ak.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/am.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ar.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/as.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/be.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/bg.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/bin.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/bn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/bo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/bs.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ca.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/cs.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/da.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/de.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/el.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/es.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/et.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/fa.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ff.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/fi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/fil.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/fr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ga.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/gd.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/gu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ha.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/he.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/hi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/hr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/hu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/hy.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/id.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/is.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/it.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ja.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ka.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/kk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/km.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/kn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ko.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/kok.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/lo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/lt.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/lv.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/mi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/mk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ml.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/mn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/mr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ms.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/mul.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/my.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/nb.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ne.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/nl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/nn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/or.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/pa.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/pl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/pt-BR.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/pt.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ro.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ru.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sd.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/shn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/si.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sv.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/sw.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ta.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/te.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/th.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ti.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/tr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/uk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/und.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/ur.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/vi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/yi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/yo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/zh.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser/vocab/zu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser.egg-info/dependency_links.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser.egg-info/requires.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/nameparser.egg-info/top_level.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/setup.cfg +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/base.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/conftest.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_bound_given_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_brute_force.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_capitalization.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_comma_variants.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_conjunctions.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_east_slavic_patronymic_order.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_initials.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_middle_name_as_last.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_nicknames.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_output_format.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_particles.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_suffixes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_titles.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_turkic_patronymic_order.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/test_variations.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/_differential_fixtures.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/conftest.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/design_docs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_assemble.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_assign.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_classify.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_comma.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_extract.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_group.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_pieces.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_post_rules.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_script_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_state.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_tokenize.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/pipeline/test_vocab.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/rules_budget.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/rules_doc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/rules_skeleton.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_benchmark.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_cldr_agreement.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_cldr_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_cli.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_config_aliases.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_contracts.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_corpora.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_corpus_build.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_design_docs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_differential.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_doc_citations.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_doc_spellings.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_facade_cases.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_gnd_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_layering.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_lexicon.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_local_jrc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_locale.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_locales.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_order_correspondence.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_policy.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_regex_sync.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_reprs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_rules_budget.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_rules_doc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_rules_doc_grammar.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_rules_skeleton.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_snapshot.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_types.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_vocab.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_wikidata_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_wikidata_native_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.0}/tests/v2/test_zh_surnames_tool.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nameparser
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: A simple Python module for parsing human names into their individual components.
|
|
5
5
|
Author-email: Derek Gulbranson <derek73@gmail.com>
|
|
6
6
|
License-Expression: LGPL-2.1-or-later
|
|
@@ -35,27 +35,30 @@ nameparser parses human names into seven fields — title, given, middle,
|
|
|
35
35
|
family, suffix, nickname, maiden. Results are immutable, configuration is
|
|
36
36
|
composable, and locale packs are opt-in.
|
|
37
37
|
|
|
38
|
-
📣 **nameparser 2.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
📣 **nameparser 2.8 is out, the last 2.x feature release.**
|
|
39
|
+
|
|
40
|
+
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
41
|
+
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
42
|
+
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
43
|
+
constructs it, loads it from a pickle, or changes the shared
|
|
44
|
+
``CONSTANTS``. It keeps working through 2.x; ``parse()`` is the
|
|
45
|
+
replacement, and `Coming from 1.x`_ below says where to start. After
|
|
46
|
+
2.8 the 2.x line takes fixes only, and new work goes into 3.0.
|
|
47
|
+
|
|
48
|
+
2.8 also carries on 2.7's reading of titles that are also given names:
|
|
49
|
+
a title only inside a title phrase, so ``Queen Latifah`` keeps the
|
|
50
|
+
given name ``Queen`` while ``Her Majesty Queen Elizabeth`` reads the
|
|
51
|
+
title. The `release log
|
|
46
52
|
<https://nameparser.readthedocs.io/en/latest/release_log.html>`__ has
|
|
47
|
-
the details.
|
|
53
|
+
the details. Please `open an
|
|
54
|
+
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
55
|
+
that parses wrong.
|
|
48
56
|
|
|
49
57
|
Chinese, Japanese and Korean names written in their own scripts are read
|
|
50
58
|
family-first, unspaced Korean names are split against the census surname
|
|
51
59
|
list, and CJK honorifics are recognized. See `East Asian names
|
|
52
60
|
<https://nameparser.readthedocs.io/en/latest/usage.html#east-asian-names>`__.
|
|
53
61
|
|
|
54
|
-
Existing ``HumanName`` code from 1.x keeps working through 2.x, and most
|
|
55
|
-
of it needs no changes; see `Coming from 1.x`_ below. Please `open an
|
|
56
|
-
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
57
|
-
that parses wrong.
|
|
58
|
-
|
|
59
62
|
Installation
|
|
60
63
|
------------
|
|
61
64
|
|
|
@@ -127,8 +130,10 @@ Learn more
|
|
|
127
130
|
Coming from 1.x
|
|
128
131
|
----------------
|
|
129
132
|
|
|
130
|
-
``HumanName`` and ``CONSTANTS`` keep working
|
|
131
|
-
attributes, same mutation API
|
|
133
|
+
``HumanName`` and ``CONSTANTS`` keep working through 2.x — same imports,
|
|
134
|
+
same attributes, same mutation API — and warn from 2.8 on, since 3.0
|
|
135
|
+
removes them. Run your tests under ``python -W error::DeprecationWarning``
|
|
136
|
+
to find the sites; a read of ``CONSTANTS`` does not warn. What 2.0 removes is the batch of
|
|
132
137
|
deprecations 1.3 and 1.4 announced, so if your test suite runs clean on
|
|
133
138
|
1.4 under ``python -W error::DeprecationWarning``, you are nearly done.
|
|
134
139
|
Two things that check will not catch: four removals 1.4 never warned
|
|
@@ -7,27 +7,30 @@ nameparser parses human names into seven fields — title, given, middle,
|
|
|
7
7
|
family, suffix, nickname, maiden. Results are immutable, configuration is
|
|
8
8
|
composable, and locale packs are opt-in.
|
|
9
9
|
|
|
10
|
-
📣 **nameparser 2.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
📣 **nameparser 2.8 is out, the last 2.x feature release.**
|
|
11
|
+
|
|
12
|
+
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
13
|
+
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
14
|
+
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
15
|
+
constructs it, loads it from a pickle, or changes the shared
|
|
16
|
+
``CONSTANTS``. It keeps working through 2.x; ``parse()`` is the
|
|
17
|
+
replacement, and `Coming from 1.x`_ below says where to start. After
|
|
18
|
+
2.8 the 2.x line takes fixes only, and new work goes into 3.0.
|
|
19
|
+
|
|
20
|
+
2.8 also carries on 2.7's reading of titles that are also given names:
|
|
21
|
+
a title only inside a title phrase, so ``Queen Latifah`` keeps the
|
|
22
|
+
given name ``Queen`` while ``Her Majesty Queen Elizabeth`` reads the
|
|
23
|
+
title. The `release log
|
|
18
24
|
<https://nameparser.readthedocs.io/en/latest/release_log.html>`__ has
|
|
19
|
-
the details.
|
|
25
|
+
the details. Please `open an
|
|
26
|
+
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
27
|
+
that parses wrong.
|
|
20
28
|
|
|
21
29
|
Chinese, Japanese and Korean names written in their own scripts are read
|
|
22
30
|
family-first, unspaced Korean names are split against the census surname
|
|
23
31
|
list, and CJK honorifics are recognized. See `East Asian names
|
|
24
32
|
<https://nameparser.readthedocs.io/en/latest/usage.html#east-asian-names>`__.
|
|
25
33
|
|
|
26
|
-
Existing ``HumanName`` code from 1.x keeps working through 2.x, and most
|
|
27
|
-
of it needs no changes; see `Coming from 1.x`_ below. Please `open an
|
|
28
|
-
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
29
|
-
that parses wrong.
|
|
30
|
-
|
|
31
34
|
Installation
|
|
32
35
|
------------
|
|
33
36
|
|
|
@@ -99,8 +102,10 @@ Learn more
|
|
|
99
102
|
Coming from 1.x
|
|
100
103
|
----------------
|
|
101
104
|
|
|
102
|
-
``HumanName`` and ``CONSTANTS`` keep working
|
|
103
|
-
attributes, same mutation API
|
|
105
|
+
``HumanName`` and ``CONSTANTS`` keep working through 2.x — same imports,
|
|
106
|
+
same attributes, same mutation API — and warn from 2.8 on, since 3.0
|
|
107
|
+
removes them. Run your tests under ``python -W error::DeprecationWarning``
|
|
108
|
+
to find the sites; a read of ``CONSTANTS`` does not warn. What 2.0 removes is the batch of
|
|
104
109
|
deprecations 1.3 and 1.4 announced, so if your test suite runs clean on
|
|
105
110
|
1.4 under ``python -W error::DeprecationWarning``, you are nearly done.
|
|
106
111
|
Two things that check will not catch: four removals 1.4 never warned
|
|
@@ -4,7 +4,7 @@ re-exports these names from the swap
|
|
|
4
4
|
commit onward; the whole module is deleted in 3.0 with the facade.
|
|
5
5
|
|
|
6
6
|
Layering: facade layer -- may import anything public; here that's
|
|
7
|
-
``nameparser.util`` for ``lc()``, ``nameparser.config.regexes`` for
|
|
7
|
+
``nameparser.util`` for ``lc()`` (as ``_lc``, the name that does not warn), ``nameparser.config.regexes`` for
|
|
8
8
|
the read-only regexes proxy's underlying compiled patterns, and
|
|
9
9
|
``nameparser._lexicon``/``_policy``/``_parser`` for the ``_snapshot()``
|
|
10
10
|
translation and the shared parser cache.
|
|
@@ -20,12 +20,16 @@ that cycle.
|
|
|
20
20
|
"""
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
|
+
import copy
|
|
23
24
|
import functools
|
|
25
|
+
import re
|
|
26
|
+
import sys
|
|
24
27
|
import warnings
|
|
25
28
|
from collections.abc import (
|
|
26
29
|
Callable, ItemsView, Iterable, Iterator, KeysView, Mapping, Set,
|
|
27
30
|
ValuesView,
|
|
28
31
|
)
|
|
32
|
+
from types import FrameType
|
|
29
33
|
from typing import NamedTuple, Self
|
|
30
34
|
|
|
31
35
|
from nameparser._lexicon import (
|
|
@@ -33,7 +37,7 @@ from nameparser._lexicon import (
|
|
|
33
37
|
)
|
|
34
38
|
from nameparser._parser import Parser
|
|
35
39
|
from nameparser._policy import PatronymicRule, Policy
|
|
36
|
-
from nameparser.util import lc
|
|
40
|
+
from nameparser.util import _lc as lc
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
#: The eight multi-word entries the pre-2.0 DEFAULT vocabulary shipped.
|
|
@@ -712,12 +716,64 @@ _UNSET = object()
|
|
|
712
716
|
_UNSET_KWARG = object()
|
|
713
717
|
|
|
714
718
|
|
|
719
|
+
#: The migration guide every 2.8 removal message points at.
|
|
720
|
+
MIGRATION_GUIDE = "https://nameparser.readthedocs.io/en/latest/migrate.html"
|
|
721
|
+
|
|
722
|
+
# The 2.8 removal messages (decisions/3-0-reevaluations, 2026-10-28).
|
|
723
|
+
# Each names code that type-checks and runs, pinned by
|
|
724
|
+
# tests/v2/test_deprecations.py, and each opens with a fixed phrase
|
|
725
|
+
# pyproject's filterwarnings ignores by message.
|
|
715
726
|
_SHARED_MUTATION_MESSAGE = (
|
|
716
727
|
"mutating the shared CONSTANTS singleton is deprecated and will be "
|
|
717
|
-
"removed in 3.0
|
|
718
|
-
"
|
|
719
|
-
"
|
|
728
|
+
"removed in 3.0 with HumanName and Constants; configure a Parser "
|
|
729
|
+
"instead, e.g. Parser(lexicon=Lexicon.default().add(titles={'dean'})). "
|
|
730
|
+
f"See {MIGRATION_GUIDE}"
|
|
731
|
+
)
|
|
732
|
+
CONSTANTS_DEPRECATION = (
|
|
733
|
+
"Constants is deprecated and will be removed in 3.0 with HumanName; "
|
|
734
|
+
"configure a Parser instead, e.g. "
|
|
735
|
+
"Parser(lexicon=Lexicon.default().add(titles={'dean'})). "
|
|
736
|
+
f"See {MIGRATION_GUIDE}"
|
|
737
|
+
)
|
|
738
|
+
CONSTANTS_PICKLE_DEPRECATION = (
|
|
739
|
+
"Constants pickles stop loading in 3.0, when Constants is removed; "
|
|
740
|
+
"pickle a Parser instead, e.g. "
|
|
741
|
+
"Parser(lexicon=Lexicon.default().add(titles={'dean'})). "
|
|
742
|
+
f"See {MIGRATION_GUIDE}"
|
|
720
743
|
)
|
|
744
|
+
#: one message per manager class, keyed by name, for
|
|
745
|
+
#: nameparser.config.__getattr__
|
|
746
|
+
MANAGER_DEPRECATIONS = {
|
|
747
|
+
name: (
|
|
748
|
+
f"nameparser.config.{name} is deprecated and will be removed in "
|
|
749
|
+
f"3.0 with Constants; Lexicon fields take plain sets, e.g. "
|
|
750
|
+
f"Lexicon.default().add(titles={{'dean'}}). See {MIGRATION_GUIDE}"
|
|
751
|
+
)
|
|
752
|
+
for name in ("SetManager", "TupleManager", "RegexTupleManager")
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def _quiet_setstate(new: object, state: dict[str, object], base: type,
|
|
757
|
+
message: str) -> None:
|
|
758
|
+
"""Restore a copy through its class's own ``__setstate__``.
|
|
759
|
+
|
|
760
|
+
``copy.copy``/``copy.deepcopy`` reconstruct through ``__setstate__``,
|
|
761
|
+
which since 2.8 warns that a pickle was loaded, and a copy is no
|
|
762
|
+
load. ``base``'s own hook restores privately; a subclass's override
|
|
763
|
+
is called, as it was before 2.8, with only the load warning
|
|
764
|
+
filtered, by message. The filter is taken only then: entering
|
|
765
|
+
``catch_warnings`` clears every module's warnings registry, so on
|
|
766
|
+
every copy it would re-show warnings the caller's filters show once
|
|
767
|
+
per line. A copy of the shared ``CONSTANTS`` stays quiet, as before:
|
|
768
|
+
a ``HumanName`` built on the copy still warns.
|
|
769
|
+
"""
|
|
770
|
+
if type(new).__setstate__ is base.__setstate__: # type: ignore[attr-defined]
|
|
771
|
+
new._restore(state) # type: ignore[attr-defined]
|
|
772
|
+
return
|
|
773
|
+
with warnings.catch_warnings():
|
|
774
|
+
warnings.filterwarnings("ignore", message=re.escape(message),
|
|
775
|
+
category=DeprecationWarning)
|
|
776
|
+
new.__setstate__(state) # type: ignore[attr-defined]
|
|
721
777
|
|
|
722
778
|
|
|
723
779
|
def _default_vocab() -> dict[str, frozenset[str]]:
|
|
@@ -786,9 +842,11 @@ class Constants:
|
|
|
786
842
|
|
|
787
843
|
The module-level ``CONSTANTS`` singleton (below) has ``_shared``
|
|
788
844
|
flipped to ``True``: any mutation reached through it emits
|
|
789
|
-
``DeprecationWarning`` pointing at ``Lexicon``/``Policy
|
|
790
|
-
``
|
|
791
|
-
|
|
845
|
+
``DeprecationWarning`` pointing at ``Lexicon``/``Policy``. Since 2.8
|
|
846
|
+
constructing a ``Constants``, copying one with ``copy()`` and
|
|
847
|
+
loading one from a pickle warn too, since the whole class goes in
|
|
848
|
+
3.0; the singleton is built without the warning, so importing
|
|
849
|
+
``nameparser`` stays quiet.
|
|
792
850
|
"""
|
|
793
851
|
|
|
794
852
|
_shared = False # the CONSTANTS singleton flips this to True
|
|
@@ -836,6 +894,41 @@ class Constants:
|
|
|
836
894
|
regexes: object = _UNSET_KWARG,
|
|
837
895
|
patronymic_name_order: bool = False,
|
|
838
896
|
middle_name_as_last: bool = False,
|
|
897
|
+
) -> None:
|
|
898
|
+
# every construction warns, at the caller's line; the warnings
|
|
899
|
+
# registry, not a flag here, dedups repeats from one line
|
|
900
|
+
# (decisions/3-0-reevaluations, 2026-10-28)
|
|
901
|
+
warnings.warn(CONSTANTS_DEPRECATION, DeprecationWarning,
|
|
902
|
+
stacklevel=2)
|
|
903
|
+
self._init(
|
|
904
|
+
prefixes=prefixes, suffix_acronyms=suffix_acronyms,
|
|
905
|
+
suffix_not_acronyms=suffix_not_acronyms,
|
|
906
|
+
suffix_acronyms_ambiguous=suffix_acronyms_ambiguous,
|
|
907
|
+
titles=titles, first_name_titles=first_name_titles,
|
|
908
|
+
conjunctions=conjunctions, bound_first_names=bound_first_names,
|
|
909
|
+
non_first_name_prefixes=non_first_name_prefixes,
|
|
910
|
+
capitalization_exceptions=capitalization_exceptions,
|
|
911
|
+
regexes=regexes, patronymic_name_order=patronymic_name_order,
|
|
912
|
+
middle_name_as_last=middle_name_as_last)
|
|
913
|
+
|
|
914
|
+
def _init(
|
|
915
|
+
self,
|
|
916
|
+
*,
|
|
917
|
+
prefixes: Iterable[str] | object = _UNSET_KWARG,
|
|
918
|
+
suffix_acronyms: Iterable[str] | object = _UNSET_KWARG,
|
|
919
|
+
suffix_not_acronyms: Iterable[str] | object = _UNSET_KWARG,
|
|
920
|
+
suffix_acronyms_ambiguous: Iterable[str] | object = _UNSET_KWARG,
|
|
921
|
+
titles: Iterable[str] | object = _UNSET_KWARG,
|
|
922
|
+
first_name_titles: Iterable[str] | object = _UNSET_KWARG,
|
|
923
|
+
conjunctions: Iterable[str] | object = _UNSET_KWARG,
|
|
924
|
+
bound_first_names: Iterable[str] | object = _UNSET_KWARG,
|
|
925
|
+
non_first_name_prefixes: Iterable[str] | object = _UNSET_KWARG,
|
|
926
|
+
capitalization_exceptions:
|
|
927
|
+
Mapping[str, str] | Iterable[tuple[str, str]] | object
|
|
928
|
+
= _UNSET_KWARG,
|
|
929
|
+
regexes: object = _UNSET_KWARG,
|
|
930
|
+
patronymic_name_order: bool = False,
|
|
931
|
+
middle_name_as_last: bool = False,
|
|
839
932
|
) -> None:
|
|
840
933
|
# v1.4 parity constructor kwargs (#238/#242/#244 hardening); the
|
|
841
934
|
# signature is spelled out rather than **kwargs so an unknown
|
|
@@ -921,19 +1014,20 @@ class Constants:
|
|
|
921
1014
|
"""
|
|
922
1015
|
|
|
923
1016
|
def _bump(self) -> None:
|
|
924
|
-
# stacklevel
|
|
925
|
-
#
|
|
926
|
-
#
|
|
927
|
-
#
|
|
928
|
-
#
|
|
929
|
-
#
|
|
930
|
-
# once. Either way the warning still fires from this module,
|
|
931
|
-
# not the manager's true caller, which is enough: only the
|
|
932
|
-
# DeprecationWarning's presence/category/message are load-
|
|
933
|
-
# bearing (see the specified test), not the reported line.
|
|
1017
|
+
# A fixed stacklevel lands on the caller only for one call depth:
|
|
1018
|
+
# a scalar arrives through __setattr__, a set's add() through
|
|
1019
|
+
# _changed(), a dict's update() and |= through __setitem__ per
|
|
1020
|
+
# key. Walk out of this module instead, as _lexicon's
|
|
1021
|
+
# _warn_dead_entry does, so the warning names the caller's line;
|
|
1022
|
+
# attributed here, Python's default filters hid it.
|
|
934
1023
|
if self._shared:
|
|
1024
|
+
level = 2
|
|
1025
|
+
frame: FrameType | None = sys._getframe(1)
|
|
1026
|
+
while (frame is not None
|
|
1027
|
+
and frame.f_globals.get("__name__") == __name__):
|
|
1028
|
+
frame, level = frame.f_back, level + 1
|
|
935
1029
|
warnings.warn(_SHARED_MUTATION_MESSAGE, DeprecationWarning,
|
|
936
|
-
stacklevel=
|
|
1030
|
+
stacklevel=level)
|
|
937
1031
|
object.__setattr__(self, "_generation", self._generation + 1)
|
|
938
1032
|
|
|
939
1033
|
def __setattr__(self, name: str, value: object) -> None:
|
|
@@ -987,7 +1081,27 @@ class Constants:
|
|
|
987
1081
|
v1 (which deepcopied __dict__): attributes OUTSIDE the known
|
|
988
1082
|
field surface -- e.g. ad-hoc names stashed on the instance --
|
|
989
1083
|
are not carried by copy() or pickling; only the enumerated
|
|
990
|
-
fields survive.
|
|
1084
|
+
fields survive. Warns since 2.8, as construction does: a copy
|
|
1085
|
+
is a new private ``Constants``, and ``CONSTANTS.copy()`` builds
|
|
1086
|
+
one without calling the constructor.""" # #260
|
|
1087
|
+
warnings.warn(CONSTANTS_DEPRECATION, DeprecationWarning,
|
|
1088
|
+
stacklevel=2)
|
|
1089
|
+
return self._copy()
|
|
1090
|
+
|
|
1091
|
+
def __copy__(self) -> Constants:
|
|
1092
|
+
new = object.__new__(type(self))
|
|
1093
|
+
_quiet_setstate(new, self.__getstate__(), Constants,
|
|
1094
|
+
CONSTANTS_PICKLE_DEPRECATION)
|
|
1095
|
+
return new
|
|
1096
|
+
|
|
1097
|
+
def __deepcopy__(self, memo: dict[int, object]) -> Constants:
|
|
1098
|
+
new = object.__new__(type(self))
|
|
1099
|
+
memo[id(self)] = new
|
|
1100
|
+
_quiet_setstate(new, copy.deepcopy(self.__getstate__(), memo),
|
|
1101
|
+
Constants, CONSTANTS_PICKLE_DEPRECATION)
|
|
1102
|
+
return new
|
|
1103
|
+
|
|
1104
|
+
def _copy(self) -> Constants:
|
|
991
1105
|
# An independent instance with its own generation counter and
|
|
992
1106
|
# its own manager callbacks -- not a shared-state alias like a
|
|
993
1107
|
# naive attribute-for-attribute copy would produce. v1's copy()
|
|
@@ -1376,7 +1490,22 @@ class Constants:
|
|
|
1376
1490
|
# DROPPED (#255: empty is always '' in 2.0).
|
|
1377
1491
|
state = {k: v for k, v in state.items()
|
|
1378
1492
|
if k != "empty_attribute_default"}
|
|
1379
|
-
|
|
1493
|
+
warnings.warn(CONSTANTS_PICKLE_DEPRECATION, DeprecationWarning,
|
|
1494
|
+
stacklevel=2)
|
|
1495
|
+
self._restore(state)
|
|
1496
|
+
|
|
1497
|
+
def _restore(self, state: dict[str, object]) -> None:
|
|
1498
|
+
# defaults, then overlay. A subclass's own __init__ runs here as
|
|
1499
|
+
# it did before 2.8; its super().__init__() would warn that a
|
|
1500
|
+
# Constants was constructed, which a restore is not
|
|
1501
|
+
if type(self).__init__ is Constants.__init__:
|
|
1502
|
+
self._init()
|
|
1503
|
+
else:
|
|
1504
|
+
with warnings.catch_warnings():
|
|
1505
|
+
warnings.filterwarnings(
|
|
1506
|
+
"ignore", message=re.escape(CONSTANTS_DEPRECATION),
|
|
1507
|
+
category=DeprecationWarning)
|
|
1508
|
+
self.__init__() # type: ignore[misc]
|
|
1380
1509
|
# (managers re-wrapped below so _on_change points at THIS
|
|
1381
1510
|
# instance, not whatever produced the incoming state)
|
|
1382
1511
|
managers: dict[str, SetManager] = {}
|
|
@@ -1417,5 +1546,7 @@ class Constants:
|
|
|
1417
1546
|
object.__setattr__(self, name, state[name])
|
|
1418
1547
|
|
|
1419
1548
|
|
|
1420
|
-
|
|
1549
|
+
# built past __init__, so importing nameparser never warns
|
|
1550
|
+
CONSTANTS = object.__new__(Constants)
|
|
1551
|
+
CONSTANTS._init()
|
|
1421
1552
|
object.__setattr__(CONSTANTS, "_shared", True)
|
|
@@ -7,6 +7,7 @@ Layering: facade layer -- may import anything public plus _render.
|
|
|
7
7
|
"""
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import copy
|
|
10
11
|
import dataclasses
|
|
11
12
|
import warnings
|
|
12
13
|
from collections.abc import Iterator, Mapping
|
|
@@ -29,7 +30,8 @@ from typing import Any
|
|
|
29
30
|
import nameparser.config # noqa: F401
|
|
30
31
|
|
|
31
32
|
import nameparser._render as _render
|
|
32
|
-
from nameparser._config_shim import CONSTANTS, Constants,
|
|
33
|
+
from nameparser._config_shim import (CONSTANTS, MIGRATION_GUIDE, Constants,
|
|
34
|
+
_cached_parser, _quiet_setstate)
|
|
33
35
|
from nameparser._lexicon import _normalize, _spells_an_initial
|
|
34
36
|
from nameparser._parser import Parser
|
|
35
37
|
from nameparser._types import (FOLDED_TAG, UNCLASSIFIED_TAG,
|
|
@@ -60,6 +62,19 @@ _V1_HOOKS = (
|
|
|
60
62
|
# whole module is deleted with the facade layer in 3.0.
|
|
61
63
|
_WARNED_SUBCLASSES: set[type] = set()
|
|
62
64
|
|
|
65
|
+
# The 2.8 removal messages (decisions/3-0-reevaluations, 2026-10-28);
|
|
66
|
+
# the code each offers is pinned by tests/v2/test_deprecations.py.
|
|
67
|
+
HUMANNAME_DEPRECATION = (
|
|
68
|
+
"HumanName is deprecated and will be removed in 3.0; use "
|
|
69
|
+
"nameparser.parse(text), whose fields are given and family where "
|
|
70
|
+
f"HumanName has first and last. See {MIGRATION_GUIDE}"
|
|
71
|
+
)
|
|
72
|
+
HUMANNAME_PICKLE_DEPRECATION = (
|
|
73
|
+
"HumanName pickles stop loading in 3.0, when HumanName is removed; "
|
|
74
|
+
"store parse(text).as_dict() or the original string instead. "
|
|
75
|
+
f"See {MIGRATION_GUIDE}"
|
|
76
|
+
)
|
|
77
|
+
|
|
63
78
|
|
|
64
79
|
def _empty_parsed() -> ParsedName:
|
|
65
80
|
return ParsedName(original="", tokens=(), ambiguities=())
|
|
@@ -71,7 +86,8 @@ class HumanName:
|
|
|
71
86
|
resolved from the bound ``Constants`` shim (dirty-tracked via its
|
|
72
87
|
``_generation``). Keeps every v1 spelling (``first``/``last`` over
|
|
73
88
|
the core ``given``/``family``); the v1 parsing hooks are never
|
|
74
|
-
called (#280).
|
|
89
|
+
called (#280). Deprecated since 2.8, warning at every construction,
|
|
90
|
+
and deleted with the facade layer in 3.0.
|
|
75
91
|
"""
|
|
76
92
|
|
|
77
93
|
def __init__(
|
|
@@ -101,6 +117,12 @@ class HumanName:
|
|
|
101
117
|
raise TypeError(
|
|
102
118
|
f"constants must be a Constants instance, got {constants!r}"
|
|
103
119
|
)
|
|
120
|
+
# every construction warns, at the caller's line (a subclass's
|
|
121
|
+
# super().__init__() is its author's line); never once per
|
|
122
|
+
# process, so a dependency's first HumanName cannot consume the
|
|
123
|
+
# warning meant for the caller's own
|
|
124
|
+
warnings.warn(HUMANNAME_DEPRECATION, DeprecationWarning,
|
|
125
|
+
stacklevel=2)
|
|
104
126
|
self._warn_overridden_hooks()
|
|
105
127
|
self._C = constants
|
|
106
128
|
self._snapshot_gen = -1 # forces first resolve
|
|
@@ -151,7 +173,8 @@ class HumanName:
|
|
|
151
173
|
f"{cls.__name__} overrides v1 parsing hooks "
|
|
152
174
|
f"({', '.join(overridden)}) that the 2.0 facade never "
|
|
153
175
|
f"calls; parsing is delegated to the core Parser. "
|
|
154
|
-
f"Migrate to the Lexicon/Policy API
|
|
176
|
+
f"Migrate to the Lexicon/Policy API; HumanName is "
|
|
177
|
+
f"removed in 3.0. See "
|
|
155
178
|
f"https://github.com/derek73/python-nameparser/issues/280",
|
|
156
179
|
DeprecationWarning, stacklevel=3)
|
|
157
180
|
|
|
@@ -888,6 +911,28 @@ class HumanName:
|
|
|
888
911
|
return state
|
|
889
912
|
|
|
890
913
|
def __setstate__(self, state: dict[str, Any]) -> None:
|
|
914
|
+
# unpickling skips __init__, so the construction warning never
|
|
915
|
+
# reaches a pickle; this one does, at the pickle.loads line
|
|
916
|
+
warnings.warn(HUMANNAME_PICKLE_DEPRECATION, DeprecationWarning,
|
|
917
|
+
stacklevel=2)
|
|
918
|
+
self._restore(state)
|
|
919
|
+
|
|
920
|
+
def __copy__(self) -> HumanName:
|
|
921
|
+
# copy.copy/deepcopy go through the state hooks, a subclass's
|
|
922
|
+
# included, and a copy is no pickle load (_quiet_setstate)
|
|
923
|
+
new = object.__new__(type(self))
|
|
924
|
+
_quiet_setstate(new, self.__getstate__(), HumanName,
|
|
925
|
+
HUMANNAME_PICKLE_DEPRECATION)
|
|
926
|
+
return new
|
|
927
|
+
|
|
928
|
+
def __deepcopy__(self, memo: dict[int, object]) -> HumanName:
|
|
929
|
+
new = object.__new__(type(self))
|
|
930
|
+
memo[id(self)] = new
|
|
931
|
+
_quiet_setstate(new, copy.deepcopy(self.__getstate__(), memo),
|
|
932
|
+
HumanName, HUMANNAME_PICKLE_DEPRECATION)
|
|
933
|
+
return new
|
|
934
|
+
|
|
935
|
+
def _restore(self, state: dict[str, Any]) -> None:
|
|
891
936
|
c = state.get("C")
|
|
892
937
|
self._C = CONSTANTS if c is None else c
|
|
893
938
|
self._snapshot_gen = -1
|
|
@@ -506,7 +506,7 @@ def post_rules(state: ParseState) -> ParseState:
|
|
|
506
506
|
# it, and the one name word of a name read family-first. The comma
|
|
507
507
|
# named no given part, and the order places a word nothing else
|
|
508
508
|
# decided (O5), so the title decides as it does in 'Sir John'
|
|
509
|
-
# ('
|
|
509
|
+
# ('John III, Sir' reads as 'Sir John III'), unless
|
|
510
510
|
# something else settled the word (_family_settled).
|
|
511
511
|
elif (titles and families and not givens and not middles
|
|
512
512
|
and not _family_settled(state, tokens, families)
|
|
@@ -1487,7 +1487,8 @@ def title_readings(texts: Sequence[str], folded: Sequence[str],
|
|
|
1487
1487
|
of `title_modifiers` is a title only with a head title behind it in
|
|
1488
1488
|
its run of titles: any title that is not a modifier, or a word H2's
|
|
1489
1489
|
shape reads as one, before 'of' ('Mother Superior of the Convent'),
|
|
1490
|
-
|
|
1490
|
+
behind a title that attaches to it in `title_phrases` ('Princess
|
|
1491
|
+
Royal', #913), or in the object of 'of' or 'the' there (decision 10 of
|
|
1491
1492
|
decisions/vocabulary-model). Only the leading run is the head: a
|
|
1492
1493
|
modifier outside it is read as listed, one ending the name being
|
|
1493
1494
|
H5's. A
|
|
@@ -1558,7 +1559,10 @@ def title_readings(texts: Sequence[str], folded: Sequence[str],
|
|
|
1558
1559
|
and ((head and i < lead) or (n in contested and n not in titles))):
|
|
1559
1560
|
reading[i] = behind or linked[i] or (
|
|
1560
1561
|
i < last and folded[i + 1] in _PHRASE_LINKS
|
|
1561
|
-
and folded[i + 1] in conjunctions)
|
|
1562
|
+
and folded[i + 1] in conjunctions) or (
|
|
1563
|
+
# a title before it that attaches to it ('Princess Royal')
|
|
1564
|
+
i > 0 and reading[i - 1]
|
|
1565
|
+
and f"{folded[i - 1]} {n}" in phrases)
|
|
1562
1566
|
behind = reading[i]
|
|
1563
1567
|
elif reading[i] or (head and is_title_shaped(texts[i], lexicon)):
|
|
1564
1568
|
behind = True
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
#:
|
|
5
5
|
#: Bumped when a cycle OPENS, not when it ships, so the tree says what
|
|
6
6
|
#: it is building. Note the cost of the tuple being purely numeric: it
|
|
7
|
-
#: cannot carry the dev marker, so `VERSION >= (2,
|
|
8
|
-
#: true here while 2.
|
|
7
|
+
#: cannot carry the dev marker, so `VERSION >= (2, 8, 0)` is already
|
|
8
|
+
#: true here while 2.8.0 is unreleased. Compare `__version__` instead
|
|
9
9
|
#: where that distinction matters.
|
|
10
|
-
VERSION = (2,
|
|
10
|
+
VERSION = (2, 8, 0)
|
|
11
11
|
#: PEP 440 pre-release/dev segment appended to the numeric version, or
|
|
12
12
|
#: "" for a final release. Joined WITHOUT a dot ("2.0.0rc1", not
|
|
13
13
|
#: "2.0.0.rc1"); setuptools reads __version__ as the package version.
|
|
14
14
|
#:
|
|
15
15
|
#: "dev" through the cycle, cleared at release. It normalizes to
|
|
16
|
-
#: 2.
|
|
16
|
+
#: 2.8.0.dev0, which sorts above 2.7.0 and BELOW 2.8.0, so an install
|
|
17
17
|
#: from master can never masquerade as the release it precedes.
|
|
18
18
|
PRE_RELEASE = ""
|
|
19
19
|
__version__ = ".".join(map(str, VERSION)) + PRE_RELEASE
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""v1 import-path preservation (mechanisms.md#CONFIG-SHIM-SNAPSHOT):
|
|
2
|
+
the Constants shim
|
|
3
|
+
lives in nameparser._config_shim.
|
|
4
|
+
|
|
5
|
+
Two unrelated things share this package. The names re-exported below --
|
|
6
|
+
``Constants``, ``CONSTANTS``, ``SetManager``, ``TupleManager``,
|
|
7
|
+
``RegexTupleManager`` -- are v1 compatibility surface, and go with the
|
|
8
|
+
rest of the facade in 3.0. The vocabulary data modules beside them
|
|
9
|
+
(:mod:`~nameparser.config.titles`, :mod:`~nameparser.config.particles`,
|
|
10
|
+
...) are not compatibility surface at all: they are the word lists the
|
|
11
|
+
2.0 :class:`~nameparser.Lexicon` is built from, they are named for its
|
|
12
|
+
fields since 2.2 (#293), and its documentation cross-references them.
|
|
13
|
+
Since 2.6 the word lists (all but ``surnames.py``) re-export sets
|
|
14
|
+
compiled from the per-word TOML files in ``nameparser/vocab/`` (#737).
|
|
15
|
+
|
|
16
|
+
``RegexTupleManager`` is served from the shim purely for pickle
|
|
17
|
+
compatibility (through ``__getattr__`` since 2.8, so loading such a blob
|
|
18
|
+
warns here too): a v1.4 ``Constants`` blob's ``regexes`` field was
|
|
19
|
+
pickled as ``nameparser.config.RegexTupleManager(...)``, and unpickling
|
|
20
|
+
resolves and reconstructs that nested object before
|
|
21
|
+
``Constants.__setstate__`` ever runs. Without this name, loading such a
|
|
22
|
+
blob raises ``AttributeError`` looking up the class, not a clean
|
|
23
|
+
compatibility failure.
|
|
24
|
+
"""
|
|
25
|
+
# Maintainer note, deliberately outside the docstring: the vocabulary
|
|
26
|
+
# DATA modules keep this package as their home in 3.0 (decided
|
|
27
|
+
# 2026-10-28, decisions/3-0-reevaluations); only the five shim names
|
|
28
|
+
# below go. Constants and CONSTANTS are imported eagerly -- Constants
|
|
29
|
+
# warns at construction, the CONSTANTS singleton when mutated -- while
|
|
30
|
+
# the three managers resolve through __getattr__ so that each caller's
|
|
31
|
+
# read warns, at the caller's line, and nameparser's own reads (from
|
|
32
|
+
# _config_shim directly) stay quiet. The bridge follows
|
|
33
|
+
# config/_deprecated.py's alias_getattr: the hooks sit in the `else` of
|
|
34
|
+
# a TYPE_CHECKING guard, since a module __getattr__ mypy can see turns
|
|
35
|
+
# off its missing-attribute checking for the whole module, and __dir__
|
|
36
|
+
# lists the managers, or autodoc's member scan drops them.
|
|
37
|
+
import sys as _sys
|
|
38
|
+
import warnings as _warnings
|
|
39
|
+
from typing import TYPE_CHECKING
|
|
40
|
+
|
|
41
|
+
import nameparser._config_shim as _config_shim
|
|
42
|
+
from nameparser._config_shim import CONSTANTS as CONSTANTS
|
|
43
|
+
from nameparser._config_shim import Constants as Constants
|
|
44
|
+
|
|
45
|
+
if TYPE_CHECKING:
|
|
46
|
+
from nameparser._config_shim import RegexTupleManager as RegexTupleManager
|
|
47
|
+
from nameparser._config_shim import SetManager as SetManager
|
|
48
|
+
from nameparser._config_shim import TupleManager as TupleManager
|
|
49
|
+
else:
|
|
50
|
+
def __getattr__(name: str) -> object:
|
|
51
|
+
# PEP 562. Per read, never cached into globals, so every
|
|
52
|
+
# reading site warns (why _deprecated.py never caches either).
|
|
53
|
+
# A v1.4 Constants pickle names nameparser.config.
|
|
54
|
+
# RegexTupleManager and SetManager, so loading one warns here as
|
|
55
|
+
# well as in Constants.__setstate__ -- correct, since 3.0
|
|
56
|
+
# refuses that blob.
|
|
57
|
+
message = _config_shim.MANAGER_DEPRECATIONS.get(name)
|
|
58
|
+
if message is None:
|
|
59
|
+
raise AttributeError(
|
|
60
|
+
f"module {__name__!r} has no attribute {name!r}")
|
|
61
|
+
# `from nameparser.config import SetManager` reads the name
|
|
62
|
+
# twice: importlib's _handle_fromlist probes a PACKAGE's
|
|
63
|
+
# fromlist with hasattr() first, then the import statement
|
|
64
|
+
# reads it. Warning on the probe too would report one import
|
|
65
|
+
# twice.
|
|
66
|
+
if _sys._getframe(1).f_code.co_name != "_handle_fromlist":
|
|
67
|
+
_warnings.warn(message, DeprecationWarning, stacklevel=2)
|
|
68
|
+
return getattr(_config_shim, name)
|
|
69
|
+
|
|
70
|
+
def __dir__() -> list[str]:
|
|
71
|
+
# the union, as _deprecated.py's __dir__ explains
|
|
72
|
+
return sorted(set(globals()) | set(_config_shim.MANAGER_DEPRECATIONS))
|
|
73
|
+
|
|
74
|
+
# a star import reads __all__ alone, so listing the managers routes
|
|
75
|
+
# each through __getattr__ and warns, rather than dropping them unwarned
|
|
76
|
+
__all__ = ["CONSTANTS", "Constants", "RegexTupleManager", "SetManager", "TupleManager"]
|