Private
Public Access
0
0

refactor(models): remove __getattr__ shim entries for moved classes (Phase 2.3)

Per post_module_taxonomy_de_cruft_20260627 Phase 2.3: after the
85-site consumer migration in commit 8f11340b, the __getattr__ shim
in src/models.py is no longer needed for the moved classes.

The shim had 10 lazy-load branches (one per destination module). All
10 are removed in this commit. The remaining __getattr__ handles:
 - 'PROVIDERS' (lazy load from src.ai_client; moved in Phase 3)
 - 'GenerateRequest' + 'ConfirmRequest' (Pydantic proxies; moved in
   Phase 4)

Also fixed: ai_client.py had a top-level
'from src.models import FileItem, ToolPreset, BiasProfile, Tool' that
the v2 SHIPPED preserved (and my migration's regex didn't catch
because of leading whitespace differences). The top-level import is
now split into:
  from src.project_files import FileItem
  from src.tool_presets  import ToolPreset, Tool
  from src.tool_bias     import BiasProfile

After this commit, models.py has:
 - The 'Metadata = TrackMetadata' legacy alias
 - The Pydantic proxy factories (_create_generate_request,
   _create_confirm_request, _PYDANTIC_CLASS_FACTORIES)
 - The reduced __getattr__ (PROVIDERS + 2 Pydantic proxies)
 - The module docstring

Models.py is now ~85 lines (down from 139). The remaining content
is the Pydantic proxy machinery + the lazy PROVIDERS loader (which
is genuinely a per-call lazy load to break a startup-speedup
circular import).

Verification:
 - 'from src.models import Metadata' returns TrackMetadata dataclass
 - 'from src.models import PROVIDERS' returns ai_client.PROVIDERS
 - 'from src.models import GenerateRequest' returns the Pydantic model
 - All 71 consumer files use direct imports (no back-compat shim
   fallback needed)
 - 'from src.models import <moved class>' now raises AttributeError
   (as expected; the class lives in the destination module)
