You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 410f2aa
Browse filesBrowse the repository at this point in the historyBrowse files
Finding the sites names the vocabulary modules; no call-per-constant claim (#1012 review)
2.8.1 warns where code reads a constant of a removed vocabulary module,
never at a bare import, so migrate.rst's "Finding the sites" says to
upgrade to 2.8.1, lists the bare import among what passes and still
fails, and adds the eight modules to the search list. Three sites still
claimed one call per constant where TITLE_PHRASES has none and several
are comprehensions; the release bullet no longer pairs TITLES with a
call returning more words; AGENTS.md's layering example names a module
that exists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -236,7 +236,7 @@ The compiled sets, read by `Lexicon` (mostly as the `_sets` field of the same na
236
236
The 2.0 rewrite landed as underscore-private modules beside the v1 code, which 2.0 and then 3.0 deleted. These conventions apply to all of it. The full design record (rationale, settled-decision logs, dated amendments) lives in untracked `docs/superpowers/specs/`; this section is the enforceable subset. **A commit that establishes or amends one of these conventions must update this section in the same commit** — grep-driven staleness sweeps miss paraphrased prose (see Workflow above), so write-time maintenance is the mechanism, audits are the backstop.
237
237
238
238
-**Module layout**: every module is underscore-private (`_types.py`, `_lexicon.py`, `_policy.py`, `_locale.py`, `_render.py`, `_reading_index.py`, `_pipeline/`, `_parser.py`). The public import surface is exactly `nameparser`, `nameparser.locales` and the public data modules under `nameparser.config` (`surnames`, `regexes`; the vocabulary's compiled sets are private since 3.0, #1007); `nameparser/__init__.py` holds re-exports and `__all__` only — no logic.
239
-
- **Layering is enforced by `tests/v2/test_layering.py`** (exact-module matching; `if TYPE_CHECKING:` imports don't count): `_types` imports nothing internal at module level — its rendering delegates import `_render` at call time; `_lexicon` and `_policy` sit above `_types` independently (`_lexicon` may import `nameparser.config.*` DATA modules, e.g. `config/maiden_markers.py`, and `_reading_index` at call time only, to compile a configured lexicon's readings, since `tools/vocab/build.py` loads it by path, 3.0's 4i-b); `_reading_index` imports nothing internal at module level and the index, `config/_index.py`, at call time, since `tools/vocab/build.py` loads it by path; `_locale` sits on `_lexicon`+`_policy` (plus `_types` for the shared pickle mixin, and `config/_rules.py` at call time, in `rules_patch`); `_render` imports `_types`, `_lexicon` (for `Lexicon.default()` and `_normalize`) and `_policy` (for the scripts that write no initials); `_pipeline/*` imports `_types`+`_lexicon`+`_policy` plus in-package `_pipeline` helpers, `_assemble` also `_reading_index`, for the kinds `Reading.languages` matches (`CATEGORY`; the files themselves it reads through `Lexicon._files`, 4i-d; `_vocab` imported it in 3.0's 4b and 4c for a listed suffix word's kind and a patronymic particle's, which since 4i-b the lexicon compiles into `_sets`); `_parser` sits on everything except `_render`, `_reading_index` at call time only, to validate a choice's tags and move the case masks it moves (the choice itself compiles in `_lexicon._built`); `__main__` imports only the public package; locale pack modules (`locales/*.py`) import `_locale`/`_lexicon`/`_policy`/`_types` only (`_types` joined the list in #272 — `locales/ja.py`'s segmenter factory constructs a `Segmentation`), and the `locales/__init__` additionally lazy-imports its packs (PEP 562). Extend the test's `ALLOWED` table when adding a module.
239
+
- **Layering is enforced by `tests/v2/test_layering.py`** (exact-module matching; `if TYPE_CHECKING:` imports don't count): `_types` imports nothing internal at module level — its rendering delegates import `_render` at call time; `_lexicon` and `_policy` sit above `_types` independently (`_lexicon` may import `nameparser.config.*` DATA modules, e.g. `config/surnames.py` and the private `config/_compiled.py`, and `_reading_index` at call time only, to compile a configured lexicon's readings, since `tools/vocab/build.py` loads it by path, 3.0's 4i-b); `_reading_index` imports nothing internal at module level and the index, `config/_index.py`, at call time, since `tools/vocab/build.py` loads it by path; `_locale` sits on `_lexicon`+`_policy` (plus `_types` for the shared pickle mixin, and `config/_rules.py` at call time, in `rules_patch`); `_render` imports `_types`, `_lexicon` (for `Lexicon.default()` and `_normalize`) and `_policy` (for the scripts that write no initials); `_pipeline/*` imports `_types`+`_lexicon`+`_policy` plus in-package `_pipeline` helpers, `_assemble` also `_reading_index`, for the kinds `Reading.languages` matches (`CATEGORY`; the files themselves it reads through `Lexicon._files`, 4i-d; `_vocab` imported it in 3.0's 4b and 4c for a listed suffix word's kind and a patronymic particle's, which since 4i-b the lexicon compiles into `_sets`); `_parser` sits on everything except `_render`, `_reading_index` at call time only, to validate a choice's tags and move the case masks it moves (the choice itself compiles in `_lexicon._built`); `__main__` imports only the public package; locale pack modules (`locales/*.py`) import `_locale`/`_lexicon`/`_policy`/`_types` only (`_types` joined the list in #272 — `locales/ja.py`'s segmenter factory constructs a `Segmentation`), and the `locales/__init__` additionally lazy-imports its packs (PEP 562). Extend the test's `ALLOWED` table when adding a module.
240
240
-**Canonical field order** — the seven roles in `Role` enum declaration order, defined once and derived everywhere (properties, `as_dict`, reprs, `comparison_key`). Never restate the order literally. `Role` is a `StrEnum`: members compare as their field-name strings, and `tokens_for()` coerces strings via `_coerce_enum`.
241
241
-**Method organization**, fixed section order in every class: fields + `__post_init__` validation → alternative constructors → dunders (construction/equality → protocol → operators) → properties → public methods by concern (access → editing → comparison → rendering delegates) → private helpers last, except a helper serving exactly one section may sit at that section's head.
242
242
- **Validation is eager and fail-loud**: every `raise` states the offending value, the expected form, and the fix. Exception taxonomy: wrong type — including wrong element type inside a collection, bare `str` where an iterable of strings is expected, or a `Mapping` where a plain iterable is expected — raises `TypeError`; well-typed but unacceptable values raise `ValueError`; failed enum lookups stay `ValueError` for any input (stdlib `EnumType` precedent). **When the message hands the reader code to paste, that code has to survive a type checker, and then RUN** — nameparser ships `py.typed`, and a placeholder can type-check and still raise: the 2.4 release sweep's first fix to the `capitalization_exceptions` hint offered `('key', 'Value')`, which passes mypy and fails #459's mask check, so `test_add_capitalization_exceptions_raises_pointing_at_replace` now executes the offered code. #337's segmenterless warning offered `Policy(segment_scripts=())`, an `arg-type` error, because these fields are annotated with what they STORE rather than everything the constructor accepts. Prefer the `frozenset()` / `()` spellings in messages and docstrings, and pin the offered spelling in a test — the warning tests matched on `ja_segmenter` and never checked the actionable half of the message. **A warning emitted in `Parser.__post_init__` needs `parser_for` to re-emit it from its own frame** (the `catch_warnings(record=True)` block at its return): `__post_init__`'s `stacklevel` is sized for direct `Parser(...)` construction, and through `parser_for`'s extra frame the default one-line rendering attributes the warning to the library's own `return Parser(...)` — the exact call the message tells the user to change becomes invisible. No single stacklevel serves both entry points; a new construction warning gets the re-emission for free, but a new CONSTRUCTION SITE for `Parser` inside this package needs its own re-emission or its callers get library-attributed warnings (#337 review).
Copy file name to clipboardExpand all lines: docs/release_log.rst
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,7 +30,7 @@ Release Log
30
30
31
31
- **Configure a Lexicon by reading; its set fields are internal.** ``Lexicon.default().remove("dean", kind="given")`` reads ``Dean Smith`` title ``Dean``, the spelling of 2.8.0's ``Lexicon.default().add(titles={"dean"})``, which now raises ``TypeError`` naming that call, as do ``Lexicon(titles=...)`` and ``dataclasses.replace`` with a set field, and reading ``lexicon.titles`` raises ``AttributeError``; ``add(*words, kind=..., **properties)``, ``remove(*words, kind=None)`` and ``readings_of(word)``, returning ``LexiconReading``, take the vocabulary files' kinds, and :doc:`migrate` has a row per 2.8.0 field. A 2.8.0 pickle of a ``Lexicon``, ``Parser`` or ``Locale`` loads where readings compile its sets back, keeping the vocabulary it was pickled with rather than taking 3.0's, and is refused otherwise; a 2.x call or pickle that left a word in a marker set over a set it took the word out of reads as though the marker went with it (after ``remove(titles={"air"})``, ``John Smith, AIR`` gives suffix ``AIR``, given ``AIR`` in 2.8.0). :issue:`754`
32
32
- **Deprecate loading a Lexicon, Parser or locale pack pickled by 2.x, which 3.1 refuses.** ``pickle.loads`` of a ``Parser`` pickled by 2.8.0 emits a ``DeprecationWarning``, once for each ``Lexicon`` it holds, and 3.1 will refuse it; re-pickle the loaded object under 3.0 and that pickle loads without one. The errors naming a word-by-word fix for a 2.x ``Lexicon`` spelling keep it in 3.0 and point at :doc:`migrate` in 3.1. :issue:`754`, :issue:`1003`
33
-
- **Remove the vocabulary modules in nameparser.config, which 2.8.1 warns of.** ``from nameparser.config.titles import TITLES`` raises ``ModuleNotFoundError``, as it does for ``suffixes``, ``particles``, ``conjunctions``, ``bound_given_names``, ``given_names``, ``maiden_markers`` and ``capitalization``, where 2.8.0 imported each; ``Lexicon.default().words(kind="title")`` lists the words, :doc:`migrate` gives the call for every constant, and ``nameparser.config.surnames`` stays. :issue:`1007`
33
+
- **Remove the vocabulary modules in nameparser.config, which 2.8.1 warns of.** ``from nameparser.config.titles import TITLES`` raises ``ModuleNotFoundError``, as it does for ``suffixes``, ``particles``, ``conjunctions``, ``bound_given_names``, ``given_names``, ``maiden_markers`` and ``capitalization``, where 2.8.0 imported each; ``Lexicon.default().words(kind="title")`` lists the title words in 3.0, :doc:`migrate` gives the call or comprehension for each constant, and ``nameparser.config.surnames`` stays. :issue:`1007`
34
34
- **Remove HumanName, Constants and the rest of the 1.x compatibility layer.** ``from nameparser import HumanName`` raises ``ImportError``, where 1.4.0 through 2.8.0 imported it (2.8.0 warning where it was constructed); ``parse("Dr. Juan de la Vega")`` reads the same name, with given ``Juan`` and family ``de la Vega``. ``nameparser.parser``, ``nameparser.util``, ``nameparser.config``'s ``Constants``, ``CONSTANTS`` and managers, and the five word-list names and two module paths 2.2 renamed go too, and a pickled ``HumanName`` or ``Constants`` no longer loads. See :doc:`migrate`. :issue:`357`
0 commit comments