Skip to content

refactor: stop identify_feature_group being a re-export facade - #908

Merged
TomKaltofen merged 4 commits into
mainfrom
refactor/settle-resolution-import-surface
Jul 31, 2026
Merged

refactor: stop identify_feature_group being a re-export facade#908
TomKaltofen merged 4 commits into
mainfrom
refactor/settle-resolution-import-surface

Conversation

@TKaltofen

@TKaltofen TKaltofen commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #891, which split identify_feature_group.py into resolution_types.py <- resolution_failure_renderer.py <- the matcher. That PR deliberately kept every pre-split import working via an __all__ re-export block, so no call site had to move. This removes that block. Behavior-preserving.

Why remove it rather than tidy it

The block was a compatibility layer for an API that no release exposes. At tag 0.10.0, still the latest release, mloda/core/prepare/identify_feature_group.py contained four top-level names (split_frameworks_by_capability, since deleted; matches_feature_group_scope; _scope_callout, private; IdentifyFeatureGroupClass) and declared no __all__ at all. Neither sibling module existed. So 13 of the 15 names it re-exported have never shipped, and mloda.core.* is internal regardless: the public facades are mloda.user, mloda.provider and mloda.steward, which import only FeatureResolutionError, ResolutionDiagnosis and ResolutionRecord.

Removing __all__ also restores the released behavior rather than changing it: 0.10.0 had none.

Changes

  • __all__ deleted outright rather than trimmed. Under mypy --strict (--no-implicit-reexport) a module always exports what it defines, so __all__ there only ever re-exported names it merely imports. With it gone, an import kept for a downstream consumer is just an unused import and ruff F401 rejects it, which is what keeps the facade from returning one name at a time. That is now noted in the import block.
  • All 26 call sites import each name from its owner: resolution_types for the result dataclasses and PARTIAL_RECORDS_CAP, resolution_failure_renderer for the rendering names, the matcher for FeatureResolutionError, ComputeFrameworkPinError, IdentifyFeatureGroupClass, matches_feature_group_scope, evaluate_and_render, resolve_or_raise. The three facades keep their own __all__ unchanged; only the source of two names moves.
  • ResolutionDiagnosis also leaves the matcher's imports: it was imported solely to feed __all__ and the module body never used it.
  • The pin test replaces three hand-maintained name tuples with one static sweep that fails any import of a borrowed name from the matcher, anywhere in mloda/, mloda_plugins/, tests/ and docs/. mypy is the primary enforcement and catches every static evasion; the sweep covers the case mypy goes quiet on, someone re-adding __all__ and routing call sites back through it.
  • Renamed test_identify_feature_group_failure_renderer.py to test_resolution_failure_renderer.py and corrected two docstrings that placed _render_multiple and PARTIAL_RECORDS_CAP in the matcher. docs/docs/in_depth/mloda-api.md no longer advertises EvaluationResult as importable from the matcher.

Verification

tox green: 7535 passed, 170 skipped, ruff, license allowlist, mypy --strict over 901 files, bandit. Test count is net -1 because the pin file went from 9 tests to 8; no skip-count change.

Two independent deep reviews ran against the full diff. Findings worth recording:

  • The sweep was silently vacuous under tox -e installed. It derived the repo root from the imported module, which under an sdist install resolves to site-packages, where there is no tests tree; the is_dir() guard then skipped everything and the test still passed. Reproduced (138 files swept, zero tests) and fixed by deriving the root from the test file, which is in the checkout under any import mode.
  • docs/ holds marimo notebooks excluded from both mypy and F401, the one surface no gate covered. Added to the sweep.
  • One review suggested keeping a restricted __all__ so import * stays tidy. Not taken: exactly one of 127 modules under mloda/core declares __all__ and it is an __init__.py, the two sibling modules from this same split declare none, and there are no star imports of any mloda.core module in the repo. It would reintroduce the hand-maintained list this PR removes.

…module

The identify_feature_group split kept every pre-split import working, so
plugin_docs still reached the renderer and the result types through the
matcher. Point each call site at the module that owns the name and drop the
TROUBLESHOOTING_URL and scope_callout re-exports, which nothing consumed
through the matcher.
Two reviews found the surface decision could not be re-derived from the
comments: the stated criterion explained importing rather than re-exporting,
and nothing said why the result types stay a block. Also pin that every public
renderer name is classified, so a new one cannot land unpinned.
The compatibility block guarded an API no release exposes: at 0.10.0 the
module had four top-level names and no __all__, so 13 of the 15 names it
re-exported have never shipped. Delete __all__ outright, since a module
always exports what it defines, and point all 26 call sites at the owning
module. A static sweep now fails any import of a borrowed name from the
matcher, replacing three hand-maintained name tuples.
@TKaltofen
TKaltofen requested a review from TomKaltofen as a code owner July 31, 2026 07:23
Deriving the repo root from the imported module made the sweep silently
vacuous under the sdist-installed env, where the matcher resolves to
site-packages and the tests tree is simply absent. Derive it from the test
file, add docs/ (its marimo notebooks are outside mypy and F401), and gate on
the bare module segment so an unusual dotted spelling stays in scope.
@TKaltofen TKaltofen changed the title refactor: consume the rendering-only resolution names from their own module refactor: stop identify_feature_group being a re-export facade Jul 31, 2026
@TomKaltofen
TomKaltofen merged commit 61066b5 into main Jul 31, 2026
18 checks passed
@TomKaltofen
TomKaltofen deleted the refactor/settle-resolution-import-surface branch July 31, 2026 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants