Skip to content

Simplify the 4i choice compile and reading-files code (#754) - #1001

Merged
derek73 merged 1 commit into
masterfrom
claude/simplify-4i-lexicon-d1434a
Nov 2, 2026
Merged

derek73 merged 1 commit into
masterfrom
claude/simplify-4i-lexicon-d1434a

Conversation

@derek73

@derek73 derek73 commented Nov 2, 2026

Copy link
Copy Markdown
Owner

A /simplify pass over the code the 4i series (#989, #991, #992, #997) added for #754. It is a quality pass only, with no behaviour, message, signature, repr or pickle change.

The 2.x translation code (_target_readings, _inert_dropped/_MARKER_READ_WITH, _edits_toward, _translation, _refusal's translation arms, _changed, the 2.x pickle load) is deliberately left alone. It is migration scaffolding, deprecated in 3.0 and deleted in 3.1. The findings that apply only there are listed at the end, for the 3.1 deletion.

Line delta

file + −
nameparser/_lexicon.py 28 31
nameparser/_reading_index.py 21 3

_parser.py and _pipeline/_assemble.py are unchanged.

What was folded or removed, and why

  • One strict-choice predicate (mechanisms.md#ONE-PREDICATE-PER-QUESTION).
    • "The chosen files' and native-script readings" was spelled out three times: in _reading_index.strict_pool, _lexicon._chosen_pool, and the per-word path of _ReadingFiles.languages.
    • _reading_index.strict_kept(readings, chosen) is now the one copy.
    • chosen_readings(readings, chosen, strict) is that filter followed by choose. Both compile_choice and _ReadingFiles.languages read through it.
    • Before, the Reading.languages path was exact only as long as it matched the compile by hand.
  • Lexicon._pool reads through _ReadingFiles.pool(). The two held the same four values (base, log, choice, strict) and the same no-log/log branch. _ReadingFiles.languages' log arm calls the same method.
  • _compiled_for is flattened. The three nested arms, including an elif that tested base again, are now two flat guards with the same arms in the same order.
  • _reading_files uses maxsize=128, as _built does. With 64 it evicted first, so two equal lexicons built after an eviction stopped sharing assemble's memo. Results were correct either way.
  • _rechosen_masks loads the default's masks only in the arm that reads them.
  • _unwritten reads the unwritten values from _reading_index.ReadingProperties. Those are acronym, addresses and flag. Its docstring already said it did, but the code restated them. The new version is checked equal to the old one over every kind × property.
  • A stale comment in Lexicon.__setstate__. It said no field was marked _ADDED_IN ("none yet"), but _languages and _strict both are.

Considered and skipped

  • Keeping the pool on _ReadingFiles, so a memo miss never looks up or rebuilds _built. Assemble's 4096-entry _languages memo keys on the _ReadingFiles, so each cached object would pin a whole pool alive. That is an unbounded memory cost traded for a miss path that is rare.
  • Folding _with_packs' two mask branches into one _rechosen_masks call. A parser_for that chooses no language would then load the reading index, which it does not do today.
  • Caching _check_base's validation of a snapshot base. A snapshot base is reached only from another release's pickle.
  • _failed_layer, _clashes_unchosen and parser_for's three-state strict. Nothing simpler keeps the messages, and folding the two strict checks would change which error wins when an argument is bad in two ways.

Candidate needing a decision

  • _MARKER_READ_WITH's after_given_titles row lists titles alone, where its title siblings also list titles_ambiguous.
    • So Lexicon.default().add("dean", kind="salutation", after_given=True) compiles dean into after_given_titles and titles_ambiguous, and _inert_dropped then drops it, against its docstring.
    • It is harmless today: the drop applies to both sides of every compare, and no default word is in both sets.
    • Widening the row changes which 2.x spellings count as exact, so it is left for the 3.1 deletion to make moot.

Left for the 3.1 deletion

These are findings that only make sense inside the translation code:

  • The category groups (_TITLE_FIELDS, _ACRONYM_FIELDS, _WORD_FIELDS, _PARTICLE_FIELDS and an inline conjunction pair) can be derived from _MARKER_READ_WITH. They were checked equal.
  • _target_readings' pop-then-set marker properties could be a table.
  • _by_kind is the first element of each list _props_by_kind builds.
  • _translation and _translated_2x share a "compared sets" step (titles_ambiguous - titles, then _inert_dropped).
  • _refusal could take the op rather than string-sniffing where.
  • _translation's prefix default is never used.
  • _shown_value repeats _prop_value's property list.

Gates

All of these were run on the final tree and pass:

  • uv run pytest: 34,734 passed. This includes test_snapshot.py, unchanged, and the 2.8 and 4i-b pickle rows.
  • With namedivider installed, the same suite: 34,757 passed.
  • uv run pytest -n0 -m serial: 42 passed, so the frame baseline holds.
  • uv run --python 3.15 pytest: passes.
  • uv run mypy and uv run ruff check: clean.
  • sphinx-build -b doctest docs and python -m doctest README.rst: clean.
  • tools/differential/cldr_agreement.py: every record matches.

🤖 Generated with Claude Code

One strict-choice predicate: _reading_index.strict_kept is the filter
strict_pool, _lexicon._chosen_pool and _ReadingFiles.languages each
spelled out, and chosen_readings the filter-then-choose that
compile_choice and the per-word path share. Lexicon._pool reads
through _ReadingFiles.pool(), which holds the same base, log and
choice. _compiled_for's nested arms are flattened; _reading_files is
sized as _built; _rechosen_masks loads the default's masks only where
it reads them; _unwritten reads the unwritten values from
ReadingProperties instead of restating them; a __setstate__ comment
said no field was marked ADDED_IN. No behaviour or message change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added this to the 3.0 milestone Nov 2, 2026
@derek73 derek73 self-assigned this Nov 2, 2026
@derek73
derek73 merged commit fc8fda1 into master Nov 2, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant