nameparser 1.2.1__tar.gz → 1.3.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-1.2.1/nameparser.egg-info → nameparser-1.3.1}/PKG-INFO +63 -37
- {nameparser-1.2.1 → nameparser-1.3.1}/README.rst +62 -36
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/_version.py +1 -1
- nameparser-1.3.1/nameparser/config/__init__.py +861 -0
- nameparser-1.3.1/nameparser/config/bound_first_names.py +12 -0
- nameparser-1.3.1/nameparser/config/capitalization.py +10 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/config/conjunctions.py +2 -2
- nameparser-1.3.1/nameparser/config/prefixes.py +97 -0
- nameparser-1.3.1/nameparser/config/regexes.py +53 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/config/suffixes.py +48 -9
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/config/titles.py +55 -4
- nameparser-1.3.1/nameparser/parser.py +1595 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/util.py +1 -2
- {nameparser-1.2.1 → nameparser-1.3.1/nameparser.egg-info}/PKG-INFO +63 -37
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser.egg-info/SOURCES.txt +7 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/pyproject.toml +7 -5
- nameparser-1.3.1/tests/base.py +71 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/conftest.py +9 -21
- nameparser-1.3.1/tests/test_bound_first_names.py +154 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_brute_force.py +14 -6
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_capitalization.py +60 -0
- nameparser-1.3.1/tests/test_config_attribute_docstrings.py +79 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_conjunctions.py +73 -0
- nameparser-1.3.1/tests/test_constants.py +971 -0
- nameparser-1.3.1/tests/test_east_slavic_patronymic_order.py +194 -0
- nameparser-1.3.1/tests/test_initials.py +219 -0
- nameparser-1.3.1/tests/test_middle_name_as_last.py +122 -0
- nameparser-1.3.1/tests/test_nicknames.py +309 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_output_format.py +56 -5
- nameparser-1.3.1/tests/test_parser_util.py +39 -0
- nameparser-1.3.1/tests/test_prefixes.py +395 -0
- nameparser-1.3.1/tests/test_python_api.py +647 -0
- nameparser-1.3.1/tests/test_suffixes.py +448 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_titles.py +131 -0
- nameparser-1.3.1/tests/test_turkic_patronymic_order.py +302 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_variations.py +21 -11
- nameparser-1.2.1/nameparser/config/__init__.py +0 -288
- nameparser-1.2.1/nameparser/config/capitalization.py +0 -10
- nameparser-1.2.1/nameparser/config/prefixes.py +0 -47
- nameparser-1.2.1/nameparser/config/regexes.py +0 -28
- nameparser-1.2.1/nameparser/parser.py +0 -999
- nameparser-1.2.1/tests/base.py +0 -40
- nameparser-1.2.1/tests/test_constants.py +0 -106
- nameparser-1.2.1/tests/test_initials.py +0 -128
- nameparser-1.2.1/tests/test_nicknames.py +0 -176
- nameparser-1.2.1/tests/test_prefixes.py +0 -118
- nameparser-1.2.1/tests/test_python_api.py +0 -226
- nameparser-1.2.1/tests/test_suffixes.py +0 -138
- {nameparser-1.2.1 → nameparser-1.3.1}/AUTHORS +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/LICENSE +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/MANIFEST.in +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/__init__.py +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/__main__.py +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser/py.typed +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser.egg-info/dependency_links.txt +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser.egg-info/requires.txt +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/nameparser.egg-info/top_level.txt +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/setup.cfg +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/__init__.py +0 -0
- {nameparser-1.2.1 → nameparser-1.3.1}/tests/test_first_name.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nameparser
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.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: LGPL
|
|
@@ -29,7 +29,7 @@ Dynamic: license-file
|
|
|
29
29
|
Name Parser
|
|
30
30
|
===========
|
|
31
31
|
|
|
32
|
-
|Build Status| |PyPI| |PyPI version| |Documentation|
|
|
32
|
+
|Build Status| |PyPI| |PyPI version| |Documentation| |License| |Downloads| |Codecov|
|
|
33
33
|
|
|
34
34
|
A simple Python (3.10+) module for parsing human names into their
|
|
35
35
|
individual components.
|
|
@@ -40,8 +40,12 @@ individual components.
|
|
|
40
40
|
* hn.last
|
|
41
41
|
* hn.suffix
|
|
42
42
|
* hn.nickname
|
|
43
|
+
* hn.maiden
|
|
43
44
|
* hn.surnames *(middle + last)*
|
|
45
|
+
* hn.given_names *(first + middle)*
|
|
44
46
|
* hn.initials *(first initial of each name part)*
|
|
47
|
+
* hn.last_base *(last, minus any prefixes)*
|
|
48
|
+
* hn.last_prefixes *(leading last-name particles, e.g. "van der")*
|
|
45
49
|
|
|
46
50
|
Supported Name Structures
|
|
47
51
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -53,19 +57,35 @@ are optional. Comma-separated format like "Last, First" is also supported.
|
|
|
53
57
|
2. Lastname [Suffix], Title Firstname (Nickname) Middle Middle[,] Suffix [, Suffix]
|
|
54
58
|
3. Title Firstname M Lastname [Suffix], Suffix [Suffix] [, Suffix]
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
How It Works
|
|
61
|
+
~~~~~~~~~~~~
|
|
62
|
+
|
|
63
|
+
The parser works in two layers.
|
|
64
|
+
|
|
65
|
+
A **vocabulary layer** recognizes name pieces by what they are, using
|
|
66
|
+
configurable sets of known words: titles ("Dr."), suffixes ("III", "PhD"),
|
|
67
|
+
last-name prefixes ("de la"), conjunctions ("y", "&"), and delimited
|
|
68
|
+
nicknames ("Doc"). Titles and conjunctions chain together to handle complex
|
|
69
|
+
titles like "Asst Secretary of State"; prefixes join forward so "de la Vega"
|
|
70
|
+
stays one last name. This layer doesn't care where in the string a word
|
|
71
|
+
appears — and it's the layer you customize, by adding or removing entries
|
|
72
|
+
in the sets to fit your dataset.
|
|
73
|
+
|
|
74
|
+
A **positional layer** then assigns everything the vocabulary layer didn't
|
|
75
|
+
claim, based purely on where it sits: the first unclaimed word is the first
|
|
76
|
+
name, the last one is the last name, and anything between them is a middle
|
|
77
|
+
name. There is no semantic understanding — "Dr" is a title when it comes
|
|
78
|
+
before a name and a suffix when it comes after ("pre-nominal" and
|
|
79
|
+
"post-nominal" would probably be better names) — and no attempt to correct
|
|
80
|
+
mistakes in the input.
|
|
81
|
+
|
|
82
|
+
It attempts the best guess that can be made with a simple, deterministic,
|
|
83
|
+
rule-based approach — no statistical models or machine learning; the same
|
|
84
|
+
input always parses the same way. The positional layer assumes Western name
|
|
85
|
+
order (given name first), so the main use case is English and other
|
|
86
|
+
languages that share that structure. It can also try to correct the
|
|
87
|
+
capitalization of names that are all upper- or lowercase. It's not perfect,
|
|
88
|
+
but it gets you pretty far.
|
|
69
89
|
|
|
70
90
|
Installation
|
|
71
91
|
------------
|
|
@@ -93,17 +113,18 @@ Quick Start Example
|
|
|
93
113
|
>>> name = HumanName("Dr. Juan Q. Xavier de la Vega III (Doc Vega)")
|
|
94
114
|
>>> name
|
|
95
115
|
<HumanName : [
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
116
|
+
title: 'Dr.'
|
|
117
|
+
first: 'Juan'
|
|
118
|
+
middle: 'Q. Xavier'
|
|
119
|
+
last: 'de la Vega'
|
|
120
|
+
suffix: 'III'
|
|
121
|
+
nickname: 'Doc Vega'
|
|
122
|
+
maiden: ''
|
|
102
123
|
]>
|
|
103
124
|
>>> name.last
|
|
104
125
|
'de la Vega'
|
|
105
126
|
>>> name.as_dict()
|
|
106
|
-
{'
|
|
127
|
+
{'title': 'Dr.', 'first': 'Juan', 'middle': 'Q. Xavier', 'last': 'de la Vega', 'suffix': 'III', 'nickname': 'Doc Vega', 'maiden': ''}
|
|
107
128
|
>>> str(name)
|
|
108
129
|
'Dr. Juan Q. Xavier de la Vega III (Doc Vega)'
|
|
109
130
|
>>> name.string_format = "{first} {last}"
|
|
@@ -111,32 +132,31 @@ Quick Start Example
|
|
|
111
132
|
'Juan de la Vega'
|
|
112
133
|
|
|
113
134
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
the difference between 'title' and 'suffix' is positional, not semantic. "Dr" is a title
|
|
117
|
-
when it comes before the name and a suffix when it comes after. ("Pre-nominal"
|
|
118
|
-
and "post-nominal" would probably be better names.)
|
|
135
|
+
Because the positional layer has no semantic understanding, position is
|
|
136
|
+
everything:
|
|
119
137
|
|
|
120
138
|
::
|
|
121
139
|
|
|
122
140
|
>>> name = HumanName("1 & 2, 3 4 5, Mr.")
|
|
123
141
|
>>> name
|
|
124
142
|
<HumanName : [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
title: ''
|
|
144
|
+
first: '3'
|
|
145
|
+
middle: '4 5'
|
|
146
|
+
last: '1 & 2'
|
|
147
|
+
suffix: 'Mr.'
|
|
148
|
+
nickname: ''
|
|
149
|
+
maiden: ''
|
|
131
150
|
]>
|
|
132
151
|
|
|
133
152
|
Customization
|
|
134
153
|
-------------
|
|
135
154
|
|
|
136
|
-
Your project may need some adjustment for your dataset.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
155
|
+
Your project may need some adjustment for your dataset. Most customization
|
|
156
|
+
is vocabulary — `customizing the configured pre-defined sets`_ of titles,
|
|
157
|
+
prefixes, etc. that the vocabulary layer matches against. You can also do
|
|
158
|
+
your own pre- or post-processing, or subclass the `HumanName` class for
|
|
159
|
+
deeper changes. See the `full documentation`_ for more information.
|
|
140
160
|
|
|
141
161
|
|
|
142
162
|
`Full documentation`_
|
|
@@ -172,3 +192,9 @@ https://github.com/derek73/python-nameparser
|
|
|
172
192
|
:target: http://nameparser.readthedocs.io/en/latest/?badge=latest
|
|
173
193
|
.. |PyPI version| image:: https://img.shields.io/pypi/pyversions/nameparser.svg
|
|
174
194
|
:target: https://pypi.org/project/nameparser/
|
|
195
|
+
.. |License| image:: https://img.shields.io/pypi/l/nameparser.svg
|
|
196
|
+
:target: https://pypi.org/project/nameparser/
|
|
197
|
+
.. |Downloads| image:: https://static.pepy.tech/badge/nameparser
|
|
198
|
+
:target: https://pepy.tech/project/nameparser
|
|
199
|
+
.. |Codecov| image:: https://codecov.io/gh/derek73/python-nameparser/branch/master/graph/badge.svg
|
|
200
|
+
:target: https://codecov.io/gh/derek73/python-nameparser
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Name Parser
|
|
2
2
|
===========
|
|
3
3
|
|
|
4
|
-
|Build Status| |PyPI| |PyPI version| |Documentation|
|
|
4
|
+
|Build Status| |PyPI| |PyPI version| |Documentation| |License| |Downloads| |Codecov|
|
|
5
5
|
|
|
6
6
|
A simple Python (3.10+) module for parsing human names into their
|
|
7
7
|
individual components.
|
|
@@ -12,8 +12,12 @@ individual components.
|
|
|
12
12
|
* hn.last
|
|
13
13
|
* hn.suffix
|
|
14
14
|
* hn.nickname
|
|
15
|
+
* hn.maiden
|
|
15
16
|
* hn.surnames *(middle + last)*
|
|
17
|
+
* hn.given_names *(first + middle)*
|
|
16
18
|
* hn.initials *(first initial of each name part)*
|
|
19
|
+
* hn.last_base *(last, minus any prefixes)*
|
|
20
|
+
* hn.last_prefixes *(leading last-name particles, e.g. "van der")*
|
|
17
21
|
|
|
18
22
|
Supported Name Structures
|
|
19
23
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -25,19 +29,35 @@ are optional. Comma-separated format like "Last, First" is also supported.
|
|
|
25
29
|
2. Lastname [Suffix], Title Firstname (Nickname) Middle Middle[,] Suffix [, Suffix]
|
|
26
30
|
3. Title Firstname M Lastname [Suffix], Suffix [Suffix] [, Suffix]
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
How It Works
|
|
33
|
+
~~~~~~~~~~~~
|
|
34
|
+
|
|
35
|
+
The parser works in two layers.
|
|
36
|
+
|
|
37
|
+
A **vocabulary layer** recognizes name pieces by what they are, using
|
|
38
|
+
configurable sets of known words: titles ("Dr."), suffixes ("III", "PhD"),
|
|
39
|
+
last-name prefixes ("de la"), conjunctions ("y", "&"), and delimited
|
|
40
|
+
nicknames ("Doc"). Titles and conjunctions chain together to handle complex
|
|
41
|
+
titles like "Asst Secretary of State"; prefixes join forward so "de la Vega"
|
|
42
|
+
stays one last name. This layer doesn't care where in the string a word
|
|
43
|
+
appears — and it's the layer you customize, by adding or removing entries
|
|
44
|
+
in the sets to fit your dataset.
|
|
45
|
+
|
|
46
|
+
A **positional layer** then assigns everything the vocabulary layer didn't
|
|
47
|
+
claim, based purely on where it sits: the first unclaimed word is the first
|
|
48
|
+
name, the last one is the last name, and anything between them is a middle
|
|
49
|
+
name. There is no semantic understanding — "Dr" is a title when it comes
|
|
50
|
+
before a name and a suffix when it comes after ("pre-nominal" and
|
|
51
|
+
"post-nominal" would probably be better names) — and no attempt to correct
|
|
52
|
+
mistakes in the input.
|
|
53
|
+
|
|
54
|
+
It attempts the best guess that can be made with a simple, deterministic,
|
|
55
|
+
rule-based approach — no statistical models or machine learning; the same
|
|
56
|
+
input always parses the same way. The positional layer assumes Western name
|
|
57
|
+
order (given name first), so the main use case is English and other
|
|
58
|
+
languages that share that structure. It can also try to correct the
|
|
59
|
+
capitalization of names that are all upper- or lowercase. It's not perfect,
|
|
60
|
+
but it gets you pretty far.
|
|
41
61
|
|
|
42
62
|
Installation
|
|
43
63
|
------------
|
|
@@ -65,17 +85,18 @@ Quick Start Example
|
|
|
65
85
|
>>> name = HumanName("Dr. Juan Q. Xavier de la Vega III (Doc Vega)")
|
|
66
86
|
>>> name
|
|
67
87
|
<HumanName : [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
88
|
+
title: 'Dr.'
|
|
89
|
+
first: 'Juan'
|
|
90
|
+
middle: 'Q. Xavier'
|
|
91
|
+
last: 'de la Vega'
|
|
92
|
+
suffix: 'III'
|
|
93
|
+
nickname: 'Doc Vega'
|
|
94
|
+
maiden: ''
|
|
74
95
|
]>
|
|
75
96
|
>>> name.last
|
|
76
97
|
'de la Vega'
|
|
77
98
|
>>> name.as_dict()
|
|
78
|
-
{'
|
|
99
|
+
{'title': 'Dr.', 'first': 'Juan', 'middle': 'Q. Xavier', 'last': 'de la Vega', 'suffix': 'III', 'nickname': 'Doc Vega', 'maiden': ''}
|
|
79
100
|
>>> str(name)
|
|
80
101
|
'Dr. Juan Q. Xavier de la Vega III (Doc Vega)'
|
|
81
102
|
>>> name.string_format = "{first} {last}"
|
|
@@ -83,32 +104,31 @@ Quick Start Example
|
|
|
83
104
|
'Juan de la Vega'
|
|
84
105
|
|
|
85
106
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
the difference between 'title' and 'suffix' is positional, not semantic. "Dr" is a title
|
|
89
|
-
when it comes before the name and a suffix when it comes after. ("Pre-nominal"
|
|
90
|
-
and "post-nominal" would probably be better names.)
|
|
107
|
+
Because the positional layer has no semantic understanding, position is
|
|
108
|
+
everything:
|
|
91
109
|
|
|
92
110
|
::
|
|
93
111
|
|
|
94
112
|
>>> name = HumanName("1 & 2, 3 4 5, Mr.")
|
|
95
113
|
>>> name
|
|
96
114
|
<HumanName : [
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
115
|
+
title: ''
|
|
116
|
+
first: '3'
|
|
117
|
+
middle: '4 5'
|
|
118
|
+
last: '1 & 2'
|
|
119
|
+
suffix: 'Mr.'
|
|
120
|
+
nickname: ''
|
|
121
|
+
maiden: ''
|
|
103
122
|
]>
|
|
104
123
|
|
|
105
124
|
Customization
|
|
106
125
|
-------------
|
|
107
126
|
|
|
108
|
-
Your project may need some adjustment for your dataset.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
Your project may need some adjustment for your dataset. Most customization
|
|
128
|
+
is vocabulary — `customizing the configured pre-defined sets`_ of titles,
|
|
129
|
+
prefixes, etc. that the vocabulary layer matches against. You can also do
|
|
130
|
+
your own pre- or post-processing, or subclass the `HumanName` class for
|
|
131
|
+
deeper changes. See the `full documentation`_ for more information.
|
|
112
132
|
|
|
113
133
|
|
|
114
134
|
`Full documentation`_
|
|
@@ -144,3 +164,9 @@ https://github.com/derek73/python-nameparser
|
|
|
144
164
|
:target: http://nameparser.readthedocs.io/en/latest/?badge=latest
|
|
145
165
|
.. |PyPI version| image:: https://img.shields.io/pypi/pyversions/nameparser.svg
|
|
146
166
|
:target: https://pypi.org/project/nameparser/
|
|
167
|
+
.. |License| image:: https://img.shields.io/pypi/l/nameparser.svg
|
|
168
|
+
:target: https://pypi.org/project/nameparser/
|
|
169
|
+
.. |Downloads| image:: https://static.pepy.tech/badge/nameparser
|
|
170
|
+
:target: https://pepy.tech/project/nameparser
|
|
171
|
+
.. |Codecov| image:: https://codecov.io/gh/derek73/python-nameparser/branch/master/graph/badge.svg
|
|
172
|
+
:target: https://codecov.io/gh/derek73/python-nameparser
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
VERSION = (1,
|
|
1
|
+
VERSION = (1, 3, 1)
|
|
2
2
|
__version__ = '.'.join(map(str, VERSION))
|