diff --git a/src/models.py b/src/models.py index ae3d5793..ece7d78c 100644 --- a/src/models.py +++ b/src/models.py @@ -276,6 +276,10 @@ def __getattr__(name: str) -> Any: val = _Tool if name == "Tool" else _ToolPreset globals()[name] = val return val + if name == "BiasProfile": + from src.tool_bias import BiasProfile as _BiasProfile + globals()[name] = _BiasProfile + return _BiasProfile raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # MMA Core dataclasses (ThinkingSegment, Ticket, Track, WorkerContext, TrackMetadata) @@ -291,31 +295,10 @@ def __getattr__(name: str) -> Any: # src.project_files directly. #region: Tool Models -# Tool + ToolPreset moved to src/tool_presets.py in -# module_taxonomy_refactor_20260627 Phase 3d. The re-exports at the top of -# this module keep 'from src.models import Tool' (and ToolPreset) working for -# legacy callers. BiasProfile stays here until Phase 3e. - -@dataclass -class BiasProfile: - name: str - tool_weights: Dict[str, int] = field(default_factory=dict) - category_multipliers: Dict[str, float] = field(default_factory=dict) - - def to_dict(self) -> Metadata: - return { - "name": self.name, - "tool_weights": self.tool_weights, - "category_multipliers": self.category_multipliers, - } - - @classmethod - def from_dict(cls, data: Metadata) -> "BiasProfile": - return cls( - name = data["name"], - tool_weights = data.get("tool_weights", {}), - category_multipliers = data.get("category_multipliers", {}), - ) +# Tool + ToolPreset moved to src/tool_presets.py in Phase 3d. BiasProfile +# moved to src/tool_bias.py in Phase 3e. All three are re-exported lazily +# via the __getattr__ below to avoid the circular import (tool_presets and +# tool_bias both want to import from each other via models). #region: UI/Editor diff --git a/src/tool_bias.py b/src/tool_bias.py index 7fe38fc6..f23ae77c 100644 --- a/src/tool_bias.py +++ b/src/tool_bias.py @@ -1,6 +1,32 @@ -from typing import List, Dict, Any, Optional +from __future__ import annotations -from src.models import Tool, ToolPreset, BiasProfile +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional + +from src.tool_presets import Tool, ToolPreset +from src.type_aliases import Metadata + + +@dataclass +class BiasProfile: + name: str + tool_weights: Dict[str, int] = field(default_factory=dict) + category_multipliers: Dict[str, float] = field(default_factory=dict) + + def to_dict(self) -> Metadata: + return { + "name": self.name, + "tool_weights": self.tool_weights, + "category_multipliers": self.category_multipliers, + } + + @classmethod + def from_dict(cls, data: Metadata) -> "BiasProfile": + return cls( + name = data["name"], + tool_weights = data.get("tool_weights", {}), + category_multipliers = data.get("category_multipliers", {}), + ) class ToolBiasEngine: diff --git a/src/tool_presets.py b/src/tool_presets.py index cd8d2bac..168b0f26 100644 --- a/src/tool_presets.py +++ b/src/tool_presets.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import tomllib import tomli_w @@ -6,7 +8,6 @@ from pathlib import Path from typing import Dict, List, Optional, Union, Any from src import paths -from src.models import BiasProfile from src.type_aliases import Metadata @@ -135,10 +136,11 @@ class ToolPresetManager: del data["presets"][name] self._write_raw(path, data) - def load_all_bias_profiles(self) -> Dict[str, BiasProfile]: + def load_all_bias_profiles(self) -> Dict[str, "BiasProfile"]: """ [C: tests/test_tool_preset_manager.py:test_bias_profiles_merged, tests/test_tool_preset_manager.py:test_delete_bias_profile, tests/test_tool_preset_manager.py:test_save_bias_profile] """ + from src.tool_bias import BiasProfile global_path = paths.get_global_tool_presets_path() global_data = self._read_raw(global_path).get("bias_profiles", {})