Repository navigation
Compile a language file's [rules] into its pack's policy patch (3.0, 4f) - #953
Merged
Merged
Conversation
RU's and TR_AZ's PolicyPatch are now build output: ru.toml and tr.toml carry a [rules] table (patronymic_rules = ["east-slavic"] / ["turkic"]), tools/vocab/build.py checks it (check 12: RULE_KEYS, PACK_RULES, no scalar default) and writes nameparser/config/_rules.py, and nameparser._locale.rules_patch(tag) turns a file's table into the patch. Both packs compare equal to the Locales written by hand, their pickles load across the change, and no parse moves. DEVIATES stays hand-written, now held by a test to the rules each pack's compiled patch turns on; ZH and JA keep their hand-written segmentation patches. Decisions: decisions/vocabulary-model's 2026-10-29 sub-phase 4f entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- RFC: describe what shipped (tuples in config/_rules.py, built into the patch by rules_patch at pack import); list phase 4's landed sub-phases in the phase table. - decisions 4f: give ZH and JA each their own condition; state the import figures with nameparser preloaded and the recipe; link the Open questions to their issues. - vocab README: describe the files holding [rules] by PACK_RULES rather than a count; one instruction for a new rule kind, matching mechanisms.md#LOCALE-PACKS-PURE-DATA (field with ADDED_IN, RULE_KEYS and _RULE_VALUES rows, its own mechanisms entry). - build.py: the no-pack-reads message no longer doubles the quote. - test_the_rule_tables_agree_with_policy requires a RULE_DEFAULTS entry for every scalar key, each converting to Policy()'s value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 4f decisions entry gains a SUPERSEDES line naming item 10's clause that made ZH's surname list and the RU and TR_AZ endings rule data for [rules]; items 5 and 7 state the reversal; the 2026-10-27 #753 head names the superseded part; the RFC's "existing packs fit" sentence describes what 4f built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
3.0 sub-phase 4f of #754 (and #753): a language file's
[rules]table compiles into its shippedLocale'sPolicyPatch. RU and TR_AZ are now build output fromru.tomlandtr.toml, value-equal to the packs written by hand, and no parse moves.The schema
Each key is the
Policyfield of its name, and its value takes that field's shape:patronymic_rulesset: a non-empty array, each name once"east-slavic","turkic"(PatronymicRulevalues)name_orderchoice: one name"family-first","family-first-given-last"two_family_namesflagtrueA rule is written only to turn it on. The defaults (
name_order = "given-first",two_family_names = false) are refused, because a pack's scalar overrides the caller's own scalar inapply_patch. 4g's compound given name will be a newPolicyfield plus one row inRULE_KEYSand one in_locale._RULE_VALUES.What changed
tools/vocab/build.py: new tablesRULE_KEYS,RULE_DEFAULTSandPACK_RULES(ru→RU,tr→TR_AZ). Build check 12 refuses:rulesthat is not a table;The build writes a third generated module,
nameparser/config/_rules.py. It holds tuples only, one line per file, and--checkexits 1 when it is stale.nameparser._locale.rules_patch(tag): importsconfig/_rules.pyat call time and builds thePolicyPatch. The pack modules still import_locale,_lexiconand_policyonly. Intest_layering.py,_locale's row gainsnameparser.config._rules.locales/ru.pyandlocales/tr_az.py: nowpolicy=rules_patch("ru")andpolicy=rules_patch("tr").Tests:
PolicyPatch's fields and toPolicy()'s defaults, which runs every accepted name through the converter;_rules.pycheck;PACK_RULEStolocales._REGISTRY;Locales pinned with==;DEVIATESfor it fails.Decisions the spec left open
All are recorded in decisions/vocabulary-model's 2026-10-29 sub-phase 4f entry.
config/_rules.py, read through_locale.rules_patch. Weighed against generatingPolicyPatch(...)source, which would make a config module import_policy, and against a converter in each pack.PACK_RULES. TR_AZ readstr.toml: there is noaz.toml, and the rule is the same for both languages. The table does not choose the file's vocabulary, solanguagesstays empty for both packs._pipeline/_vocab.py). A file turns a rule on; it never supplies what the rule matches.DEVIATESstays hand-written, now held by a test to the rules the patch turns on. Deriving it outright, by moving each rule's surface predicate beside its enum member, is left Open for 4g.segment_scriptsturn-on depends on a Python surname list (ZH) or the caller's segmenter (JA), so a table would split the pack without making it pure data.Evidence the packs and parses are unchanged
locales.RUandlocales.TR_AZ==the hand-writtenLocales, and their rules arePatronymicRulemembers.RU,TR_AZ,parser_for(RU),parser_for(TR_AZ)andparser_for(RU, TR_AZ).PYTHONSAFEPATH=1, from a directory outside the worktree; the tell printed2.8.0from the uv cache) and under base23aacddcload in this tree, compare equal and parse alike.PYTHONHASHSEED=0, all five of this tree's pickles are byte-identical to the base's.test_snapshot.py,test_cldr_agreement.pyand the locale agreement records. Neithercldr_agreement_locales.jsonnorwikidata_native_agreement_locales.jsonwas re-recorded.Import time and frames
Each figure is the median of 25 fresh processes, Python 3.11.
import nameparser.localeslocales.RU,nameparseralready importedlocales.TR_AZ,nameparseralready importedThe difference is the import of
config/_rules.py. Packs still load lazily. The default parse runs no new code, sincerules_patchruns once per pack, at the pack's import. The serial benchmark pass (-n0 -m serial, which holds the frame budget) passes.Checks
uv run pytestuv run pytest -n0 -m serialuv run --python 3.15 pytest -qmypy,ruffbuild.py --checksphinx-build -b doctestNo release-log bullet: nothing changes for users. The new docs are for contributors:
nameparser/vocab/README.md's new "Rules" section and a step indocs/locales.rst's "Contributing a pack".🤖 Generated with Claude Code