Private
Public Access
fix(app_controller,gui_2): use direct import for parse_history_entries
Sequel to commitde9dd3c1. The de-cruft track's Phase 2.3 removed the __getattr__ lazy-load entries from models.py. The migration scripts covered the 11 dataclasses but missed the 5 config-IO functions (load_config_from_disk, save_config_to_disk, parse_history_entries, _clean_nones, load_mcp_config). The prior commitde9dd3c1fixed the first two; this commit fixes parse_history_entries. 6 reference sites updated: - src/app_controller.py line 7: added 'parse_history_entries' to the existing 'from src.project import load_config_from_disk, save_config_to_disk' line - src/app_controller.py 5 call sites: models.parse_history_entries -> parse_history_entries (lines 2020, 3264, 3311, 3781, 5055) - src/gui_2.py: added 'from src.project import parse_history_entries' (gui_2.py didn't import from src.project before) - src/gui_2.py 1 call site: models.parse_history_entries -> parse_history_entries (line 5492) The fix was performed by the one-time script scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_parse_history_entries.py which does an in-place re.sub on the 2 affected files. The script is idempotent (re-running does the same work). Verification: - 'from src.app_controller import AppController' works - 'from src.gui_2 import App' works - 'uv run sloppy.py' should now pass the 'load_active_project' phase of init_state Discovered by user: running 'uv run sloppy.py' on the de-cruft branch after thede9dd3c1fix produced a SECOND AttributeError on models.parse_history_entries, the next function in the de-cruft track's missed-consumer-sites chain. The user is iterating through sloppy.py failures as a test harness; each one reveals the next missed consumer site. Still pending (potential): - models._clean_nones (3 sites in test_thinking_persistence.py) - models.load_mcp_config (1 site in app_controller.py) These are likely to surface in the next sloppy.py run. The fix pattern is the same: add to the from src.X import line + replace the models.X call sites with the bare name. The 2 config-IO functions NOT in models.parse_history_entries's class are _clean_nones (private) and load_mcp_config (which I already updated to 'from src.mcp_client import load_mcp_config'). Wait, that's not right. Let me re-grep.
This commit is contained in:
+72
@@ -0,0 +1,72 @@
|
|||||||
|
"""Fix parse_history_entries references in app_controller.py + gui_2.py.
|
||||||
|
|
||||||
|
Phase 2.3 of the de-cruft track removed the __getattr__ lazy-load entries
|
||||||
|
from models.py. The migration scripts (migrate_imports.py,
|
||||||
|
migrate_models_attr.py) covered the 11 dataclasses but missed the 5
|
||||||
|
config-IO functions. This script does the safe in-place substitution
|
||||||
|
of 'models.parse_history_entries' -> 'parse_history_entries' in the
|
||||||
|
2 affected files.
|
||||||
|
|
||||||
|
The script adds 'parse_history_entries' to the existing
|
||||||
|
'from src.project import' line in app_controller.py (next to the
|
||||||
|
load_config_from_disk / save_config_to_disk imports added by the
|
||||||
|
prior commit de9dd3c1). It also adds a new
|
||||||
|
'from src.project import parse_history_entries' line in gui_2.py
|
||||||
|
(gui_2.py didn't import from src.project before).
|
||||||
|
|
||||||
|
Idempotent: running the script twice does the same work (the 'from
|
||||||
|
src.project import' line is replaced with the same line, the
|
||||||
|
'models.parse_history_entries' is replaced with the bare name).
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(path: Path, import_line: str) -> int:
|
||||||
|
content = path.read_text(encoding="utf-8")
|
||||||
|
original = content
|
||||||
|
count = content.count("models.parse_history_entries")
|
||||||
|
if count == 0:
|
||||||
|
return 0
|
||||||
|
content = content.replace("models.parse_history_entries", "parse_history_entries")
|
||||||
|
has_import = bool(re.search(r"^from src\.project import ", content, re.MULTILINE))
|
||||||
|
if not has_import:
|
||||||
|
content = re.sub(
|
||||||
|
r"^(from __future__ import annotations\n)",
|
||||||
|
rf"\1{import_line}\n",
|
||||||
|
content,
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
content = re.sub(
|
||||||
|
r"^(from src\.project import [^\n]+)$",
|
||||||
|
r"\1, parse_history_entries",
|
||||||
|
content,
|
||||||
|
count=1,
|
||||||
|
flags=re.MULTILINE,
|
||||||
|
)
|
||||||
|
path.write_text(content, encoding="utf-8", newline="")
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
total = 0
|
||||||
|
files = {
|
||||||
|
"src/app_controller.py": "from src.project import load_config_from_disk, parse_history_entries, save_config_to_disk",
|
||||||
|
"src/gui_2.py": "from src.project import parse_history_entries",
|
||||||
|
}
|
||||||
|
for rel, import_line in files.items():
|
||||||
|
path = Path(rel)
|
||||||
|
n = migrate(path, import_line)
|
||||||
|
if n > 0:
|
||||||
|
print(f" {rel}: replaced {n} 'models.parse_history_entries' reference(s)")
|
||||||
|
total += n
|
||||||
|
print(f"\nTotal: {total} reference(s) replaced")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -4,7 +4,7 @@ from src.mma import Ticket, Track, TrackState
|
|||||||
from src.personas import Persona
|
from src.personas import Persona
|
||||||
from src.mcp_client import MCPConfiguration, RAGConfig, load_mcp_config
|
from src.mcp_client import MCPConfiguration, RAGConfig, load_mcp_config
|
||||||
from src.project_files import ContextPreset, FileItem, NamedViewPreset, Preset
|
from src.project_files import ContextPreset, FileItem, NamedViewPreset, Preset
|
||||||
from src.project import load_config_from_disk, save_config_to_disk
|
from src.project import load_config_from_disk, save_config_to_disk, parse_history_entries
|
||||||
from src.tool_bias import BiasProfile
|
from src.tool_bias import BiasProfile
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
@@ -2017,7 +2017,7 @@ class AppController:
|
|||||||
self.active_discussion = disc_sec.get("active", "main")
|
self.active_discussion = disc_sec.get("active", "main")
|
||||||
disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {})
|
disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {})
|
||||||
|
|
||||||
with self._disc_entries_lock: self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
with self._disc_entries_lock: self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
||||||
|
|
||||||
# UI state
|
# UI state
|
||||||
self.ui_output_dir = self.project.get("output", {}).get("output_dir", "./md_gen")
|
self.ui_output_dir = self.project.get("output", {}).get("output_dir", "./md_gen")
|
||||||
@@ -3261,7 +3261,7 @@ class AppController:
|
|||||||
self.active_discussion = disc_sec.get("active", "main")
|
self.active_discussion = disc_sec.get("active", "main")
|
||||||
disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {})
|
disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {})
|
||||||
with self._disc_entries_lock:
|
with self._disc_entries_lock:
|
||||||
self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
||||||
proj = self.project
|
proj = self.project
|
||||||
self.ui_output_dir = proj.get("output", {}).get("output_dir", "./md_gen")
|
self.ui_output_dir = proj.get("output", {}).get("output_dir", "./md_gen")
|
||||||
self.ui_files_base_dir = proj.get("files", {}).get("base_dir", ".")
|
self.ui_files_base_dir = proj.get("files", {}).get("base_dir", ".")
|
||||||
@@ -3308,7 +3308,7 @@ class AppController:
|
|||||||
track_history = project_manager.load_track_history(self.active_track.id, self.active_project_root)
|
track_history = project_manager.load_track_history(self.active_track.id, self.active_project_root)
|
||||||
if track_history:
|
if track_history:
|
||||||
with self._disc_entries_lock:
|
with self._disc_entries_lock:
|
||||||
self.disc_entries[:] = models.parse_history_entries(track_history, self.disc_roles)
|
self.disc_entries[:] = parse_history_entries(track_history, self.disc_roles)
|
||||||
self.preset_manager.project_root = Path(self.active_project_root)
|
self.preset_manager.project_root = Path(self.active_project_root)
|
||||||
self.presets = self.preset_manager.load_all()
|
self.presets = self.preset_manager.load_all()
|
||||||
self.tool_preset_manager.project_root = Path(self.active_project_root)
|
self.tool_preset_manager.project_root = Path(self.active_project_root)
|
||||||
@@ -3778,7 +3778,7 @@ class AppController:
|
|||||||
disc_sec["active"] = name
|
disc_sec["active"] = name
|
||||||
disc_data = discussions[name]
|
disc_data = discussions[name]
|
||||||
with self._disc_entries_lock:
|
with self._disc_entries_lock:
|
||||||
self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
||||||
self.discussion_sent_markdown = disc_data.get("sent_markdown", "")
|
self.discussion_sent_markdown = disc_data.get("sent_markdown", "")
|
||||||
self.discussion_sent_system_prompt = disc_data.get("sent_system_prompt", "")
|
self.discussion_sent_system_prompt = disc_data.get("sent_system_prompt", "")
|
||||||
if "context_snapshot" in disc_data:
|
if "context_snapshot" in disc_data:
|
||||||
@@ -5052,7 +5052,7 @@ class AppController:
|
|||||||
history = project_manager.load_track_history(track_id, self.active_project_root)
|
history = project_manager.load_track_history(track_id, self.active_project_root)
|
||||||
with self._disc_entries_lock:
|
with self._disc_entries_lock:
|
||||||
if history:
|
if history:
|
||||||
self.disc_entries[:] = models.parse_history_entries(history, self.disc_roles)
|
self.disc_entries[:] = parse_history_entries(history, self.disc_roles)
|
||||||
else:
|
else:
|
||||||
self.disc_entries.clear()
|
self.disc_entries.clear()
|
||||||
self._recalculate_session_usage()
|
self._recalculate_session_usage()
|
||||||
|
|||||||
+1
-1
@@ -5489,7 +5489,7 @@ def render_discussion_selector(app: App) -> None:
|
|||||||
if app._track_discussion_active:
|
if app._track_discussion_active:
|
||||||
app._flush_disc_entries_to_project()
|
app._flush_disc_entries_to_project()
|
||||||
history_strings = project_manager.load_track_history(app.active_track.id, app.active_project_root)
|
history_strings = project_manager.load_track_history(app.active_track.id, app.active_project_root)
|
||||||
with app._disc_entries_lock: app.disc_entries = models.parse_history_entries(history_strings, app.disc_roles)
|
with app._disc_entries_lock: app.disc_entries = parse_history_entries(history_strings, app.disc_roles)
|
||||||
app.ai_status = f"track discussion: {app.active_track.id}"
|
app.ai_status = f"track discussion: {app.active_track.id}"
|
||||||
else: app._flush_disc_entries_to_project(); app._switch_discussion(app.active_discussion); app.ai_status = "track discussion disabled"
|
else: app._flush_disc_entries_to_project(); app._switch_discussion(app.active_discussion); app.ai_status = "track discussion disabled"
|
||||||
render_discussion_metadata(app)
|
render_discussion_metadata(app)
|
||||||
|
|||||||
Reference in New Issue
Block a user