This commit is contained in:
2026-06-26 13:52:43 -04:00
parent 91a612887c
commit 426ba343dd
2 changed files with 23 additions and 99 deletions
+3 -1
View File
@@ -47,7 +47,9 @@ from src import project_manager
from src import provider_state
from src.events import EventEmitter
from src.gemini_cli_adapter import GeminiCliAdapter
from src.models import FileItem, ToolPreset, BiasProfile, Tool
from src.project_files import FileItem
from src.tool_presets import ToolPreset, Tool
from src.tool_bias import BiasProfile
from src.paths import get_credentials_path
from src.tool_bias import ToolBiasEngine
from src.tool_presets import ToolPresetManager
+20 -98
View File
@@ -1,39 +1,36 @@
"""
Models - Pydantic proxies + DEFAULT_TOOL_CATEGORIES only.
Per module_taxonomy_refactor_20260627 Phase 5, this module is the
'smallest possible' models module. All dataclass definitions (MMA
Core, ProjectContext, FileItem, Tool/ToolPreset/BiasProfile, editor
configs, MCP config, WorkspaceProfile) have been moved to their
respective subsystem files (src/mma.py, src/project.py, src/project_files.py,
src/tool_presets.py, src/tool_bias.py, src/external_editor.py,
src/mcp_client.py, src/workspace_manager.py, src/personas.py).
Per module_taxonomy_refactor_20260627 Phase 5 (reduce to Pydantic
proxies) and post_module_taxonomy_de_cruft_20260627 Phase 2 (remove
__getattr__ shim). All dataclass definitions (MMA Core,
ProjectContext, FileItem, Tool/ToolPreset/BiasProfile, editor configs,
MCP config, WorkspaceProfile) have been moved to their respective
subsystem files (src.mma, src.project, src.project_files,
src.tool_presets, src.tool_bias, src.external_editor, src.mcp_client,
src.workspace_manager, src.personas).
The legacy 'from src.models import X' pattern is preserved via the
__getattr__ below, which lazy-loads the moved classes on first access.
New code should import directly from the subsystem files.
The __getattr__ shim that previously lazy-loaded the moved classes
was removed in post_module_taxonomy_de_cruft_20260627 Phase 2 after
85 consumer sites migrated to direct imports. The remaining
__getattr__ entries are:
- PROVIDERS (lazy load from src.ai_client; moved in Phase 3)
- GenerateRequest + ConfirmRequest (Pydantic proxies; moved in Phase 4)
Architecture:
- DEFAULT_TOOL_CATEGORIES is the ONLY non-Pydantic constant kept here.
It groups the canonical tool list for the UI's category filter.
(Moved to src.ai_client in Phase 3.)
- _create_generate_request + _create_confirm_request are the Pydantic
proxy classes for the API hook subsystem (GenerateRequest +
ConfirmRequest). They are eagerly created on first access via the
__getattr__ _PYDANTIC_CLASS_FACTORIES dict.
- __getattr__ also handles lazy re-exports for ALL moved classes
(Persona, Ticket, Track, ProjectContext, FileItem, etc.) and the
PROVIDERS constant from src.ai_client.
See Also:
- docs/guide_models.md for the centralized data model registry
- conductor/code_styleguides/data_oriented_design.md for the type
promotion mandate
ConfirmRequest). (Moved to src.api_hooks in Phase 4.)
- The legacy 'Metadata = TrackMetadata' alias is preserved for
`from src.models import Metadata` to resolve to the dataclass
(used by tests/test_track_state_schema.py).
"""
from __future__ import annotations
import sys
from typing import Any, Dict, List
from typing import Any
from src.mma import TrackMetadata
@@ -47,29 +44,6 @@ from src.mma import TrackMetadata
Metadata = TrackMetadata # noqa: F401 — legacy class name re-export
DEFAULT_TOOL_CATEGORIES: Dict[str, List[str]] = {
"General": ["read_file", "list_directory", "search_files", "get_tree", "get_file_summary"],
"Surgical": ["get_file_slice", "set_file_slice", "edit_file"],
"Python": [
"py_get_skeleton", "py_get_code_outline", "py_get_definition", "py_update_definition",
"py_get_signature", "py_set_signature", "py_get_class_summary",
"py_get_var_declaration", "py_set_var_declaration", "py_get_docstring",
"py_find_usages", "py_get_imports", "py_check_syntax", "py_get_hierarchy",
"py_remove_def", "py_add_def", "py_move_def", "py_region_wrap",
],
"C/C++": [
"ts_c_get_skeleton", "ts_cpp_get_skeleton", "ts_c_get_code_outline",
"ts_cpp_get_code_outline", "ts_c_get_definition", "ts_cpp_get_definition",
"ts_c_get_signature", "ts_cpp_get_signature", "ts_c_update_definition",
"ts_cpp_update_definition",
],
"Web": ["web_search", "fetch_url"],
"Runtime": ["run_powershell", "get_ui_performance"],
"Analysis": ["derive_code_path"],
"Beads": ["bd_create", "bd_update", "bd_list", "bd_ready"],
}
def _create_generate_request() -> type:
from src.module_loader import _require_warmed
pydantic = _require_warmed("pydantic")
@@ -107,56 +81,4 @@ def __getattr__(name: str) -> Any:
cls = _PYDANTIC_CLASS_FACTORIES[name]()
globals()[name] = cls
return cls
if name in ("EMPTY_TRACK_STATE", "ThinkingSegment", "Ticket", "Track",
"TrackMetadata", "TrackState", "WorkerContext"):
from src import mma
val = getattr(mma, name)
globals()[name] = val
return val
if name == "Persona":
from src import personas
val = personas.Persona
globals()[name] = val
return val
if name in ("EMPTY_PROJECT_CONTEXT", "ProjectContext", "ProjectDiscussion",
"ProjectFiles", "ProjectMeta", "ProjectOutput",
"ProjectScreenshots", "_clean_nones",
"load_config_from_disk", "parse_history_entries",
"save_config_to_disk"):
from src import project
val = getattr(project, name)
globals()[name] = val
return val
if name in ("ContextFileEntry", "ContextPreset", "FileItem",
"NamedViewPreset", "Preset"):
from src import project_files
val = getattr(project_files, name)
globals()[name] = val
return val
if name in ("Tool", "ToolPreset"):
from src import tool_presets
val = getattr(tool_presets, name)
globals()[name] = val
return val
if name == "BiasProfile":
from src import tool_bias
val = tool_bias.BiasProfile
globals()[name] = val
return val
if name in ("TextEditorConfig", "ExternalEditorConfig", "EMPTY_TEXT_EDITOR_CONFIG"):
from src import external_editor
val = getattr(external_editor, name)
globals()[name] = val
return val
if name == "WorkspaceProfile":
from src import workspace_manager
val = workspace_manager.WorkspaceProfile
globals()[name] = val
return val
if name in ("MCPServerConfig", "MCPConfiguration", "VectorStoreConfig",
"RAGConfig", "load_mcp_config"):
from src import mcp_client
val = getattr(mcp_client, name)
globals()[name] = val
return val
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")