Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
151 lines (138 loc) · 5.22 KB
/
Copy pathpyproject.toml
File metadata and controls
151 lines (138 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
[project]
name = "nameparser"
description = "Parse human names into title, given, middle, family, suffix, nickname and maiden name. Typed, zero-dependency, CJK-aware."
readme = "README.rst"
requires-python = ">=3.11"
license = "LGPL-2.1-or-later"
license-files = ["LICENSE", "AUTHORS"]
authors = [{name = "Derek Gulbranson", email = "derek73@gmail.com"}]
dynamic = ["version"]
keywords = ["names", "parser", "name parsing", "human names", "nlp", "data cleaning", "record linkage", "cjk", "i18n"]
classifiers = [
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
"Development Status :: 5 - Production/Stable",
"Natural Language :: English",
"Topic :: Scientific/Engineering :: Information Analysis",
"Topic :: Sociology :: Genealogy",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Text Processing :: Linguistic",
"Typing :: Typed",
]
dependencies = []
[project.urls]
Documentation = "https://nameparser.readthedocs.io/en/latest/"
Changelog = "https://nameparser.readthedocs.io/en/latest/release_log.html"
Source = "https://github.com/derek73/python-nameparser"
Issues = "https://github.com/derek73/python-nameparser/issues"
[project.optional-dependencies]
# Japanese kanji-name segmentation (#272), wrapped by
# locales.ja_segmenter(). Optional and never bundled: the core stays
# zero-dependency. 0.4 is the floor its BasicNameDivider/DividedName
# API dates from.
ja = ["namedivider-python>=0.4"]
[build-system]
requires = ["setuptools (>=82.0.1)"]
build-backend = "setuptools.build_meta"
[tool.setuptools.dynamic]
version = {attr = "nameparser._version.__version__"}
[tool.setuptools.package-data]
# The per-word vocabulary ships as data for tools and later phases to
# read; the parser itself reads the compiled module, never the TOML.
nameparser = ["py.typed", "vocab/*.toml"]
[dependency-groups]
dev = [
"pytest (>=8)",
"dill (>=0.2.5)",
"sphinx (>=8)",
"furo",
"mypy (>=2.1)",
"ruff (>=0.15)",
"pytest-timeout>=2.4.0",
"pytest-cov>=6",
"pytest-xdist>=3.6",
"hypothesis",
]
[tool.mypy]
packages = ["nameparser", "tests"]
[[tool.mypy.overrides]]
module = [
"dill.*",
# optional extras, unstubbed and absent from the dev environment:
# the ja pack imports namedivider lazily, inside the factory
"namedivider.*",
]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = [
"nameparser._types",
"nameparser._lexicon",
"nameparser._policy",
"nameparser._render",
"nameparser._locale",
"nameparser._pipeline.*",
"nameparser._parser",
]
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_any_generics = true
warn_return_any = true
strict_equality = true
# strict_equality for the WHOLE package rather than the core modules
# above. A comparison between non-overlapping types is always False and
# is always a bug, wherever it is written, and the block above does not
# name the package's __init__, _version, config.*, locales.* or
# __main__.
# Measured 2026-09-18: clean over nameparser/ as it then stood (the
# 2.x facade layer included), so it cost nothing and catches the next
# one. tests/ keep the default,
# where the check has real hits (a test comparing an off-contract value
# to a real one is doing its job).
[[tool.mypy.overrides]]
module = ["nameparser", "nameparser.*"]
strict_equality = true
[[tool.mypy.overrides]]
module = ["tests.v2.*"]
check_untyped_defs = true
[tool.pytest.ini_options]
testpaths = ["tests", "nameparser"]
# Parallel by default: the suite is CPU-bound and took 110s serial
# against 35s on 8 workers (measured 2026-10-23). worksteal because the
# property grids are a few long tests among 23,000 short ones, and
# fixed chunks left one worker running them alone. -n0 runs serially.
addopts = "--doctest-modules -n auto --dist worksteal"
markers = [
# deselected in a parallel run by tests/conftest.py; run them with
# `uv run pytest -n0 -m serial`
"serial: measures the clock, so other workers' load can fail it",
]
python_classes = ["*Tests", "*TestCase"]
# Fail if an xfail-marked test unexpectedly passes, so a fixed/regressed
# expectation surfaces instead of silently turning into an xpass.
xfail_strict = true
# Unexpected warnings are failures: warnings are load-bearing API (the
# multi-word-entry UserWarning, the construction warnings), and without
# this a warning regression is invisible to the suite -- a real bug
# (eight spurious warnings on restoring a 1.4 Constants pickle) shipped
# to review this way. Tests that EXPECT a warning assert it with
# pytest.warns; targeted ignores below need a comment justifying each.
filterwarnings = [
"error",
]
[tool.ruff.lint]
extend-select = [
"ANN", # flake8-annotations
"UP", # pyupgrade
"B033", # duplicate set items: a frozenset drops them silently, so a bulk vocabulary import can carry them unseen
]
ignore = [
"E74", # ambiguous-{variable,class,function}-name (I have trouble believing that these are real rules)
]