nameparser 2.8.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.8.0/nameparser.egg-info → nameparser-2.8.1}/PKG-INFO +10 -1
- {nameparser-2.8.0 → nameparser-2.8.1}/README.rst +9 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_config_shim.py +15 -14
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_lexicon.py +177 -14
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_version.py +5 -5
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/__init__.py +12 -9
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/_deprecated.py +84 -5
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/bound_given_names.py +15 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/capitalization.py +20 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/conjunctions.py +20 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/given_names.py +15 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/maiden_markers.py +20 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/particles.py +16 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/regexes.py +26 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/suffixes.py +14 -2
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/titles.py +19 -2
- {nameparser-2.8.0 → nameparser-2.8.1/nameparser.egg-info}/PKG-INFO +10 -1
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser.egg-info/SOURCES.txt +1 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/pyproject.toml +5 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/removals.py +6 -1
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_config_aliases.py +26 -4
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_contracts.py +7 -1
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_deprecations.py +4 -1
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_lexicon.py +5 -0
- nameparser-2.8.1/tests/v2/test_removals_2_8_1.py +435 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/AUTHORS +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/LICENSE +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/MANIFEST.in +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/__main__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_facade.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_locale.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_parser.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_assemble.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_assign.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_classify.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_comma.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_extract.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_group.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_pieces.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_post_rules.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_script_segment.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_segment.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_state.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_tokenize.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_pipeline/_vocab.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_policy.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_render.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/_types.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/_compiled.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/_invariants.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/_titles_2_6_0.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/bound_first_names.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/prefixes.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/config/surnames.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/locales/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/locales/ja.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/locales/ru.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/locales/tr_az.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/locales/zh.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/parser.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/py.typed +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/util.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ak.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/am.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ar.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/as.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/be.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/bg.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/bin.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/bn.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/bo.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/bs.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ca.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/cs.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/da.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/de.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/el.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/en.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/es.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/et.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/fa.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ff.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/fi.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/fil.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/fr.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ga.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/gd.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/gu.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ha.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/he.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/hi.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/hr.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/hu.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/hy.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/id.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/is.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/it.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ja.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ka.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/kk.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/km.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/kn.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ko.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/kok.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/lo.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/lt.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/lv.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/mi.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/mk.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ml.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/mn.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/mr.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ms.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/mul.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/my.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/nb.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ne.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/nl.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/nn.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/or.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/pa.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/pl.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/pt-BR.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/pt.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ro.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ru.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sd.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/shn.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/si.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sk.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sl.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sr.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sv.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/sw.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ta.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/te.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/th.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ti.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/tr.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/uk.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/und.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/ur.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/vi.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/yi.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/yo.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/zh.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser/vocab/zu.toml +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser.egg-info/dependency_links.txt +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser.egg-info/requires.txt +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/nameparser.egg-info/top_level.txt +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/setup.cfg +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/base.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/conftest.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_bound_given_names.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_brute_force.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_capitalization.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_comma_variants.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_conjunctions.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_constants.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_east_slavic_patronymic_order.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_first_name.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_initials.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_middle_name_as_last.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_nicknames.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_output_format.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_particles.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_python_api.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_suffixes.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_titles.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_turkic_patronymic_order.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/test_variations.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/_differential_fixtures.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/cases.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/conftest.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/design_docs.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/__init__.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_assemble.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_assign.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_classify.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_comma.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_extract.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_group.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_pieces.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_post_rules.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_script_segment.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_segment.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_state.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_tokenize.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/pipeline/test_vocab.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/rules_budget.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/rules_doc.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/rules_skeleton.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_benchmark.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_cases.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_cldr_agreement.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_cldr_corpus.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_cli.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_config_shim.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_corpora.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_corpus_build.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_design_docs.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_differential.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_doc_citations.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_doc_spellings.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_facade.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_facade_cases.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_gnd_corpus.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_layering.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_local_agreement.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_local_corpora.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_local_jrc.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_local_orcid.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_local_patentsview.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_locale.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_locales.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_measure.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_name_usage_tool.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_order_correspondence.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_parser.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_policy.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_properties.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_regex_sync.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_render.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_reprs.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_rules_budget.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_rules_doc.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_rules_doc_grammar.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_rules_skeleton.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_snapshot.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_types.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_vocab.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_wikidata_corpus.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_wikidata_native_corpus.py +0 -0
- {nameparser-2.8.0 → nameparser-2.8.1}/tests/v2/test_word_report.py +0 -0
- {nameparser-2.8.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.8.
|
|
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
|
|
@@ -37,6 +37,15 @@ composable, and locale packs are opt-in.
|
|
|
37
37
|
|
|
38
38
|
📣 **nameparser 2.8 is out, the last 2.x feature release.**
|
|
39
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
|
+
|
|
40
49
|
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
41
50
|
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
42
51
|
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
@@ -9,6 +9,15 @@ composable, and locale packs are opt-in.
|
|
|
9
9
|
|
|
10
10
|
📣 **nameparser 2.8 is out, the last 2.x feature release.**
|
|
11
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
|
+
|
|
12
21
|
⚠️ **HumanName is deprecated, and 3.0 removes it.** From 2.8 the 1.x
|
|
13
22
|
compatibility layer — ``HumanName``, ``Constants`` and the shared
|
|
14
23
|
``CONSTANTS`` — emits a ``DeprecationWarning`` where your code
|
|
@@ -533,8 +533,8 @@ class _RegexesProxy:
|
|
|
533
533
|
def _regexes() -> Mapping[str, object]:
|
|
534
534
|
# deferred import: see the module docstring's note on why every
|
|
535
535
|
# nameparser.config.<data module> import in this file is lazy
|
|
536
|
-
from nameparser.config.regexes import
|
|
537
|
-
return
|
|
536
|
+
from nameparser.config.regexes import _REGEXES
|
|
537
|
+
return _REGEXES
|
|
538
538
|
|
|
539
539
|
#: dict methods this read-only proxy deliberately does not carry.
|
|
540
540
|
#: Without this, __getattr__ reports them as missing regexes and
|
|
@@ -777,18 +777,19 @@ def _quiet_setstate(new: object, state: dict[str, object], base: type,
|
|
|
777
777
|
|
|
778
778
|
|
|
779
779
|
def _default_vocab() -> dict[str, frozenset[str]]:
|
|
780
|
-
#
|
|
780
|
+
# the compiled vocabulary, read from _compiled: the public modules'
|
|
781
|
+
# constants warn at a caller's read since 2.8.1 (#1007)
|
|
781
782
|
# (same rule as Lexicon.default()).
|
|
782
|
-
from nameparser.config.
|
|
783
|
-
from nameparser.config.
|
|
784
|
-
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 (
|
|
785
786
|
NON_GIVEN_NAME_PARTICLES, PARTICLES,
|
|
786
787
|
)
|
|
787
|
-
from nameparser.config.
|
|
788
|
+
from nameparser.config._compiled import (
|
|
788
789
|
SUFFIX_ACRONYMS, SUFFIX_ACRONYMS_AMBIGUOUS, SUFFIX_WORDS,
|
|
789
790
|
)
|
|
790
791
|
from nameparser.config._titles_2_6_0 import TITLES_2_6_0
|
|
791
|
-
from nameparser.config.
|
|
792
|
+
from nameparser.config._compiled import (
|
|
792
793
|
GIVEN_NAME_TITLES, TITLES, TITLES_AMBIGUOUS)
|
|
793
794
|
return {
|
|
794
795
|
"prefixes": PARTICLES,
|
|
@@ -971,7 +972,7 @@ class Constants:
|
|
|
971
972
|
self, name,
|
|
972
973
|
SetManager(value, _on_change=self._bump, _field=name)) # type: ignore[arg-type]
|
|
973
974
|
if capitalization_exceptions is _UNSET_KWARG:
|
|
974
|
-
from nameparser.config.
|
|
975
|
+
from nameparser.config._compiled import (
|
|
975
976
|
CAPITALIZATION_EXCEPTIONS,
|
|
976
977
|
)
|
|
977
978
|
capitalization_exceptions = CAPITALIZATION_EXCEPTIONS
|
|
@@ -1164,14 +1165,14 @@ class Constants:
|
|
|
1164
1165
|
singleton -- only direct attribute mutation is on the 3.0
|
|
1165
1166
|
removal path.
|
|
1166
1167
|
"""
|
|
1167
|
-
from nameparser.config.
|
|
1168
|
-
from nameparser.config.
|
|
1169
|
-
from nameparser.config.
|
|
1170
|
-
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 (
|
|
1171
1172
|
AGNOMENS, GLUED_HONORIFICS, SUFFIX_WORDS_AMBIGUOUS)
|
|
1172
1173
|
from nameparser.config.surnames import KOREAN_SURNAMES
|
|
1173
1174
|
from nameparser.config._titles_2_6_0 import TITLES_2_6_0
|
|
1174
|
-
from nameparser.config.
|
|
1175
|
+
from nameparser.config._compiled import (
|
|
1175
1176
|
AFTER_GIVEN_TITLES, TITLE_MODIFIERS, TITLE_PHRASES, TITLE_STYLES,
|
|
1176
1177
|
TITLES_AMBIGUOUS)
|
|
1177
1178
|
# Every set field and every capitalization_exceptions key passes
|
|
@@ -12,7 +12,7 @@ import functools
|
|
|
12
12
|
import sys
|
|
13
13
|
import unicodedata
|
|
14
14
|
import warnings
|
|
15
|
-
from collections.abc import Iterable, Mapping, Set
|
|
15
|
+
from collections.abc import Iterable, Iterator, Mapping, Set
|
|
16
16
|
from dataclasses import dataclass, field
|
|
17
17
|
from types import FrameType, MappingProxyType
|
|
18
18
|
from typing import cast
|
|
@@ -337,6 +337,101 @@ def _warn_dead_entry(message: str) -> None:
|
|
|
337
337
|
warnings.warn(message, UserWarning, stacklevel=level)
|
|
338
338
|
|
|
339
339
|
|
|
340
|
+
#: 2.8.1 (#754): the 3.0 migration guide's table of what each set field
|
|
341
|
+
#: becomes. 3.0 configures a lexicon by reading -- what a word is -- and
|
|
342
|
+
#: refuses these fields with a TypeError naming the readings for the
|
|
343
|
+
#: words given, a translation this release does not attempt: it depends
|
|
344
|
+
#: on the word's other readings, so the guide's row and 3.0's error are
|
|
345
|
+
#: the sources.
|
|
346
|
+
_FIELDS_GUIDE = ("https://nameparser.readthedocs.io/en/latest/migrate.html"
|
|
347
|
+
"#lexicon-fields-readings")
|
|
348
|
+
|
|
349
|
+
#: modules whose frames sit between a caller and a Lexicon's
|
|
350
|
+
#: construction: this one (add, remove, __or__, __init__),
|
|
351
|
+
#: dataclasses.replace and copy.replace
|
|
352
|
+
_CONSTRUCTION_MODULES = (__name__, "dataclasses", "copy")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _outside_caller(
|
|
356
|
+
construction: bool,
|
|
357
|
+
) -> tuple[int, Mapping[str, object] | None, str] | None:
|
|
358
|
+
"""Where a set-field warning belongs: the stacklevel, counted from
|
|
359
|
+
the function that calls warnings.warn (itself called from the
|
|
360
|
+
method this asks for), of the first frame outside this module,
|
|
361
|
+
dataclasses and copy, with the locals of a dataclasses.replace
|
|
362
|
+
frame passed on the way and the replace the caller called
|
|
363
|
+
(``copy.replace()`` where a copy frame was passed, else
|
|
364
|
+
``dataclasses.replace()``); or None where the library itself made the
|
|
365
|
+
call -- that frame inside nameparser (Lexicon.default(), the locale
|
|
366
|
+
packs, parser_for, the v1 facade), or, for a construction, a method
|
|
367
|
+
of this module building the lexicon: add() and remove() warn for
|
|
368
|
+
themselves, and __or__ is 3.0's own spelling.
|
|
369
|
+
"""
|
|
370
|
+
level = 3
|
|
371
|
+
frame: FrameType | None = sys._getframe(2)
|
|
372
|
+
replacing: Mapping[str, object] | None = None
|
|
373
|
+
replace_call = "dataclasses.replace()"
|
|
374
|
+
while frame is not None:
|
|
375
|
+
module = frame.f_globals.get("__name__")
|
|
376
|
+
if module not in _CONSTRUCTION_MODULES:
|
|
377
|
+
break
|
|
378
|
+
if module == "copy":
|
|
379
|
+
replace_call = "copy.replace()"
|
|
380
|
+
code = frame.f_code.co_name
|
|
381
|
+
if (construction and module == __name__
|
|
382
|
+
and code not in ("__init__", "__post_init__")):
|
|
383
|
+
return None
|
|
384
|
+
if module == "dataclasses" and code in ("replace", "_replace"):
|
|
385
|
+
replacing = frame.f_locals
|
|
386
|
+
frame, level = frame.f_back, level + 1
|
|
387
|
+
caller = "" if frame is None else frame.f_globals.get("__name__", "")
|
|
388
|
+
if caller == "nameparser" or caller.startswith("nameparser."):
|
|
389
|
+
return None
|
|
390
|
+
return level, replacing, replace_call
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _surnames_code(op: str, words: frozenset[str]) -> str:
|
|
394
|
+
"""Code doing add() or remove()'s surnames edit the 3.0 way, which
|
|
395
|
+
runs quietly on 2.8.1 too; prose for a long list, whose code would
|
|
396
|
+
swamp the message."""
|
|
397
|
+
if len(words) > 5:
|
|
398
|
+
return (f"join a Lexicon holding those {len(words)} surnames to it "
|
|
399
|
+
f"with |" if op == "add" else
|
|
400
|
+
f"subtract those {len(words)} surnames from lexicon.surnames "
|
|
401
|
+
f"in dataclasses.replace()")
|
|
402
|
+
listed = "{" + ", ".join(map(repr, sorted(words))) + "}"
|
|
403
|
+
return (f"write lexicon | Lexicon(surnames=frozenset({listed}))"
|
|
404
|
+
if op == "add" else
|
|
405
|
+
f"write dataclasses.replace(lexicon, "
|
|
406
|
+
f"surnames=lexicon.surnames - {listed})")
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _warn_set_fields(level: int, spelling: str, fields: Iterable[str],
|
|
410
|
+
surnames: str = "") -> None:
|
|
411
|
+
"""Warn at `level` (from _outside_caller) that `spelling`, a call,
|
|
412
|
+
writes `fields`, naming each and the guide row that replaces it.
|
|
413
|
+
surnames gets a sentence of its own, ending on `surnames`, the code
|
|
414
|
+
for the edit (_surnames_code): 3.0 keeps the field, and only add()
|
|
415
|
+
and remove() stop taking it."""
|
|
416
|
+
fields = list(fields)
|
|
417
|
+
internal = [name for name in fields if name != "surnames"]
|
|
418
|
+
parts = []
|
|
419
|
+
if internal:
|
|
420
|
+
parts.append(
|
|
421
|
+
f"{spelling} writes {', '.join(internal)}, which 3.0 makes "
|
|
422
|
+
f"internal and refuses with a TypeError naming the readings "
|
|
423
|
+
f"that replace it for the words given; the guide's \"Lexicon "
|
|
424
|
+
f"fields → readings\" table has a row for each field")
|
|
425
|
+
if "surnames" in fields:
|
|
426
|
+
parts.append(
|
|
427
|
+
f"3.0 keeps surnames a field, but {spelling} no longer takes "
|
|
428
|
+
f"it: {surnames}, which runs on 2.8.1 too")
|
|
429
|
+
warnings.warn(
|
|
430
|
+
f"Lexicon's set fields are deprecated (#754): {'; and '.join(parts)}. "
|
|
431
|
+
f"See {_FIELDS_GUIDE}",
|
|
432
|
+
DeprecationWarning, stacklevel=level)
|
|
433
|
+
|
|
434
|
+
|
|
340
435
|
def _normset(
|
|
341
436
|
entries: Iterable[str], field_name: str, warn: bool = True,
|
|
342
437
|
) -> frozenset[str]:
|
|
@@ -590,7 +685,15 @@ class Lexicon:
|
|
|
590
685
|
matched against two adjacent title words (``"chief justice"``).
|
|
591
686
|
Field docs below show examples, not full
|
|
592
687
|
contents; inspect any field's shipped vocabulary directly, e.g.
|
|
593
|
-
``Lexicon.default().conjunctions``.
|
|
688
|
+
``Lexicon.default().conjunctions``.
|
|
689
|
+
|
|
690
|
+
Deprecated since 2.8.1: 3.0 makes the set fields internal and
|
|
691
|
+
configures vocabulary by reading, so writing one here, through
|
|
692
|
+
``add``, ``remove`` or ``dataclasses.replace`` warns. ``surnames``
|
|
693
|
+
and ``capitalization_exceptions`` stay fields in 3.0, so passing them
|
|
694
|
+
here or to ``dataclasses.replace`` is quiet, but ``add`` and
|
|
695
|
+
``remove`` with ``surnames`` warn, since 3.0's take readings only;
|
|
696
|
+
see the migration guide's "Deprecated in 2.8.1"."""
|
|
594
697
|
|
|
595
698
|
#: Pre-nominal titles ("dr", "sir", "capt", ...). Full default
|
|
596
699
|
#: list: :data:`~nameparser.config.titles.TITLES`.
|
|
@@ -804,6 +907,41 @@ class Lexicon:
|
|
|
804
907
|
default_factory=lambda: MappingProxyType({}))
|
|
805
908
|
|
|
806
909
|
def __post_init__(self) -> None:
|
|
910
|
+
self._validate()
|
|
911
|
+
# 2.8.1 (#754): a caller's construction or dataclasses.replace()
|
|
912
|
+
# with a set field 3.0 refuses. Not from __setstate__, which runs
|
|
913
|
+
# _validate alone: loading a pickle writes no field.
|
|
914
|
+
where = _outside_caller(construction=True)
|
|
915
|
+
if where is not None:
|
|
916
|
+
self._warn_constructed(*where)
|
|
917
|
+
|
|
918
|
+
def _warn_constructed(self, level: int,
|
|
919
|
+
replacing: Mapping[str, object] | None,
|
|
920
|
+
replace_call: str) -> None:
|
|
921
|
+
# surnames is never named here: 3.0 accepts it in Lexicon() and
|
|
922
|
+
# dataclasses.replace(), as it does capitalization_exceptions
|
|
923
|
+
internal = [name for name in _VOCAB_FIELDS if name != "surnames"]
|
|
924
|
+
if replacing is None:
|
|
925
|
+
# a field left at its default is empty, so a non-empty one
|
|
926
|
+
# was passed
|
|
927
|
+
written = [name for name in internal if getattr(self, name)]
|
|
928
|
+
spelling = "Lexicon()"
|
|
929
|
+
else:
|
|
930
|
+
# dataclasses.replace() names the instance `obj`, and 3.13's
|
|
931
|
+
# dataclasses._replace (behind copy.replace) `self`; a field
|
|
932
|
+
# not passed is filled in with the instance's own value
|
|
933
|
+
old = replacing.get("obj", replacing.get("self"))
|
|
934
|
+
changes = replacing.get("changes")
|
|
935
|
+
if not isinstance(old, Lexicon) or not isinstance(changes, Mapping):
|
|
936
|
+
return
|
|
937
|
+
written = [name for name in internal if name in changes
|
|
938
|
+
and changes[name] is not getattr(old, name)]
|
|
939
|
+
spelling = replace_call
|
|
940
|
+
if written:
|
|
941
|
+
# one more frame than __post_init__ itself
|
|
942
|
+
_warn_set_fields(level + 1, spelling, written)
|
|
943
|
+
|
|
944
|
+
def _validate(self) -> None:
|
|
807
945
|
for name in _VOCAB_FIELDS:
|
|
808
946
|
object.__setattr__(self, name, _normset(getattr(self, name), name))
|
|
809
947
|
canonical = _normpairs(self.capitalization_exceptions)
|
|
@@ -949,7 +1087,7 @@ class Lexicon:
|
|
|
949
1087
|
# without changing its name, so an old pickle would otherwise
|
|
950
1088
|
# load a semantically inverted lexicon in silence. Rebuilds
|
|
951
1089
|
# _cap_map for free, which this used to do by hand.
|
|
952
|
-
self.
|
|
1090
|
+
self._validate()
|
|
953
1091
|
# __post_init__ also normalizes, and quietly accepting a
|
|
954
1092
|
# rewritten value would make this a place where caller data
|
|
955
1093
|
# changes without a word. A pickle this library wrote is always
|
|
@@ -1038,28 +1176,53 @@ class Lexicon:
|
|
|
1038
1176
|
return dataclasses.replace(self, **updates) # type: ignore[arg-type]
|
|
1039
1177
|
|
|
1040
1178
|
def add(self, **entries: Iterable[str]) -> Lexicon:
|
|
1041
|
-
|
|
1179
|
+
"""A copy with each named field's words added. Deprecated since
|
|
1180
|
+
2.8.1: 3.0's ``add`` takes readings, not fields."""
|
|
1181
|
+
return self._edit_warning("add", entries)
|
|
1042
1182
|
|
|
1043
1183
|
def remove(self, **entries: Iterable[str]) -> Lexicon:
|
|
1044
|
-
|
|
1184
|
+
"""A copy with each named field's words removed. Deprecated
|
|
1185
|
+
since 2.8.1: 3.0's ``remove`` takes readings, not fields."""
|
|
1186
|
+
return self._edit_warning("remove", entries)
|
|
1187
|
+
|
|
1188
|
+
def _edit_warning(self, op: str,
|
|
1189
|
+
entries: Mapping[str, Iterable[str]]) -> Lexicon:
|
|
1190
|
+
# 2.8.1 (#754): 3.0's add() and remove() take readings, and
|
|
1191
|
+
# refuse every field keyword, surnames included. The warning
|
|
1192
|
+
# follows a successful edit, so a bad value raises its own
|
|
1193
|
+
# error first. An iterator of surnames is read once here, so the
|
|
1194
|
+
# warning can spell the edit and _edit still sees the words.
|
|
1195
|
+
named = entries.get("surnames")
|
|
1196
|
+
if isinstance(named, Iterator):
|
|
1197
|
+
entries = {**entries, "surnames": tuple(named)}
|
|
1198
|
+
edited = self._edit(op, entries)
|
|
1199
|
+
if entries:
|
|
1200
|
+
where = _outside_caller(construction=False)
|
|
1201
|
+
if where is not None:
|
|
1202
|
+
code = ("" if "surnames" not in entries else _surnames_code(
|
|
1203
|
+
op, _normset(entries["surnames"], "surnames", warn=False)))
|
|
1204
|
+
_warn_set_fields(where[0], f"{op}()", entries, code)
|
|
1205
|
+
return edited
|
|
1045
1206
|
|
|
1046
1207
|
|
|
1047
1208
|
@functools.cache
|
|
1048
1209
|
def _default_lexicon() -> Lexicon:
|
|
1049
|
-
#
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
from nameparser.config.
|
|
1053
|
-
from nameparser.config.
|
|
1210
|
+
# The compiled vocabulary, read from _compiled rather than the public
|
|
1211
|
+
# nameparser.config modules, whose constants warn at a caller's read
|
|
1212
|
+
# since 2.8.1 (#1007); surnames.py is not deprecated.
|
|
1213
|
+
from nameparser.config._compiled import BOUND_GIVEN_NAMES
|
|
1214
|
+
from nameparser.config._compiled import GIVEN_NAME_ABBREVIATIONS
|
|
1215
|
+
from nameparser.config._compiled import CAPITALIZATION_EXCEPTIONS
|
|
1216
|
+
from nameparser.config._compiled import (
|
|
1054
1217
|
CONJUNCTIONS, CONJUNCTIONS_AMBIGUOUS)
|
|
1055
|
-
from nameparser.config.
|
|
1056
|
-
from nameparser.config.
|
|
1057
|
-
from nameparser.config.
|
|
1218
|
+
from nameparser.config._compiled import MAIDEN_MARKERS
|
|
1219
|
+
from nameparser.config._compiled import NON_GIVEN_NAME_PARTICLES, PARTICLES
|
|
1220
|
+
from nameparser.config._compiled import (
|
|
1058
1221
|
AGNOMENS, GLUED_HONORIFICS, SUFFIX_ACRONYMS, SUFFIX_ACRONYMS_AMBIGUOUS,
|
|
1059
1222
|
SUFFIX_WORDS, SUFFIX_WORDS_AMBIGUOUS,
|
|
1060
1223
|
)
|
|
1061
1224
|
from nameparser.config.surnames import KOREAN_SURNAMES
|
|
1062
|
-
from nameparser.config.
|
|
1225
|
+
from nameparser.config._compiled import (
|
|
1063
1226
|
AFTER_GIVEN_TITLES, GIVEN_NAME_TITLES, TITLE_MODIFIERS, TITLE_PHRASES,
|
|
1064
1227
|
TITLE_STYLES, TITLES, TITLES_AMBIGUOUS)
|
|
1065
1228
|
|
|
@@ -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,
|
|
8
|
-
#: true here while 2.8.
|
|
7
|
+
#: cannot carry the dev marker, so `VERSION >= (2, 8, 1)` is already
|
|
8
|
+
#: true here while 2.8.1 is unreleased. Compare `__version__` instead
|
|
9
9
|
#: where that distinction matters.
|
|
10
|
-
VERSION = (2, 8,
|
|
10
|
+
VERSION = (2, 8, 1)
|
|
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.8.
|
|
17
|
-
#: from
|
|
16
|
+
#: 2.8.1.dev0, which sorts above 2.8.0 and BELOW 2.8.1, so an install
|
|
17
|
+
#: from the 2.x branch can never masquerade as the release it precedes.
|
|
18
18
|
PRE_RELEASE = ""
|
|
19
19
|
__version__ = ".".join(map(str, VERSION)) + PRE_RELEASE
|
|
@@ -7,11 +7,13 @@ Two unrelated things share this package. The names re-exported below --
|
|
|
7
7
|
``RegexTupleManager`` -- are v1 compatibility surface, and go with the
|
|
8
8
|
rest of the facade in 3.0. The vocabulary data modules beside them
|
|
9
9
|
(:mod:`~nameparser.config.titles`, :mod:`~nameparser.config.particles`,
|
|
10
|
-
...)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
...) hold the word lists the 2.x :class:`~nameparser.Lexicon` is built
|
|
11
|
+
from, named for its fields since 2.2 (#293); since 2.6 each (all but
|
|
12
|
+
``surnames.py``) re-exports sets compiled from the per-word TOML files
|
|
13
|
+
in ``nameparser/vocab/`` (#737). 3.0 removes them too, all but
|
|
14
|
+
``surnames``, and since 2.8.1 reading one of their constants warns,
|
|
15
|
+
naming what 3.0 offers in its place (#1007), as reading
|
|
16
|
+
``nameparser.config.regexes`` does (#1008).
|
|
15
17
|
|
|
16
18
|
``RegexTupleManager`` is served from the shim purely for pickle
|
|
17
19
|
compatibility (through ``__getattr__`` since 2.8, so loading such a blob
|
|
@@ -22,10 +24,11 @@ resolves and reconstructs that nested object before
|
|
|
22
24
|
blob raises ``AttributeError`` looking up the class, not a clean
|
|
23
25
|
compatibility failure.
|
|
24
26
|
"""
|
|
25
|
-
# Maintainer note, deliberately outside the docstring: the
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
27
|
+
# Maintainer note, deliberately outside the docstring: 3.0 removes the
|
|
28
|
+
# five shim names below and the vocabulary DATA modules but surnames
|
|
29
|
+
# (#1007, #1008, superseding decisions/3-0-reevaluations's 2026-10-28
|
|
30
|
+
# entry, which kept the modules); the modules warn per constant since
|
|
31
|
+
# 2.8.1. Constants and CONSTANTS are imported eagerly -- Constants
|
|
29
32
|
# warns at construction, the CONSTANTS singleton when mutated -- while
|
|
30
33
|
# the three managers resolve through __getattr__ so that each caller's
|
|
31
34
|
# read warns, at the caller's line, and nameparser's own reads (from
|
|
@@ -46,10 +46,55 @@ _MESSAGE = (
|
|
|
46
46
|
"use {new_module}.{new} instead."
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
#: 3.0's migration guide, which every 2.8.1 removal message points at:
|
|
50
|
+
#: Read the Docs' "latest" builds master, the 3.0 cycle.
|
|
51
|
+
MIGRATION_GUIDE = "https://nameparser.readthedocs.io/en/latest/migrate.html"
|
|
52
|
+
|
|
53
|
+
# 2.8.1: the live names of a module 3.0 deletes (#1007, #1008). Every
|
|
54
|
+
# message opens "nameparser.config.", names the removal and closes on
|
|
55
|
+
# the guide; pyproject's filterwarnings ignores the family by message,
|
|
56
|
+
# and tests/v2/test_removals_2_8_1.py asserts each one.
|
|
57
|
+
_REMOVED_MESSAGE = (
|
|
58
|
+
"{module}.{name} is deprecated and will be removed in 3.0 ({issue}); "
|
|
59
|
+
"{replacement}. See {guide}"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def words_of(args: str, which: str = "") -> str:
|
|
64
|
+
"""The replacement clause for a vocabulary constant: the 3.0 call
|
|
65
|
+
listing a kind's words (``Lexicon.words``, #1007). Without `which`
|
|
66
|
+
the call lists exactly the set's words over the default vocabulary
|
|
67
|
+
(checked against master, 2026-11-02); with it the call lists more or
|
|
68
|
+
other words, and `which` says what the set held instead."""
|
|
69
|
+
call = f"in 3.0, Lexicon.default().words({args})"
|
|
70
|
+
if not which:
|
|
71
|
+
return f"{call} lists the same words"
|
|
72
|
+
return (f"{call} lists every word of that kind, where this set held "
|
|
73
|
+
f"{which}; Lexicon.default().readings_of(word) says what one "
|
|
74
|
+
f"word is")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def removal_message(module: str, name: str) -> str | None:
|
|
78
|
+
"""The 2.8.1 removal message for ``module.name``, or ``None`` where
|
|
79
|
+
3.0 keeps the name. Reads the module's hook, so it warns nothing."""
|
|
80
|
+
hook = vars(importlib.import_module(module)).get("__getattr__")
|
|
81
|
+
removed: Mapping[str, str] = getattr(hook, "removed_messages", {})
|
|
82
|
+
return removed.get(name)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _quiet_value(module: str, name: str) -> Any: # noqa: ANN401
|
|
86
|
+
loaded = importlib.import_module(module)
|
|
87
|
+
hook = vars(loaded).get("__getattr__")
|
|
88
|
+
held: Mapping[str, Any] = getattr(hook, "removed_values", {})
|
|
89
|
+
return held[name] if name in held else getattr(loaded, name)
|
|
90
|
+
|
|
49
91
|
|
|
50
92
|
def alias_getattr(
|
|
51
93
|
module: str,
|
|
52
94
|
aliases: Mapping[str, tuple[str, str]],
|
|
95
|
+
removed: Mapping[str, str] | None = None,
|
|
96
|
+
namespace: dict[str, Any] | None = None,
|
|
97
|
+
issue: str = "#1007",
|
|
53
98
|
) -> tuple[Callable[[str], Any], Callable[[], list[str]]]:
|
|
54
99
|
"""Build the ``__getattr__``/``__dir__`` pair for a module carrying
|
|
55
100
|
deprecated vocabulary names.
|
|
@@ -84,9 +129,33 @@ def alias_getattr(
|
|
|
84
129
|
module: mypy reads no module ``__getattr__`` for the alias-bearing
|
|
85
130
|
modules any more, and does not analyze the ``else`` branch it is
|
|
86
131
|
assigned in. It stays ``Any`` as what ``getattr`` itself returns.
|
|
132
|
+
|
|
133
|
+
``removed`` (2.8.1) maps each LIVE name 3.0 deletes to the clause
|
|
134
|
+
naming its 3.0 replacement, and ``namespace`` is the module's
|
|
135
|
+
``globals()``: each such name is popped out of it into the hook, so
|
|
136
|
+
the module keeps its assignment statement -- which is where autodoc
|
|
137
|
+
finds the constant's documentation -- while every read reaches
|
|
138
|
+
``__getattr__`` and warns at the reader's line. The library reads
|
|
139
|
+
these values from ``nameparser.config._compiled`` (and regexes.py's
|
|
140
|
+
``_REGEXES``), never through here, so only a caller's read warns.
|
|
87
141
|
"""
|
|
142
|
+
removed = dict(removed or {})
|
|
143
|
+
values: dict[str, Any] = {}
|
|
144
|
+
if removed:
|
|
145
|
+
if namespace is None:
|
|
146
|
+
raise TypeError("alias_getattr: removed names need namespace=")
|
|
147
|
+
values = {name: namespace.pop(name) for name in removed}
|
|
148
|
+
messages = {
|
|
149
|
+
name: _REMOVED_MESSAGE.format(
|
|
150
|
+
module=module, name=name, issue=issue, replacement=replacement,
|
|
151
|
+
guide=MIGRATION_GUIDE)
|
|
152
|
+
for name, replacement in removed.items()}
|
|
88
153
|
|
|
89
154
|
def __getattr__(name: str) -> Any: # noqa: ANN401
|
|
155
|
+
if name in values:
|
|
156
|
+
# 2: the reading frame, as for an alias below
|
|
157
|
+
warnings.warn(messages[name], DeprecationWarning, stacklevel=2)
|
|
158
|
+
return values[name]
|
|
90
159
|
target = aliases.get(name)
|
|
91
160
|
if target is None:
|
|
92
161
|
raise AttributeError(f"module {module!r} has no attribute {name!r}")
|
|
@@ -94,11 +163,18 @@ def alias_getattr(
|
|
|
94
163
|
# resolved BEFORE warning, so a mistyped alias target fails as
|
|
95
164
|
# a ModuleNotFoundError or an AttributeError from here rather
|
|
96
165
|
# than first advising the reader to move to a path that does
|
|
97
|
-
# not exist.
|
|
98
|
-
|
|
166
|
+
# not exist. Quietly: a target 3.0 removes too is held by its
|
|
167
|
+
# module's hook, whose own warning would name this file.
|
|
168
|
+
value = _quiet_value(new_module, new_name)
|
|
169
|
+
message = _MESSAGE.format(
|
|
170
|
+
module=module, old=name, new_module=new_module, new=new_name)
|
|
171
|
+
# one warning saying so, rather than advice to move to a name
|
|
172
|
+
# that warns in its turn
|
|
173
|
+
also = removal_message(new_module, new_name)
|
|
174
|
+
if also is not None:
|
|
175
|
+
message += " That name is removed in 3.0 too: " + also
|
|
99
176
|
warnings.warn(
|
|
100
|
-
|
|
101
|
-
module=module, old=name, new_module=new_module, new=new_name),
|
|
177
|
+
message,
|
|
102
178
|
DeprecationWarning,
|
|
103
179
|
# 2: the frame that touched the name -- for the
|
|
104
180
|
# `from nameparser.config.prefixes import ...` form, the
|
|
@@ -126,7 +202,7 @@ def alias_getattr(
|
|
|
126
202
|
# are still nameable, so they are what is left to list (#356).
|
|
127
203
|
live = sys.modules.get(module)
|
|
128
204
|
names = set(vars(live)) if live is not None else set()
|
|
129
|
-
return sorted(names | set(aliases))
|
|
205
|
+
return sorted(names | set(aliases) | set(values))
|
|
130
206
|
|
|
131
207
|
# The table itself, reachable without tripping a warning. __all__ is
|
|
132
208
|
# hand-written per module (it must stay in SOURCE order for autodoc,
|
|
@@ -137,5 +213,8 @@ def alias_getattr(
|
|
|
137
213
|
# and no AttributeError. test_config_aliases
|
|
138
214
|
# ::test_every_alias_table_row_reaches_star_import cross-checks them.
|
|
139
215
|
__getattr__.deprecated_aliases = dict(aliases) # type: ignore[attr-defined]
|
|
216
|
+
# the 2.8.1 removals, read by removal_message and _quiet_value
|
|
217
|
+
__getattr__.removed_messages = messages # type: ignore[attr-defined]
|
|
218
|
+
__getattr__.removed_values = values # type: ignore[attr-defined]
|
|
140
219
|
|
|
141
220
|
return __getattr__, __dir__
|
|
@@ -25,3 +25,18 @@ BOUND_GIVEN_NAMES: frozenset[str] = _compiled.BOUND_GIVEN_NAMES
|
|
|
25
25
|
# the constant, is bound by a star import as though it were vocabulary
|
|
26
26
|
# (#356).
|
|
27
27
|
__all__ = ["BOUND_GIVEN_NAMES"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# 2.8.1: 3.0 deletes this module (#1007), so each constant is served by
|
|
31
|
+
# __getattr__ and warns at the line that reads it, naming what 3.0
|
|
32
|
+
# offers in its place (alias_getattr's docstring says how the
|
|
33
|
+
# assignment above stays documented). The library reads _compiled, never
|
|
34
|
+
# this module. Hidden from mypy as alias_getattr explains; goes in 3.0.
|
|
35
|
+
from typing import TYPE_CHECKING # noqa: E402
|
|
36
|
+
|
|
37
|
+
from nameparser.config._deprecated import alias_getattr, words_of # noqa: E402
|
|
38
|
+
|
|
39
|
+
if not TYPE_CHECKING:
|
|
40
|
+
__getattr__, __dir__ = alias_getattr(__name__, {}, removed={
|
|
41
|
+
"BOUND_GIVEN_NAMES": words_of('kind="bound_given"'),
|
|
42
|
+
}, namespace=globals())
|
|
@@ -44,3 +44,23 @@ its own. The map also carries the Irish patronymic particles ``ó``,
|
|
|
44
44
|
(``de la Vega``), Irish writes these capitalized (``Liam Ó Murchú``),
|
|
45
45
|
and a mask outranks the particle lowercase (rules/R4).
|
|
46
46
|
"""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# 2.8.1: 3.0 deletes this module (#1007), so each constant is served by
|
|
50
|
+
# __getattr__ and warns at the line that reads it, naming what 3.0
|
|
51
|
+
# offers in its place (alias_getattr's docstring says how the
|
|
52
|
+
# assignment above stays documented). The library reads _compiled, never
|
|
53
|
+
# this module. Hidden from mypy as alias_getattr explains; goes in 3.0.
|
|
54
|
+
from typing import TYPE_CHECKING # noqa: E402
|
|
55
|
+
|
|
56
|
+
from nameparser.config._deprecated import alias_getattr # noqa: E402
|
|
57
|
+
|
|
58
|
+
if not TYPE_CHECKING:
|
|
59
|
+
__getattr__, __dir__ = alias_getattr(__name__, {}, removed={
|
|
60
|
+
"CAPITALIZATION_EXCEPTIONS": "in 3.0, read Lexicon.default().capitalization_exceptions, which stays a field",
|
|
61
|
+
}, namespace=globals())
|
|
62
|
+
|
|
63
|
+
# Star imports read __all__ and never the module __getattr__ -- see the
|
|
64
|
+
# note in prefixes.py -- so without it a star import would bind none
|
|
65
|
+
# of the names served above, silently.
|
|
66
|
+
__all__ = ["CAPITALIZATION_EXCEPTIONS"]
|
|
@@ -24,3 +24,23 @@ Single-letter entries of :data:`CONJUNCTIONS` that read as an initial,
|
|
|
24
24
|
not a connective, in a name written wholly in one case.
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
+
|
|
28
|
+
# 2.8.1: 3.0 deletes this module (#1007), so each constant is served by
|
|
29
|
+
# __getattr__ and warns at the line that reads it, naming what 3.0
|
|
30
|
+
# offers in its place (alias_getattr's docstring says how the
|
|
31
|
+
# assignment above stays documented). The library reads _compiled, never
|
|
32
|
+
# this module. Hidden from mypy as alias_getattr explains; goes in 3.0.
|
|
33
|
+
from typing import TYPE_CHECKING # noqa: E402
|
|
34
|
+
|
|
35
|
+
from nameparser.config._deprecated import alias_getattr, words_of # noqa: E402
|
|
36
|
+
|
|
37
|
+
if not TYPE_CHECKING:
|
|
38
|
+
__getattr__, __dir__ = alias_getattr(__name__, {}, removed={
|
|
39
|
+
"CONJUNCTIONS": words_of('kind="conjunction"'),
|
|
40
|
+
"CONJUNCTIONS_AMBIGUOUS": words_of('kind="conjunction", may_be_initial=True'),
|
|
41
|
+
}, namespace=globals())
|
|
42
|
+
|
|
43
|
+
# Star imports read __all__ and never the module __getattr__ -- see the
|
|
44
|
+
# note in prefixes.py -- so without it a star import would bind none
|
|
45
|
+
# of the names served above, silently.
|
|
46
|
+
__all__ = ["CONJUNCTIONS", "CONJUNCTIONS_AMBIGUOUS"]
|
|
@@ -16,3 +16,18 @@ GIVEN_NAME_ABBREVIATIONS: frozenset[str] = _compiled.GIVEN_NAME_ABBREVIATIONS
|
|
|
16
16
|
# Star imports read __all__ and never the module __getattr__ -- see the
|
|
17
17
|
# note in prefixes.py.
|
|
18
18
|
__all__ = ["GIVEN_NAME_ABBREVIATIONS"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 2.8.1: 3.0 deletes this module (#1007), so each constant is served by
|
|
22
|
+
# __getattr__ and warns at the line that reads it, naming what 3.0
|
|
23
|
+
# offers in its place (alias_getattr's docstring says how the
|
|
24
|
+
# assignment above stays documented). The library reads _compiled, never
|
|
25
|
+
# this module. Hidden from mypy as alias_getattr explains; goes in 3.0.
|
|
26
|
+
from typing import TYPE_CHECKING # noqa: E402
|
|
27
|
+
|
|
28
|
+
from nameparser.config._deprecated import alias_getattr, words_of # noqa: E402
|
|
29
|
+
|
|
30
|
+
if not TYPE_CHECKING:
|
|
31
|
+
__getattr__, __dir__ = alias_getattr(__name__, {}, removed={
|
|
32
|
+
"GIVEN_NAME_ABBREVIATIONS": words_of('kind="given"', "the given names whose reading carries same_as"),
|
|
33
|
+
}, namespace=globals())
|
|
@@ -92,3 +92,23 @@ decisions/vocabulary-exclusions, Excluded (MAIDEN_MARKERS). The full participle
|
|
|
92
92
|
rozená stays, being unambiguous; a caller who needs the abbreviation
|
|
93
93
|
adds it to their own Lexicon.
|
|
94
94
|
"""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# 2.8.1: 3.0 deletes this module (#1007), so each constant is served by
|
|
98
|
+
# __getattr__ and warns at the line that reads it, naming what 3.0
|
|
99
|
+
# offers in its place (alias_getattr's docstring says how the
|
|
100
|
+
# assignment above stays documented). The library reads _compiled, never
|
|
101
|
+
# this module. Hidden from mypy as alias_getattr explains; goes in 3.0.
|
|
102
|
+
from typing import TYPE_CHECKING # noqa: E402
|
|
103
|
+
|
|
104
|
+
from nameparser.config._deprecated import alias_getattr, words_of # noqa: E402
|
|
105
|
+
|
|
106
|
+
if not TYPE_CHECKING:
|
|
107
|
+
__getattr__, __dir__ = alias_getattr(__name__, {}, removed={
|
|
108
|
+
"MAIDEN_MARKERS": words_of('kind="birth_marker"'),
|
|
109
|
+
}, namespace=globals())
|
|
110
|
+
|
|
111
|
+
# Star imports read __all__ and never the module __getattr__ -- see the
|
|
112
|
+
# note in prefixes.py -- so without it a star import would bind none
|
|
113
|
+
# of the names served above, silently.
|
|
114
|
+
__all__ = ["MAIDEN_MARKERS"]
|