From ee4287ae4de62040e544b769c883f23818eb2d66 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 24 Jun 2026 17:24:55 -0400 Subject: [PATCH] fix(exception): NG1 fixed - 4 INTERNAL_OPTIONAL_RETURN violations migrated to Result[T] --- src/external_editor.py | 25 +++++++++++++++++-------- src/project_manager.py | 10 +++++++--- src/session_logger.py | 12 ++++++++---- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/external_editor.py b/src/external_editor.py index 1ce47e4f..9ede3015 100644 --- a/src/external_editor.py +++ b/src/external_editor.py @@ -10,6 +10,7 @@ from pathlib import Path from typing import Optional, List, Dict, Any from src.models import ExternalEditorConfig, TextEditorConfig +from src.result_types import ErrorInfo, ErrorKind, Result class ExternalEditorLauncher: @@ -38,23 +39,31 @@ class ExternalEditorLauncher: """ [C: src/gui_2.py:App._open_patch_in_external_editor, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_file_not_found, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_missing_editor, tests/test_external_editor.py:TestExternalEditorLauncher.test_launch_diff_success] """ + r = self.launch_diff_result(editor_name, original_path, modified_path) + return r.data if r.ok else None + + def launch_diff_result(self, editor_name: Optional[str], original_path: str, modified_path: str) -> Result[subprocess.Popen]: editor = self.get_editor(editor_name) if not editor: - return None + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"No editor configured: {editor_name}", source="external_editor.launch_diff_result")]) cmd = self.build_diff_command(editor, original_path, modified_path) try: - return subprocess.Popen(cmd) - except FileNotFoundError: - return None + return Result(data=subprocess.Popen(cmd)) + except FileNotFoundError as e: + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"Editor binary not found: {cmd[0]}", source="external_editor.launch_diff_result", original=e)]) def launch_editor(self, editor_name: Optional[str], file_path: str) -> Optional[subprocess.Popen]: + r = self.launch_editor_result(editor_name, file_path) + return r.data if r.ok else None + + def launch_editor_result(self, editor_name: Optional[str], file_path: str) -> Result[subprocess.Popen]: editor = self.get_editor(editor_name) if not editor: - return None + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"No editor configured: {editor_name}", source="external_editor.launch_editor_result")]) try: - return subprocess.Popen([editor.path, file_path]) - except FileNotFoundError: - return None + return Result(data=subprocess.Popen([editor.path, file_path])) + except FileNotFoundError as e: + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"Editor binary not found: {editor.path}", source="external_editor.launch_editor_result", original=e)]) _cached_vscode_config: Optional[TextEditorConfig] = None diff --git a/src/project_manager.py b/src/project_manager.py index 196fddf1..c0720c28 100644 --- a/src/project_manager.py +++ b/src/project_manager.py @@ -40,10 +40,14 @@ def now_ts() -> str: return datetime.datetime.now().strftime(TS_FMT) def parse_ts(s: str) -> Optional[datetime.datetime]: + r = parse_ts_result(s) + return r.data if r.ok else None + +def parse_ts_result(s: str) -> Result[datetime.datetime]: try: - return datetime.datetime.strptime(s, TS_FMT) - except (ValueError, TypeError): - return None + return Result(data=datetime.datetime.strptime(s, TS_FMT)) + except (ValueError, TypeError) as e: + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.INVALID_INPUT, message=f"Invalid timestamp {s!r}: {e}", source="project_manager.parse_ts_result", original=e)]) # ── entry serialisation ────────────────────────────────────────────────────── def entry_to_str(entry: Metadata) -> str: diff --git a/src/session_logger.py b/src/session_logger.py index beac59f0..3972eec3 100644 --- a/src/session_logger.py +++ b/src/session_logger.py @@ -214,9 +214,13 @@ def log_tool_output(content: str) -> Optional[str]: Returns the path of the written file. [C: tests/test_session_logger_optimization.py:test_log_tool_output_returns_none_if_no_session, tests/test_session_logger_optimization.py:test_log_tool_output_saves_in_session_outputs] """ + r = log_tool_output_result(content) + return r.data if r.ok else None + +def log_tool_output_result(content: str) -> Result[str]: global _output_seq if _session_dir is None: - return None + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message="No active session directory", source="session_logger.log_tool_output_result")]) with _output_seq_lock: _output_seq += 1 @@ -227,9 +231,9 @@ def log_tool_output(content: str) -> Optional[str]: try: out_path.write_text(content, encoding="utf-8") - return str(out_path) - except (OSError, UnicodeEncodeError): - return None + return Result(data=str(out_path)) + except (OSError, UnicodeEncodeError) as e: + return Result(data=None, errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=f"Failed to write tool output: {e}", source="session_logger.log_tool_output_result", original=e)]) def log_cli_call(command: str, stdin_content: Optional[str], stdout_content: Optional[str], stderr_content: Optional[str], latency: float) -> Result[bool]: """Log details of a CLI subprocess execution."""