nameparser 2.7.0__tar.gz → 2.8.1__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.1}/PKG-INFO +31 -17
- {nameparser-2.7.0 → nameparser-2.8.1}/README.rst +30 -16
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_config_shim.py +168 -36
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_facade.py +48 -3
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_lexicon.py +177 -14
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_post_rules.py +1 -1
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_vocab.py +6 -2
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_version.py +5 -5
- nameparser-2.8.1/nameparser/config/__init__.py +79 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/_compiled.py +97 -8
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/_deprecated.py +84 -5
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/bound_given_names.py +15 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/capitalization.py +20 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/conjunctions.py +20 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/given_names.py +15 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/maiden_markers.py +20 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/particles.py +16 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/regexes.py +26 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/suffixes.py +14 -2
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/titles.py +20 -3
- nameparser-2.8.1/nameparser/util.py +46 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/en.toml +37 -17
- {nameparser-2.7.0 → nameparser-2.8.1/nameparser.egg-info}/PKG-INFO +31 -17
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser.egg-info/SOURCES.txt +5 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/pyproject.toml +14 -0
- nameparser-2.8.1/tests/removals.py +31 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_constants.py +9 -3
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_first_name.py +7 -3
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_python_api.py +11 -8
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/cases.py +182 -7
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_cases.py +10 -4
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_config_aliases.py +26 -4
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_config_shim.py +6 -1
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_contracts.py +7 -1
- nameparser-2.8.1/tests/v2/test_deprecations.py +460 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_facade.py +3 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_lexicon.py +5 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_local_agreement.py +82 -6
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_local_corpora.py +147 -7
- nameparser-2.8.1/tests/v2/test_local_orcid.py +561 -0
- nameparser-2.8.1/tests/v2/test_local_patentsview.py +366 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_measure.py +5 -2
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_name_usage_tool.py +100 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_properties.py +1 -1
- nameparser-2.8.1/tests/v2/test_removals_2_8_1.py +435 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_render.py +4 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/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.1}/AUTHORS +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/LICENSE +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/MANIFEST.in +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/__main__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_locale.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_assemble.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_assign.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_classify.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_comma.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_extract.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_group.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_pieces.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_script_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_state.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_pipeline/_tokenize.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_policy.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_render.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/_types.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/_invariants.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/_titles_2_6_0.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/bound_first_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/prefixes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/config/surnames.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/locales/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/locales/ja.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/locales/ru.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/locales/tr_az.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/locales/zh.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/py.typed +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ak.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/am.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ar.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/as.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/be.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/bg.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/bin.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/bn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/bo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/bs.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ca.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/cs.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/da.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/de.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/el.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/es.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/et.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/fa.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ff.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/fi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/fil.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/fr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ga.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/gd.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/gu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ha.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/he.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/hi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/hr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/hu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/hy.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/id.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/is.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/it.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ja.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ka.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/kk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/km.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/kn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ko.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/kok.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/lo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/lt.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/lv.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/mi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/mk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ml.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/mn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/mr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ms.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/mul.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/my.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/nb.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ne.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/nl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/nn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/or.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/pa.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/pl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/pt-BR.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/pt.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ro.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ru.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sd.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/shn.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/si.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sl.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sv.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/sw.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ta.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/te.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/th.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ti.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/tr.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/uk.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/und.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/ur.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/vi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/yi.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/yo.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/zh.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser/vocab/zu.toml +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser.egg-info/dependency_links.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser.egg-info/requires.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/nameparser.egg-info/top_level.txt +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/setup.cfg +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/base.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/conftest.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_bound_given_names.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_brute_force.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_capitalization.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_comma_variants.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_conjunctions.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_east_slavic_patronymic_order.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_initials.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_middle_name_as_last.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_nicknames.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_output_format.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_particles.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_suffixes.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_titles.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_turkic_patronymic_order.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/test_variations.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/_differential_fixtures.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/conftest.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/design_docs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/__init__.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_assemble.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_assign.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_classify.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_comma.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_extract.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_group.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_pieces.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_post_rules.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_script_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_segment.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_state.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_tokenize.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/pipeline/test_vocab.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/rules_budget.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/rules_doc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/rules_skeleton.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_benchmark.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_cldr_agreement.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_cldr_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_cli.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_corpora.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_corpus_build.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_design_docs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_differential.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_doc_citations.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_doc_spellings.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_facade_cases.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_gnd_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_layering.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_local_jrc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_locale.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_locales.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_order_correspondence.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_parser.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_policy.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_regex_sync.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_reprs.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_rules_budget.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_rules_doc.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_rules_doc_grammar.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_rules_skeleton.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_snapshot.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_types.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_vocab.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_wikidata_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/tests/v2/test_wikidata_native_corpus.py +0 -0
- {nameparser-2.7.0 → nameparser-2.8.1}/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.1
|
|
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,39 @@ 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
|
+
⚠️ **2.8.1 adds three more DeprecationWarnings** for things 3.0 changes:
|
|
41
|
+
configuring a ``Lexicon`` through its set fields
|
|
42
|
+
(``Lexicon.default().add(titles={"dean"})``), reading the vocabulary
|
|
43
|
+
constants in ``nameparser.config`` (``TITLES`` and the rest, all but
|
|
44
|
+
``surnames``), and ``nameparser.config.regexes``. A test run that turns
|
|
45
|
+
warnings into errors (``-W error``, or pytest's ``filterwarnings =
|
|
46
|
+
error``) fails where your code does any of these; see the `migration
|
|
47
|
+
guide <https://nameparser.readthedocs.io/en/stable/migrate.html#deprecated-in-2-8-1>`__.
|
|
48
|
+
|
|
49
|
+
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
50
|
+
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
51
|
+
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
52
|
+
constructs it, loads it from a pickle, or changes the shared
|
|
53
|
+
``CONSTANTS``. It keeps working through 2.x; ``parse()`` is the
|
|
54
|
+
replacement, and `Coming from 1.x`_ below says where to start. After
|
|
55
|
+
2.8 the 2.x line takes fixes only, and new work goes into 3.0.
|
|
56
|
+
|
|
57
|
+
2.8 also carries on 2.7's reading of titles that are also given names:
|
|
58
|
+
a title only inside a title phrase, so ``Queen Latifah`` keeps the
|
|
59
|
+
given name ``Queen`` while ``Her Majesty Queen Elizabeth`` reads the
|
|
60
|
+
title. The `release log
|
|
46
61
|
<https://nameparser.readthedocs.io/en/latest/release_log.html>`__ has
|
|
47
|
-
the details.
|
|
62
|
+
the details. Please `open an
|
|
63
|
+
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
64
|
+
that parses wrong.
|
|
48
65
|
|
|
49
66
|
Chinese, Japanese and Korean names written in their own scripts are read
|
|
50
67
|
family-first, unspaced Korean names are split against the census surname
|
|
51
68
|
list, and CJK honorifics are recognized. See `East Asian names
|
|
52
69
|
<https://nameparser.readthedocs.io/en/latest/usage.html#east-asian-names>`__.
|
|
53
70
|
|
|
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
71
|
Installation
|
|
60
72
|
------------
|
|
61
73
|
|
|
@@ -127,8 +139,10 @@ Learn more
|
|
|
127
139
|
Coming from 1.x
|
|
128
140
|
----------------
|
|
129
141
|
|
|
130
|
-
``HumanName`` and ``CONSTANTS`` keep working
|
|
131
|
-
attributes, same mutation API
|
|
142
|
+
``HumanName`` and ``CONSTANTS`` keep working through 2.x — same imports,
|
|
143
|
+
same attributes, same mutation API — and warn from 2.8 on, since 3.0
|
|
144
|
+
removes them. Run your tests under ``python -W error::DeprecationWarning``
|
|
145
|
+
to find the sites; a read of ``CONSTANTS`` does not warn. What 2.0 removes is the batch of
|
|
132
146
|
deprecations 1.3 and 1.4 announced, so if your test suite runs clean on
|
|
133
147
|
1.4 under ``python -W error::DeprecationWarning``, you are nearly done.
|
|
134
148
|
Two things that check will not catch: four removals 1.4 never warned
|
|
@@ -7,27 +7,39 @@ 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
|
+
⚠️ **2.8.1 adds three more DeprecationWarnings** for things 3.0 changes:
|
|
13
|
+
configuring a ``Lexicon`` through its set fields
|
|
14
|
+
(``Lexicon.default().add(titles={"dean"})``), reading the vocabulary
|
|
15
|
+
constants in ``nameparser.config`` (``TITLES`` and the rest, all but
|
|
16
|
+
``surnames``), and ``nameparser.config.regexes``. A test run that turns
|
|
17
|
+
warnings into errors (``-W error``, or pytest's ``filterwarnings =
|
|
18
|
+
error``) fails where your code does any of these; see the `migration
|
|
19
|
+
guide <https://nameparser.readthedocs.io/en/stable/migrate.html#deprecated-in-2-8-1>`__.
|
|
20
|
+
|
|
21
|
+
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
22
|
+
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
23
|
+
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
24
|
+
constructs it, loads it from a pickle, or changes the shared
|
|
25
|
+
``CONSTANTS``. It keeps working through 2.x; ``parse()`` is the
|
|
26
|
+
replacement, and `Coming from 1.x`_ below says where to start. After
|
|
27
|
+
2.8 the 2.x line takes fixes only, and new work goes into 3.0.
|
|
28
|
+
|
|
29
|
+
2.8 also carries on 2.7's reading of titles that are also given names:
|
|
30
|
+
a title only inside a title phrase, so ``Queen Latifah`` keeps the
|
|
31
|
+
given name ``Queen`` while ``Her Majesty Queen Elizabeth`` reads the
|
|
32
|
+
title. The `release log
|
|
18
33
|
<https://nameparser.readthedocs.io/en/latest/release_log.html>`__ has
|
|
19
|
-
the details.
|
|
34
|
+
the details. Please `open an
|
|
35
|
+
issue <https://github.com/derek73/python-nameparser/issues>`__ for anything
|
|
36
|
+
that parses wrong.
|
|
20
37
|
|
|
21
38
|
Chinese, Japanese and Korean names written in their own scripts are read
|
|
22
39
|
family-first, unspaced Korean names are split against the census surname
|
|
23
40
|
list, and CJK honorifics are recognized. See `East Asian names
|
|
24
41
|
<https://nameparser.readthedocs.io/en/latest/usage.html#east-asian-names>`__.
|
|
25
42
|
|
|
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
43
|
Installation
|
|
32
44
|
------------
|
|
33
45
|
|
|
@@ -99,8 +111,10 @@ Learn more
|
|
|
99
111
|
Coming from 1.x
|
|
100
112
|
----------------
|
|
101
113
|
|
|
102
|
-
``HumanName`` and ``CONSTANTS`` keep working
|
|
103
|
-
attributes, same mutation API
|
|
114
|
+
``HumanName`` and ``CONSTANTS`` keep working through 2.x — same imports,
|
|
115
|
+
same attributes, same mutation API — and warn from 2.8 on, since 3.0
|
|
116
|
+
removes them. Run your tests under ``python -W error::DeprecationWarning``
|
|
117
|
+
to find the sites; a read of ``CONSTANTS`` does not warn. What 2.0 removes is the batch of
|
|
104
118
|
deprecations 1.3 and 1.4 announced, so if your test suite runs clean on
|
|
105
119
|
1.4 under ``python -W error::DeprecationWarning``, you are nearly done.
|
|
106
120
|
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.
|
|
@@ -529,8 +533,8 @@ class _RegexesProxy:
|
|
|
529
533
|
def _regexes() -> Mapping[str, object]:
|
|
530
534
|
# deferred import: see the module docstring's note on why every
|
|
531
535
|
# nameparser.config.<data module> import in this file is lazy
|
|
532
|
-
from nameparser.config.regexes import
|
|
533
|
-
return
|
|
536
|
+
from nameparser.config.regexes import _REGEXES
|
|
537
|
+
return _REGEXES
|
|
534
538
|
|
|
535
539
|
#: dict methods this read-only proxy deliberately does not carry.
|
|
536
540
|
#: Without this, __getattr__ reports them as missing regexes and
|
|
@@ -712,27 +716,80 @@ _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]]:
|
|
724
|
-
#
|
|
780
|
+
# the compiled vocabulary, read from _compiled: the public modules'
|
|
781
|
+
# constants warn at a caller's read since 2.8.1 (#1007)
|
|
725
782
|
# (same rule as Lexicon.default()).
|
|
726
|
-
from nameparser.config.
|
|
727
|
-
from nameparser.config.
|
|
728
|
-
from nameparser.config.
|
|
783
|
+
from nameparser.config._compiled import BOUND_GIVEN_NAMES
|
|
784
|
+
from nameparser.config._compiled import CONJUNCTIONS
|
|
785
|
+
from nameparser.config._compiled import (
|
|
729
786
|
NON_GIVEN_NAME_PARTICLES, PARTICLES,
|
|
730
787
|
)
|
|
731
|
-
from nameparser.config.
|
|
788
|
+
from nameparser.config._compiled import (
|
|
732
789
|
SUFFIX_ACRONYMS, SUFFIX_ACRONYMS_AMBIGUOUS, SUFFIX_WORDS,
|
|
733
790
|
)
|
|
734
791
|
from nameparser.config._titles_2_6_0 import TITLES_2_6_0
|
|
735
|
-
from nameparser.config.
|
|
792
|
+
from nameparser.config._compiled import (
|
|
736
793
|
GIVEN_NAME_TITLES, TITLES, TITLES_AMBIGUOUS)
|
|
737
794
|
return {
|
|
738
795
|
"prefixes": PARTICLES,
|
|
@@ -786,9 +843,11 @@ class Constants:
|
|
|
786
843
|
|
|
787
844
|
The module-level ``CONSTANTS`` singleton (below) has ``_shared``
|
|
788
845
|
flipped to ``True``: any mutation reached through it emits
|
|
789
|
-
``DeprecationWarning`` pointing at ``Lexicon``/``Policy
|
|
790
|
-
``
|
|
791
|
-
|
|
846
|
+
``DeprecationWarning`` pointing at ``Lexicon``/``Policy``. Since 2.8
|
|
847
|
+
constructing a ``Constants``, copying one with ``copy()`` and
|
|
848
|
+
loading one from a pickle warn too, since the whole class goes in
|
|
849
|
+
3.0; the singleton is built without the warning, so importing
|
|
850
|
+
``nameparser`` stays quiet.
|
|
792
851
|
"""
|
|
793
852
|
|
|
794
853
|
_shared = False # the CONSTANTS singleton flips this to True
|
|
@@ -836,6 +895,41 @@ class Constants:
|
|
|
836
895
|
regexes: object = _UNSET_KWARG,
|
|
837
896
|
patronymic_name_order: bool = False,
|
|
838
897
|
middle_name_as_last: bool = False,
|
|
898
|
+
) -> None:
|
|
899
|
+
# every construction warns, at the caller's line; the warnings
|
|
900
|
+
# registry, not a flag here, dedups repeats from one line
|
|
901
|
+
# (decisions/3-0-reevaluations, 2026-10-28)
|
|
902
|
+
warnings.warn(CONSTANTS_DEPRECATION, DeprecationWarning,
|
|
903
|
+
stacklevel=2)
|
|
904
|
+
self._init(
|
|
905
|
+
prefixes=prefixes, suffix_acronyms=suffix_acronyms,
|
|
906
|
+
suffix_not_acronyms=suffix_not_acronyms,
|
|
907
|
+
suffix_acronyms_ambiguous=suffix_acronyms_ambiguous,
|
|
908
|
+
titles=titles, first_name_titles=first_name_titles,
|
|
909
|
+
conjunctions=conjunctions, bound_first_names=bound_first_names,
|
|
910
|
+
non_first_name_prefixes=non_first_name_prefixes,
|
|
911
|
+
capitalization_exceptions=capitalization_exceptions,
|
|
912
|
+
regexes=regexes, patronymic_name_order=patronymic_name_order,
|
|
913
|
+
middle_name_as_last=middle_name_as_last)
|
|
914
|
+
|
|
915
|
+
def _init(
|
|
916
|
+
self,
|
|
917
|
+
*,
|
|
918
|
+
prefixes: Iterable[str] | object = _UNSET_KWARG,
|
|
919
|
+
suffix_acronyms: Iterable[str] | object = _UNSET_KWARG,
|
|
920
|
+
suffix_not_acronyms: Iterable[str] | object = _UNSET_KWARG,
|
|
921
|
+
suffix_acronyms_ambiguous: Iterable[str] | object = _UNSET_KWARG,
|
|
922
|
+
titles: Iterable[str] | object = _UNSET_KWARG,
|
|
923
|
+
first_name_titles: Iterable[str] | object = _UNSET_KWARG,
|
|
924
|
+
conjunctions: Iterable[str] | object = _UNSET_KWARG,
|
|
925
|
+
bound_first_names: Iterable[str] | object = _UNSET_KWARG,
|
|
926
|
+
non_first_name_prefixes: Iterable[str] | object = _UNSET_KWARG,
|
|
927
|
+
capitalization_exceptions:
|
|
928
|
+
Mapping[str, str] | Iterable[tuple[str, str]] | object
|
|
929
|
+
= _UNSET_KWARG,
|
|
930
|
+
regexes: object = _UNSET_KWARG,
|
|
931
|
+
patronymic_name_order: bool = False,
|
|
932
|
+
middle_name_as_last: bool = False,
|
|
839
933
|
) -> None:
|
|
840
934
|
# v1.4 parity constructor kwargs (#238/#242/#244 hardening); the
|
|
841
935
|
# signature is spelled out rather than **kwargs so an unknown
|
|
@@ -878,7 +972,7 @@ class Constants:
|
|
|
878
972
|
self, name,
|
|
879
973
|
SetManager(value, _on_change=self._bump, _field=name)) # type: ignore[arg-type]
|
|
880
974
|
if capitalization_exceptions is _UNSET_KWARG:
|
|
881
|
-
from nameparser.config.
|
|
975
|
+
from nameparser.config._compiled import (
|
|
882
976
|
CAPITALIZATION_EXCEPTIONS,
|
|
883
977
|
)
|
|
884
978
|
capitalization_exceptions = CAPITALIZATION_EXCEPTIONS
|
|
@@ -921,19 +1015,20 @@ class Constants:
|
|
|
921
1015
|
"""
|
|
922
1016
|
|
|
923
1017
|
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.
|
|
1018
|
+
# A fixed stacklevel lands on the caller only for one call depth:
|
|
1019
|
+
# a scalar arrives through __setattr__, a set's add() through
|
|
1020
|
+
# _changed(), a dict's update() and |= through __setitem__ per
|
|
1021
|
+
# key. Walk out of this module instead, as _lexicon's
|
|
1022
|
+
# _warn_dead_entry does, so the warning names the caller's line;
|
|
1023
|
+
# attributed here, Python's default filters hid it.
|
|
934
1024
|
if self._shared:
|
|
1025
|
+
level = 2
|
|
1026
|
+
frame: FrameType | None = sys._getframe(1)
|
|
1027
|
+
while (frame is not None
|
|
1028
|
+
and frame.f_globals.get("__name__") == __name__):
|
|
1029
|
+
frame, level = frame.f_back, level + 1
|
|
935
1030
|
warnings.warn(_SHARED_MUTATION_MESSAGE, DeprecationWarning,
|
|
936
|
-
stacklevel=
|
|
1031
|
+
stacklevel=level)
|
|
937
1032
|
object.__setattr__(self, "_generation", self._generation + 1)
|
|
938
1033
|
|
|
939
1034
|
def __setattr__(self, name: str, value: object) -> None:
|
|
@@ -987,7 +1082,27 @@ class Constants:
|
|
|
987
1082
|
v1 (which deepcopied __dict__): attributes OUTSIDE the known
|
|
988
1083
|
field surface -- e.g. ad-hoc names stashed on the instance --
|
|
989
1084
|
are not carried by copy() or pickling; only the enumerated
|
|
990
|
-
fields survive.
|
|
1085
|
+
fields survive. Warns since 2.8, as construction does: a copy
|
|
1086
|
+
is a new private ``Constants``, and ``CONSTANTS.copy()`` builds
|
|
1087
|
+
one without calling the constructor.""" # #260
|
|
1088
|
+
warnings.warn(CONSTANTS_DEPRECATION, DeprecationWarning,
|
|
1089
|
+
stacklevel=2)
|
|
1090
|
+
return self._copy()
|
|
1091
|
+
|
|
1092
|
+
def __copy__(self) -> Constants:
|
|
1093
|
+
new = object.__new__(type(self))
|
|
1094
|
+
_quiet_setstate(new, self.__getstate__(), Constants,
|
|
1095
|
+
CONSTANTS_PICKLE_DEPRECATION)
|
|
1096
|
+
return new
|
|
1097
|
+
|
|
1098
|
+
def __deepcopy__(self, memo: dict[int, object]) -> Constants:
|
|
1099
|
+
new = object.__new__(type(self))
|
|
1100
|
+
memo[id(self)] = new
|
|
1101
|
+
_quiet_setstate(new, copy.deepcopy(self.__getstate__(), memo),
|
|
1102
|
+
Constants, CONSTANTS_PICKLE_DEPRECATION)
|
|
1103
|
+
return new
|
|
1104
|
+
|
|
1105
|
+
def _copy(self) -> Constants:
|
|
991
1106
|
# An independent instance with its own generation counter and
|
|
992
1107
|
# its own manager callbacks -- not a shared-state alias like a
|
|
993
1108
|
# naive attribute-for-attribute copy would produce. v1's copy()
|
|
@@ -1050,14 +1165,14 @@ class Constants:
|
|
|
1050
1165
|
singleton -- only direct attribute mutation is on the 3.0
|
|
1051
1166
|
removal path.
|
|
1052
1167
|
"""
|
|
1053
|
-
from nameparser.config.
|
|
1054
|
-
from nameparser.config.
|
|
1055
|
-
from nameparser.config.
|
|
1056
|
-
from nameparser.config.
|
|
1168
|
+
from nameparser.config._compiled import CONJUNCTIONS_AMBIGUOUS
|
|
1169
|
+
from nameparser.config._compiled import GIVEN_NAME_ABBREVIATIONS
|
|
1170
|
+
from nameparser.config._compiled import MAIDEN_MARKERS
|
|
1171
|
+
from nameparser.config._compiled import (
|
|
1057
1172
|
AGNOMENS, GLUED_HONORIFICS, SUFFIX_WORDS_AMBIGUOUS)
|
|
1058
1173
|
from nameparser.config.surnames import KOREAN_SURNAMES
|
|
1059
1174
|
from nameparser.config._titles_2_6_0 import TITLES_2_6_0
|
|
1060
|
-
from nameparser.config.
|
|
1175
|
+
from nameparser.config._compiled import (
|
|
1061
1176
|
AFTER_GIVEN_TITLES, TITLE_MODIFIERS, TITLE_PHRASES, TITLE_STYLES,
|
|
1062
1177
|
TITLES_AMBIGUOUS)
|
|
1063
1178
|
# Every set field and every capitalization_exceptions key passes
|
|
@@ -1376,7 +1491,22 @@ class Constants:
|
|
|
1376
1491
|
# DROPPED (#255: empty is always '' in 2.0).
|
|
1377
1492
|
state = {k: v for k, v in state.items()
|
|
1378
1493
|
if k != "empty_attribute_default"}
|
|
1379
|
-
|
|
1494
|
+
warnings.warn(CONSTANTS_PICKLE_DEPRECATION, DeprecationWarning,
|
|
1495
|
+
stacklevel=2)
|
|
1496
|
+
self._restore(state)
|
|
1497
|
+
|
|
1498
|
+
def _restore(self, state: dict[str, object]) -> None:
|
|
1499
|
+
# defaults, then overlay. A subclass's own __init__ runs here as
|
|
1500
|
+
# it did before 2.8; its super().__init__() would warn that a
|
|
1501
|
+
# Constants was constructed, which a restore is not
|
|
1502
|
+
if type(self).__init__ is Constants.__init__:
|
|
1503
|
+
self._init()
|
|
1504
|
+
else:
|
|
1505
|
+
with warnings.catch_warnings():
|
|
1506
|
+
warnings.filterwarnings(
|
|
1507
|
+
"ignore", message=re.escape(CONSTANTS_DEPRECATION),
|
|
1508
|
+
category=DeprecationWarning)
|
|
1509
|
+
self.__init__() # type: ignore[misc]
|
|
1380
1510
|
# (managers re-wrapped below so _on_change points at THIS
|
|
1381
1511
|
# instance, not whatever produced the incoming state)
|
|
1382
1512
|
managers: dict[str, SetManager] = {}
|
|
@@ -1417,5 +1547,7 @@ class Constants:
|
|
|
1417
1547
|
object.__setattr__(self, name, state[name])
|
|
1418
1548
|
|
|
1419
1549
|
|
|
1420
|
-
|
|
1550
|
+
# built past __init__, so importing nameparser never warns
|
|
1551
|
+
CONSTANTS = object.__new__(Constants)
|
|
1552
|
+
CONSTANTS._init()
|
|
1421
1553
|
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
|