diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index cb5369e..999f252 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -40,7 +40,7 @@ jobs: run: mypy - name: Run Tests run: | - python tests.py + pytest python -m build --sdist twine check dist/* sphinx-build -b html docs dist/docs diff --git a/AGENTS.md b/AGENTS.md index 536332e..47f6293 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,13 +9,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co pip install --group dev # Run all tests -python tests.py +pytest -# Run a single test by class/method -python -m unittest tests.HumanNamePythonTests.test_utf8 +# Run a single test file / class / method +pytest tests/test_python_api.py +pytest tests/test_python_api.py::HumanNamePythonTests::test_utf8 # Debug how a specific name string is parsed (prints HumanName repr) -python tests.py "Dr. Juan Q. Xavier de la Vega III" +python -m nameparser "Dr. Juan Q. Xavier de la Vega III" # Build docs sphinx-build -b html docs dist/docs @@ -65,6 +66,6 @@ Parse flow: 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. -### Tests (`tests.py`) +### Tests (`tests/`) -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`. +Tests run under **pytest** and are split one file per concern (`tests/test_titles.py`, `tests/test_suffixes.py`, etc.). `tests/base.py` holds `HumanNameTestBase` — a plain (non-`unittest`) base whose `m()` helper is a custom assert that prints the original name string on failure (plus thin `assert*` shims so the moved test bodies are unchanged). `tests/conftest.py` defines an autouse fixture that runs **every test twice** — once with `empty_attribute_default = ''` and once with `None` — so reported counts are doubled (e.g. 11 methods → 22 results); it also snapshots/restores the scalar `CONSTANTS` config around each test to keep tests order-independent. `TEST_NAMES` (in `tests/test_variations.py`) is a list of name strings permuted into comma-separated variants as a regression check. Tests that should fail use `@pytest.mark.xfail`. When adding a parsing case, add it to the relevant `tests/test_*.py` file and consider adding the base form to `TEST_NAMES`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90898ec..f3123d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,17 +11,23 @@ Install dev dependencies: Running Tests --------------- - python tests.py + pytest -You can also pass a name string to `tests.py` to see how it will be parsed: +Run a single test file or test: - $ python tests.py "Secretary of State Hillary Rodham-Clinton" + pytest tests/test_titles.py + pytest tests/test_titles.py::TitleTestCase + +You can also pass a name string to see how it will be parsed: + + $ python -m nameparser "Secretary of State Hillary Rodham-Clinton" CI runs tests against Python 3.10–3.14 via GitHub Actions on every push and pull request. diff --git a/MANIFEST.in b/MANIFEST.in index b212477..b2a2312 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ include AUTHORS include LICENSE include README.rst -include tests.py +recursive-include tests *.py diff --git a/docs/release_log.rst b/docs/release_log.rst index 322a4fd..af28d23 100644 --- a/docs/release_log.rst +++ b/docs/release_log.rst @@ -1,5 +1,9 @@ Release Log =========== +* Unreleased + - Fix ``initials()`` interpolating the literal ``None`` for empty name parts when ``empty_attribute_default = None`` (e.g. ``"J. None D."``); empty parts now render as an empty string and a fully-empty result returns ``empty_attribute_default`` + - Add ``python -m nameparser "Name String"`` command-line helper that prints a parsed name + - Reorganize the test suite from a single ``tests.py`` into a ``tests/`` pytest package * 1.2.0 - June 11, 2026 - Drop Python 2 and Python < 3.10 support; Python 3.10–3.14 now required - Add type hints and type declarations (PEP 561 ``py.typed`` marker) diff --git a/docs/usage.rst b/docs/usage.rst index 0a89098..c781703 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -191,8 +191,9 @@ Three attributes exist for the format, `first`, `middle` and `last`. >>> CONSTANTS.initials_format = "{first} {middle}" >>> HumanName("Doe, John A. Kenneth, Jr.").initials() 'J. A. K.' - >>> HumanName("Doe, John A. Kenneth, Jr.", initials_format="{last}, {first}).initials() + >>> HumanName("Doe, John A. Kenneth, Jr.", initials_format="{last}, {first}").initials() 'D., J.' + >>> CONSTANTS.initials_format = "{first} {middle} {last}" Furthermore, the delimiter for the string output can be set through: @@ -201,16 +202,15 @@ Furthermore, the delimiter for the string output can be set through: .. doctest:: initials delimiter >>> HumanName("Doe, John A. Kenneth, Jr.", initials_delimiter=";").initials() - "J; A; K;" - >>> from nameparser.config import CONSTANTS - >>> CONSTANTS.initials_delimiter = "." - >>> HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first}{middle}{last}).initials() - "J.A.K.D." + 'J; A; K; D;' + >>> HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first}{middle}{last}", initials_delimiter=".").initials() + 'J.A. K.D.' To get a list representation of the initials, use :py:meth:`~nameparser.HumanName.initials_list`. This function is unaffected by :py:attr:`~nameparser.config.Constants.initials_format` .. doctest:: list format + >>> HumanName("Doe, John A. Kenneth, Jr.", initials_delimiter=";").initials_list() - ["J", "A", "K", "D"] + ['J', 'A', 'K', 'D'] diff --git a/nameparser/__main__.py b/nameparser/__main__.py new file mode 100644 index 0000000..5d96ec8 --- /dev/null +++ b/nameparser/__main__.py @@ -0,0 +1,31 @@ +"""Command-line debug helper: parse a name and print the result. + +Usage: + + python -m nameparser "Dr. Juan Q. Xavier de la Vega III" +""" +import logging +import sys + +from nameparser import HumanName + + +def main() -> None: + if len(sys.argv) <= 1: + print('Usage: python -m nameparser "Name String"') + raise SystemExit(1) + log = logging.getLogger('HumanName') + log.setLevel(logging.ERROR) + log.addHandler(logging.StreamHandler()) + name_string = sys.argv[1] + hn = HumanName(name_string) + print(repr(hn)) + hn.capitalize() + print(repr(hn)) + # Use comma rather than concatenation: initials() returns + # empty_attribute_default (possibly None) when there are no initials. + print("Initials:", hn.initials()) + + +if __name__ == '__main__': + main() diff --git a/nameparser/parser.py b/nameparser/parser.py index ee361de..9edc905 100644 --- a/nameparser/parser.py +++ b/nameparser/parser.py @@ -273,17 +273,21 @@ def initials(self) -> str: middle_initials_list = [self.__process_initial__(name) for name in self.middle_list if name] last_initials_list = [self.__process_initial__(name) for name in self.last_list if name] + # Empty parts must render as '' (not empty_attribute_default, which may be + # None) so str.format does not interpolate the literal "None" into the + # output. A fully-empty result falls back to empty_attribute_default, + # matching the other attribute accessors (e.g. ``first``). initials_dict = { "first": (self.initials_delimiter + " ").join(first_initials_list) + self.initials_delimiter - if len(first_initials_list) else self.C.empty_attribute_default, + if len(first_initials_list) else "", "middle": (self.initials_delimiter + " ").join(middle_initials_list) + self.initials_delimiter - if len(middle_initials_list) else self.C.empty_attribute_default, + if len(middle_initials_list) else "", "last": (self.initials_delimiter + " ").join(last_initials_list) + self.initials_delimiter - if len(last_initials_list) else self.C.empty_attribute_default + if len(last_initials_list) else "" } _s = self.initials_format.format(**initials_dict) - return self.collapse_whitespace(_s) + return self.collapse_whitespace(_s) or self.C.empty_attribute_default @property def has_own_config(self) -> bool: diff --git a/pyproject.toml b/pyproject.toml index cba07ff..d9d4366 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ nameparser = ["py.typed"] [dependency-groups] dev = [ + "pytest (>=8)", "dill (>=0.2.5)", "sphinx (>=8)", "mypy (>=2.1)", @@ -54,6 +55,13 @@ module = [ ] ignore_missing_imports = true +[tool.pytest.ini_options] +testpaths = ["tests"] +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 + [tool.ruff.lint] extend-select = [ "ANN", # flake8-annotations diff --git a/tests.py b/tests.py deleted file mode 100644 index c137ab4..0000000 --- a/tests.py +++ /dev/null @@ -1,2630 +0,0 @@ -# ruff: noqa: E402 -import unittest -""" -Run this file to run the tests. - -``python tests.py`` - -Or install nose and run nosetests. - -``pip install nose`` - -then: - -``nosetests`` - -Post a ticket and/or clone and fix it. Pull requests with tests gladly accepted. -https://github.com/derek73/python-nameparser/issues -https://github.com/derek73/python-nameparser/pulls -""" - -import logging -import re -from typing import Generic, TypeVar - -try: - import dill -except ImportError: - dill = False - -from nameparser import HumanName -from nameparser.config import Constants, TupleManager - -log = logging.getLogger('HumanName') - - -T = TypeVar('T') - - -class HumanNameTestBase(unittest.TestCase, Generic[T]): - def m(self, actual: T, expected: T, hn: HumanName) -> None: - """assertEqual with a better message and awareness of hn.C.empty_attribute_default""" - expected_ = expected or hn.C.empty_attribute_default - try: - self.assertEqual(actual, expected_, "'%s' != '%s' for '%s'\n%r" % ( - actual, - expected, - hn.original, - hn - )) - except UnicodeDecodeError: - self.assertEqual(actual, expected_) - - -class HumanNamePythonTests(HumanNameTestBase): - - def test_utf8(self) -> None: - hn = HumanName("de la Véña, Jüan") - self.m(hn.first, "Jüan", hn) - self.m(hn.last, "de la Véña", hn) - - def test_string_output(self) -> None: - hn = HumanName("de la Véña, Jüan") - self.m(str(hn), "Jüan de la Véña", hn) - - def test_escaped_utf8_bytes(self) -> None: - hn = HumanName(b'B\xc3\xb6ck, Gerald') - self.m(hn.first, "Gerald", hn) - self.m(hn.last, "Böck", hn) - - def test_len(self) -> None: - hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") - self.m(len(hn), 5, hn) - hn = HumanName("John Doe") - self.m(len(hn), 2, hn) - - @unittest.skipUnless(dill, "requires python-dill module to test pickling") - def test_config_pickle(self) -> None: - constants = Constants() - self.assertTrue(dill.pickles(constants)) - - @unittest.skipUnless(dill, "requires python-dill module to test pickling") - def test_name_instance_pickle(self) -> None: - hn = HumanName("Title First Middle Middle Last, Jr.") - self.assertTrue(dill.pickles(hn)) - - def test_comparison(self) -> None: - hn1 = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") - hn2 = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") - self.assertTrue(hn1 == hn2) - self.assertTrue(hn1 is not hn2) - self.assertTrue(hn1 == "Dr. John P. Doe-Ray CLU, CFP, LUTC") - hn1 = HumanName("Doe, Dr. John P., CLU, CFP, LUTC") - hn2 = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") - self.assertTrue(not hn1 == hn2) - self.assertTrue(not hn1 == 0) - self.assertTrue(not hn1 == "test") - self.assertTrue(not hn1 == ["test"]) - self.assertTrue(not hn1 == {"test": hn2}) - - def test_assignment_to_full_name(self) -> None: - hn = HumanName("John A. Kenneth Doe, Jr.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "Jr.", hn) - hn.full_name = "Juan Velasquez y Garcia III" - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test_get_full_name_attribute_references_internal_lists(self) -> None: - hn = HumanName("John Williams") - hn.first_list = ["Larry"] - self.m(hn.full_name, "Larry Williams", hn) - - def test_assignment_to_attribute(self) -> None: - hn = HumanName("John A. Kenneth Doe, Jr.") - hn.last = "de la Vega" - self.m(hn.last, "de la Vega", hn) - hn.title = "test" - self.m(hn.title, "test", hn) - hn.first = "test" - self.m(hn.first, "test", hn) - hn.middle = "test" - self.m(hn.middle, "test", hn) - hn.suffix = "test" - self.m(hn.suffix, "test", hn) - with self.assertRaises(TypeError): - hn.suffix = [['test']] - with self.assertRaises(TypeError): - hn.suffix = {"test": "test"} - - def test_assign_list_to_attribute(self) -> None: - hn = HumanName("John A. Kenneth Doe, Jr.") - hn.title = ["test1", "test2"] - self.m(hn.title, "test1 test2", hn) - hn.first = ["test3", "test4"] - self.m(hn.first, "test3 test4", hn) - hn.middle = ["test5", "test6", "test7"] - self.m(hn.middle, "test5 test6 test7", hn) - hn.last = ["test8", "test9", "test10"] - self.m(hn.last, "test8 test9 test10", hn) - hn.suffix = ['test'] - self.m(hn.suffix, "test", hn) - - def test_comparison_case_insensitive(self) -> None: - hn1 = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") - hn2 = HumanName("dr. john p. doe-Ray, CLU, CFP, LUTC") - self.assertTrue(hn1 == hn2) - self.assertTrue(hn1 is not hn2) - self.assertTrue(hn1 == "Dr. John P. Doe-ray clu, CFP, LUTC") - - def test_slice(self) -> None: - hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") - self.m(list(hn), ['Dr.', 'John', 'P.', 'Doe-Ray', 'CLU, CFP, LUTC'], hn) - self.m(hn[1:], ['John', 'P.', 'Doe-Ray', 'CLU, CFP, LUTC', hn.C.empty_attribute_default], hn) - self.m(hn[1:-2], ['John', 'P.', 'Doe-Ray'], hn) - - def test_getitem(self) -> None: - hn = HumanName("Dr. John A. Kenneth Doe, Jr.") - self.m(hn['title'], "Dr.", hn) - self.m(hn['first'], "John", hn) - self.m(hn['last'], "Doe", hn) - self.m(hn['middle'], "A. Kenneth", hn) - self.m(hn['suffix'], "Jr.", hn) - - def test_setitem(self) -> None: - hn = HumanName("Dr. John A. Kenneth Doe, Jr.") - hn['title'] = 'test' - self.m(hn['title'], "test", hn) - hn['last'] = ['test', 'test2'] - self.m(hn['last'], "test test2", hn) - with self.assertRaises(TypeError): - hn["suffix"] = [['test']] - with self.assertRaises(TypeError): - hn["suffix"] = {"test": "test"} - - def test_conjunction_names(self) -> None: - hn = HumanName("johnny y") - self.m(hn.first, "johnny", hn) - self.m(hn.last, "y", hn) - - def test_prefix_names(self) -> None: - hn = HumanName("vai la") - self.m(hn.first, "vai", hn) - self.m(hn.last, "la", hn) - - def test_blank_name(self) -> None: - hn = HumanName() - self.m(hn.first, "", hn) - self.m(hn.last, "", hn) - - def test_surnames_list_attribute(self) -> None: - hn = HumanName("John Edgar Casey Williams III") - self.m(hn.surnames_list, ["Edgar", "Casey", "Williams"], hn) - - def test_surnames_attribute(self) -> None: - hn = HumanName("John Edgar Casey Williams III") - self.m(hn.surnames, "Edgar Casey Williams", hn) - - def test_is_prefix_with_list(self) -> None: - hn = HumanName() - items = ['firstname', 'lastname', 'del'] - self.assertTrue(hn.is_prefix(items)) - self.assertTrue(hn.is_prefix(items[1:])) - - def test_is_conjunction_with_list(self) -> None: - hn = HumanName() - items = ['firstname', 'lastname', 'and'] - self.assertTrue(hn.is_conjunction(items)) - self.assertTrue(hn.is_conjunction(items[1:])) - - def test_override_constants(self) -> None: - C = Constants() - hn = HumanName(constants=C) - self.assertTrue(hn.C is C) - - def test_override_regex(self) -> None: - var = TupleManager([("spaces", re.compile(r"\s+", re.U)),]) - C = Constants(regexes=var) - hn = HumanName(constants=C) - self.assertTrue(hn.C.regexes == var) - - def test_override_titles(self) -> None: - var = ["abc","def"] - C = Constants(titles=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.titles) == sorted(var)) - - def test_override_first_name_titles(self) -> None: - var = ["abc","def"] - C = Constants(first_name_titles=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.first_name_titles) == sorted(var)) - - def test_override_prefixes(self) -> None: - var = ["abc","def"] - C = Constants(prefixes=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.prefixes) == sorted(var)) - - def test_override_suffix_acronyms(self) -> None: - var = ["abc","def"] - C = Constants(suffix_acronyms=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.suffix_acronyms) == sorted(var)) - - def test_override_suffix_not_acronyms(self) -> None: - var = ["abc","def"] - C = Constants(suffix_not_acronyms=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.suffix_not_acronyms) == sorted(var)) - - def test_override_conjunctions(self) -> None: - var = ["abc","def"] - C = Constants(conjunctions=var) - hn = HumanName(constants=C) - self.assertTrue(sorted(hn.C.conjunctions) == sorted(var)) - - def test_override_capitalization_exceptions(self) -> None: - var = TupleManager([("spaces", re.compile(r"\s+", re.U)),]) - C = Constants(capitalization_exceptions=var) - hn = HumanName(constants=C) - self.assertTrue(hn.C.capitalization_exceptions == var) - - -class FirstNameHandlingTests(HumanNameTestBase): - def test_first_name(self) -> None: - hn = HumanName("Andrew") - self.m(hn.first, "Andrew", hn) - - def test_assume_title_and_one_other_name_is_last_name(self) -> None: - hn = HumanName("Rev Andrews") - self.m(hn.title, "Rev", hn) - self.m(hn.last, "Andrews", hn) - - # TODO: Seems "Andrews, M.D.", Andrews should be treated as a last name - # but other suffixes like "George Jr." should be first names. Might be - # related to https://github.com/derek73/python-nameparser/issues/2 - @unittest.expectedFailure - def test_assume_suffix_title_and_one_other_name_is_last_name(self) -> None: - hn = HumanName("Andrews, M.D.") - self.m(hn.suffix, "M.D.", hn) - self.m(hn.last, "Andrews", hn) - - def test_suffix_in_lastname_part_of_lastname_comma_format(self) -> None: - hn = HumanName("Smith Jr., John") - self.m(hn.last, "Smith", hn) - self.m(hn.first, "John", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_sir_exception_to_first_name_rule(self) -> None: - hn = HumanName("Sir Gerald") - self.m(hn.title, "Sir", hn) - self.m(hn.first, "Gerald", hn) - - def test_king_exception_to_first_name_rule(self) -> None: - hn = HumanName("King Henry") - self.m(hn.title, "King", hn) - self.m(hn.first, "Henry", hn) - - def test_queen_exception_to_first_name_rule(self) -> None: - hn = HumanName("Queen Elizabeth") - self.m(hn.title, "Queen", hn) - self.m(hn.first, "Elizabeth", hn) - - def test_dame_exception_to_first_name_rule(self) -> None: - hn = HumanName("Dame Mary") - self.m(hn.title, "Dame", hn) - self.m(hn.first, "Mary", hn) - - def test_first_name_is_not_prefix_if_only_two_parts(self) -> None: - """When there are only two parts, don't join prefixes or conjunctions""" - hn = HumanName("Van Nguyen") - self.m(hn.first, "Van", hn) - self.m(hn.last, "Nguyen", hn) - - def test_first_name_is_not_prefix_if_only_two_parts_comma(self) -> None: - hn = HumanName("Nguyen, Van") - self.m(hn.first, "Van", hn) - self.m(hn.last, "Nguyen", hn) - - @unittest.expectedFailure - def test_first_name_is_prefix_if_three_parts(self) -> None: - """Not sure how to fix this without breaking Mr and Mrs""" - hn = HumanName("Mr. Van Nguyen") - self.m(hn.first, "Van", hn) - self.m(hn.last, "Nguyen", hn) - - -class HumanNameBruteForceTests(HumanNameTestBase): - - def test1(self) -> None: - hn = HumanName("John Doe") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test2(self) -> None: - hn = HumanName("John Doe, Jr.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test3(self) -> None: - hn = HumanName("John Doe III") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test4(self) -> None: - hn = HumanName("Doe, John") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test5(self) -> None: - hn = HumanName("Doe, John, Jr.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test6(self) -> None: - hn = HumanName("Doe, John III") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test7(self) -> None: - hn = HumanName("John A. Doe") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - - def test8(self) -> None: - hn = HumanName("John A. Doe, Jr") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "Jr", hn) - - def test9(self) -> None: - hn = HumanName("John A. Doe III") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "III", hn) - - def test10(self) -> None: - hn = HumanName("Doe, John A.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - - def test11(self) -> None: - hn = HumanName("Doe, John A., Jr.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test12(self) -> None: - hn = HumanName("Doe, John A., III") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "III", hn) - - def test13(self) -> None: - hn = HumanName("John A. Kenneth Doe") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - - def test14(self) -> None: - hn = HumanName("John A. Kenneth Doe, Jr.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "Jr.", hn) - - def test15(self) -> None: - hn = HumanName("John A. Kenneth Doe III") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "III", hn) - - def test16(self) -> None: - hn = HumanName("Doe, John. A. Kenneth") - self.m(hn.first, "John.", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - - def test17(self) -> None: - hn = HumanName("Doe, John. A. Kenneth, Jr.") - self.m(hn.first, "John.", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "Jr.", hn) - - def test18(self) -> None: - hn = HumanName("Doe, John. A. Kenneth III") - self.m(hn.first, "John.", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "III", hn) - - def test19(self) -> None: - hn = HumanName("Dr. John Doe") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.title, "Dr.", hn) - - def test20(self) -> None: - hn = HumanName("Dr. John Doe, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test21(self) -> None: - hn = HumanName("Dr. John Doe III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test22(self) -> None: - hn = HumanName("Doe, Dr. John") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test23(self) -> None: - hn = HumanName("Doe, Dr. John, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test24(self) -> None: - hn = HumanName("Doe, Dr. John III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test25(self) -> None: - hn = HumanName("Dr. John A. Doe") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - - def test26(self) -> None: - hn = HumanName("Dr. John A. Doe, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test27(self) -> None: - hn = HumanName("Dr. John A. Doe III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "III", hn) - - def test28(self) -> None: - hn = HumanName("Doe, Dr. John A.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - - def test29(self) -> None: - hn = HumanName("Doe, Dr. John A. Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test30(self) -> None: - hn = HumanName("Doe, Dr. John A. III") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test31(self) -> None: - hn = HumanName("Dr. John A. Kenneth Doe") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test32(self) -> None: - hn = HumanName("Dr. John A. Kenneth Doe, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test33(self) -> None: - hn = HumanName("Al Arnold Gore, Jr.") - self.m(hn.middle, "Arnold", hn) - self.m(hn.first, "Al", hn) - self.m(hn.last, "Gore", hn) - self.m(hn.suffix, "Jr.", hn) - - def test34(self) -> None: - hn = HumanName("Dr. John A. Kenneth Doe III") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test35(self) -> None: - hn = HumanName("Doe, Dr. John A. Kenneth") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test36(self) -> None: - hn = HumanName("Doe, Dr. John A. Kenneth Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Jr.", hn) - - def test37(self) -> None: - hn = HumanName("Doe, Dr. John A. Kenneth III") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "III", hn) - - def test38(self) -> None: - hn = HumanName("Juan de la Vega") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - - def test39(self) -> None: - hn = HumanName("Juan de la Vega, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "Jr.", hn) - - def test40(self) -> None: - hn = HumanName("Juan de la Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "III", hn) - - def test41(self) -> None: - hn = HumanName("de la Vega, Juan") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - - def test42(self) -> None: - hn = HumanName("de la Vega, Juan, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "Jr.", hn) - - def test43(self) -> None: - hn = HumanName("de la Vega, Juan III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "III", hn) - - def test44(self) -> None: - hn = HumanName("Juan Velasquez y Garcia") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test45(self) -> None: - hn = HumanName("Juan Velasquez y Garcia, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test46(self) -> None: - hn = HumanName("Juan Velasquez y Garcia III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test47(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test48(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test49(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test50(self) -> None: - hn = HumanName("Dr. Juan de la Vega") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - - def test51(self) -> None: - hn = HumanName("Dr. Juan de la Vega, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "Jr.", hn) - - def test52(self) -> None: - hn = HumanName("Dr. Juan de la Vega III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "III", hn) - - def test53(self) -> None: - hn = HumanName("de la Vega, Dr. Juan") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - - def test54(self) -> None: - hn = HumanName("de la Vega, Dr. Juan, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "Jr.", hn) - - def test55(self) -> None: - hn = HumanName("de la Vega, Dr. Juan III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "III", hn) - - def test56(self) -> None: - hn = HumanName("Dr. Juan Velasquez y Garcia") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test57(self) -> None: - hn = HumanName("Dr. Juan Velasquez y Garcia, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test58(self) -> None: - hn = HumanName("Dr. Juan Velasquez y Garcia III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test59(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test60(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test61(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan III") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test62(self) -> None: - hn = HumanName("Juan Q. de la Vega") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.last, "de la Vega", hn) - - def test63(self) -> None: - hn = HumanName("Juan Q. de la Vega, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test64(self) -> None: - hn = HumanName("Juan Q. de la Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.suffix, "III", hn) - - def test65(self) -> None: - hn = HumanName("de la Vega, Juan Q.") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.last, "de la Vega", hn) - - def test66(self) -> None: - hn = HumanName("de la Vega, Juan Q., Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test67(self) -> None: - hn = HumanName("de la Vega, Juan Q. III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.suffix, "III", hn) - - def test68(self) -> None: - hn = HumanName("Juan Q. Velasquez y Garcia") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test69(self) -> None: - hn = HumanName("Juan Q. Velasquez y Garcia, Jr.") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test70(self) -> None: - hn = HumanName("Juan Q. Velasquez y Garcia III") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test71(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q.") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test72(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q., Jr.") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test73(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q. III") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test74(self) -> None: - hn = HumanName("Dr. Juan Q. de la Vega") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.last, "de la Vega", hn) - - def test75(self) -> None: - hn = HumanName("Dr. Juan Q. de la Vega, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test76(self) -> None: - hn = HumanName("Dr. Juan Q. de la Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.suffix, "III", hn) - - def test77(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q.") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.title, "Dr.", hn) - - def test78(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q., Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.suffix, "Jr.", hn) - self.m(hn.title, "Dr.", hn) - - def test79(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q. III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.suffix, "III", hn) - self.m(hn.title, "Dr.", hn) - - def test80(self) -> None: - hn = HumanName("Dr. Juan Q. Velasquez y Garcia") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test81(self) -> None: - hn = HumanName("Dr. Juan Q. Velasquez y Garcia, Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test82(self) -> None: - hn = HumanName("Dr. Juan Q. Velasquez y Garcia III") - self.m(hn.middle, "Q.", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test83(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q.") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test84(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q., Jr.") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test85(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q. III") - self.m(hn.middle, "Q.", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test86(self) -> None: - hn = HumanName("Juan Q. Xavier de la Vega") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.last, "de la Vega", hn) - - def test87(self) -> None: - hn = HumanName("Juan Q. Xavier de la Vega, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "Jr.", hn) - - def test88(self) -> None: - hn = HumanName("Juan Q. Xavier de la Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test89(self) -> None: - hn = HumanName("de la Vega, Juan Q. Xavier") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.last, "de la Vega", hn) - - def test90(self) -> None: - hn = HumanName("de la Vega, Juan Q. Xavier, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "Jr.", hn) - - def test91(self) -> None: - hn = HumanName("de la Vega, Juan Q. Xavier III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test92(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier de la Vega") - self.m(hn.first, "Juan", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "de la Vega", hn) - - def test93(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier de la Vega, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "Jr.", hn) - - def test94(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier de la Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test95(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q. Xavier") - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.last, "de la Vega", hn) - - def test96(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q. Xavier, Jr.") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "Jr.", hn) - - def test97(self) -> None: - hn = HumanName("de la Vega, Dr. Juan Q. Xavier III") - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "de la Vega", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test98(self) -> None: - hn = HumanName("Juan Q. Xavier Velasquez y Garcia") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test99(self) -> None: - hn = HumanName("Juan Q. Xavier Velasquez y Garcia, Jr.") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test100(self) -> None: - hn = HumanName("Juan Q. Xavier Velasquez y Garcia III") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test101(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q. Xavier") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test102(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q. Xavier, Jr.") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test103(self) -> None: - hn = HumanName("Velasquez y Garcia, Juan Q. Xavier III") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test104(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test105(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia, Jr.") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test106(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia III") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test107(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - - def test108(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier, Jr.") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "Jr.", hn) - - def test109(self) -> None: - hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier III") - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.first, "Juan", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.last, "Velasquez y Garcia", hn) - self.m(hn.suffix, "III", hn) - - def test110(self) -> None: - hn = HumanName("John Doe, CLU, CFP, LUTC") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "CLU, CFP, LUTC", hn) - - def test111(self) -> None: - hn = HumanName("John P. Doe, CLU, CFP, LUTC") - self.m(hn.first, "John", hn) - self.m(hn.middle, "P.", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "CLU, CFP, LUTC", hn) - - def test112(self) -> None: - hn = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") - self.m(hn.first, "John", hn) - self.m(hn.middle, "P.", hn) - self.m(hn.last, "Doe-Ray", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.suffix, "CLU, CFP, LUTC", hn) - - def test113(self) -> None: - hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "P.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe-Ray", hn) - self.m(hn.suffix, "CLU, CFP, LUTC", hn) - - def test115(self) -> None: - hn = HumanName("Hon. Barrington P. Doe-Ray, Jr.") - self.m(hn.title, "Hon.", hn) - self.m(hn.middle, "P.", hn) - self.m(hn.first, "Barrington", hn) - self.m(hn.last, "Doe-Ray", hn) - - def test116(self) -> None: - hn = HumanName("Doe-Ray, Hon. Barrington P. Jr., CFP, LUTC") - self.m(hn.title, "Hon.", hn) - self.m(hn.middle, "P.", hn) - self.m(hn.first, "Barrington", hn) - self.m(hn.last, "Doe-Ray", hn) - self.m(hn.suffix, "Jr., CFP, LUTC", hn) - - def test117(self) -> None: - hn = HumanName("Rt. Hon. Paul E. Mary") - self.m(hn.title, "Rt. Hon.", hn) - self.m(hn.first, "Paul", hn) - self.m(hn.middle, "E.", hn) - self.m(hn.last, "Mary", hn) - - def test119(self) -> None: - hn = HumanName("Lord God Almighty") - self.m(hn.title, "Lord", hn) - self.m(hn.first, "God", hn) - self.m(hn.last, "Almighty", hn) - - -class HumanNameConjunctionTestCase(HumanNameTestBase): - # Last name with conjunction - def test_last_name_with_conjunction(self) -> None: - hn = HumanName('Jose Aznar y Lopez') - self.m(hn.first, "Jose", hn) - self.m(hn.last, "Aznar y Lopez", hn) - - def test_multiple_conjunctions(self) -> None: - hn = HumanName("part1 of The part2 of the part3 and part4") - self.m(hn.first, "part1 of The part2 of the part3 and part4", hn) - - def test_multiple_conjunctions2(self) -> None: - hn = HumanName("part1 of and The part2 of the part3 And part4") - self.m(hn.first, "part1 of and The part2 of the part3 And part4", hn) - - def test_ends_with_conjunction(self) -> None: - hn = HumanName("Jon Dough and") - self.m(hn.first, "Jon", hn) - self.m(hn.last, "Dough and", hn) - - def test_ends_with_two_conjunctions(self) -> None: - hn = HumanName("Jon Dough and of") - self.m(hn.first, "Jon", hn) - self.m(hn.last, "Dough and of", hn) - - def test_starts_with_conjunction(self) -> None: - hn = HumanName("and Jon Dough") - self.m(hn.first, "and Jon", hn) - self.m(hn.last, "Dough", hn) - - def test_starts_with_two_conjunctions(self) -> None: - hn = HumanName("the and Jon Dough") - self.m(hn.first, "the and Jon", hn) - self.m(hn.last, "Dough", hn) - - # Potential conjunction/prefix treated as initial (because uppercase) - def test_uppercase_middle_initial_conflict_with_conjunction(self) -> None: - hn = HumanName('John E Smith') - self.m(hn.first, "John", hn) - self.m(hn.middle, "E", hn) - self.m(hn.last, "Smith", hn) - - def test_lowercase_middle_initial_with_period_conflict_with_conjunction(self) -> None: - hn = HumanName('john e. smith') - self.m(hn.first, "john", hn) - self.m(hn.middle, "e.", hn) - self.m(hn.last, "smith", hn) - - # The conjunction "e" can also be an initial - def test_lowercase_first_initial_conflict_with_conjunction(self) -> None: - hn = HumanName('e j smith') - self.m(hn.first, "e", hn) - self.m(hn.middle, "j", hn) - self.m(hn.last, "smith", hn) - - def test_lowercase_middle_initial_conflict_with_conjunction(self) -> None: - hn = HumanName('John e Smith') - self.m(hn.first, "John", hn) - self.m(hn.middle, "e", hn) - self.m(hn.last, "Smith", hn) - - def test_lowercase_middle_initial_and_suffix_conflict_with_conjunction(self) -> None: - hn = HumanName('John e Smith, III') - self.m(hn.first, "John", hn) - self.m(hn.middle, "e", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "III", hn) - - def test_lowercase_middle_initial_and_nocomma_suffix_conflict_with_conjunction(self) -> None: - hn = HumanName('John e Smith III') - self.m(hn.first, "John", hn) - self.m(hn.middle, "e", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "III", hn) - - def test_lowercase_middle_initial_comma_lastname_and_suffix_conflict_with_conjunction(self) -> None: - hn = HumanName('Smith, John e, III, Jr') - self.m(hn.first, "John", hn) - self.m(hn.middle, "e", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "III, Jr", hn) - - @unittest.expectedFailure - def test_two_initials_conflict_with_conjunction(self) -> None: - # Supporting this seems to screw up titles with periods in them like M.B.A. - hn = HumanName('E.T. Smith') - self.m(hn.first, "E.", hn) - self.m(hn.middle, "T.", hn) - self.m(hn.last, "Smith", hn) - - def test_couples_names(self) -> None: - hn = HumanName('John and Jane Smith') - self.m(hn.first, "John and Jane", hn) - self.m(hn.last, "Smith", hn) - - def test_couples_names_with_conjunction_lastname(self) -> None: - hn = HumanName('John and Jane Aznar y Lopez') - self.m(hn.first, "John and Jane", hn) - self.m(hn.last, "Aznar y Lopez", hn) - - def test_couple_titles(self) -> None: - hn = HumanName('Mr. and Mrs. John and Jane Smith') - self.m(hn.title, "Mr. and Mrs.", hn) - self.m(hn.first, "John and Jane", hn) - self.m(hn.last, "Smith", hn) - - def test_title_with_three_part_name_last_initial_is_suffix_uppercase_no_period(self) -> None: - hn = HumanName("King John Alexander V") - self.m(hn.title, "King", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Alexander", hn) - self.m(hn.suffix, "V", hn) - - def test_four_name_parts_with_suffix_that_could_be_initial_lowercase_no_period(self) -> None: - hn = HumanName("larry james edward johnson v") - self.m(hn.first, "larry", hn) - self.m(hn.middle, "james edward", hn) - self.m(hn.last, "johnson", hn) - self.m(hn.suffix, "v", hn) - - def test_four_name_parts_with_suffix_that_could_be_initial_uppercase_no_period(self) -> None: - hn = HumanName("Larry James Johnson I") - self.m(hn.first, "Larry", hn) - self.m(hn.middle, "James", hn) - self.m(hn.last, "Johnson", hn) - self.m(hn.suffix, "I", hn) - - def test_roman_numeral_initials(self) -> None: - hn = HumanName("Larry V I") - self.m(hn.first, "Larry", hn) - self.m(hn.middle, "V", hn) - self.m(hn.last, "I", hn) - self.m(hn.suffix, "", hn) - - def test_roman_numeral_suffix_not_in_suffix_list(self) -> None: - # VI-X are not in the suffix word lists, so they reach the - # is_roman_numeral(nxt) branch rather than are_suffixes() - hn = HumanName("John Smith VI") - self.m(hn.first, "John", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "VI", hn) - - # tests for Rev. title (Reverend) - def test124(self) -> None: - hn = HumanName("Rev. John A. Kenneth Doe") - self.m(hn.title, "Rev.", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test125(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe") - self.m(hn.title, "Rev", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test126(self) -> None: - hn = HumanName("Doe, Rev. John A. Jr.") - self.m(hn.title, "Rev.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "Jr.", hn) - - def test127(self) -> None: - hn = HumanName("Buca di Beppo") - self.m(hn.first, "Buca", hn) - self.m(hn.last, "di Beppo", hn) - - def test_le_as_last_name(self) -> None: - hn = HumanName("Yin Le") - self.m(hn.first, "Yin", hn) - self.m(hn.last, "Le", hn) - - def test_le_as_last_name_with_middle_initial(self) -> None: - hn = HumanName("Yin a Le") - self.m(hn.first, "Yin", hn) - self.m(hn.middle, "a", hn) - self.m(hn.last, "Le", hn) - - def test_conjunction_in_an_address_with_a_title(self) -> None: - hn = HumanName("His Excellency Lord Duncan") - self.m(hn.title, "His Excellency Lord", hn) - self.m(hn.last, "Duncan", hn) - - @unittest.expectedFailure - def test_conjunction_in_an_address_with_a_first_name_title(self) -> None: - hn = HumanName("Her Majesty Queen Elizabeth") - self.m(hn.title, "Her Majesty Queen", hn) - # if you want to be technical, Queen is in FIRST_NAME_TITLES - self.m(hn.first, "Elizabeth", hn) - - def test_name_is_conjunctions(self) -> None: - hn = HumanName("e and e") - self.m(hn.first, "e and e", hn) - - -class ConstantsCustomization(HumanNameTestBase): - - def test_add_title(self) -> None: - hn = HumanName("Te Awanui-a-Rangi Black", constants=None) - start_len = len(hn.C.titles) - self.assertTrue(start_len > 0) - hn.C.titles.add('te') - self.assertEqual(start_len + 1, len(hn.C.titles)) - hn.parse_full_name() - self.m(hn.title, "Te", hn) - self.m(hn.first, "Awanui-a-Rangi", hn) - self.m(hn.last, "Black", hn) - - def test_remove_title(self) -> None: - hn = HumanName("Hon Solo", constants=None) - start_len = len(hn.C.titles) - self.assertTrue(start_len > 0) - hn.C.titles.remove('hon') - self.assertEqual(start_len - 1, len(hn.C.titles)) - hn.parse_full_name() - self.m(hn.first, "Hon", hn) - self.m(hn.last, "Solo", hn) - - def test_add_multiple_arguments(self) -> None: - hn = HumanName("Assoc Dean of Chemistry Robert Johns", constants=None) - hn.C.titles.add('dean', 'Chemistry') - hn.parse_full_name() - self.m(hn.title, "Assoc Dean of Chemistry", hn) - self.m(hn.first, "Robert", hn) - self.m(hn.last, "Johns", hn) - - def test_instances_can_have_own_constants(self) -> None: - hn = HumanName("", None) - hn2 = HumanName("") - hn.C.titles.remove('hon') - self.assertEqual('hon' in hn.C.titles, False) - self.assertEqual(hn.has_own_config, True) - self.assertEqual('hon' in hn2.C.titles, True) - self.assertEqual(hn2.has_own_config, False) - - def test_can_change_global_constants(self) -> None: - hn = HumanName("") - hn2 = HumanName("") - hn.C.titles.remove('hon') - self.assertEqual('hon' in hn.C.titles, False) - self.assertEqual('hon' in hn2.C.titles, False) - self.assertEqual(hn.has_own_config, False) - self.assertEqual(hn2.has_own_config, False) - # clean up so we don't mess up other tests - hn.C.titles.add('hon') - - def test_remove_multiple_arguments(self) -> None: - hn = HumanName("Ms Hon Solo", constants=None) - hn.C.titles.remove('hon', 'ms') - hn.parse_full_name() - self.m(hn.first, "Ms", hn) - self.m(hn.middle, "Hon", hn) - self.m(hn.last, "Solo", hn) - - def test_chain_multiple_arguments(self) -> None: - hn = HumanName("Dean Ms Hon Solo", constants=None) - hn.C.titles.remove('hon', 'ms').add('dean') - hn.parse_full_name() - self.m(hn.title, "Dean", hn) - self.m(hn.first, "Ms", hn) - self.m(hn.middle, "Hon", hn) - self.m(hn.last, "Solo", hn) - - def test_empty_attribute_default(self) -> None: - from nameparser.config import CONSTANTS - _orig = CONSTANTS.empty_attribute_default - CONSTANTS.empty_attribute_default = None - hn = HumanName("") - self.m(hn.title, None, hn) - self.m(hn.first, None, hn) - self.m(hn.middle, None, hn) - self.m(hn.last, None, hn) - self.m(hn.suffix, None, hn) - self.m(hn.nickname, None, hn) - CONSTANTS.empty_attribute_default = _orig - - def test_empty_attribute_on_instance(self) -> None: - hn = HumanName("", None) - hn.C.empty_attribute_default = None - self.m(hn.title, None, hn) - self.m(hn.first, None, hn) - self.m(hn.middle, None, hn) - self.m(hn.last, None, hn) - self.m(hn.suffix, None, hn) - self.m(hn.nickname, None, hn) - - def test_none_empty_attribute_string_formatting(self) -> None: - hn = HumanName("", None) - hn.C.empty_attribute_default = None - self.assertEqual('', str(hn), hn) - - def test_add_constant_with_explicit_encoding(self) -> None: - c = Constants() - c.titles.add_with_encoding(b'b\351ck', encoding='latin_1') - self.assertIn('béck', c.titles) - - -class NicknameTestCase(HumanNameTestBase): - # https://code.google.com/p/python-nameparser/issues/detail?id=33 - def test_nickname_in_parenthesis(self) -> None: - hn = HumanName("Benjamin (Ben) Franklin") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Ben", hn) - - def test_two_word_nickname_in_parenthesis(self) -> None: - hn = HumanName("Benjamin (Big Ben) Franklin") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Big Ben", hn) - - def test_two_words_in_quotes(self) -> None: - hn = HumanName('Benjamin "Big Ben" Franklin') - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Big Ben", hn) - - def test_nickname_in_parenthesis_with_comma(self) -> None: - hn = HumanName("Franklin, Benjamin (Ben)") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Ben", hn) - - def test_nickname_in_parenthesis_with_comma_and_suffix(self) -> None: - hn = HumanName("Franklin, Benjamin (Ben), Jr.") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.suffix, "Jr.", hn) - self.m(hn.nickname, "Ben", hn) - - def test_nickname_in_single_quotes(self) -> None: - hn = HumanName("Benjamin 'Ben' Franklin") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Ben", hn) - - def test_nickname_in_double_quotes(self) -> None: - hn = HumanName("Benjamin \"Ben\" Franklin") - self.m(hn.first, "Benjamin", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.nickname, "Ben", hn) - - def test_single_quotes_on_first_name_not_treated_as_nickname(self) -> None: - hn = HumanName("Brian Andrew O'connor") - self.m(hn.first, "Brian", hn) - self.m(hn.middle, "Andrew", hn) - self.m(hn.last, "O'connor", hn) - self.m(hn.nickname, "", hn) - - def test_single_quotes_on_both_name_not_treated_as_nickname(self) -> None: - hn = HumanName("La'tanya O'connor") - self.m(hn.first, "La'tanya", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "O'connor", hn) - self.m(hn.nickname, "", hn) - - def test_single_quotes_on_end_of_last_name_not_treated_as_nickname(self) -> None: - hn = HumanName("Mari' Aube'") - self.m(hn.first, "Mari'", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Aube'", hn) - self.m(hn.nickname, "", hn) - - def test_okina_inside_name_not_treated_as_nickname(self) -> None: - hn = HumanName("Harrieta Keōpūolani Nāhiʻenaʻena") - self.m(hn.first, "Harrieta", hn) - self.m(hn.middle, "Keōpūolani", hn) - self.m(hn.last, "Nāhiʻenaʻena", hn) - self.m(hn.nickname, "", hn) - - def test_single_quotes_not_treated_as_nickname_Hawaiian_example(self) -> None: - hn = HumanName("Harietta Keopuolani Nahi'ena'ena") - self.m(hn.first, "Harietta", hn) - self.m(hn.middle, "Keopuolani", hn) - self.m(hn.last, "Nahi'ena'ena", hn) - self.m(hn.nickname, "", hn) - - def test_single_quotes_not_treated_as_nickname_Kenyan_example(self) -> None: - hn = HumanName("Naomi Wambui Ng'ang'a") - self.m(hn.first, "Naomi", hn) - self.m(hn.middle, "Wambui", hn) - self.m(hn.last, "Ng'ang'a", hn) - self.m(hn.nickname, "", hn) - - def test_single_quotes_not_treated_as_nickname_Samoan_example(self) -> None: - hn = HumanName("Va'apu'u Vitale") - self.m(hn.first, "Va'apu'u", hn) - self.m(hn.middle, "", hn) - self.m(hn.last, "Vitale", hn) - self.m(hn.nickname, "", hn) - - # http://code.google.com/p/python-nameparser/issues/detail?id=17 - def test_parenthesis_are_removed_from_name(self) -> None: - hn = HumanName("John Jones (Unknown)") - self.m(hn.first, "John", hn) - self.m(hn.last, "Jones", hn) - # not testing the nicknames because we don't actually care - # about Google Docs here - - def test_duplicate_parenthesis_are_removed_from_name(self) -> None: - hn = HumanName("John Jones (Google Docs), Jr. (Unknown)") - self.m(hn.first, "John", hn) - self.m(hn.last, "Jones", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_nickname_and_last_name(self) -> None: - hn = HumanName('"Rick" Edmonds') - self.m(hn.first, "", hn) - self.m(hn.last, "Edmonds", hn) - self.m(hn.nickname, "Rick", hn) - - @unittest.expectedFailure - def test_nickname_and_last_name_with_title(self) -> None: - hn = HumanName('Senator "Rick" Edmonds') - self.m(hn.title, "Senator", hn) - self.m(hn.first, "", hn) - self.m(hn.last, "Edmonds", hn) - self.m(hn.nickname, "Rick", hn) - - -# class MaidenNameTestCase(HumanNameTestBase): -# -# def test_parenthesis_and_quotes_together(self): -# hn = HumanName("Jennifer 'Jen' Jones (Duff)") -# self.m(hn.first, "Jennifer", hn) -# self.m(hn.last, "Jones", hn) -# self.m(hn.nickname, "Jen", hn) -# self.m(hn.maiden, "Duff", hn) -# -# def test_maiden_name_with_nee(self): -# # https://en.wiktionary.org/wiki/née -# hn = HumanName("Mary Toogood nee Johnson") -# self.m(hn.first, "Mary", hn) -# self.m(hn.last, "Toogood", hn) -# self.m(hn.maiden, "Johnson", hn) -# -# def test_maiden_name_with_accented_nee(self): -# # https://en.wiktionary.org/wiki/née -# hn = HumanName("Mary Toogood née Johnson") -# self.m(hn.first, "Mary", hn) -# self.m(hn.last, "Toogood", hn) -# self.m(hn.maiden, "Johnson", hn) -# -# def test_maiden_name_with_nee_and_comma(self): -# # https://en.wiktionary.org/wiki/née -# hn = HumanName("Mary Toogood, née Johnson") -# self.m(hn.first, "Mary", hn) -# self.m(hn.last, "Toogood", hn) -# self.m(hn.maiden, "Johnson", hn) -# -# def test_maiden_name_with_nee_with_parenthesis(self): -# hn = HumanName("Mary Toogood (nee Johnson)") -# self.m(hn.first, "Mary", hn) -# self.m(hn.last, "Toogood", hn) -# self.m(hn.maiden, "Johnson", hn) -# -# def test_maiden_name_with_parenthesis(self): -# hn = HumanName("Mary Toogood (Johnson)") -# self.m(hn.first, "Mary", hn) -# self.m(hn.last, "Toogood", hn) -# self.m(hn.maiden, "Johnson", hn) -# - -class PrefixesTestCase(HumanNameTestBase): - - def test_prefix(self) -> None: - hn = HumanName("Juan del Sur") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "del Sur", hn) - - def test_prefix_with_period(self) -> None: - hn = HumanName("Jill St. John") - self.m(hn.first, "Jill", hn) - self.m(hn.last, "St. John", hn) - - def test_prefix_before_two_part_last_name(self) -> None: - hn = HumanName("pennie von bergen wessels") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - - def test_prefix_is_first_name(self) -> None: - hn = HumanName("Van Johnson") - self.m(hn.first, "Van", hn) - self.m(hn.last, "Johnson", hn) - - def test_prefix_is_first_name_with_middle_name(self) -> None: - hn = HumanName("Van Jeremy Johnson") - self.m(hn.first, "Van", hn) - self.m(hn.middle, "Jeremy", hn) - self.m(hn.last, "Johnson", hn) - - def test_prefix_before_two_part_last_name_with_suffix(self) -> None: - hn = HumanName("pennie von bergen wessels III") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "III", hn) - - def test_prefix_before_two_part_last_name_with_acronym_suffix(self) -> None: - hn = HumanName("pennie von bergen wessels M.D.") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "M.D.", hn) - - def test_two_part_last_name_with_suffix_comma(self) -> None: - hn = HumanName("pennie von bergen wessels, III") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "III", hn) - - def test_two_part_last_name_with_suffix(self) -> None: - hn = HumanName("von bergen wessels, pennie III") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "III", hn) - - def test_last_name_two_part_last_name_with_two_suffixes(self) -> None: - hn = HumanName("von bergen wessels MD, pennie III") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "MD, III", hn) - - def test_comma_two_part_last_name_with_acronym_suffix(self) -> None: - hn = HumanName("von bergen wessels, pennie MD") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "MD", hn) - - def test_comma_two_part_last_name_with_suffix_in_first_part(self) -> None: - # I'm kinda surprised this works, not really sure if this is a - # realistic place for a suffix to be. - hn = HumanName("von bergen wessels MD, pennie") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "MD", hn) - - def test_title_two_part_last_name_with_suffix_in_first_part(self) -> None: - hn = HumanName("pennie von bergen wessels MD, III") - self.m(hn.first, "pennie", hn) - self.m(hn.last, "von bergen wessels", hn) - self.m(hn.suffix, "MD, III", hn) - - def test_portuguese_dos(self) -> None: - hn = HumanName("Rafael Sousa dos Anjos") - self.m(hn.first, "Rafael", hn) - self.m(hn.middle, "Sousa", hn) - self.m(hn.last, "dos Anjos", hn) - - def test_portuguese_prefixes(self) -> None: - hn = HumanName("Joao da Silva do Amaral de Souza") - self.m(hn.first, "Joao", hn) - self.m(hn.middle, "da Silva do Amaral", hn) - self.m(hn.last, "de Souza", hn) - - def test_three_conjunctions(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier de la dos Vega III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la dos Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test_lastname_three_conjunctions(self) -> None: - hn = HumanName("de la dos Vega, Dr. Juan Q. Xavier III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la dos Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - def test_comma_three_conjunctions(self) -> None: - hn = HumanName("Dr. Juan Q. Xavier de la dos Vega, III") - self.m(hn.first, "Juan", hn) - self.m(hn.last, "de la dos Vega", hn) - self.m(hn.title, "Dr.", hn) - self.m(hn.middle, "Q. Xavier", hn) - self.m(hn.suffix, "III", hn) - - -class SuffixesTestCase(HumanNameTestBase): - - def test_suffix(self) -> None: - hn = HumanName("Joe Franklin Jr") - self.m(hn.first, "Joe", hn) - self.m(hn.last, "Franklin", hn) - self.m(hn.suffix, "Jr", hn) - - def test_suffix_with_periods(self) -> None: - hn = HumanName("Joe Dentist D.D.S.") - self.m(hn.first, "Joe", hn) - self.m(hn.last, "Dentist", hn) - self.m(hn.suffix, "D.D.S.", hn) - - def test_two_suffixes(self) -> None: - hn = HumanName("Kenneth Clarke QC MP") - self.m(hn.first, "Kenneth", hn) - self.m(hn.last, "Clarke", hn) - # NOTE: this adds a comma when the original format did not have one. - # not ideal but at least its in the right bucket - self.m(hn.suffix, "QC, MP", hn) - - def test_two_suffixes_lastname_comma_format(self) -> None: - hn = HumanName("Washington Jr. MD, Franklin") - self.m(hn.first, "Franklin", hn) - self.m(hn.last, "Washington", hn) - # NOTE: this adds a comma when the original format did not have one. - self.m(hn.suffix, "Jr., MD", hn) - - def test_two_suffixes_suffix_comma_format(self) -> None: - hn = HumanName("Franklin Washington, Jr. MD") - self.m(hn.first, "Franklin", hn) - self.m(hn.last, "Washington", hn) - self.m(hn.suffix, "Jr. MD", hn) - - def test_suffix_containing_periods(self) -> None: - hn = HumanName("Kenneth Clarke Q.C.") - self.m(hn.first, "Kenneth", hn) - self.m(hn.last, "Clarke", hn) - self.m(hn.suffix, "Q.C.", hn) - - def test_suffix_containing_periods_lastname_comma_format(self) -> None: - hn = HumanName("Clarke, Kenneth, Q.C. M.P.") - self.m(hn.first, "Kenneth", hn) - self.m(hn.last, "Clarke", hn) - self.m(hn.suffix, "Q.C. M.P.", hn) - - def test_suffix_containing_periods_suffix_comma_format(self) -> None: - hn = HumanName("Kenneth Clarke Q.C., M.P.") - self.m(hn.first, "Kenneth", hn) - self.m(hn.last, "Clarke", hn) - self.m(hn.suffix, "Q.C., M.P.", hn) - - def test_suffix_with_single_comma_format(self) -> None: - hn = HumanName("John Doe jr., MD") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "jr., MD", hn) - - def test_suffix_with_double_comma_format(self) -> None: - hn = HumanName("Doe, John jr., MD") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "jr., MD", hn) - - def test_phd_with_erroneous_space(self) -> None: - hn = HumanName("John Smith, Ph. D.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "Ph. D.", hn) - - def test_phd_extracted_without_comma(self) -> None: - hn = HumanName("John Smith Ph. D.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Smith", hn) - self.m(hn.suffix, "Ph. D.", hn) - - def test_phd_conflict(self) -> None: - hn = HumanName("Adolph D") - self.m(hn.first, "Adolph", hn) - self.m(hn.last, "D", hn) - - # http://en.wikipedia.org/wiki/Ma_(surname) - - def test_potential_suffix_that_is_also_last_name(self) -> None: - hn = HumanName("Jack Ma") - self.m(hn.first, "Jack", hn) - self.m(hn.last, "Ma", hn) - - def test_potential_suffix_that_is_also_last_name_comma(self) -> None: - hn = HumanName("Ma, Jack") - self.m(hn.first, "Jack", hn) - self.m(hn.last, "Ma", hn) - - def test_potential_suffix_that_is_also_last_name_with_suffix(self) -> None: - hn = HumanName("Jack Ma Jr") - self.m(hn.first, "Jack", hn) - self.m(hn.last, "Ma", hn) - self.m(hn.suffix, "Jr", hn) - - def test_potential_suffix_that_is_also_last_name_with_suffix_comma(self) -> None: - hn = HumanName("Ma III, Jack Jr") - self.m(hn.first, "Jack", hn) - self.m(hn.last, "Ma", hn) - self.m(hn.suffix, "III, Jr", hn) - - # https://github.com/derek73/python-nameparser/issues/27 - @unittest.expectedFailure - def test_king(self) -> None: - hn = HumanName("Dr King Jr") - self.m(hn.title, "Dr", hn) - self.m(hn.last, "King", hn) - self.m(hn.suffix, "Jr", hn) - - def test_multiple_letter_suffix_with_periods(self) -> None: - hn = HumanName("John Doe Msc.Ed.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Msc.Ed.", hn) - - def test_suffix_with_periods_with_comma(self) -> None: - hn = HumanName("John Doe, Msc.Ed.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Msc.Ed.", hn) - - def test_suffix_with_periods_with_lastname_comma(self) -> None: - hn = HumanName("Doe, John Msc.Ed.") - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.suffix, "Msc.Ed.", hn) - - -class TitleTestCase(HumanNameTestBase): - - def test_last_name_is_also_title(self) -> None: - hn = HumanName("Amy E Maid") - self.m(hn.first, "Amy", hn) - self.m(hn.middle, "E", hn) - self.m(hn.last, "Maid", hn) - - def test_last_name_is_also_title_no_comma(self) -> None: - hn = HumanName("Dr. Martin Luther King Jr.") - self.m(hn.title, "Dr.", hn) - self.m(hn.first, "Martin", hn) - self.m(hn.middle, "Luther", hn) - self.m(hn.last, "King", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_last_name_is_also_title_with_comma(self) -> None: - hn = HumanName("Dr Martin Luther King, Jr.") - self.m(hn.title, "Dr", hn) - self.m(hn.first, "Martin", hn) - self.m(hn.middle, "Luther", hn) - self.m(hn.last, "King", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_last_name_is_also_title3(self) -> None: - hn = HumanName("John King") - self.m(hn.first, "John", hn) - self.m(hn.last, "King", hn) - - def test_title_with_conjunction(self) -> None: - hn = HumanName("Secretary of State Hillary Clinton") - self.m(hn.title, "Secretary of State", hn) - self.m(hn.first, "Hillary", hn) - self.m(hn.last, "Clinton", hn) - - def test_compound_title_with_conjunction(self) -> None: - hn = HumanName("Cardinal Secretary of State Hillary Clinton") - self.m(hn.title, "Cardinal Secretary of State", hn) - self.m(hn.first, "Hillary", hn) - self.m(hn.last, "Clinton", hn) - - def test_title_is_title(self) -> None: - hn = HumanName("Coach") - self.m(hn.title, "Coach", hn) - - # TODO: fix handling of U.S. - @unittest.expectedFailure - def test_chained_title_first_name_title_is_initials(self) -> None: - hn = HumanName("U.S. District Judge Marc Thomas Treadwell") - self.m(hn.title, "U.S. District Judge", hn) - self.m(hn.first, "Marc", hn) - self.m(hn.middle, "Thomas", hn) - self.m(hn.last, "Treadwell", hn) - - def test_conflict_with_chained_title_first_name_initial(self) -> None: - hn = HumanName("U. S. Grant") - self.m(hn.first, "U.", hn) - self.m(hn.middle, "S.", hn) - self.m(hn.last, "Grant", hn) - - def test_chained_title_first_name_initial_with_no_period(self) -> None: - hn = HumanName("US Magistrate Judge T Michael Putnam") - self.m(hn.title, "US Magistrate Judge", hn) - self.m(hn.first, "T", hn) - self.m(hn.middle, "Michael", hn) - self.m(hn.last, "Putnam", hn) - - def test_chained_hyphenated_title(self) -> None: - hn = HumanName("US Magistrate-Judge Elizabeth E Campbell") - self.m(hn.title, "US Magistrate-Judge", hn) - self.m(hn.first, "Elizabeth", hn) - self.m(hn.middle, "E", hn) - self.m(hn.last, "Campbell", hn) - - def test_chained_hyphenated_title_with_comma_suffix(self) -> None: - hn = HumanName("Mag-Judge Harwell G Davis, III") - self.m(hn.title, "Mag-Judge", hn) - self.m(hn.first, "Harwell", hn) - self.m(hn.middle, "G", hn) - self.m(hn.last, "Davis", hn) - self.m(hn.suffix, "III", hn) - - @unittest.expectedFailure - def test_title_multiple_titles_with_apostrophe_s(self) -> None: - hn = HumanName("The Right Hon. the President of the Queen's Bench Division") - self.m(hn.title, "The Right Hon. the President of the Queen's Bench Division", hn) - - def test_title_starts_with_conjunction(self) -> None: - hn = HumanName("The Rt Hon John Jones") - self.m(hn.title, "The Rt Hon", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Jones", hn) - - def test_conjunction_before_title(self) -> None: - hn = HumanName('The Lord of the Universe') - self.m(hn.title, "The Lord of the Universe", hn) - - def test_double_conjunction_on_title(self) -> None: - hn = HumanName('Lord of the Universe') - self.m(hn.title, "Lord of the Universe", hn) - - def test_triple_conjunction_on_title(self) -> None: - hn = HumanName('Lord and of the Universe') - self.m(hn.title, "Lord and of the Universe", hn) - - def test_multiple_conjunctions_on_multiple_titles(self) -> None: - hn = HumanName('Lord of the Universe and Associate Supreme Queen of the World Lisa Simpson') - self.m(hn.title, "Lord of the Universe and Associate Supreme Queen of the World", hn) - self.m(hn.first, "Lisa", hn) - self.m(hn.last, "Simpson", hn) - - def test_title_with_last_initial_is_suffix(self) -> None: - hn = HumanName("King John V.") - self.m(hn.title, "King", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "V.", hn) - - def test_initials_also_suffix(self) -> None: - hn = HumanName("Smith, J.R.") - self.m(hn.first, "J.R.", hn) - # self.m(hn.middle, "R.", hn) - self.m(hn.last, "Smith", hn) - - def test_two_title_parts_separated_by_periods(self) -> None: - hn = HumanName("Lt.Gen. John A. Kenneth Doe IV") - self.m(hn.title, "Lt.Gen.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "IV", hn) - - def test_two_part_title(self) -> None: - hn = HumanName("Lt. Gen. John A. Kenneth Doe IV") - self.m(hn.title, "Lt. Gen.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "IV", hn) - - def test_two_part_title_with_lastname_comma(self) -> None: - hn = HumanName("Doe, Lt. Gen. John A. Kenneth IV") - self.m(hn.title, "Lt. Gen.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "IV", hn) - - def test_two_part_title_with_suffix_comma(self) -> None: - hn = HumanName("Lt. Gen. John A. Kenneth Doe, Jr.") - self.m(hn.title, "Lt. Gen.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A. Kenneth", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_possible_conflict_with_middle_initial_that_could_be_suffix(self) -> None: - hn = HumanName("Doe, Rev. John V, Jr.") - self.m(hn.title, "Rev.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "V", hn) - self.m(hn.suffix, "Jr.", hn) - - def test_possible_conflict_with_suffix_that_could_be_initial(self) -> None: - hn = HumanName("Doe, Rev. John A., V, Jr.") - self.m(hn.title, "Rev.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - self.m(hn.middle, "A.", hn) - self.m(hn.suffix, "V, Jr.", hn) - - # 'ben' is removed from PREFIXES in v0.2.5 - # this test could re-enable this test if we decide to support 'ben' as a prefix - @unittest.expectedFailure - def test_ben_as_conjunction(self) -> None: - hn = HumanName("Ahmad ben Husain") - self.m(hn.first, "Ahmad", hn) - self.m(hn.last, "ben Husain", hn) - - def test_ben_as_first_name(self) -> None: - hn = HumanName("Ben Johnson") - self.m(hn.first, "Ben", hn) - self.m(hn.last, "Johnson", hn) - - def test_ben_as_first_name_with_middle_name(self) -> None: - hn = HumanName("Ben Alex Johnson") - self.m(hn.first, "Ben", hn) - self.m(hn.middle, "Alex", hn) - self.m(hn.last, "Johnson", hn) - - def test_ben_as_middle_name(self) -> None: - hn = HumanName("Alex Ben Johnson") - self.m(hn.first, "Alex", hn) - self.m(hn.middle, "Ben", hn) - self.m(hn.last, "Johnson", hn) - - # http://code.google.com/p/python-nameparser/issues/detail?id=13 - def test_last_name_also_prefix(self) -> None: - hn = HumanName("Jane Doctor") - self.m(hn.first, "Jane", hn) - self.m(hn.last, "Doctor", hn) - - def test_title_with_periods(self) -> None: - hn = HumanName("Lt.Gov. John Doe") - self.m(hn.title, "Lt.Gov.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test_title_with_periods_lastname_comma(self) -> None: - hn = HumanName("Doe, Lt.Gov. John") - self.m(hn.title, "Lt.Gov.", hn) - self.m(hn.first, "John", hn) - self.m(hn.last, "Doe", hn) - - def test_mac_with_spaces(self) -> None: - hn = HumanName("Jane Mac Beth") - self.m(hn.first, "Jane", hn) - self.m(hn.last, "Mac Beth", hn) - - def test_mac_as_first_name(self) -> None: - hn = HumanName("Mac Miller") - self.m(hn.first, "Mac", hn) - self.m(hn.last, "Miller", hn) - - def test_multiple_prefixes(self) -> None: - hn = HumanName("Mike van der Velt") - self.m(hn.first, "Mike", hn) - self.m(hn.last, "van der Velt", hn) - - def test_2_same_prefixes_in_the_name(self) -> None: - hh = HumanName("Vincent van Gogh van Beethoven") - self.m(hh.first, "Vincent", hh) - self.m(hh.middle, "van Gogh", hh) - self.m(hh.last, "van Beethoven", hh) - -class HumanNameCapitalizationTestCase(HumanNameTestBase): - def test_capitalization_exception_for_III(self) -> None: - hn = HumanName('juan q. xavier velasquez y garcia iii') - hn.capitalize() - self.m(str(hn), 'Juan Q. Xavier Velasquez y Garcia III', hn) - - # FIXME: this test does not pass due to a known issue - # http://code.google.com/p/python-nameparser/issues/detail?id=22 - @unittest.expectedFailure - def test_capitalization_exception_for_already_capitalized_III_KNOWN_FAILURE(self) -> None: - hn = HumanName('juan garcia III') - hn.capitalize() - self.m(str(hn), 'Juan Garcia III', hn) - - def test_capitalize_title(self) -> None: - hn = HumanName('lt. gen. john a. kenneth doe iv') - hn.capitalize() - self.m(str(hn), 'Lt. Gen. John A. Kenneth Doe IV', hn) - - def test_capitalize_title_to_lower(self) -> None: - hn = HumanName('LT. GEN. JOHN A. KENNETH DOE IV') - hn.capitalize() - self.m(str(hn), 'Lt. Gen. John A. Kenneth Doe IV', hn) - - # Capitalization with M(a)c and hyphenated names - def test_capitalization_with_Mac_as_hyphenated_names(self) -> None: - hn = HumanName('donovan mcnabb-smith') - hn.capitalize() - self.m(str(hn), 'Donovan McNabb-Smith', hn) - - def test_capitization_middle_initial_is_also_a_conjunction(self) -> None: - hn = HumanName('scott e. werner') - hn.capitalize() - self.m(str(hn), 'Scott E. Werner', hn) - - # Leaving already-capitalized names alone - def test_no_change_to_mixed_chase(self) -> None: - hn = HumanName('Shirley Maclaine') - hn.capitalize() - self.m(str(hn), 'Shirley Maclaine', hn) - - def test_force_capitalization(self) -> None: - hn = HumanName('Shirley Maclaine') - hn.capitalize(force=True) - self.m(str(hn), 'Shirley MacLaine', hn) - - def test_capitalize_diacritics(self) -> None: - hn = HumanName('matthëus schmidt') - hn.capitalize() - self.m(str(hn), 'Matthëus Schmidt', hn) - - # http://code.google.com/p/python-nameparser/issues/detail?id=15 - def test_downcasing_mac(self) -> None: - hn = HumanName('RONALD MACDONALD') - hn.capitalize() - self.m(str(hn), 'Ronald MacDonald', hn) - - # http://code.google.com/p/python-nameparser/issues/detail?id=23 - def test_downcasing_mc(self) -> None: - hn = HumanName('RONALD MCDONALD') - hn.capitalize() - self.m(str(hn), 'Ronald McDonald', hn) - - def test_short_names_with_mac(self) -> None: - hn = HumanName('mack johnson') - hn.capitalize() - self.m(str(hn), 'Mack Johnson', hn) - - def test_portuguese_prefixes(self) -> None: - hn = HumanName("joao da silva do amaral de souza") - hn.capitalize() - self.m(str(hn), 'Joao da Silva do Amaral de Souza', hn) - - def test_capitalize_prefix_clash_on_first_name(self) -> None: - hn = HumanName("van nguyen") - hn.capitalize() - self.m(str(hn), 'Van Nguyen', hn) - - -class HumanNameOutputFormatTests(HumanNameTestBase): - - def test_formatting_init_argument(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)", - string_format="TEST1") - self.assertEqual(str(hn), "TEST1") - - def test_formatting_constants_attribute(self) -> None: - from nameparser.config import CONSTANTS - _orig = CONSTANTS.string_format - CONSTANTS.string_format = "TEST2" - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - self.assertEqual(str(hn), "TEST2") - CONSTANTS.string_format = _orig - - def test_capitalize_name_constants_attribute(self) -> None: - from nameparser.config import CONSTANTS - CONSTANTS.capitalize_name = True - hn = HumanName("bob v. de la macdole-eisenhower phd") - self.assertEqual(str(hn), "Bob V. de la MacDole-Eisenhower Ph.D.") - CONSTANTS.capitalize_name = False - - def test_force_mixed_case_capitalization_constants_attribute(self) -> None: - from nameparser.config import CONSTANTS - CONSTANTS.force_mixed_case_capitalization = True - hn = HumanName('Shirley Maclaine') - hn.capitalize() - self.assertEqual(str(hn), "Shirley MacLaine") - CONSTANTS.force_mixed_case_capitalization = False - - def test_capitalize_name_and_force_mixed_case_capitalization_constants_attributes(self) -> None: - from nameparser.config import CONSTANTS - CONSTANTS.capitalize_name = True - CONSTANTS.force_mixed_case_capitalization = True - hn = HumanName('Shirley Maclaine') - self.assertEqual(str(hn), "Shirley MacLaine") - - def test_quote_nickname_formating(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") - hn.string_format = "{last}, {title} {first} {middle}, {suffix} '{nickname}'" - self.assertEqual(str(hn), "Doe, Rev John A. Kenneth, III 'Kenny'") - - def test_formating_removing_keys_from_format_string(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") - hn.string_format = "{last}, {title} {first} {middle}, {suffix}" - self.assertEqual(str(hn), "Doe, Rev John A. Kenneth, III") - hn.string_format = "{last}, {title} {first} {middle}" - self.assertEqual(str(hn), "Doe, Rev John A. Kenneth") - hn.string_format = "{last}, {first} {middle}" - self.assertEqual(str(hn), "Doe, John A. Kenneth") - hn.string_format = "{last}, {first}" - self.assertEqual(str(hn), "Doe, John") - hn.string_format = "{first} {last}" - self.assertEqual(str(hn), "John Doe") - - def test_formating_removing_pieces_from_name_buckets(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") - hn.string_format = "{title} {first} {middle} {last} {suffix}" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") - hn.middle = '' - self.assertEqual(str(hn), "Rev John Doe III") - hn.suffix = '' - self.assertEqual(str(hn), "Rev John Doe") - hn.title = '' - self.assertEqual(str(hn), "John Doe") - - def test_formating_of_nicknames_with_parenthesis(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} ({nickname})" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III (Kenny)") - hn.nickname = '' - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") - - def test_formating_of_nicknames_with_single_quotes(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") - hn.nickname = '' - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") - - def test_formating_of_nicknames_with_double_quotes(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} {middle} {last} {suffix} \"{nickname}\"" - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III \"Kenny\"") - hn.nickname = '' - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") - - def test_formating_of_nicknames_in_middle(self) -> None: - hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") - hn.string_format = "{title} {first} ({nickname}) {middle} {last} {suffix}" - self.assertEqual(str(hn), "Rev John (Kenny) A. Kenneth Doe III") - hn.nickname = '' - self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") - - def test_remove_emojis(self) -> None: - hn = HumanName("Sam Smith 😊") - self.m(hn.first, "Sam", hn) - self.m(hn.last, "Smith", hn) - self.assertEqual(str(hn), "Sam Smith") - - def test_keep_non_emojis(self) -> None: - hn = HumanName("∫≜⩕ Smith 😊") - self.m(hn.first, "∫≜⩕", hn) - self.m(hn.last, "Smith", hn) - self.assertEqual(str(hn), "∫≜⩕ Smith") - - def test_keep_emojis(self) -> None: - from nameparser.config import Constants - constants = Constants() - constants.regexes.emoji = False - hn = HumanName("∫≜⩕ Smith😊", constants) - self.m(hn.first, "∫≜⩕", hn) - self.m(hn.last, "Smith😊", hn) - self.assertEqual(str(hn), "∫≜⩕ Smith😊") - # test cleanup - - -class InitialsTestCase(HumanNameTestBase): - def test_initials(self) -> None: - hn = HumanName("Andrew Boris Petersen") - self.m(hn.initials(), "A. B. P.", hn) - - def test_initials_simple_name(self) -> None: - hn = HumanName("John Doe") - self.m(hn.initials(), "J. D.", hn) - hn = HumanName("John Doe", initials_format="{first} {last}") - self.m(hn.initials(), "J. D.", hn) - hn = HumanName("John Doe", initials_format="{last}") - self.m(hn.initials(), "D.", hn) - hn = HumanName("John Doe", initials_format="{first}") - self.m(hn.initials(), "J.", hn) - hn = HumanName("John Doe", initials_format="{middle}") - self.m(hn.initials(), "", hn) - - def test_initials_complex_name(self) -> None: - hn = HumanName("Doe, John A. Kenneth, Jr.") - self.m(hn.initials(), "J. A. K. D.", hn) - - def test_initials_format(self) -> None: - hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first} {middle}") - self.m(hn.initials(), "J. A. K.", hn) - hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first} {last}") - self.m(hn.initials(), "J. D.", hn) - hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{middle} {last}") - self.m(hn.initials(), "A. K. D.", hn) - hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first}, {last}") - self.m(hn.initials(), "J., D.", hn) - - def test_initials_format_constants(self) -> None: - from nameparser.config import CONSTANTS - _orig = CONSTANTS.initials_format - CONSTANTS.initials_format = "{first} {last}" - hn = HumanName("Doe, John A. Kenneth, Jr.") - self.m(hn.initials(), "J. D.", hn) - CONSTANTS.initials_format = "{first} {last}" - hn = HumanName("Doe, John A. Kenneth, Jr.") - self.m(hn.initials(), "J. D.", hn) - CONSTANTS.initials_format = _orig - - def test_initials_delimiter(self) -> None: - hn = HumanName("Doe, John A. Kenneth, Jr.", initials_delimiter=";") - self.m(hn.initials(), "J; A; K; D;", hn) - - def test_initials_delimiter_constants(self) -> None: - from nameparser.config import CONSTANTS - _orig = CONSTANTS.initials_delimiter - CONSTANTS.initials_delimiter = ";" - hn = HumanName("Doe, John A. Kenneth, Jr.") - self.m(hn.initials(), "J; A; K; D;", hn) - CONSTANTS.initials_delimiter = _orig - - def test_initials_list(self) -> None: - hn = HumanName("Andrew Boris Petersen") - self.m(hn.initials_list(), ["A", "B", "P"], hn) - - def test_initials_list_complex_name(self) -> None: - hn = HumanName("Doe, John A. Kenneth, Jr.") - self.m(hn.initials_list(), ["J", "A", "K", "D"], hn) - - def test_initials_with_prefix_firstname(self) -> None: - hn = HumanName("Van Jeremy Johnson") - self.m(hn.initials_list(), ["V", "J", "J"], hn) - - def test_initials_with_prefix(self) -> None: - hn = HumanName("Alex van Johnson") - self.m(hn.initials_list(), ["A", "J"], hn) - - def test_constructor_first(self) -> None: - hn = HumanName(first="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.first, "TheName", hn) - - def test_constructor_middle(self) -> None: - hn = HumanName(middle="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.middle, "TheName", hn) - - def test_constructor_last(self) -> None: - hn = HumanName(last="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.last, "TheName", hn) - - def test_constructor_title(self) -> None: - hn = HumanName(title="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.title, "TheName", hn) - - def test_constructor_suffix(self) -> None: - hn = HumanName(suffix="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.suffix, "TheName", hn) - - def test_constructor_nickname(self) -> None: - hn = HumanName(nickname="TheName") - self.assertFalse(hn.unparsable) - self.m(hn.nickname, "TheName", hn) - - def test_constructor_multiple(self) -> None: - hn = HumanName(first="TheName", last="lastname", title="mytitle", full_name="donotparse") - self.assertFalse(hn.unparsable) - self.m(hn.first, "TheName", hn) - self.m(hn.last, "lastname", hn) - self.m(hn.title, "mytitle", hn) - - -TEST_NAMES = ( - "John Doe", - "John Doe, Jr.", - "John Doe III", - "Doe, John", - "Doe, John, Jr.", - "Doe, John III", - "John A. Doe", - "John A. Doe, Jr.", - "John A. Doe III", - "Doe, John A.", - "Doe, John A., Jr.", - "Doe, John A. III", - "John A. Kenneth Doe", - "John A. Kenneth Doe, Jr.", - "John A. Kenneth Doe III", - "Doe, John A. Kenneth", - "Doe, John A. Kenneth, Jr.", - "Doe, John A. Kenneth III", - "Dr. John Doe", - "Dr. John Doe, Jr.", - "Dr. John Doe III", - "Doe, Dr. John", - "Doe, Dr. John, Jr.", - "Doe, Dr. John III", - "Dr. John A. Doe", - "Dr. John A. Doe, Jr.", - "Dr. John A. Doe III", - "Doe, Dr. John A.", - "Doe, Dr. John A. Jr.", - "Doe, Dr. John A. III", - "Dr. John A. Kenneth Doe", - "Dr. John A. Kenneth Doe, Jr.", - "Dr. John A. Kenneth Doe III", - "Doe, Dr. John A. Kenneth", - "Doe, Dr. John A. Kenneth Jr.", - "Doe, Dr. John A. Kenneth III", - "Juan de la Vega", - "Juan de la Vega, Jr.", - "Juan de la Vega III", - "de la Vega, Juan", - "de la Vega, Juan, Jr.", - "de la Vega, Juan III", - "Juan Velasquez y Garcia", - "Juan Velasquez y Garcia, Jr.", - "Juan Velasquez y Garcia III", - "Velasquez y Garcia, Juan", - "Velasquez y Garcia, Juan, Jr.", - "Velasquez y Garcia, Juan III", - "Dr. Juan de la Vega", - "Dr. Juan de la Vega, Jr.", - "Dr. Juan de la Vega III", - "de la Vega, Dr. Juan", - "de la Vega, Dr. Juan, Jr.", - "de la Vega, Dr. Juan III", - "Dr. Juan Velasquez y Garcia", - "Dr. Juan Velasquez y Garcia, Jr.", - "Dr. Juan Velasquez y Garcia III", - "Velasquez y Garcia, Dr. Juan", - "Velasquez y Garcia, Dr. Juan, Jr.", - "Velasquez y Garcia, Dr. Juan III", - "Juan Q. de la Vega", - "Juan Q. de la Vega, Jr.", - "Juan Q. de la Vega III", - "de la Vega, Juan Q.", - "de la Vega, Juan Q., Jr.", - "de la Vega, Juan Q. III", - "Juan Q. Velasquez y Garcia", - "Juan Q. Velasquez y Garcia, Jr.", - "Juan Q. Velasquez y Garcia III", - "Velasquez y Garcia, Juan Q.", - "Velasquez y Garcia, Juan Q., Jr.", - "Velasquez y Garcia, Juan Q. III", - "Dr. Juan Q. de la Vega", - "Dr. Juan Q. de la Vega, Jr.", - "Dr. Juan Q. de la Vega III", - "de la Vega, Dr. Juan Q.", - "de la Vega, Dr. Juan Q., Jr.", - "de la Vega, Dr. Juan Q. III", - "Dr. Juan Q. Velasquez y Garcia", - "Dr. Juan Q. Velasquez y Garcia, Jr.", - "Dr. Juan Q. Velasquez y Garcia III", - "Velasquez y Garcia, Dr. Juan Q.", - "Velasquez y Garcia, Dr. Juan Q., Jr.", - "Velasquez y Garcia, Dr. Juan Q. III", - "Juan Q. Xavier de la Vega", - "Juan Q. Xavier de la Vega, Jr.", - "Juan Q. Xavier de la Vega III", - "de la Vega, Juan Q. Xavier", - "de la Vega, Juan Q. Xavier, Jr.", - "de la Vega, Juan Q. Xavier III", - "Juan Q. Xavier Velasquez y Garcia", - "Juan Q. Xavier Velasquez y Garcia, Jr.", - "Juan Q. Xavier Velasquez y Garcia III", - "Velasquez y Garcia, Juan Q. Xavier", - "Velasquez y Garcia, Juan Q. Xavier, Jr.", - "Velasquez y Garcia, Juan Q. Xavier III", - "Dr. Juan Q. Xavier de la Vega", - "Dr. Juan Q. Xavier de la Vega, Jr.", - "Dr. Juan Q. Xavier de la Vega III", - "de la Vega, Dr. Juan Q. Xavier", - "de la Vega, Dr. Juan Q. Xavier, Jr.", - "de la Vega, Dr. Juan Q. Xavier III", - "Dr. Juan Q. Xavier Velasquez y Garcia", - "Dr. Juan Q. Xavier Velasquez y Garcia, Jr.", - "Dr. Juan Q. Xavier Velasquez y Garcia III", - "Velasquez y Garcia, Dr. Juan Q. Xavier", - "Velasquez y Garcia, Dr. Juan Q. Xavier, Jr.", - "Velasquez y Garcia, Dr. Juan Q. Xavier III", - "John Doe, CLU, CFP, LUTC", - "John P. Doe, CLU, CFP, LUTC", - "Dr. John P. Doe-Ray, CLU, CFP, LUTC", - "Doe-Ray, Dr. John P., CLU, CFP, LUTC", - "Hon. Barrington P. Doe-Ray, Jr.", - "Doe-Ray, Hon. Barrington P. Jr.", - "Doe-Ray, Hon. Barrington P. Jr., CFP, LUTC", - "Jose Aznar y Lopez", - "John E Smith", - "John e Smith", - "John and Jane Smith", - "Rev. John A. Kenneth Doe", - "Donovan McNabb-Smith", - "Rev John A. Kenneth Doe", - "Doe, Rev. John A. Jr.", - "Buca di Beppo", - "Lt. Gen. John A. Kenneth Doe, Jr.", - "Doe, Lt. Gen. John A. Kenneth IV", - "Lt. Gen. John A. Kenneth Doe IV", - 'Mr. and Mrs. John Smith', - 'John Jones (Google Docs)', - 'john e jones', - 'john e jones, III', - 'jones, john e', - 'E.T. Smith', - 'E.T. Smith, II', - 'Smith, E.T., Jr.', - 'A.B. Vajpayee', - 'Rt. Hon. Paul E. Mary', - 'Maid Marion', - 'Amy E. Maid', - 'Jane Doctor', - 'Doctor, Jane E.', - 'dr. ben alex johnson III', - 'Lord of the Universe and Supreme King of the World Lisa Simpson', - 'Benjamin (Ben) Franklin', - 'Benjamin "Ben" Franklin', - "Brian O'connor", - "Sir Gerald", - "Magistrate Judge John F. Forster, Jr", - # "Magistrate Judge Joaquin V.E. Manibusan, Jr", Intials seem to mess this up - "Magistrate-Judge Elizabeth Todd Campbell", - "Mag-Judge Harwell G Davis, III", - "Mag. Judge Byron G. Cudmore", - "Chief Judge J. Leon Holmes", - "Chief Judge Sharon Lovelace Blackburn", - "Judge James M. Moody", - "Judge G. Thomas Eisele", - # "Judge Callie V. S. Granade", - "Judge C Lynwood Smith, Jr", - "Senior Judge Charles R. Butler, Jr", - "Senior Judge Harold D. Vietor", - "Senior Judge Virgil Pittman", - "Honorable Terry F. Moorer", - "Honorable W. Harold Albritton, III", - "Honorable Judge W. Harold Albritton, III", - "Honorable Judge Terry F. Moorer", - "Honorable Judge Susan Russ Walker", - "Hon. Marian W. Payson", - "Hon. Charles J. Siragusa", - "US Magistrate Judge T Michael Putnam", - "Designated Judge David A. Ezra", - "Sr US District Judge Richard G Kopf", - "U.S. District Judge Marc Thomas Treadwell", - "Dra. Andréia da Silva", - "Srta. Andréia da Silva", - -) - - -class HumanNameVariationTests(HumanNameTestBase): - # test automated variations of names in TEST_NAMES. - # Helps test that the 3 code trees work the same - - TEST_NAMES = TEST_NAMES - - def test_variations_of_TEST_NAMES(self) -> None: - for name in self.TEST_NAMES: - hn = HumanName(name) - if len(hn.suffix_list) > 1: - hn = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn.as_dict()).split(',')[0]) - hn.C.empty_attribute_default = '' # format strings below require empty string - hn_dict = hn.as_dict() - nocomma = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn_dict)) - lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix}".format(**hn_dict)) - if hn.suffix: - suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix}".format(**hn_dict)) - if hn.nickname: - nocomma = HumanName("{title} {first} {middle} {last} {suffix} ({nickname})".format(**hn_dict)) - lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix} ({nickname})".format(**hn_dict)) - if hn.suffix: - suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix} ({nickname})".format(**hn_dict)) - for attr in hn._members: - self.m(getattr(hn, attr), getattr(nocomma, attr), hn) - self.m(getattr(hn, attr), getattr(lastnamecomma, attr), hn) - if hn.suffix: - self.m(getattr(hn, attr), getattr(suffixcomma, attr), hn) - - -if __name__ == '__main__': - import sys - - if len(sys.argv) > 1: - log.setLevel(logging.ERROR) - log.addHandler(logging.StreamHandler()) - name_string = sys.argv[1] - hn_instance = HumanName(name_string, encoding=sys.stdout.encoding) - print(repr(hn_instance)) - hn_instance.capitalize() - print(repr(hn_instance)) - print("Initials: " + hn_instance.initials()) - else: - print("-"*80) - print("Running tests") - unittest.main(exit=False) - print("-"*80) - print("Running tests with empty_attribute_default = None") - from nameparser.config import CONSTANTS - CONSTANTS.empty_attribute_default = None - unittest.main() diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/base.py b/tests/base.py new file mode 100644 index 0000000..25032e2 --- /dev/null +++ b/tests/base.py @@ -0,0 +1,40 @@ +from typing import Generic, TypeVar + +from nameparser import HumanName + +T = TypeVar('T') + + +class HumanNameTestBase(Generic[T]): + """Shared assert helpers for the parsing tests. + + Formerly subclassed unittest.TestCase. It is now a plain class so pytest can + apply the parametrized dual-run fixture in conftest.py — parametrized + fixtures do not apply to unittest.TestCase subclasses. The assert* methods + are thin shims so existing test bodies move over unchanged. + """ + + def m(self, actual: T, expected: T, hn: HumanName) -> None: + """assertEqual with a better message and awareness of hn.C.empty_attribute_default""" + expected_ = expected or hn.C.empty_attribute_default + try: + assert actual == expected_, "'%s' != '%s' for '%s'\n%r" % ( + actual, + expected, + hn.original, + hn, + ) + except UnicodeDecodeError: + assert actual == expected_ + + def assertEqual(self, first: object, second: object, msg: object = None) -> None: + assert first == second, msg + + def assertTrue(self, expr: object, msg: object = None) -> None: + assert expr, msg + + def assertFalse(self, expr: object, msg: object = None) -> None: + assert not expr, msg + + def assertIn(self, member: object, container: object, msg: object = None) -> None: + assert member in container, msg # type: ignore[operator] diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..27f19d8 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,80 @@ +from collections.abc import Iterator + +import pytest + +from nameparser.config import CONSTANTS, SetManager, TupleManager + +ConfigCollection = SetManager | TupleManager + +# Scalar (non-collection) config attributes that individual tests mutate on the +# global CONSTANTS singleton. Several tests change these without restoring them; +# the original suite only survived because unittest happens to run methods in +# alphabetical order, so a later test reset the value. pytest runs in definition +# order, so we snapshot and restore these around every test to keep tests +# isolated regardless of order. +_SCALAR_CONFIG_ATTRS = ( + "empty_attribute_default", + "string_format", + "initials_format", + "initials_delimiter", + "capitalize_name", + "force_mixed_case_capitalization", +) + +# Collection config attributes (the SetManager / TupleManager constants). Tests +# that customize the global CONSTANTS — e.g. adding or removing a title — mutate +# these in place, so a shallow snapshot of the reference would not protect later +# tests. We snapshot independent copies and restore them, making collection +# mutations order-independent too. +_COLLECTION_CONFIG_ATTRS = ( + "prefixes", + "suffix_acronyms", + "suffix_not_acronyms", + "titles", + "first_name_titles", + "conjunctions", + "capitalization_exceptions", + "regexes", +) + + +def _clone_config_collection(value: ConfigCollection) -> ConfigCollection: + """Return an independent copy of a config collection manager. + + ``copy.deepcopy`` is not used because ``RegexTupleManager`` carries compiled + patterns that its ``__reduce__`` cannot round-trip. Rebuilding from the + manager's own contents copies the container while sharing the (immutable) + elements, which is all the snapshot needs. + """ + if isinstance(value, SetManager): + return SetManager(set(value)) + # TupleManager / RegexTupleManager are dict subclasses. + return type(value)(dict(value)) + + +@pytest.fixture(autouse=True, params=['', None], ids=['default', 'none']) +def empty_attribute_default(request: pytest.FixtureRequest) -> Iterator[str | None]: + """Run every test under both empty_attribute_default settings, isolating global config. + + Reproduces the original tests.py __main__ block, which ran the whole suite + twice — once with the default ('') and once with None — as a regression + check that the three parsing code paths agree. The surrounding snapshot of + both the scalar and the collection CONSTANTS attributes restores any global + config a test mutates, so tests do not leak state into one another (the + original relied on unittest's alphabetical method ordering to mask such + leaks). + """ + scalar_snapshot = {attr: getattr(CONSTANTS, attr) for attr in _SCALAR_CONFIG_ATTRS} + collection_snapshot = { + attr: _clone_config_collection(getattr(CONSTANTS, attr)) + for attr in _COLLECTION_CONFIG_ATTRS + } + CONSTANTS.empty_attribute_default = request.param + yield request.param + for attr, value in scalar_snapshot.items(): + setattr(CONSTANTS, attr, value) + for attr, value in collection_snapshot.items(): + setattr(CONSTANTS, attr, value) + # Invalidate the lazily-built suffixes/prefixes/titles cache so it is + # recomputed from the restored collections rather than a mutated one. + CONSTANTS._pst = None diff --git a/tests/test_brute_force.py b/tests/test_brute_force.py new file mode 100644 index 0000000..c46e81f --- /dev/null +++ b/tests/test_brute_force.py @@ -0,0 +1,808 @@ +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class HumanNameBruteForceTests(HumanNameTestBase): + + def test1(self) -> None: + hn = HumanName("John Doe") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test2(self) -> None: + hn = HumanName("John Doe, Jr.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test3(self) -> None: + hn = HumanName("John Doe III") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test4(self) -> None: + hn = HumanName("Doe, John") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test5(self) -> None: + hn = HumanName("Doe, John, Jr.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test6(self) -> None: + hn = HumanName("Doe, John III") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test7(self) -> None: + hn = HumanName("John A. Doe") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + + def test8(self) -> None: + hn = HumanName("John A. Doe, Jr") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "Jr", hn) + + def test9(self) -> None: + hn = HumanName("John A. Doe III") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "III", hn) + + def test10(self) -> None: + hn = HumanName("Doe, John A.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + + def test11(self) -> None: + hn = HumanName("Doe, John A., Jr.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test12(self) -> None: + hn = HumanName("Doe, John A., III") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "III", hn) + + def test13(self) -> None: + hn = HumanName("John A. Kenneth Doe") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + + def test14(self) -> None: + hn = HumanName("John A. Kenneth Doe, Jr.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "Jr.", hn) + + def test15(self) -> None: + hn = HumanName("John A. Kenneth Doe III") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "III", hn) + + def test16(self) -> None: + hn = HumanName("Doe, John. A. Kenneth") + self.m(hn.first, "John.", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + + def test17(self) -> None: + hn = HumanName("Doe, John. A. Kenneth, Jr.") + self.m(hn.first, "John.", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "Jr.", hn) + + def test18(self) -> None: + hn = HumanName("Doe, John. A. Kenneth III") + self.m(hn.first, "John.", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "III", hn) + + def test19(self) -> None: + hn = HumanName("Dr. John Doe") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.title, "Dr.", hn) + + def test20(self) -> None: + hn = HumanName("Dr. John Doe, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test21(self) -> None: + hn = HumanName("Dr. John Doe III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test22(self) -> None: + hn = HumanName("Doe, Dr. John") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test23(self) -> None: + hn = HumanName("Doe, Dr. John, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test24(self) -> None: + hn = HumanName("Doe, Dr. John III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test25(self) -> None: + hn = HumanName("Dr. John A. Doe") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + + def test26(self) -> None: + hn = HumanName("Dr. John A. Doe, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test27(self) -> None: + hn = HumanName("Dr. John A. Doe III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "III", hn) + + def test28(self) -> None: + hn = HumanName("Doe, Dr. John A.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + + def test29(self) -> None: + hn = HumanName("Doe, Dr. John A. Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test30(self) -> None: + hn = HumanName("Doe, Dr. John A. III") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test31(self) -> None: + hn = HumanName("Dr. John A. Kenneth Doe") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test32(self) -> None: + hn = HumanName("Dr. John A. Kenneth Doe, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test33(self) -> None: + hn = HumanName("Al Arnold Gore, Jr.") + self.m(hn.middle, "Arnold", hn) + self.m(hn.first, "Al", hn) + self.m(hn.last, "Gore", hn) + self.m(hn.suffix, "Jr.", hn) + + def test34(self) -> None: + hn = HumanName("Dr. John A. Kenneth Doe III") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test35(self) -> None: + hn = HumanName("Doe, Dr. John A. Kenneth") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test36(self) -> None: + hn = HumanName("Doe, Dr. John A. Kenneth Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Jr.", hn) + + def test37(self) -> None: + hn = HumanName("Doe, Dr. John A. Kenneth III") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "III", hn) + + def test38(self) -> None: + hn = HumanName("Juan de la Vega") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + + def test39(self) -> None: + hn = HumanName("Juan de la Vega, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "Jr.", hn) + + def test40(self) -> None: + hn = HumanName("Juan de la Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "III", hn) + + def test41(self) -> None: + hn = HumanName("de la Vega, Juan") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + + def test42(self) -> None: + hn = HumanName("de la Vega, Juan, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "Jr.", hn) + + def test43(self) -> None: + hn = HumanName("de la Vega, Juan III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "III", hn) + + def test44(self) -> None: + hn = HumanName("Juan Velasquez y Garcia") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test45(self) -> None: + hn = HumanName("Juan Velasquez y Garcia, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test46(self) -> None: + hn = HumanName("Juan Velasquez y Garcia III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test47(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test48(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test49(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test50(self) -> None: + hn = HumanName("Dr. Juan de la Vega") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + + def test51(self) -> None: + hn = HumanName("Dr. Juan de la Vega, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "Jr.", hn) + + def test52(self) -> None: + hn = HumanName("Dr. Juan de la Vega III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "III", hn) + + def test53(self) -> None: + hn = HumanName("de la Vega, Dr. Juan") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + + def test54(self) -> None: + hn = HumanName("de la Vega, Dr. Juan, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "Jr.", hn) + + def test55(self) -> None: + hn = HumanName("de la Vega, Dr. Juan III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "III", hn) + + def test56(self) -> None: + hn = HumanName("Dr. Juan Velasquez y Garcia") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test57(self) -> None: + hn = HumanName("Dr. Juan Velasquez y Garcia, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test58(self) -> None: + hn = HumanName("Dr. Juan Velasquez y Garcia III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test59(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test60(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test61(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan III") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test62(self) -> None: + hn = HumanName("Juan Q. de la Vega") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.last, "de la Vega", hn) + + def test63(self) -> None: + hn = HumanName("Juan Q. de la Vega, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test64(self) -> None: + hn = HumanName("Juan Q. de la Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.suffix, "III", hn) + + def test65(self) -> None: + hn = HumanName("de la Vega, Juan Q.") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.last, "de la Vega", hn) + + def test66(self) -> None: + hn = HumanName("de la Vega, Juan Q., Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test67(self) -> None: + hn = HumanName("de la Vega, Juan Q. III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.suffix, "III", hn) + + def test68(self) -> None: + hn = HumanName("Juan Q. Velasquez y Garcia") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test69(self) -> None: + hn = HumanName("Juan Q. Velasquez y Garcia, Jr.") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test70(self) -> None: + hn = HumanName("Juan Q. Velasquez y Garcia III") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test71(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q.") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test72(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q., Jr.") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test73(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q. III") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test74(self) -> None: + hn = HumanName("Dr. Juan Q. de la Vega") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.last, "de la Vega", hn) + + def test75(self) -> None: + hn = HumanName("Dr. Juan Q. de la Vega, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test76(self) -> None: + hn = HumanName("Dr. Juan Q. de la Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.suffix, "III", hn) + + def test77(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q.") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.title, "Dr.", hn) + + def test78(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q., Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.suffix, "Jr.", hn) + self.m(hn.title, "Dr.", hn) + + def test79(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q. III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.suffix, "III", hn) + self.m(hn.title, "Dr.", hn) + + def test80(self) -> None: + hn = HumanName("Dr. Juan Q. Velasquez y Garcia") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test81(self) -> None: + hn = HumanName("Dr. Juan Q. Velasquez y Garcia, Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test82(self) -> None: + hn = HumanName("Dr. Juan Q. Velasquez y Garcia III") + self.m(hn.middle, "Q.", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test83(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q.") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test84(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q., Jr.") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test85(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q. III") + self.m(hn.middle, "Q.", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test86(self) -> None: + hn = HumanName("Juan Q. Xavier de la Vega") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.last, "de la Vega", hn) + + def test87(self) -> None: + hn = HumanName("Juan Q. Xavier de la Vega, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "Jr.", hn) + + def test88(self) -> None: + hn = HumanName("Juan Q. Xavier de la Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test89(self) -> None: + hn = HumanName("de la Vega, Juan Q. Xavier") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.last, "de la Vega", hn) + + def test90(self) -> None: + hn = HumanName("de la Vega, Juan Q. Xavier, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "Jr.", hn) + + def test91(self) -> None: + hn = HumanName("de la Vega, Juan Q. Xavier III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test92(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier de la Vega") + self.m(hn.first, "Juan", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "de la Vega", hn) + + def test93(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier de la Vega, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "Jr.", hn) + + def test94(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier de la Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test95(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q. Xavier") + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.last, "de la Vega", hn) + + def test96(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q. Xavier, Jr.") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "Jr.", hn) + + def test97(self) -> None: + hn = HumanName("de la Vega, Dr. Juan Q. Xavier III") + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "de la Vega", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test98(self) -> None: + hn = HumanName("Juan Q. Xavier Velasquez y Garcia") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test99(self) -> None: + hn = HumanName("Juan Q. Xavier Velasquez y Garcia, Jr.") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test100(self) -> None: + hn = HumanName("Juan Q. Xavier Velasquez y Garcia III") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test101(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q. Xavier") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test102(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q. Xavier, Jr.") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test103(self) -> None: + hn = HumanName("Velasquez y Garcia, Juan Q. Xavier III") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test104(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test105(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia, Jr.") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test106(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier Velasquez y Garcia III") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test107(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + + def test108(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier, Jr.") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "Jr.", hn) + + def test109(self) -> None: + hn = HumanName("Velasquez y Garcia, Dr. Juan Q. Xavier III") + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.first, "Juan", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test110(self) -> None: + hn = HumanName("John Doe, CLU, CFP, LUTC") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "CLU, CFP, LUTC", hn) + + def test111(self) -> None: + hn = HumanName("John P. Doe, CLU, CFP, LUTC") + self.m(hn.first, "John", hn) + self.m(hn.middle, "P.", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "CLU, CFP, LUTC", hn) + + def test112(self) -> None: + hn = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") + self.m(hn.first, "John", hn) + self.m(hn.middle, "P.", hn) + self.m(hn.last, "Doe-Ray", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.suffix, "CLU, CFP, LUTC", hn) + + def test113(self) -> None: + hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "P.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe-Ray", hn) + self.m(hn.suffix, "CLU, CFP, LUTC", hn) + + def test115(self) -> None: + hn = HumanName("Hon. Barrington P. Doe-Ray, Jr.") + self.m(hn.title, "Hon.", hn) + self.m(hn.middle, "P.", hn) + self.m(hn.first, "Barrington", hn) + self.m(hn.last, "Doe-Ray", hn) + + def test116(self) -> None: + hn = HumanName("Doe-Ray, Hon. Barrington P. Jr., CFP, LUTC") + self.m(hn.title, "Hon.", hn) + self.m(hn.middle, "P.", hn) + self.m(hn.first, "Barrington", hn) + self.m(hn.last, "Doe-Ray", hn) + self.m(hn.suffix, "Jr., CFP, LUTC", hn) + + def test117(self) -> None: + hn = HumanName("Rt. Hon. Paul E. Mary") + self.m(hn.title, "Rt. Hon.", hn) + self.m(hn.first, "Paul", hn) + self.m(hn.middle, "E.", hn) + self.m(hn.last, "Mary", hn) + + def test119(self) -> None: + hn = HumanName("Lord God Almighty") + self.m(hn.title, "Lord", hn) + self.m(hn.first, "God", hn) + self.m(hn.last, "Almighty", hn) diff --git a/tests/test_capitalization.py b/tests/test_capitalization.py new file mode 100644 index 0000000..a281b81 --- /dev/null +++ b/tests/test_capitalization.py @@ -0,0 +1,84 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class HumanNameCapitalizationTestCase(HumanNameTestBase): + def test_capitalization_exception_for_III(self) -> None: + hn = HumanName('juan q. xavier velasquez y garcia iii') + hn.capitalize() + self.m(str(hn), 'Juan Q. Xavier Velasquez y Garcia III', hn) + + # FIXME: this test does not pass due to a known issue + # http://code.google.com/p/python-nameparser/issues/detail?id=22 + @pytest.mark.xfail + def test_capitalization_exception_for_already_capitalized_III_KNOWN_FAILURE(self) -> None: + hn = HumanName('juan garcia III') + hn.capitalize() + self.m(str(hn), 'Juan Garcia III', hn) + + def test_capitalize_title(self) -> None: + hn = HumanName('lt. gen. john a. kenneth doe iv') + hn.capitalize() + self.m(str(hn), 'Lt. Gen. John A. Kenneth Doe IV', hn) + + def test_capitalize_title_to_lower(self) -> None: + hn = HumanName('LT. GEN. JOHN A. KENNETH DOE IV') + hn.capitalize() + self.m(str(hn), 'Lt. Gen. John A. Kenneth Doe IV', hn) + + # Capitalization with M(a)c and hyphenated names + def test_capitalization_with_Mac_as_hyphenated_names(self) -> None: + hn = HumanName('donovan mcnabb-smith') + hn.capitalize() + self.m(str(hn), 'Donovan McNabb-Smith', hn) + + def test_capitization_middle_initial_is_also_a_conjunction(self) -> None: + hn = HumanName('scott e. werner') + hn.capitalize() + self.m(str(hn), 'Scott E. Werner', hn) + + # Leaving already-capitalized names alone + def test_no_change_to_mixed_chase(self) -> None: + hn = HumanName('Shirley Maclaine') + hn.capitalize() + self.m(str(hn), 'Shirley Maclaine', hn) + + def test_force_capitalization(self) -> None: + hn = HumanName('Shirley Maclaine') + hn.capitalize(force=True) + self.m(str(hn), 'Shirley MacLaine', hn) + + def test_capitalize_diacritics(self) -> None: + hn = HumanName('matthëus schmidt') + hn.capitalize() + self.m(str(hn), 'Matthëus Schmidt', hn) + + # http://code.google.com/p/python-nameparser/issues/detail?id=15 + def test_downcasing_mac(self) -> None: + hn = HumanName('RONALD MACDONALD') + hn.capitalize() + self.m(str(hn), 'Ronald MacDonald', hn) + + # http://code.google.com/p/python-nameparser/issues/detail?id=23 + def test_downcasing_mc(self) -> None: + hn = HumanName('RONALD MCDONALD') + hn.capitalize() + self.m(str(hn), 'Ronald McDonald', hn) + + def test_short_names_with_mac(self) -> None: + hn = HumanName('mack johnson') + hn.capitalize() + self.m(str(hn), 'Mack Johnson', hn) + + def test_portuguese_prefixes(self) -> None: + hn = HumanName("joao da silva do amaral de souza") + hn.capitalize() + self.m(str(hn), 'Joao da Silva do Amaral de Souza', hn) + + def test_capitalize_prefix_clash_on_first_name(self) -> None: + hn = HumanName("van nguyen") + hn.capitalize() + self.m(str(hn), 'Van Nguyen', hn) diff --git a/tests/test_conjunctions.py b/tests/test_conjunctions.py new file mode 100644 index 0000000..73ee3cc --- /dev/null +++ b/tests/test_conjunctions.py @@ -0,0 +1,203 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class HumanNameConjunctionTestCase(HumanNameTestBase): + # Last name with conjunction + def test_last_name_with_conjunction(self) -> None: + hn = HumanName('Jose Aznar y Lopez') + self.m(hn.first, "Jose", hn) + self.m(hn.last, "Aznar y Lopez", hn) + + def test_multiple_conjunctions(self) -> None: + hn = HumanName("part1 of The part2 of the part3 and part4") + self.m(hn.first, "part1 of The part2 of the part3 and part4", hn) + + def test_multiple_conjunctions2(self) -> None: + hn = HumanName("part1 of and The part2 of the part3 And part4") + self.m(hn.first, "part1 of and The part2 of the part3 And part4", hn) + + def test_ends_with_conjunction(self) -> None: + hn = HumanName("Jon Dough and") + self.m(hn.first, "Jon", hn) + self.m(hn.last, "Dough and", hn) + + def test_ends_with_two_conjunctions(self) -> None: + hn = HumanName("Jon Dough and of") + self.m(hn.first, "Jon", hn) + self.m(hn.last, "Dough and of", hn) + + def test_starts_with_conjunction(self) -> None: + hn = HumanName("and Jon Dough") + self.m(hn.first, "and Jon", hn) + self.m(hn.last, "Dough", hn) + + def test_starts_with_two_conjunctions(self) -> None: + hn = HumanName("the and Jon Dough") + self.m(hn.first, "the and Jon", hn) + self.m(hn.last, "Dough", hn) + + # Potential conjunction/prefix treated as initial (because uppercase) + def test_uppercase_middle_initial_conflict_with_conjunction(self) -> None: + hn = HumanName('John E Smith') + self.m(hn.first, "John", hn) + self.m(hn.middle, "E", hn) + self.m(hn.last, "Smith", hn) + + def test_lowercase_middle_initial_with_period_conflict_with_conjunction(self) -> None: + hn = HumanName('john e. smith') + self.m(hn.first, "john", hn) + self.m(hn.middle, "e.", hn) + self.m(hn.last, "smith", hn) + + # The conjunction "e" can also be an initial + def test_lowercase_first_initial_conflict_with_conjunction(self) -> None: + hn = HumanName('e j smith') + self.m(hn.first, "e", hn) + self.m(hn.middle, "j", hn) + self.m(hn.last, "smith", hn) + + def test_lowercase_middle_initial_conflict_with_conjunction(self) -> None: + hn = HumanName('John e Smith') + self.m(hn.first, "John", hn) + self.m(hn.middle, "e", hn) + self.m(hn.last, "Smith", hn) + + def test_lowercase_middle_initial_and_suffix_conflict_with_conjunction(self) -> None: + hn = HumanName('John e Smith, III') + self.m(hn.first, "John", hn) + self.m(hn.middle, "e", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "III", hn) + + def test_lowercase_middle_initial_and_nocomma_suffix_conflict_with_conjunction(self) -> None: + hn = HumanName('John e Smith III') + self.m(hn.first, "John", hn) + self.m(hn.middle, "e", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "III", hn) + + def test_lowercase_middle_initial_comma_lastname_and_suffix_conflict_with_conjunction(self) -> None: + hn = HumanName('Smith, John e, III, Jr') + self.m(hn.first, "John", hn) + self.m(hn.middle, "e", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "III, Jr", hn) + + @pytest.mark.xfail + def test_two_initials_conflict_with_conjunction(self) -> None: + # Supporting this seems to screw up titles with periods in them like M.B.A. + hn = HumanName('E.T. Smith') + self.m(hn.first, "E.", hn) + self.m(hn.middle, "T.", hn) + self.m(hn.last, "Smith", hn) + + def test_couples_names(self) -> None: + hn = HumanName('John and Jane Smith') + self.m(hn.first, "John and Jane", hn) + self.m(hn.last, "Smith", hn) + + def test_couples_names_with_conjunction_lastname(self) -> None: + hn = HumanName('John and Jane Aznar y Lopez') + self.m(hn.first, "John and Jane", hn) + self.m(hn.last, "Aznar y Lopez", hn) + + def test_couple_titles(self) -> None: + hn = HumanName('Mr. and Mrs. John and Jane Smith') + self.m(hn.title, "Mr. and Mrs.", hn) + self.m(hn.first, "John and Jane", hn) + self.m(hn.last, "Smith", hn) + + def test_title_with_three_part_name_last_initial_is_suffix_uppercase_no_period(self) -> None: + hn = HumanName("King John Alexander V") + self.m(hn.title, "King", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Alexander", hn) + self.m(hn.suffix, "V", hn) + + def test_four_name_parts_with_suffix_that_could_be_initial_lowercase_no_period(self) -> None: + hn = HumanName("larry james edward johnson v") + self.m(hn.first, "larry", hn) + self.m(hn.middle, "james edward", hn) + self.m(hn.last, "johnson", hn) + self.m(hn.suffix, "v", hn) + + def test_four_name_parts_with_suffix_that_could_be_initial_uppercase_no_period(self) -> None: + hn = HumanName("Larry James Johnson I") + self.m(hn.first, "Larry", hn) + self.m(hn.middle, "James", hn) + self.m(hn.last, "Johnson", hn) + self.m(hn.suffix, "I", hn) + + def test_roman_numeral_initials(self) -> None: + hn = HumanName("Larry V I") + self.m(hn.first, "Larry", hn) + self.m(hn.middle, "V", hn) + self.m(hn.last, "I", hn) + self.m(hn.suffix, "", hn) + + def test_roman_numeral_suffix_not_in_suffix_list(self) -> None: + # VI-X are not in the suffix word lists, so they reach the + # is_roman_numeral(nxt) branch rather than are_suffixes() + hn = HumanName("John Smith VI") + self.m(hn.first, "John", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "VI", hn) + + # tests for Rev. title (Reverend) + def test124(self) -> None: + hn = HumanName("Rev. John A. Kenneth Doe") + self.m(hn.title, "Rev.", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test125(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe") + self.m(hn.title, "Rev", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test126(self) -> None: + hn = HumanName("Doe, Rev. John A. Jr.") + self.m(hn.title, "Rev.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "Jr.", hn) + + def test127(self) -> None: + hn = HumanName("Buca di Beppo") + self.m(hn.first, "Buca", hn) + self.m(hn.last, "di Beppo", hn) + + def test_le_as_last_name(self) -> None: + hn = HumanName("Yin Le") + self.m(hn.first, "Yin", hn) + self.m(hn.last, "Le", hn) + + def test_le_as_last_name_with_middle_initial(self) -> None: + hn = HumanName("Yin a Le") + self.m(hn.first, "Yin", hn) + self.m(hn.middle, "a", hn) + self.m(hn.last, "Le", hn) + + def test_conjunction_in_an_address_with_a_title(self) -> None: + hn = HumanName("His Excellency Lord Duncan") + self.m(hn.title, "His Excellency Lord", hn) + self.m(hn.last, "Duncan", hn) + + @pytest.mark.xfail + def test_conjunction_in_an_address_with_a_first_name_title(self) -> None: + hn = HumanName("Her Majesty Queen Elizabeth") + self.m(hn.title, "Her Majesty Queen", hn) + # if you want to be technical, Queen is in FIRST_NAME_TITLES + self.m(hn.first, "Elizabeth", hn) + + def test_name_is_conjunctions(self) -> None: + hn = HumanName("e and e") + self.m(hn.first, "e and e", hn) diff --git a/tests/test_constants.py b/tests/test_constants.py new file mode 100644 index 0000000..9f619c3 --- /dev/null +++ b/tests/test_constants.py @@ -0,0 +1,106 @@ +from nameparser import HumanName +from nameparser.config import Constants + +from tests.base import HumanNameTestBase + + +class ConstantsCustomizationTests(HumanNameTestBase): + + def test_add_title(self) -> None: + hn = HumanName("Te Awanui-a-Rangi Black", constants=None) + start_len = len(hn.C.titles) + self.assertTrue(start_len > 0) + hn.C.titles.add('te') + self.assertEqual(start_len + 1, len(hn.C.titles)) + hn.parse_full_name() + self.m(hn.title, "Te", hn) + self.m(hn.first, "Awanui-a-Rangi", hn) + self.m(hn.last, "Black", hn) + + def test_remove_title(self) -> None: + hn = HumanName("Hon Solo", constants=None) + start_len = len(hn.C.titles) + self.assertTrue(start_len > 0) + hn.C.titles.remove('hon') + self.assertEqual(start_len - 1, len(hn.C.titles)) + hn.parse_full_name() + self.m(hn.first, "Hon", hn) + self.m(hn.last, "Solo", hn) + + def test_add_multiple_arguments(self) -> None: + hn = HumanName("Assoc Dean of Chemistry Robert Johns", constants=None) + hn.C.titles.add('dean', 'Chemistry') + hn.parse_full_name() + self.m(hn.title, "Assoc Dean of Chemistry", hn) + self.m(hn.first, "Robert", hn) + self.m(hn.last, "Johns", hn) + + def test_instances_can_have_own_constants(self) -> None: + hn = HumanName("", None) + hn2 = HumanName("") + hn.C.titles.remove('hon') + self.assertEqual('hon' in hn.C.titles, False) + self.assertEqual(hn.has_own_config, True) + self.assertEqual('hon' in hn2.C.titles, True) + self.assertEqual(hn2.has_own_config, False) + + def test_can_change_global_constants(self) -> None: + hn = HumanName("") + hn2 = HumanName("") + hn.C.titles.remove('hon') + self.assertEqual('hon' in hn.C.titles, False) + self.assertEqual('hon' in hn2.C.titles, False) + self.assertEqual(hn.has_own_config, False) + self.assertEqual(hn2.has_own_config, False) + # No manual cleanup needed: the autouse fixture in conftest.py snapshots + # and restores the global CONSTANTS collections around every test. + + def test_remove_multiple_arguments(self) -> None: + hn = HumanName("Ms Hon Solo", constants=None) + hn.C.titles.remove('hon', 'ms') + hn.parse_full_name() + self.m(hn.first, "Ms", hn) + self.m(hn.middle, "Hon", hn) + self.m(hn.last, "Solo", hn) + + def test_chain_multiple_arguments(self) -> None: + hn = HumanName("Dean Ms Hon Solo", constants=None) + hn.C.titles.remove('hon', 'ms').add('dean') + hn.parse_full_name() + self.m(hn.title, "Dean", hn) + self.m(hn.first, "Ms", hn) + self.m(hn.middle, "Hon", hn) + self.m(hn.last, "Solo", hn) + + def test_empty_attribute_default(self) -> None: + from nameparser.config import CONSTANTS + _orig = CONSTANTS.empty_attribute_default + CONSTANTS.empty_attribute_default = None + hn = HumanName("") + self.m(hn.title, None, hn) + self.m(hn.first, None, hn) + self.m(hn.middle, None, hn) + self.m(hn.last, None, hn) + self.m(hn.suffix, None, hn) + self.m(hn.nickname, None, hn) + CONSTANTS.empty_attribute_default = _orig + + def test_empty_attribute_on_instance(self) -> None: + hn = HumanName("", None) + hn.C.empty_attribute_default = None + self.m(hn.title, None, hn) + self.m(hn.first, None, hn) + self.m(hn.middle, None, hn) + self.m(hn.last, None, hn) + self.m(hn.suffix, None, hn) + self.m(hn.nickname, None, hn) + + def test_none_empty_attribute_string_formatting(self) -> None: + hn = HumanName("", None) + hn.C.empty_attribute_default = None + self.assertEqual('', str(hn), hn) + + def test_add_constant_with_explicit_encoding(self) -> None: + c = Constants() + c.titles.add_with_encoding(b'b\351ck', encoding='latin_1') + self.assertIn('béck', c.titles) diff --git a/tests/test_first_name.py b/tests/test_first_name.py new file mode 100644 index 0000000..0058acc --- /dev/null +++ b/tests/test_first_name.py @@ -0,0 +1,69 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class FirstNameHandlingTests(HumanNameTestBase): + def test_first_name(self) -> None: + hn = HumanName("Andrew") + self.m(hn.first, "Andrew", hn) + + def test_assume_title_and_one_other_name_is_last_name(self) -> None: + hn = HumanName("Rev Andrews") + self.m(hn.title, "Rev", hn) + self.m(hn.last, "Andrews", hn) + + # TODO: Seems "Andrews, M.D.", Andrews should be treated as a last name + # but other suffixes like "George Jr." should be first names. Might be + # related to https://github.com/derek73/python-nameparser/issues/2 + @pytest.mark.xfail + def test_assume_suffix_title_and_one_other_name_is_last_name(self) -> None: + hn = HumanName("Andrews, M.D.") + self.m(hn.suffix, "M.D.", hn) + self.m(hn.last, "Andrews", hn) + + def test_suffix_in_lastname_part_of_lastname_comma_format(self) -> None: + hn = HumanName("Smith Jr., John") + self.m(hn.last, "Smith", hn) + self.m(hn.first, "John", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_sir_exception_to_first_name_rule(self) -> None: + hn = HumanName("Sir Gerald") + self.m(hn.title, "Sir", hn) + self.m(hn.first, "Gerald", hn) + + def test_king_exception_to_first_name_rule(self) -> None: + hn = HumanName("King Henry") + self.m(hn.title, "King", hn) + self.m(hn.first, "Henry", hn) + + def test_queen_exception_to_first_name_rule(self) -> None: + hn = HumanName("Queen Elizabeth") + self.m(hn.title, "Queen", hn) + self.m(hn.first, "Elizabeth", hn) + + def test_dame_exception_to_first_name_rule(self) -> None: + hn = HumanName("Dame Mary") + self.m(hn.title, "Dame", hn) + self.m(hn.first, "Mary", hn) + + def test_first_name_is_not_prefix_if_only_two_parts(self) -> None: + """When there are only two parts, don't join prefixes or conjunctions""" + hn = HumanName("Van Nguyen") + self.m(hn.first, "Van", hn) + self.m(hn.last, "Nguyen", hn) + + def test_first_name_is_not_prefix_if_only_two_parts_comma(self) -> None: + hn = HumanName("Nguyen, Van") + self.m(hn.first, "Van", hn) + self.m(hn.last, "Nguyen", hn) + + @pytest.mark.xfail + def test_first_name_is_prefix_if_three_parts(self) -> None: + """Not sure how to fix this without breaking Mr and Mrs""" + hn = HumanName("Mr. Van Nguyen") + self.m(hn.first, "Van", hn) + self.m(hn.last, "Nguyen", hn) diff --git a/tests/test_initials.py b/tests/test_initials.py new file mode 100644 index 0000000..bccf8b4 --- /dev/null +++ b/tests/test_initials.py @@ -0,0 +1,128 @@ +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class InitialsTestCase(HumanNameTestBase): + def test_initials(self) -> None: + hn = HumanName("Andrew Boris Petersen") + self.m(hn.initials(), "A. B. P.", hn) + + def test_initials_simple_name(self) -> None: + hn = HumanName("John Doe") + self.m(hn.initials(), "J. D.", hn) + hn = HumanName("John Doe", initials_format="{first} {last}") + self.m(hn.initials(), "J. D.", hn) + hn = HumanName("John Doe", initials_format="{last}") + self.m(hn.initials(), "D.", hn) + hn = HumanName("John Doe", initials_format="{first}") + self.m(hn.initials(), "J.", hn) + hn = HumanName("John Doe", initials_format="{middle}") + self.m(hn.initials(), "", hn) + + def test_initials_empty_part_with_none_default_not_literal_none(self) -> None: + # Regression: when empty_attribute_default is None, an empty name part + # used to be interpolated by str.format as the literal "None" (e.g. + # "John Doe" -> "J. None D."). Empty parts must render as ''. + hn = HumanName("John Doe", constants=None) + hn.C.empty_attribute_default = None + self.assertEqual(hn.initials(), "J. D.") + self.assertTrue("None" not in hn.initials()) + + def test_initials_all_empty_returns_empty_attribute_default(self) -> None: + # Regression: a fully-empty result must fall back to + # empty_attribute_default (here None), matching the first/last accessors, + # rather than rendering the literal "None None None". + hn = HumanName("", constants=None) + hn.C.empty_attribute_default = None + self.assertEqual(hn.initials(), None) + + def test_initials_complex_name(self) -> None: + hn = HumanName("Doe, John A. Kenneth, Jr.") + self.m(hn.initials(), "J. A. K. D.", hn) + + def test_initials_format(self) -> None: + hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first} {middle}") + self.m(hn.initials(), "J. A. K.", hn) + hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first} {last}") + self.m(hn.initials(), "J. D.", hn) + hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{middle} {last}") + self.m(hn.initials(), "A. K. D.", hn) + hn = HumanName("Doe, John A. Kenneth, Jr.", initials_format="{first}, {last}") + self.m(hn.initials(), "J., D.", hn) + + def test_initials_format_constants(self) -> None: + from nameparser.config import CONSTANTS + _orig = CONSTANTS.initials_format + CONSTANTS.initials_format = "{first} {last}" + hn = HumanName("Doe, John A. Kenneth, Jr.") + self.m(hn.initials(), "J. D.", hn) + CONSTANTS.initials_format = "{first} {last}" + hn = HumanName("Doe, John A. Kenneth, Jr.") + self.m(hn.initials(), "J. D.", hn) + CONSTANTS.initials_format = _orig + + def test_initials_delimiter(self) -> None: + hn = HumanName("Doe, John A. Kenneth, Jr.", initials_delimiter=";") + self.m(hn.initials(), "J; A; K; D;", hn) + + def test_initials_delimiter_constants(self) -> None: + from nameparser.config import CONSTANTS + _orig = CONSTANTS.initials_delimiter + CONSTANTS.initials_delimiter = ";" + hn = HumanName("Doe, John A. Kenneth, Jr.") + self.m(hn.initials(), "J; A; K; D;", hn) + CONSTANTS.initials_delimiter = _orig + + def test_initials_list(self) -> None: + hn = HumanName("Andrew Boris Petersen") + self.m(hn.initials_list(), ["A", "B", "P"], hn) + + def test_initials_list_complex_name(self) -> None: + hn = HumanName("Doe, John A. Kenneth, Jr.") + self.m(hn.initials_list(), ["J", "A", "K", "D"], hn) + + def test_initials_with_prefix_firstname(self) -> None: + hn = HumanName("Van Jeremy Johnson") + self.m(hn.initials_list(), ["V", "J", "J"], hn) + + def test_initials_with_prefix(self) -> None: + hn = HumanName("Alex van Johnson") + self.m(hn.initials_list(), ["A", "J"], hn) + + def test_constructor_first(self) -> None: + hn = HumanName(first="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.first, "TheName", hn) + + def test_constructor_middle(self) -> None: + hn = HumanName(middle="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.middle, "TheName", hn) + + def test_constructor_last(self) -> None: + hn = HumanName(last="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.last, "TheName", hn) + + def test_constructor_title(self) -> None: + hn = HumanName(title="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.title, "TheName", hn) + + def test_constructor_suffix(self) -> None: + hn = HumanName(suffix="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.suffix, "TheName", hn) + + def test_constructor_nickname(self) -> None: + hn = HumanName(nickname="TheName") + self.assertFalse(hn.unparsable) + self.m(hn.nickname, "TheName", hn) + + def test_constructor_multiple(self) -> None: + hn = HumanName(first="TheName", last="lastname", title="mytitle", full_name="donotparse") + self.assertFalse(hn.unparsable) + self.m(hn.first, "TheName", hn) + self.m(hn.last, "lastname", hn) + self.m(hn.title, "mytitle", hn) diff --git a/tests/test_nicknames.py b/tests/test_nicknames.py new file mode 100644 index 0000000..c5aea85 --- /dev/null +++ b/tests/test_nicknames.py @@ -0,0 +1,176 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class NicknameTestCase(HumanNameTestBase): + # https://code.google.com/p/python-nameparser/issues/detail?id=33 + def test_nickname_in_parenthesis(self) -> None: + hn = HumanName("Benjamin (Ben) Franklin") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Ben", hn) + + def test_two_word_nickname_in_parenthesis(self) -> None: + hn = HumanName("Benjamin (Big Ben) Franklin") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Big Ben", hn) + + def test_two_words_in_quotes(self) -> None: + hn = HumanName('Benjamin "Big Ben" Franklin') + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Big Ben", hn) + + def test_nickname_in_parenthesis_with_comma(self) -> None: + hn = HumanName("Franklin, Benjamin (Ben)") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Ben", hn) + + def test_nickname_in_parenthesis_with_comma_and_suffix(self) -> None: + hn = HumanName("Franklin, Benjamin (Ben), Jr.") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.suffix, "Jr.", hn) + self.m(hn.nickname, "Ben", hn) + + def test_nickname_in_single_quotes(self) -> None: + hn = HumanName("Benjamin 'Ben' Franklin") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Ben", hn) + + def test_nickname_in_double_quotes(self) -> None: + hn = HumanName("Benjamin \"Ben\" Franklin") + self.m(hn.first, "Benjamin", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.nickname, "Ben", hn) + + def test_single_quotes_on_first_name_not_treated_as_nickname(self) -> None: + hn = HumanName("Brian Andrew O'connor") + self.m(hn.first, "Brian", hn) + self.m(hn.middle, "Andrew", hn) + self.m(hn.last, "O'connor", hn) + self.m(hn.nickname, "", hn) + + def test_single_quotes_on_both_name_not_treated_as_nickname(self) -> None: + hn = HumanName("La'tanya O'connor") + self.m(hn.first, "La'tanya", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "O'connor", hn) + self.m(hn.nickname, "", hn) + + def test_single_quotes_on_end_of_last_name_not_treated_as_nickname(self) -> None: + hn = HumanName("Mari' Aube'") + self.m(hn.first, "Mari'", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Aube'", hn) + self.m(hn.nickname, "", hn) + + def test_okina_inside_name_not_treated_as_nickname(self) -> None: + hn = HumanName("Harrieta Keōpūolani Nāhiʻenaʻena") + self.m(hn.first, "Harrieta", hn) + self.m(hn.middle, "Keōpūolani", hn) + self.m(hn.last, "Nāhiʻenaʻena", hn) + self.m(hn.nickname, "", hn) + + def test_single_quotes_not_treated_as_nickname_Hawaiian_example(self) -> None: + hn = HumanName("Harietta Keopuolani Nahi'ena'ena") + self.m(hn.first, "Harietta", hn) + self.m(hn.middle, "Keopuolani", hn) + self.m(hn.last, "Nahi'ena'ena", hn) + self.m(hn.nickname, "", hn) + + def test_single_quotes_not_treated_as_nickname_Kenyan_example(self) -> None: + hn = HumanName("Naomi Wambui Ng'ang'a") + self.m(hn.first, "Naomi", hn) + self.m(hn.middle, "Wambui", hn) + self.m(hn.last, "Ng'ang'a", hn) + self.m(hn.nickname, "", hn) + + def test_single_quotes_not_treated_as_nickname_Samoan_example(self) -> None: + hn = HumanName("Va'apu'u Vitale") + self.m(hn.first, "Va'apu'u", hn) + self.m(hn.middle, "", hn) + self.m(hn.last, "Vitale", hn) + self.m(hn.nickname, "", hn) + + # http://code.google.com/p/python-nameparser/issues/detail?id=17 + def test_parenthesis_are_removed_from_name(self) -> None: + hn = HumanName("John Jones (Unknown)") + self.m(hn.first, "John", hn) + self.m(hn.last, "Jones", hn) + # not testing the nicknames because we don't actually care + # about Google Docs here + + def test_duplicate_parenthesis_are_removed_from_name(self) -> None: + hn = HumanName("John Jones (Google Docs), Jr. (Unknown)") + self.m(hn.first, "John", hn) + self.m(hn.last, "Jones", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_nickname_and_last_name(self) -> None: + hn = HumanName('"Rick" Edmonds') + self.m(hn.first, "", hn) + self.m(hn.last, "Edmonds", hn) + self.m(hn.nickname, "Rick", hn) + + @pytest.mark.xfail + def test_nickname_and_last_name_with_title(self) -> None: + hn = HumanName('Senator "Rick" Edmonds') + self.m(hn.title, "Senator", hn) + self.m(hn.first, "", hn) + self.m(hn.last, "Edmonds", hn) + self.m(hn.nickname, "Rick", hn) + + +# class MaidenNameTestCase(HumanNameTestBase): +# +# def test_parenthesis_and_quotes_together(self): +# hn = HumanName("Jennifer 'Jen' Jones (Duff)") +# self.m(hn.first, "Jennifer", hn) +# self.m(hn.last, "Jones", hn) +# self.m(hn.nickname, "Jen", hn) +# self.m(hn.maiden, "Duff", hn) +# +# def test_maiden_name_with_nee(self): +# # https://en.wiktionary.org/wiki/née +# hn = HumanName("Mary Toogood nee Johnson") +# self.m(hn.first, "Mary", hn) +# self.m(hn.last, "Toogood", hn) +# self.m(hn.maiden, "Johnson", hn) +# +# def test_maiden_name_with_accented_nee(self): +# # https://en.wiktionary.org/wiki/née +# hn = HumanName("Mary Toogood née Johnson") +# self.m(hn.first, "Mary", hn) +# self.m(hn.last, "Toogood", hn) +# self.m(hn.maiden, "Johnson", hn) +# +# def test_maiden_name_with_nee_and_comma(self): +# # https://en.wiktionary.org/wiki/née +# hn = HumanName("Mary Toogood, née Johnson") +# self.m(hn.first, "Mary", hn) +# self.m(hn.last, "Toogood", hn) +# self.m(hn.maiden, "Johnson", hn) +# +# def test_maiden_name_with_nee_with_parenthesis(self): +# hn = HumanName("Mary Toogood (nee Johnson)") +# self.m(hn.first, "Mary", hn) +# self.m(hn.last, "Toogood", hn) +# self.m(hn.maiden, "Johnson", hn) +# +# def test_maiden_name_with_parenthesis(self): +# hn = HumanName("Mary Toogood (Johnson)") +# self.m(hn.first, "Mary", hn) diff --git a/tests/test_output_format.py b/tests/test_output_format.py new file mode 100644 index 0000000..a036752 --- /dev/null +++ b/tests/test_output_format.py @@ -0,0 +1,126 @@ +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class HumanNameOutputFormatTests(HumanNameTestBase): + + def test_formatting_init_argument(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)", + string_format="TEST1") + self.assertEqual(str(hn), "TEST1") + + def test_formatting_constants_attribute(self) -> None: + from nameparser.config import CONSTANTS + _orig = CONSTANTS.string_format + CONSTANTS.string_format = "TEST2" + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + self.assertEqual(str(hn), "TEST2") + CONSTANTS.string_format = _orig + + def test_capitalize_name_constants_attribute(self) -> None: + from nameparser.config import CONSTANTS + CONSTANTS.capitalize_name = True + hn = HumanName("bob v. de la macdole-eisenhower phd") + self.assertEqual(str(hn), "Bob V. de la MacDole-Eisenhower Ph.D.") + CONSTANTS.capitalize_name = False + + def test_force_mixed_case_capitalization_constants_attribute(self) -> None: + from nameparser.config import CONSTANTS + CONSTANTS.force_mixed_case_capitalization = True + hn = HumanName('Shirley Maclaine') + hn.capitalize() + self.assertEqual(str(hn), "Shirley MacLaine") + CONSTANTS.force_mixed_case_capitalization = False + + def test_capitalize_name_and_force_mixed_case_capitalization_constants_attributes(self) -> None: + from nameparser.config import CONSTANTS + CONSTANTS.capitalize_name = True + CONSTANTS.force_mixed_case_capitalization = True + hn = HumanName('Shirley Maclaine') + self.assertEqual(str(hn), "Shirley MacLaine") + + def test_quote_nickname_formating(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") + hn.string_format = "{last}, {title} {first} {middle}, {suffix} '{nickname}'" + self.assertEqual(str(hn), "Doe, Rev John A. Kenneth, III 'Kenny'") + + def test_formating_removing_keys_from_format_string(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") + hn.string_format = "{last}, {title} {first} {middle}, {suffix}" + self.assertEqual(str(hn), "Doe, Rev John A. Kenneth, III") + hn.string_format = "{last}, {title} {first} {middle}" + self.assertEqual(str(hn), "Doe, Rev John A. Kenneth") + hn.string_format = "{last}, {first} {middle}" + self.assertEqual(str(hn), "Doe, John A. Kenneth") + hn.string_format = "{last}, {first}" + self.assertEqual(str(hn), "Doe, John") + hn.string_format = "{first} {last}" + self.assertEqual(str(hn), "John Doe") + + def test_formating_removing_pieces_from_name_buckets(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") + hn.string_format = "{title} {first} {middle} {last} {suffix}" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") + hn.middle = '' + self.assertEqual(str(hn), "Rev John Doe III") + hn.suffix = '' + self.assertEqual(str(hn), "Rev John Doe") + hn.title = '' + self.assertEqual(str(hn), "John Doe") + + def test_formating_of_nicknames_with_parenthesis(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} ({nickname})" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III (Kenny)") + hn.nickname = '' + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") + + def test_formating_of_nicknames_with_single_quotes(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} '{nickname}'" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III 'Kenny'") + hn.nickname = '' + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") + + def test_formating_of_nicknames_with_double_quotes(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} {middle} {last} {suffix} \"{nickname}\"" + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III \"Kenny\"") + hn.nickname = '' + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") + + def test_formating_of_nicknames_in_middle(self) -> None: + hn = HumanName("Rev John A. Kenneth Doe III (Kenny)") + hn.string_format = "{title} {first} ({nickname}) {middle} {last} {suffix}" + self.assertEqual(str(hn), "Rev John (Kenny) A. Kenneth Doe III") + hn.nickname = '' + self.assertEqual(str(hn), "Rev John A. Kenneth Doe III") + + def test_remove_emojis(self) -> None: + hn = HumanName("Sam Smith 😊") + self.m(hn.first, "Sam", hn) + self.m(hn.last, "Smith", hn) + self.assertEqual(str(hn), "Sam Smith") + + def test_keep_non_emojis(self) -> None: + hn = HumanName("∫≜⩕ Smith 😊") + self.m(hn.first, "∫≜⩕", hn) + self.m(hn.last, "Smith", hn) + self.assertEqual(str(hn), "∫≜⩕ Smith") + + def test_keep_emojis(self) -> None: + from nameparser.config import Constants + constants = Constants() + constants.regexes.emoji = False + hn = HumanName("∫≜⩕ Smith😊", constants) + self.m(hn.first, "∫≜⩕", hn) + self.m(hn.last, "Smith😊", hn) + self.assertEqual(str(hn), "∫≜⩕ Smith😊") + # test cleanup diff --git a/tests/test_prefixes.py b/tests/test_prefixes.py new file mode 100644 index 0000000..134f962 --- /dev/null +++ b/tests/test_prefixes.py @@ -0,0 +1,118 @@ +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class PrefixesTestCase(HumanNameTestBase): + + def test_prefix(self) -> None: + hn = HumanName("Juan del Sur") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "del Sur", hn) + + def test_prefix_with_period(self) -> None: + hn = HumanName("Jill St. John") + self.m(hn.first, "Jill", hn) + self.m(hn.last, "St. John", hn) + + def test_prefix_before_two_part_last_name(self) -> None: + hn = HumanName("pennie von bergen wessels") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + + def test_prefix_is_first_name(self) -> None: + hn = HumanName("Van Johnson") + self.m(hn.first, "Van", hn) + self.m(hn.last, "Johnson", hn) + + def test_prefix_is_first_name_with_middle_name(self) -> None: + hn = HumanName("Van Jeremy Johnson") + self.m(hn.first, "Van", hn) + self.m(hn.middle, "Jeremy", hn) + self.m(hn.last, "Johnson", hn) + + def test_prefix_before_two_part_last_name_with_suffix(self) -> None: + hn = HumanName("pennie von bergen wessels III") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "III", hn) + + def test_prefix_before_two_part_last_name_with_acronym_suffix(self) -> None: + hn = HumanName("pennie von bergen wessels M.D.") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "M.D.", hn) + + def test_two_part_last_name_with_suffix_comma(self) -> None: + hn = HumanName("pennie von bergen wessels, III") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "III", hn) + + def test_two_part_last_name_with_suffix(self) -> None: + hn = HumanName("von bergen wessels, pennie III") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "III", hn) + + def test_last_name_two_part_last_name_with_two_suffixes(self) -> None: + hn = HumanName("von bergen wessels MD, pennie III") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "MD, III", hn) + + def test_comma_two_part_last_name_with_acronym_suffix(self) -> None: + hn = HumanName("von bergen wessels, pennie MD") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "MD", hn) + + def test_comma_two_part_last_name_with_suffix_in_first_part(self) -> None: + # I'm kinda surprised this works, not really sure if this is a + # realistic place for a suffix to be. + hn = HumanName("von bergen wessels MD, pennie") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "MD", hn) + + def test_title_two_part_last_name_with_suffix_in_first_part(self) -> None: + hn = HumanName("pennie von bergen wessels MD, III") + self.m(hn.first, "pennie", hn) + self.m(hn.last, "von bergen wessels", hn) + self.m(hn.suffix, "MD, III", hn) + + def test_portuguese_dos(self) -> None: + hn = HumanName("Rafael Sousa dos Anjos") + self.m(hn.first, "Rafael", hn) + self.m(hn.middle, "Sousa", hn) + self.m(hn.last, "dos Anjos", hn) + + def test_portuguese_prefixes(self) -> None: + hn = HumanName("Joao da Silva do Amaral de Souza") + self.m(hn.first, "Joao", hn) + self.m(hn.middle, "da Silva do Amaral", hn) + self.m(hn.last, "de Souza", hn) + + def test_three_conjunctions(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier de la dos Vega III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la dos Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test_lastname_three_conjunctions(self) -> None: + hn = HumanName("de la dos Vega, Dr. Juan Q. Xavier III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la dos Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) + + def test_comma_three_conjunctions(self) -> None: + hn = HumanName("Dr. Juan Q. Xavier de la dos Vega, III") + self.m(hn.first, "Juan", hn) + self.m(hn.last, "de la dos Vega", hn) + self.m(hn.title, "Dr.", hn) + self.m(hn.middle, "Q. Xavier", hn) + self.m(hn.suffix, "III", hn) diff --git a/tests/test_python_api.py b/tests/test_python_api.py new file mode 100644 index 0000000..eed352d --- /dev/null +++ b/tests/test_python_api.py @@ -0,0 +1,226 @@ +import re + +import pytest + +try: + import dill +except ImportError: + dill = False # type: ignore[assignment] + +from nameparser import HumanName +from nameparser.config import Constants, TupleManager + +from tests.base import HumanNameTestBase + + +class HumanNamePythonTests(HumanNameTestBase): + + def test_utf8(self) -> None: + hn = HumanName("de la Véña, Jüan") + self.m(hn.first, "Jüan", hn) + self.m(hn.last, "de la Véña", hn) + + def test_string_output(self) -> None: + hn = HumanName("de la Véña, Jüan") + self.m(str(hn), "Jüan de la Véña", hn) + + def test_escaped_utf8_bytes(self) -> None: + hn = HumanName(b'B\xc3\xb6ck, Gerald') + self.m(hn.first, "Gerald", hn) + self.m(hn.last, "Böck", hn) + + def test_len(self) -> None: + hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") + self.m(len(hn), 5, hn) + hn = HumanName("John Doe") + self.m(len(hn), 2, hn) + + @pytest.mark.skipif(not dill, reason="requires python-dill module to test pickling") + def test_config_pickle(self) -> None: + constants = Constants() + self.assertTrue(dill.pickles(constants)) + + @pytest.mark.skipif(not dill, reason="requires python-dill module to test pickling") + def test_name_instance_pickle(self) -> None: + hn = HumanName("Title First Middle Middle Last, Jr.") + self.assertTrue(dill.pickles(hn)) + + def test_comparison(self) -> None: + hn1 = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") + hn2 = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") + self.assertTrue(hn1 == hn2) + self.assertTrue(hn1 is not hn2) + self.assertTrue(hn1 == "Dr. John P. Doe-Ray CLU, CFP, LUTC") + hn1 = HumanName("Doe, Dr. John P., CLU, CFP, LUTC") + hn2 = HumanName("Dr. John P. Doe-Ray, CLU, CFP, LUTC") + self.assertTrue(not hn1 == hn2) + self.assertTrue(not hn1 == 0) + self.assertTrue(not hn1 == "test") + self.assertTrue(not hn1 == ["test"]) + self.assertTrue(not hn1 == {"test": hn2}) + + def test_assignment_to_full_name(self) -> None: + hn = HumanName("John A. Kenneth Doe, Jr.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "Jr.", hn) + hn.full_name = "Juan Velasquez y Garcia III" + self.m(hn.first, "Juan", hn) + self.m(hn.last, "Velasquez y Garcia", hn) + self.m(hn.suffix, "III", hn) + + def test_get_full_name_attribute_references_internal_lists(self) -> None: + hn = HumanName("John Williams") + hn.first_list = ["Larry"] + self.m(hn.full_name, "Larry Williams", hn) + + def test_assignment_to_attribute(self) -> None: + hn = HumanName("John A. Kenneth Doe, Jr.") + hn.last = "de la Vega" + self.m(hn.last, "de la Vega", hn) + hn.title = "test" + self.m(hn.title, "test", hn) + hn.first = "test" + self.m(hn.first, "test", hn) + hn.middle = "test" + self.m(hn.middle, "test", hn) + hn.suffix = "test" + self.m(hn.suffix, "test", hn) + with pytest.raises(TypeError): + hn.suffix = [['test']] + with pytest.raises(TypeError): + hn.suffix = {"test": "test"} + + def test_assign_list_to_attribute(self) -> None: + hn = HumanName("John A. Kenneth Doe, Jr.") + hn.title = ["test1", "test2"] + self.m(hn.title, "test1 test2", hn) + hn.first = ["test3", "test4"] + self.m(hn.first, "test3 test4", hn) + hn.middle = ["test5", "test6", "test7"] + self.m(hn.middle, "test5 test6 test7", hn) + hn.last = ["test8", "test9", "test10"] + self.m(hn.last, "test8 test9 test10", hn) + hn.suffix = ['test'] + self.m(hn.suffix, "test", hn) + + def test_comparison_case_insensitive(self) -> None: + hn1 = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") + hn2 = HumanName("dr. john p. doe-Ray, CLU, CFP, LUTC") + self.assertTrue(hn1 == hn2) + self.assertTrue(hn1 is not hn2) + self.assertTrue(hn1 == "Dr. John P. Doe-ray clu, CFP, LUTC") + + def test_slice(self) -> None: + hn = HumanName("Doe-Ray, Dr. John P., CLU, CFP, LUTC") + self.m(list(hn), ['Dr.', 'John', 'P.', 'Doe-Ray', 'CLU, CFP, LUTC'], hn) + self.m(hn[1:], ['John', 'P.', 'Doe-Ray', 'CLU, CFP, LUTC', hn.C.empty_attribute_default], hn) + self.m(hn[1:-2], ['John', 'P.', 'Doe-Ray'], hn) + + def test_getitem(self) -> None: + hn = HumanName("Dr. John A. Kenneth Doe, Jr.") + self.m(hn['title'], "Dr.", hn) + self.m(hn['first'], "John", hn) + self.m(hn['last'], "Doe", hn) + self.m(hn['middle'], "A. Kenneth", hn) + self.m(hn['suffix'], "Jr.", hn) + + def test_setitem(self) -> None: + hn = HumanName("Dr. John A. Kenneth Doe, Jr.") + hn['title'] = 'test' + self.m(hn['title'], "test", hn) + hn['last'] = ['test', 'test2'] + self.m(hn['last'], "test test2", hn) + with pytest.raises(TypeError): + hn["suffix"] = [['test']] + with pytest.raises(TypeError): + hn["suffix"] = {"test": "test"} + + def test_conjunction_names(self) -> None: + hn = HumanName("johnny y") + self.m(hn.first, "johnny", hn) + self.m(hn.last, "y", hn) + + def test_prefix_names(self) -> None: + hn = HumanName("vai la") + self.m(hn.first, "vai", hn) + self.m(hn.last, "la", hn) + + def test_blank_name(self) -> None: + hn = HumanName() + self.m(hn.first, "", hn) + self.m(hn.last, "", hn) + + def test_surnames_list_attribute(self) -> None: + hn = HumanName("John Edgar Casey Williams III") + self.m(hn.surnames_list, ["Edgar", "Casey", "Williams"], hn) + + def test_surnames_attribute(self) -> None: + hn = HumanName("John Edgar Casey Williams III") + self.m(hn.surnames, "Edgar Casey Williams", hn) + + def test_is_prefix_with_list(self) -> None: + hn = HumanName() + items = ['firstname', 'lastname', 'del'] + self.assertTrue(hn.is_prefix(items)) + self.assertTrue(hn.is_prefix(items[1:])) + + def test_is_conjunction_with_list(self) -> None: + hn = HumanName() + items = ['firstname', 'lastname', 'and'] + self.assertTrue(hn.is_conjunction(items)) + self.assertTrue(hn.is_conjunction(items[1:])) + + def test_override_constants(self) -> None: + C = Constants() + hn = HumanName(constants=C) + self.assertTrue(hn.C is C) + + def test_override_regex(self) -> None: + var = TupleManager([("spaces", re.compile(r"\s+", re.U)),]) + C = Constants(regexes=var) + hn = HumanName(constants=C) + self.assertTrue(hn.C.regexes == var) + + def test_override_titles(self) -> None: + var = ["abc","def"] + C = Constants(titles=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.titles) == sorted(var)) + + def test_override_first_name_titles(self) -> None: + var = ["abc","def"] + C = Constants(first_name_titles=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.first_name_titles) == sorted(var)) + + def test_override_prefixes(self) -> None: + var = ["abc","def"] + C = Constants(prefixes=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.prefixes) == sorted(var)) + + def test_override_suffix_acronyms(self) -> None: + var = ["abc","def"] + C = Constants(suffix_acronyms=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.suffix_acronyms) == sorted(var)) + + def test_override_suffix_not_acronyms(self) -> None: + var = ["abc","def"] + C = Constants(suffix_not_acronyms=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.suffix_not_acronyms) == sorted(var)) + + def test_override_conjunctions(self) -> None: + var = ["abc","def"] + C = Constants(conjunctions=var) + hn = HumanName(constants=C) + self.assertTrue(sorted(hn.C.conjunctions) == sorted(var)) + + def test_override_capitalization_exceptions(self) -> None: + var = TupleManager([("spaces", re.compile(r"\s+", re.U)),]) + C = Constants(capitalization_exceptions=var) + hn = HumanName(constants=C) + self.assertTrue(hn.C.capitalization_exceptions == var) diff --git a/tests/test_suffixes.py b/tests/test_suffixes.py new file mode 100644 index 0000000..b22945b --- /dev/null +++ b/tests/test_suffixes.py @@ -0,0 +1,138 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class SuffixesTestCase(HumanNameTestBase): + + def test_suffix(self) -> None: + hn = HumanName("Joe Franklin Jr") + self.m(hn.first, "Joe", hn) + self.m(hn.last, "Franklin", hn) + self.m(hn.suffix, "Jr", hn) + + def test_suffix_with_periods(self) -> None: + hn = HumanName("Joe Dentist D.D.S.") + self.m(hn.first, "Joe", hn) + self.m(hn.last, "Dentist", hn) + self.m(hn.suffix, "D.D.S.", hn) + + def test_two_suffixes(self) -> None: + hn = HumanName("Kenneth Clarke QC MP") + self.m(hn.first, "Kenneth", hn) + self.m(hn.last, "Clarke", hn) + # NOTE: this adds a comma when the original format did not have one. + # not ideal but at least its in the right bucket + self.m(hn.suffix, "QC, MP", hn) + + def test_two_suffixes_lastname_comma_format(self) -> None: + hn = HumanName("Washington Jr. MD, Franklin") + self.m(hn.first, "Franklin", hn) + self.m(hn.last, "Washington", hn) + # NOTE: this adds a comma when the original format did not have one. + self.m(hn.suffix, "Jr., MD", hn) + + def test_two_suffixes_suffix_comma_format(self) -> None: + hn = HumanName("Franklin Washington, Jr. MD") + self.m(hn.first, "Franklin", hn) + self.m(hn.last, "Washington", hn) + self.m(hn.suffix, "Jr. MD", hn) + + def test_suffix_containing_periods(self) -> None: + hn = HumanName("Kenneth Clarke Q.C.") + self.m(hn.first, "Kenneth", hn) + self.m(hn.last, "Clarke", hn) + self.m(hn.suffix, "Q.C.", hn) + + def test_suffix_containing_periods_lastname_comma_format(self) -> None: + hn = HumanName("Clarke, Kenneth, Q.C. M.P.") + self.m(hn.first, "Kenneth", hn) + self.m(hn.last, "Clarke", hn) + self.m(hn.suffix, "Q.C. M.P.", hn) + + def test_suffix_containing_periods_suffix_comma_format(self) -> None: + hn = HumanName("Kenneth Clarke Q.C., M.P.") + self.m(hn.first, "Kenneth", hn) + self.m(hn.last, "Clarke", hn) + self.m(hn.suffix, "Q.C., M.P.", hn) + + def test_suffix_with_single_comma_format(self) -> None: + hn = HumanName("John Doe jr., MD") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "jr., MD", hn) + + def test_suffix_with_double_comma_format(self) -> None: + hn = HumanName("Doe, John jr., MD") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "jr., MD", hn) + + def test_phd_with_erroneous_space(self) -> None: + hn = HumanName("John Smith, Ph. D.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "Ph. D.", hn) + + def test_phd_extracted_without_comma(self) -> None: + hn = HumanName("John Smith Ph. D.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Smith", hn) + self.m(hn.suffix, "Ph. D.", hn) + + def test_phd_conflict(self) -> None: + hn = HumanName("Adolph D") + self.m(hn.first, "Adolph", hn) + self.m(hn.last, "D", hn) + + # http://en.wikipedia.org/wiki/Ma_(surname) + + def test_potential_suffix_that_is_also_last_name(self) -> None: + hn = HumanName("Jack Ma") + self.m(hn.first, "Jack", hn) + self.m(hn.last, "Ma", hn) + + def test_potential_suffix_that_is_also_last_name_comma(self) -> None: + hn = HumanName("Ma, Jack") + self.m(hn.first, "Jack", hn) + self.m(hn.last, "Ma", hn) + + def test_potential_suffix_that_is_also_last_name_with_suffix(self) -> None: + hn = HumanName("Jack Ma Jr") + self.m(hn.first, "Jack", hn) + self.m(hn.last, "Ma", hn) + self.m(hn.suffix, "Jr", hn) + + def test_potential_suffix_that_is_also_last_name_with_suffix_comma(self) -> None: + hn = HumanName("Ma III, Jack Jr") + self.m(hn.first, "Jack", hn) + self.m(hn.last, "Ma", hn) + self.m(hn.suffix, "III, Jr", hn) + + # https://github.com/derek73/python-nameparser/issues/27 + @pytest.mark.xfail + def test_king(self) -> None: + hn = HumanName("Dr King Jr") + self.m(hn.title, "Dr", hn) + self.m(hn.last, "King", hn) + self.m(hn.suffix, "Jr", hn) + + def test_multiple_letter_suffix_with_periods(self) -> None: + hn = HumanName("John Doe Msc.Ed.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Msc.Ed.", hn) + + def test_suffix_with_periods_with_comma(self) -> None: + hn = HumanName("John Doe, Msc.Ed.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Msc.Ed.", hn) + + def test_suffix_with_periods_with_lastname_comma(self) -> None: + hn = HumanName("Doe, John Msc.Ed.") + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.suffix, "Msc.Ed.", hn) diff --git a/tests/test_titles.py b/tests/test_titles.py new file mode 100644 index 0000000..7b06121 --- /dev/null +++ b/tests/test_titles.py @@ -0,0 +1,241 @@ +import pytest + +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +class TitleTestCase(HumanNameTestBase): + + def test_last_name_is_also_title(self) -> None: + hn = HumanName("Amy E Maid") + self.m(hn.first, "Amy", hn) + self.m(hn.middle, "E", hn) + self.m(hn.last, "Maid", hn) + + def test_last_name_is_also_title_no_comma(self) -> None: + hn = HumanName("Dr. Martin Luther King Jr.") + self.m(hn.title, "Dr.", hn) + self.m(hn.first, "Martin", hn) + self.m(hn.middle, "Luther", hn) + self.m(hn.last, "King", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_last_name_is_also_title_with_comma(self) -> None: + hn = HumanName("Dr Martin Luther King, Jr.") + self.m(hn.title, "Dr", hn) + self.m(hn.first, "Martin", hn) + self.m(hn.middle, "Luther", hn) + self.m(hn.last, "King", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_last_name_is_also_title3(self) -> None: + hn = HumanName("John King") + self.m(hn.first, "John", hn) + self.m(hn.last, "King", hn) + + def test_title_with_conjunction(self) -> None: + hn = HumanName("Secretary of State Hillary Clinton") + self.m(hn.title, "Secretary of State", hn) + self.m(hn.first, "Hillary", hn) + self.m(hn.last, "Clinton", hn) + + def test_compound_title_with_conjunction(self) -> None: + hn = HumanName("Cardinal Secretary of State Hillary Clinton") + self.m(hn.title, "Cardinal Secretary of State", hn) + self.m(hn.first, "Hillary", hn) + self.m(hn.last, "Clinton", hn) + + def test_title_is_title(self) -> None: + hn = HumanName("Coach") + self.m(hn.title, "Coach", hn) + + # TODO: fix handling of U.S. + @pytest.mark.xfail + def test_chained_title_first_name_title_is_initials(self) -> None: + hn = HumanName("U.S. District Judge Marc Thomas Treadwell") + self.m(hn.title, "U.S. District Judge", hn) + self.m(hn.first, "Marc", hn) + self.m(hn.middle, "Thomas", hn) + self.m(hn.last, "Treadwell", hn) + + def test_conflict_with_chained_title_first_name_initial(self) -> None: + hn = HumanName("U. S. Grant") + self.m(hn.first, "U.", hn) + self.m(hn.middle, "S.", hn) + self.m(hn.last, "Grant", hn) + + def test_chained_title_first_name_initial_with_no_period(self) -> None: + hn = HumanName("US Magistrate Judge T Michael Putnam") + self.m(hn.title, "US Magistrate Judge", hn) + self.m(hn.first, "T", hn) + self.m(hn.middle, "Michael", hn) + self.m(hn.last, "Putnam", hn) + + def test_chained_hyphenated_title(self) -> None: + hn = HumanName("US Magistrate-Judge Elizabeth E Campbell") + self.m(hn.title, "US Magistrate-Judge", hn) + self.m(hn.first, "Elizabeth", hn) + self.m(hn.middle, "E", hn) + self.m(hn.last, "Campbell", hn) + + def test_chained_hyphenated_title_with_comma_suffix(self) -> None: + hn = HumanName("Mag-Judge Harwell G Davis, III") + self.m(hn.title, "Mag-Judge", hn) + self.m(hn.first, "Harwell", hn) + self.m(hn.middle, "G", hn) + self.m(hn.last, "Davis", hn) + self.m(hn.suffix, "III", hn) + + @pytest.mark.xfail + def test_title_multiple_titles_with_apostrophe_s(self) -> None: + hn = HumanName("The Right Hon. the President of the Queen's Bench Division") + self.m(hn.title, "The Right Hon. the President of the Queen's Bench Division", hn) + + def test_title_starts_with_conjunction(self) -> None: + hn = HumanName("The Rt Hon John Jones") + self.m(hn.title, "The Rt Hon", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Jones", hn) + + def test_conjunction_before_title(self) -> None: + hn = HumanName('The Lord of the Universe') + self.m(hn.title, "The Lord of the Universe", hn) + + def test_double_conjunction_on_title(self) -> None: + hn = HumanName('Lord of the Universe') + self.m(hn.title, "Lord of the Universe", hn) + + def test_triple_conjunction_on_title(self) -> None: + hn = HumanName('Lord and of the Universe') + self.m(hn.title, "Lord and of the Universe", hn) + + def test_multiple_conjunctions_on_multiple_titles(self) -> None: + hn = HumanName('Lord of the Universe and Associate Supreme Queen of the World Lisa Simpson') + self.m(hn.title, "Lord of the Universe and Associate Supreme Queen of the World", hn) + self.m(hn.first, "Lisa", hn) + self.m(hn.last, "Simpson", hn) + + def test_title_with_last_initial_is_suffix(self) -> None: + hn = HumanName("King John V.") + self.m(hn.title, "King", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "V.", hn) + + def test_initials_also_suffix(self) -> None: + hn = HumanName("Smith, J.R.") + self.m(hn.first, "J.R.", hn) + # self.m(hn.middle, "R.", hn) + self.m(hn.last, "Smith", hn) + + def test_two_title_parts_separated_by_periods(self) -> None: + hn = HumanName("Lt.Gen. John A. Kenneth Doe IV") + self.m(hn.title, "Lt.Gen.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "IV", hn) + + def test_two_part_title(self) -> None: + hn = HumanName("Lt. Gen. John A. Kenneth Doe IV") + self.m(hn.title, "Lt. Gen.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "IV", hn) + + def test_two_part_title_with_lastname_comma(self) -> None: + hn = HumanName("Doe, Lt. Gen. John A. Kenneth IV") + self.m(hn.title, "Lt. Gen.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "IV", hn) + + def test_two_part_title_with_suffix_comma(self) -> None: + hn = HumanName("Lt. Gen. John A. Kenneth Doe, Jr.") + self.m(hn.title, "Lt. Gen.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A. Kenneth", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_possible_conflict_with_middle_initial_that_could_be_suffix(self) -> None: + hn = HumanName("Doe, Rev. John V, Jr.") + self.m(hn.title, "Rev.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "V", hn) + self.m(hn.suffix, "Jr.", hn) + + def test_possible_conflict_with_suffix_that_could_be_initial(self) -> None: + hn = HumanName("Doe, Rev. John A., V, Jr.") + self.m(hn.title, "Rev.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + self.m(hn.middle, "A.", hn) + self.m(hn.suffix, "V, Jr.", hn) + + # 'ben' is removed from PREFIXES in v0.2.5 + # this test could re-enable this test if we decide to support 'ben' as a prefix + @pytest.mark.xfail + def test_ben_as_conjunction(self) -> None: + hn = HumanName("Ahmad ben Husain") + self.m(hn.first, "Ahmad", hn) + self.m(hn.last, "ben Husain", hn) + + def test_ben_as_first_name(self) -> None: + hn = HumanName("Ben Johnson") + self.m(hn.first, "Ben", hn) + self.m(hn.last, "Johnson", hn) + + def test_ben_as_first_name_with_middle_name(self) -> None: + hn = HumanName("Ben Alex Johnson") + self.m(hn.first, "Ben", hn) + self.m(hn.middle, "Alex", hn) + self.m(hn.last, "Johnson", hn) + + def test_ben_as_middle_name(self) -> None: + hn = HumanName("Alex Ben Johnson") + self.m(hn.first, "Alex", hn) + self.m(hn.middle, "Ben", hn) + self.m(hn.last, "Johnson", hn) + + # http://code.google.com/p/python-nameparser/issues/detail?id=13 + def test_last_name_also_prefix(self) -> None: + hn = HumanName("Jane Doctor") + self.m(hn.first, "Jane", hn) + self.m(hn.last, "Doctor", hn) + + def test_title_with_periods(self) -> None: + hn = HumanName("Lt.Gov. John Doe") + self.m(hn.title, "Lt.Gov.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test_title_with_periods_lastname_comma(self) -> None: + hn = HumanName("Doe, Lt.Gov. John") + self.m(hn.title, "Lt.Gov.", hn) + self.m(hn.first, "John", hn) + self.m(hn.last, "Doe", hn) + + def test_mac_with_spaces(self) -> None: + hn = HumanName("Jane Mac Beth") + self.m(hn.first, "Jane", hn) + self.m(hn.last, "Mac Beth", hn) + + def test_mac_as_first_name(self) -> None: + hn = HumanName("Mac Miller") + self.m(hn.first, "Mac", hn) + self.m(hn.last, "Miller", hn) + + def test_multiple_prefixes(self) -> None: + hn = HumanName("Mike van der Velt") + self.m(hn.first, "Mike", hn) + self.m(hn.last, "van der Velt", hn) + + def test_2_same_prefixes_in_the_name(self) -> None: + hh = HumanName("Vincent van Gogh van Beethoven") + self.m(hh.first, "Vincent", hh) + self.m(hh.middle, "van Gogh", hh) + self.m(hh.last, "van Beethoven", hh) diff --git a/tests/test_variations.py b/tests/test_variations.py new file mode 100644 index 0000000..6edccee --- /dev/null +++ b/tests/test_variations.py @@ -0,0 +1,211 @@ +from nameparser import HumanName + +from tests.base import HumanNameTestBase + + +TEST_NAMES = ( + "John Doe", + "John Doe, Jr.", + "John Doe III", + "Doe, John", + "Doe, John, Jr.", + "Doe, John III", + "John A. Doe", + "John A. Doe, Jr.", + "John A. Doe III", + "Doe, John A.", + "Doe, John A., Jr.", + "Doe, John A. III", + "John A. Kenneth Doe", + "John A. Kenneth Doe, Jr.", + "John A. Kenneth Doe III", + "Doe, John A. Kenneth", + "Doe, John A. Kenneth, Jr.", + "Doe, John A. Kenneth III", + "Dr. John Doe", + "Dr. John Doe, Jr.", + "Dr. John Doe III", + "Doe, Dr. John", + "Doe, Dr. John, Jr.", + "Doe, Dr. John III", + "Dr. John A. Doe", + "Dr. John A. Doe, Jr.", + "Dr. John A. Doe III", + "Doe, Dr. John A.", + "Doe, Dr. John A. Jr.", + "Doe, Dr. John A. III", + "Dr. John A. Kenneth Doe", + "Dr. John A. Kenneth Doe, Jr.", + "Dr. John A. Kenneth Doe III", + "Doe, Dr. John A. Kenneth", + "Doe, Dr. John A. Kenneth Jr.", + "Doe, Dr. John A. Kenneth III", + "Juan de la Vega", + "Juan de la Vega, Jr.", + "Juan de la Vega III", + "de la Vega, Juan", + "de la Vega, Juan, Jr.", + "de la Vega, Juan III", + "Juan Velasquez y Garcia", + "Juan Velasquez y Garcia, Jr.", + "Juan Velasquez y Garcia III", + "Velasquez y Garcia, Juan", + "Velasquez y Garcia, Juan, Jr.", + "Velasquez y Garcia, Juan III", + "Dr. Juan de la Vega", + "Dr. Juan de la Vega, Jr.", + "Dr. Juan de la Vega III", + "de la Vega, Dr. Juan", + "de la Vega, Dr. Juan, Jr.", + "de la Vega, Dr. Juan III", + "Dr. Juan Velasquez y Garcia", + "Dr. Juan Velasquez y Garcia, Jr.", + "Dr. Juan Velasquez y Garcia III", + "Velasquez y Garcia, Dr. Juan", + "Velasquez y Garcia, Dr. Juan, Jr.", + "Velasquez y Garcia, Dr. Juan III", + "Juan Q. de la Vega", + "Juan Q. de la Vega, Jr.", + "Juan Q. de la Vega III", + "de la Vega, Juan Q.", + "de la Vega, Juan Q., Jr.", + "de la Vega, Juan Q. III", + "Juan Q. Velasquez y Garcia", + "Juan Q. Velasquez y Garcia, Jr.", + "Juan Q. Velasquez y Garcia III", + "Velasquez y Garcia, Juan Q.", + "Velasquez y Garcia, Juan Q., Jr.", + "Velasquez y Garcia, Juan Q. III", + "Dr. Juan Q. de la Vega", + "Dr. Juan Q. de la Vega, Jr.", + "Dr. Juan Q. de la Vega III", + "de la Vega, Dr. Juan Q.", + "de la Vega, Dr. Juan Q., Jr.", + "de la Vega, Dr. Juan Q. III", + "Dr. Juan Q. Velasquez y Garcia", + "Dr. Juan Q. Velasquez y Garcia, Jr.", + "Dr. Juan Q. Velasquez y Garcia III", + "Velasquez y Garcia, Dr. Juan Q.", + "Velasquez y Garcia, Dr. Juan Q., Jr.", + "Velasquez y Garcia, Dr. Juan Q. III", + "Juan Q. Xavier de la Vega", + "Juan Q. Xavier de la Vega, Jr.", + "Juan Q. Xavier de la Vega III", + "de la Vega, Juan Q. Xavier", + "de la Vega, Juan Q. Xavier, Jr.", + "de la Vega, Juan Q. Xavier III", + "Juan Q. Xavier Velasquez y Garcia", + "Juan Q. Xavier Velasquez y Garcia, Jr.", + "Juan Q. Xavier Velasquez y Garcia III", + "Velasquez y Garcia, Juan Q. Xavier", + "Velasquez y Garcia, Juan Q. Xavier, Jr.", + "Velasquez y Garcia, Juan Q. Xavier III", + "Dr. Juan Q. Xavier de la Vega", + "Dr. Juan Q. Xavier de la Vega, Jr.", + "Dr. Juan Q. Xavier de la Vega III", + "de la Vega, Dr. Juan Q. Xavier", + "de la Vega, Dr. Juan Q. Xavier, Jr.", + "de la Vega, Dr. Juan Q. Xavier III", + "Dr. Juan Q. Xavier Velasquez y Garcia", + "Dr. Juan Q. Xavier Velasquez y Garcia, Jr.", + "Dr. Juan Q. Xavier Velasquez y Garcia III", + "Velasquez y Garcia, Dr. Juan Q. Xavier", + "Velasquez y Garcia, Dr. Juan Q. Xavier, Jr.", + "Velasquez y Garcia, Dr. Juan Q. Xavier III", + "John Doe, CLU, CFP, LUTC", + "John P. Doe, CLU, CFP, LUTC", + "Dr. John P. Doe-Ray, CLU, CFP, LUTC", + "Doe-Ray, Dr. John P., CLU, CFP, LUTC", + "Hon. Barrington P. Doe-Ray, Jr.", + "Doe-Ray, Hon. Barrington P. Jr.", + "Doe-Ray, Hon. Barrington P. Jr., CFP, LUTC", + "Jose Aznar y Lopez", + "John E Smith", + "John e Smith", + "John and Jane Smith", + "Rev. John A. Kenneth Doe", + "Donovan McNabb-Smith", + "Rev John A. Kenneth Doe", + "Doe, Rev. John A. Jr.", + "Buca di Beppo", + "Lt. Gen. John A. Kenneth Doe, Jr.", + "Doe, Lt. Gen. John A. Kenneth IV", + "Lt. Gen. John A. Kenneth Doe IV", + 'Mr. and Mrs. John Smith', + 'John Jones (Google Docs)', + 'john e jones', + 'john e jones, III', + 'jones, john e', + 'E.T. Smith', + 'E.T. Smith, II', + 'Smith, E.T., Jr.', + 'A.B. Vajpayee', + 'Rt. Hon. Paul E. Mary', + 'Maid Marion', + 'Amy E. Maid', + 'Jane Doctor', + 'Doctor, Jane E.', + 'dr. ben alex johnson III', + 'Lord of the Universe and Supreme King of the World Lisa Simpson', + 'Benjamin (Ben) Franklin', + 'Benjamin "Ben" Franklin', + "Brian O'connor", + "Sir Gerald", + "Magistrate Judge John F. Forster, Jr", + # "Magistrate Judge Joaquin V.E. Manibusan, Jr", Intials seem to mess this up + "Magistrate-Judge Elizabeth Todd Campbell", + "Mag-Judge Harwell G Davis, III", + "Mag. Judge Byron G. Cudmore", + "Chief Judge J. Leon Holmes", + "Chief Judge Sharon Lovelace Blackburn", + "Judge James M. Moody", + "Judge G. Thomas Eisele", + # "Judge Callie V. S. Granade", + "Judge C Lynwood Smith, Jr", + "Senior Judge Charles R. Butler, Jr", + "Senior Judge Harold D. Vietor", + "Senior Judge Virgil Pittman", + "Honorable Terry F. Moorer", + "Honorable W. Harold Albritton, III", + "Honorable Judge W. Harold Albritton, III", + "Honorable Judge Terry F. Moorer", + "Honorable Judge Susan Russ Walker", + "Hon. Marian W. Payson", + "Hon. Charles J. Siragusa", + "US Magistrate Judge T Michael Putnam", + "Designated Judge David A. Ezra", + "Sr US District Judge Richard G Kopf", + "U.S. District Judge Marc Thomas Treadwell", + "Dra. Andréia da Silva", + "Srta. Andréia da Silva", + +) + + +class HumanNameVariationTests(HumanNameTestBase): + # test automated variations of names in TEST_NAMES. + # Helps test that the 3 code trees work the same + + TEST_NAMES = TEST_NAMES + + def test_variations_of_TEST_NAMES(self) -> None: + for name in self.TEST_NAMES: + hn = HumanName(name) + if len(hn.suffix_list) > 1: + hn = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn.as_dict()).split(',')[0]) + hn.C.empty_attribute_default = '' # format strings below require empty string + hn_dict = hn.as_dict() + nocomma = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn_dict)) + lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix}".format(**hn_dict)) + if hn.suffix: + suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix}".format(**hn_dict)) + if hn.nickname: + nocomma = HumanName("{title} {first} {middle} {last} {suffix} ({nickname})".format(**hn_dict)) + lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix} ({nickname})".format(**hn_dict)) + if hn.suffix: + suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix} ({nickname})".format(**hn_dict)) + for attr in hn._members: + self.m(getattr(hn, attr), getattr(nocomma, attr), hn) + self.m(getattr(hn, attr), getattr(lastnamecomma, attr), hn) + if hn.suffix: + self.m(getattr(hn, attr), getattr(suffixcomma, attr), hn) diff --git a/uv.lock b/uv.lock index a4818aa..c01beca 100644 --- a/uv.lock +++ b/uv.lock @@ -224,6 +224,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + [[package]] name = "idna" version = "3.18" @@ -242,6 +254,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/53/fb7122b71361a0d121b669dcf3d31244ef75badbbb724af388948de543e2/imagesize-2.0.0-py2.py3-none-any.whl", hash = "sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96", size = 9441, upload-time = "2026-03-03T14:18:27.892Z" }, ] +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -503,6 +524,7 @@ dependencies = [ dev = [ { name = "dill" }, { name = "mypy" }, + { name = "pytest" }, { name = "ruff" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, @@ -516,6 +538,7 @@ requires-dist = [{ name = "typing-extensions", marker = "python_full_version < ' dev = [ { name = "dill", specifier = ">=0.2.5" }, { name = "mypy", specifier = ">=2.1" }, + { name = "pytest", specifier = ">=8" }, { name = "ruff", specifier = ">=0.15" }, { name = "sphinx", specifier = ">=8" }, ] @@ -538,6 +561,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, ] +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + [[package]] name = "pygments" version = "2.20.0" @@ -547,6 +579,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] +[[package]] +name = "pytest" +version = "9.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/84/0e/b5858858d74958632c49b72cb25a3976ff9f632397626715be71c89d3971/pytest-9.1.0.tar.gz", hash = "sha256:41dd9148c08072446394cefd3d79701701335a9f4cae69ba92e39f6c7f5c061c", size = 1634181, upload-time = "2026-06-13T18:52:45.983Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/5a/ba30a81239b909821b3153e303e7def45178bf353da4f72380e6c5e8793b/pytest-9.1.0-py3-none-any.whl", hash = "sha256:8ebb0e7888bdf2bdfc602ec51f8f62d50200af37356c74e503c79a94f5c81f32", size = 386453, upload-time = "2026-06-13T18:52:44.045Z" }, +] + [[package]] name = "requests" version = "2.34.2"