refactor: split the author-time guard subsystem out of feature_chain_parser - #907
Merged
Conversation
…parser feature_chain_parser.py mixed the runtime name-parsing and matching path with a class-definition-time validation and guard-installation subsystem that only used the class as a namespace. The author-time cluster now lives in feature_chain_author_guards.py as module-level functions. The import direction is one-way (the guards import the parser, never the reverse), so there are no compatibility re-exports: the two __init_subclass__ hooks import the new module directly. A split-boundary test pins ownership, the acyclic direction, and the absence of re-exports. Parser: 1130 -> 691 lines.
…y bank Review follow-ups to the split: - the split-boundary test now also pins the four parser members the guards module calls back into, so moving one of them fails visibly; - the clean-interpreter subprocess runs from the repo root, so it can never validate an installed copy instead of the tree; - the two build_effective_options raise tests assert no WARNING on any logger again, restoring the invariant they state; the split had narrowed them to a single logger name; - the guards module docstring names the parser-private surface it depends on; - memory-bank/systemPatterns.md records the new module and the one-way import.
Both lines already carry a public reference (#763, and the test class name), so the identifier added nothing a reader outside the tracker could use.
The branch first recorded this in memory-bank/systemPatterns.md, which main retired in the meantime; property-mapping.md is where that content landed and where the class-definition behavior is specified rather than mentioned.
TKaltofen
force-pushed
the
refactor/split-author-time-guards
branch
from
July 30, 2026 17:34
f64f433 to
6841004
Compare
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.
feature_chain_parser.pymixed two separable concerns: the runtime name-parsing andmatching path (
parse_name,match_configuration_feature_chain_parser,build_effective_options), and a class-definition-time validation and guard-installationsubsystem that only used the class as a namespace. The author-time cluster now lives in
feature_chain_author_guards.pyas module-level functions taking the owner class.Parser: 1130 -> 691 lines. New module: 470 lines.
What moved
validate_name_binding,warn_captureless_without_binding,warn_universal_optional_matcher,check_required_when,install_required_when_guard,install_name_path_presence_guard,_matcher_is_staticmethod,_reject_staticmethod_matcher,_resolve_match_arguments,_pattern_named_and_total_groups,_flatten_patterns,_str_reachable_values, plus the sixguard flags and ContextVars. Bodies, docstrings and comments moved verbatim; the only edits are
call requalification.
Import direction
One-way: the guards import the parser, never the reverse. So there are no compatibility
re-exports.
FeatureGroup.__init_subclass__andFeatureChainParserMixin.__init_subclass__import the new module directly, in the same call order as before.
The plugin-author surface is unchanged: none of the moved names was exported from
mloda.provider, and downstream plugin code only ever callsFeatureChainParser.parse_feature_name, which stays put.Behavior note
The three author diagnostics that moved (the captureless-pattern warning, the universal-matcher
warning, and the contained
required_whenpredicate raise) now log under...feature_chainer.feature_chain_author_guardsinstead of...feature_chainer.feature_chain_parser.Anyone silencing them by logger name needs the new name. Nothing in the docs pins a logger name.
Tests
A new split-boundary test pins module ownership, that the runtime match path and the four parser
members the guards call back into stay in the parser, that the parser does not import the guards
(static AST plus a fresh-interpreter check), and that no moved name reappears as a
FeatureChainParserattribute.toxgreen: 7543 passed, 170 skipped, ruff,mypy --strict, bandit.