Skip to content

Commit 9eaf91a

Browse files
derek73claude
andcommitted
Add AGENTS.md, update docs and tooling for Python 3.10+ drop of legacy support
- Add AGENTS.md (AI assistant guidance with architecture overview) - Update .gitignore with venv, AI tool dirs (.claude, .codex, .gemini), and editor files - Update CONTRIBUTING.md: remove Travis CI / Python 2.6 references, reflect GitHub Actions and Python 3.10-3.13 - Update README.rst and docs/usage.rst: drop Python 2.6/3.2 version references Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1c78af5 commit 9eaf91a

5 files changed

Lines changed: 91 additions & 40 deletions

File tree

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ dist
1212
.idea
1313
Pipfile
1414
Pipfile.lock
15+
.tm_properties
16+
17+
# virtual environments
18+
.env/
19+
.venv/
20+
venv/
21+
env/
22+
23+
# tools
24+
.claude/
25+
.codex/
26+
.gemini/
27+
.pytest_cache/
1528

1629
# docs
1730
docs/_*

AGENTS.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Commands
6+
7+
```bash
8+
# Install dev dependencies
9+
pip install -r dev-requirements.txt
10+
11+
# Run all tests
12+
python tests.py
13+
14+
# Run a single test by class/method
15+
python -m unittest tests.HumanNamePythonTests.test_utf8
16+
17+
# Debug how a specific name string is parsed (prints HumanName repr)
18+
python tests.py "Dr. Juan Q. Xavier de la Vega III"
19+
20+
# Build docs
21+
sphinx-build -b html docs dist/docs
22+
23+
# Build package for release
24+
python setup.py sdist bdist_wheel
25+
twine upload dist/*
26+
```
27+
28+
Enable debug logging to see the parser's internal decisions:
29+
30+
```python
31+
import logging
32+
logging.getLogger('HumanName').setLevel(logging.DEBUG)
33+
```
34+
35+
## Architecture
36+
37+
The library has two layers: `nameparser/config/` (data) and `nameparser/parser.py` (logic).
38+
39+
### Configuration layer (`nameparser/config/`)
40+
41+
Each module defines a plain Python set of known name pieces:
42+
43+
- `titles.py``TITLES` (prenominals) and `FIRST_NAME_TITLES` (e.g. "Sir", which treat the following name as first, not last)
44+
- `suffixes.py``SUFFIX_ACRONYMS` (with periods, e.g. "M.D.") and `SUFFIX_NOT_ACRONYMS` (e.g. "Jr.")
45+
- `prefixes.py``PREFIXES` (lastname particles, e.g. "de", "van")
46+
- `conjunctions.py``CONJUNCTIONS` (e.g. "and", "of") used to chain multi-word titles
47+
- `capitalization.py``CAPITALIZATION_EXCEPTIONS` mapping (e.g. `{'phd': 'Ph.D.'}`)
48+
- `regexes.py` — compiled regular expressions wrapped in a `TupleManager`
49+
50+
`config/__init__.py` wraps everything into `SetManager` and `TupleManager` instances inside a `Constants` class. A module-level singleton `CONSTANTS` is shared across all `HumanName` instances by default.
51+
52+
**Two-tier config pattern**: `CONSTANTS` is global; passing `None` as the second arg to `HumanName` creates a fresh per-instance `Constants()`. After modifying per-instance config you must call `hn.parse_full_name()` again. `SetManager.add()`/`remove()` normalizes inputs to lowercase with no periods, so callers don't need to worry about case.
53+
54+
### Parser (`nameparser/parser.py`)
55+
56+
`HumanName` is the single public class. Assigning to `full_name` (or instantiating with a string) triggers `parse_full_name()`.
57+
58+
Parse flow:
59+
1. `pre_process()` — strips nicknames (parenthesis/quotes) and emoji, fixes "Ph.D." variant spellings
60+
2. Split on commas → 1 part (no comma), 2 parts (suffix-comma or lastname-comma), 3+ parts
61+
3. `parse_pieces()` — splits on spaces, detects dotted abbreviations like "Lt.Gov." and adds them to constants dynamically
62+
4. `join_on_conjunctions()` — merges pieces adjacent to conjunctions into single tokens (e.g. `['Secretary', 'of', 'State']``['Secretary of State']`); also joins prefix particles to the following lastname token
63+
5. Iterates pieces, assigning to `title_list`, `first_list`, `middle_list`, `last_list`, `suffix_list`
64+
6. `post_process()``handle_firstnames()` swaps first/last when only a title + one name; `handle_capitalization()` applies optional auto-cap
65+
66+
Each named attribute (`title`, `first`, etc.) is a `@property` that joins its corresponding `_list`. Setters call `_set_list()` which runs the value through `parse_pieces()`, so assigning `hn.last = "de la Vega"` correctly re-parses prefix tokens.
67+
68+
### Tests (`tests.py`)
69+
70+
All tests live in a single file. `HumanNameTestBase.m()` is a custom assert helper that prints the original name string on failure. Many test classes group cases by name format type. `TEST_NAMES` is a list of name strings that gets automatically permuted into comma-separated variants as a regression check. When adding a new parsing case, add it to the relevant test class and consider adding the base form to `TEST_NAMES`.

