MRO Resolver & Nesting Analyzer
Relevant source files
The following files were used as context for generating this wiki page:
- src/flext_infra/refactor/class_nesting_analyzer.py
- src/flext_infra/refactor/mro_import_rewriter.py
- src/flext_infra/_utilities/namespace_analysis.py
- src/flext_infra/_constants/refactor.py
- src/flext_infra/_models/refactor.py
- src/flext_infra/rules/class-nesting-mappings.yml
- src/flext_infra/refactor/_mro_import_collect.py
The MRO (Method Resolution Order) Resolver & Nesting Analyzer is a core refactoring subsystem within the flext-infra project. Its primary purpose is to ensure structural integrity across the workspace by enforcing namespace standards, resolving complex inheritance chains in facade classes, and identifying "loose" classes that should be nested within appropriate namespaces.
This module automates the detection of violations where top-level classes exist outside of their intended facade structures and provides the mechanisms to rewrite imports and class headers to maintain a consistent MRO chain.
Class Nesting Analysis
The nesting analysis system identifies classes that are defined at the module top-level but conceptually belong within a specific namespace (e.g., FlextUtilities, FlextModels). This is primarily handled by the FlextInfraRefactorClassNestingAnalyzer.
Detection Logic
The analyzer groups target files by their project root and utilizes a scanner to identify LooseClassViolation entries. It maps these violations against a predefined index of rules and confidence scores.
The diagram above shows the high-level flow of class nesting detection.
Sources: src/flext_infra/refactor/class_nesting_analyzer.py:19-45, src/flext_infra/_constants/refactor.py:465-469
Nesting Mappings
Mappings are defined in class-nesting-mappings.yml. Each entry identifies a "loose" class, its current file, and its target namespace.
| Field | Type | Description |
|---|---|---|
loose_name | string | The current name of the class at module top-level. |
target_namespace | string | The namespace prefix or class it should be nested under. |
confidence | string | high, medium, or low confidence in the mapping. |
reason | string | The justification for nesting (e.g., "top_level_class_in_private_directory"). |
Sources: src/flext_infra/rules/class-nesting-mappings.yml:4-20, src/flext_infra/refactor/class_nesting_analyzer.py:108-124
MRO Migration and Import Rewriting
When classes are moved or absorbed into facade structures, the system must propagate these changes across the entire workspace to prevent broken imports. The FlextInfraRefactorMROImportRewriter coordinates this workspace-wide transformation.
Workspace Migration Flow
The rewriter identifies symbol moves and uses the Rope library to discover occurrences of these symbols in consumer files.
This sequence illustrates how symbol moves are discovered and propagated via Rope.
Sources: src/flext_infra/refactor/mro_import_rewriter.py:40-75, src/flext_infra/refactor/_mro_import_collect.py:27-45
Import Collection and Expansion
The rewriter distinguishes between "file moves" (specific sites where a symbol was used) and "expanded moves" (where imports might need to be added to existing Python files in a project).
- Occurrences: Uses
u.Infra.find_occurrencesto locate exact usage sites. - Symbol Map: Maps the original module name to a facade alias (e.g.,
cfor constants,ufor utilities) and specific symbol paths.
Sources: src/flext_infra/refactor/_mro_import_collect.py:48-81, src/flext_infra/_constants/refactor.py:307-320
Namespace and Header Resolution
To fix MRO completeness violations, the system must often modify the class inheritance list (bases) of a facade class.
Class Header Rewriting
The FlextInfraUtilitiesRefactorNamespaceMro utility handles the delicate task of injecting missing bases into a class definition while maintaining proper Python syntax.
# Example of transformation performed by _rewrite_class_header
# BEFORE:
class FlextExampleModels(FlextExampleModelsBase):
pass
# AFTER:
class FlextExampleModels(FlextExampleModelsBase, FlextExampleModelsDomain):
pass
Sources: src/flext_infra/_utilities/namespace_analysis.py:91-122
Missing Import Injection
After bases are added to a class header, the system identifies which modules define those bases and injects the necessary from ... import ... statements at the top of the file, following the project's import standards.
Sources: src/flext_infra/_utilities/namespace_analysis.py:124-143
Technical Constants and Rules
The behavior of the MRO Resolver is governed by several configuration constants that define the "families" of the MRO.
| Family | Alias | Suffix | Directory |
|---|---|---|---|
| Constants | c | Constants | _constants |
| Types | t | Types | _typings |
| Protocols | p | Protocols | _protocols |
| Models | m | Models | _models |
| Utilities | u | Utilities | _utilities |
Sources: src/flext_infra/_constants/refactor.py:313-333
Refactor Rules Matchers
Rules are categorized into specific RefactorRuleKind enums. The system uses these to match violations to appropriate transformers:
MRO_CLASS_MIGRATION: Specifically for moving classes into MRO facades.CLASS_NESTING: For the loose-class nesting analyzer.SYMBOL_PROPAGATION: For updating references after a symbol has moved.
Sources: src/flext_infra/_constants/refactor.py:116-168
Summary
The MRO Resolver & Nesting Analyzer provides a robust framework for managing the evolution of a codebase's internal structure. By combining static analysis (via LooseClassScanner) and deep workspace inspection (via Rope), it ensures that as classes are reorganized into their logical namespaces, the entire project remains consistent and syntactically correct. This system is critical for maintaining the "Zero-Debt" baseline required by FLEXT project standards.