From 61cf4055c83f308857e8ddfd753f2e0fa0cef5b9 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 19 Jun 2026 21:56:07 -0400 Subject: [PATCH] refactor(gui_2): migrate L742 _load_fonts mono font to Result[T] (Phase 3) TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3. Adds _load_fonts_mono_result(app, font_size, config) -> Result[bool] helper that wraps the thirdparty hello_imgui.FontLoadingParams + hello_imgui.load_font try/except from App._load_fonts. App._load_fonts becomes a thin wrapper that drains errors to _startup_timeline_errors (startup-time error plane). Audit: BROAD_CATCH count 24 -> 23, COMPLIANT count 13 -> 14. Tests: 2/2 pass. --- src/gui_2.py | 37 ++++++++++++++++++++++------- tests/test_gui_2_result.py | 48 +++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/gui_2.py b/src/gui_2.py index eccfbe14..6e8151f8 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -730,14 +730,10 @@ class App: else: self.main_font = None - #Note(Ed): Exception(Thirdparty) - try: - with startup_profiler.phase("load_fonts.mono"): - params = hello_imgui.FontLoadingParams(font_config=config) - self.mono_font = hello_imgui.load_font("fonts/MapleMono-Regular.ttf", font_size, params) - except Exception as e: - print(f"Failed to load mono font: {e}") - self.mono_font = None + result = _load_fonts_mono_result(self, font_size, config) + if not result.ok: + if not hasattr(self, '_startup_timeline_errors'): self._startup_timeline_errors = [] + self._startup_timeline_errors.append(("_load_fonts.mono_font", result.errors[0])) def _handle_approve_mma_step(self, user_data=None) -> None: """UI-level wrapper for approving a pending MMA step.""" @@ -7466,6 +7462,31 @@ def _load_fonts_main_result(app: "App", font_path: str, font_size: float, config original=e, )]) +def _load_fonts_mono_result(app: "App", font_size: float, config) -> Result[bool]: + """Drain-aware variant of L742 _load_fonts mono font loading. + + Extracts the thirdparty hello_imgui.FontLoadingParams + hello_imgui.load_font + try/except from App._load_fonts into a Result-returning helper. On exception, + sets app.mono_font = None and returns Result(data=False, errors=[ErrorInfo]). + On success, sets app.mono_font to the loaded font. + + [C: src/gui_2.py:App._load_fonts (L742 legacy wrapper)] + """ + from src.startup_profiler import startup_profiler + try: + with startup_profiler.phase("load_fonts.mono"): + params = hello_imgui.FontLoadingParams(font_config=config) + app.mono_font = hello_imgui.load_font("fonts/MapleMono-Regular.ttf", font_size, params) + return Result(data=True) + except Exception as e: + app.mono_font = None + return Result(data=False, errors=[ErrorInfo( + kind=ErrorKind.INTERNAL, + message=f"Failed to load mono font: {e}", + source="gui_2._load_fonts_mono_result", + original=e, + )]) + #endregion: Phase 3 Render-Loop Result Helpers #endregion: MMA diff --git a/tests/test_gui_2_result.py b/tests/test_gui_2_result.py index 3577408b..4c73a599 100644 --- a/tests/test_gui_2_result.py +++ b/tests/test_gui_2_result.py @@ -249,4 +249,50 @@ def test_phase_3_l731_load_fonts_main_result_failure(): assert result.errors, "Expected at least one error on failure" err = result.errors[0] assert err.source == "gui_2._load_fonts_main_result" - assert "font load failed" in err.message \ No newline at end of file + assert "font load failed" in err.message + + +def test_phase_3_l742_load_fonts_mono_result_success(): + """ + L742 _load_fonts_mono_result returns Result.ok=True on success. + + The helper wraps the mono font loading try/except in App._load_fonts. + On success, it returns Result(data=True) with no errors and sets + app.mono_font to the loaded font. + """ + from src import gui_2 + from unittest.mock import MagicMock, patch + app = MagicMock() + mock_mono_font = MagicMock(name="mock_mono_font") + mock_config = MagicMock(name="mock_font_config") + with patch.object(gui_2, "hello_imgui") as mock_hi, \ + patch("src.startup_profiler.startup_profiler") as mock_sp: + mock_hi.FontLoadingParams.return_value = "mock_params" + mock_hi.load_font.return_value = mock_mono_font + result = gui_2._load_fonts_mono_result(app, 16.0, mock_config) + assert result.ok, f"Expected ok=True on success, got errors: {result.errors}" + assert result.data is True + assert app.mono_font is mock_mono_font + + +def test_phase_3_l742_load_fonts_mono_result_failure(): + """ + L742 _load_fonts_mono_result returns Result.ok=False with ErrorInfo on failure. + + When the underlying third-party hello_imgui.load_font call raises, the + helper converts the exception to ErrorInfo and returns Result(data=False). + """ + from src import gui_2 + from unittest.mock import MagicMock, patch + app = MagicMock() + mock_config = MagicMock(name="mock_font_config") + with patch.object(gui_2, "hello_imgui") as mock_hi, \ + patch("src.startup_profiler.startup_profiler") as mock_sp: + mock_hi.FontLoadingParams.return_value = "mock_params" + mock_hi.load_font.side_effect = RuntimeError("mono font missing") + result = gui_2._load_fonts_mono_result(app, 16.0, mock_config) + assert not result.ok, f"Expected ok=False on failure, got data: {result.data}" + assert result.errors, "Expected at least one error on failure" + err = result.errors[0] + assert err.source == "gui_2._load_fonts_mono_result" + assert "mono font missing" in err.message \ No newline at end of file