CONTRIBUTING.md

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,16 @@ Contributing
44
Development Environment Setup
55
--------------------------------
66

7-
There are some external dependencies required in order to run the
8-
tests, located in the dev-requirements.txt file.
7+
Install dev dependencies:
98

109
pip install -r dev-requirements.txt
1110

12-
If you are running Python 2.6 you will also need to `pip install unitest2`
13-
in order to run the tests.
14-
15-
Travis CI
16-
---------
17-
18-
[![Build Status](https://travis-ci.org/derek73/python-nameparser.svg?branch=master)](https://travis-ci.org/derek73/python-nameparser)
19-
20-
The GitHub project is set up with Travis CI. Tests are run
21-
automatically against new code pushes to any branch in the main
22-
repository. Test results may be viewed here:
23-
24-
https://travis-ci.org/derek73/python-nameparser
25-
2611
Running Tests
2712
---------------
2813

29-
To run the tests locally, run `python tests.py`.
30-
31-
3214
python tests.py
3315

34-
35-
You can also pass a name string to `tests.py` to see how it will be parsed.
16+
You can also pass a name string to `tests.py` to see how it will be parsed:
3617

3718
$ python tests.py "Secretary of State Hillary Rodham-Clinton"
3819
<HumanName : [
@@ -43,32 +24,19 @@ You can also pass a name string to `tests.py` to see how it will be parsed.
4324
Suffix: ''
4425
]>
4526

27+
CI runs tests against Python 3.10–3.13 via GitHub Actions on every push and pull request.
4628

4729
Writing Tests
4830
----------------
4931

50-
If you make changes, please make sure you include tests with example
51-
names that you want to be parsed correctly.
52-
53-
It's a good idea to include tests of alternate comma placement formats
54-
of the name to ensure that the 3 code paths for the 3 formats work in
55-
the same way.
32+
If you make changes, please include tests with example names that should parse correctly.
5633

57-
The tests could be MUCH better. If the spirit moves you to design or
58-
implement a much more intelligent test strategy, please know that your
59-
efforts will be welcome and appreciated.
60-
61-
Unless you add better coverage someplace else, add a few examples of
62-
your names to `TEST_NAMES`. A test attempts to try the 3 different
63-
comma variations of these names automatically and make sure things
64-
don't blow up, so it can be a helpful regression indicator.
34+
It's a good idea to include tests of alternate comma placement formats of the name to ensure that the 3 code paths for the 3 formats work in the same way.
6535

36+
Unless you add better coverage someplace else, add a few examples of your names to `TEST_NAMES`. A test attempts to try the 3 different comma variations of these names automatically and make sure things don't blow up, so it can be a helpful regression indicator.
6637

6738
New Releases
6839
------------
6940

70-
[Publishing to Pypi Guide](https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/)
71-
7241
$ python setup.py sdist bdist_wheel
7342
$ twine upload dist/*
74-

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Name Parser
33

44
|Build Status| |PyPI| |PyPI version| |Documentation|
55

6-
A simple Python (3.2+ & 2.6+) module for parsing human names into their
6+
A simple Python (3.10+) module for parsing human names into their
77
individual components.
88

99
* hn.title

docs/usage.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Using the HumanName Parser
44
Example Usage
55
-------------
66

7-
The examples use Python 3, but Python 2.6+ is supported.
7+
Requires Python 3.10+.
88

99
.. doctest::
1010
:options: +NORMALIZE_WHITESPACE

0 commit comments

Comments
 (0)