refactor(src): narrow exception types in Phase 5 batch (8 sites across 5 files)

Migrates the 8 try/except sites in UI + theme + tooling files
by narrowing the exception types from broad 'except Exception' to
specific stdlib/domain exceptions.

Files and sites:
1. src/command_palette.py:120 (1 site) - command.action callback
   except Exception -> except (AttributeError, TypeError, ValueError, OSError)
2. src/commands.py:116 (1 site) - generate_md
   except Exception -> except (OSError, ValueError, TypeError)
3. src/commands.py:147 (1 site) - save_all
   except Exception -> except (OSError, ValueError)
4. src/commands.py:271 (1 site) - reset_layout
   except Exception -> except OSError
5. src/diff_viewer.py:167 (1 site) - apply_patch
   except Exception -> except (OSError, ValueError, IndexError)
6. src/external_editor.py:82 (1 site) - powershell reg lookup
   except Exception -> except (OSError, subprocess.SubprocessError,
                               subprocess.TimeoutExpired)
7. src/markdown_helper.py:123 (1 site) - open link
   except Exception -> except (OSError, ValueError)
8. src/markdown_helper.py:200 (1 site) - render_table fallback
   except Exception -> except (TypeError, AttributeError, ValueError, IndexError)

Also updates tests/test_command_palette_sim.py to use TypeError
(caught by the narrowing) instead of RuntimeError (not caught).

Decisions:
- theme_2.py:282 already narrow (ImportError, AttributeError); no change
- theme_models.py:166 is RAISE (not except); keep as-is (documented)
- external_editor.py:47, 56 already narrow (FileNotFoundError); no change

Tests verified:
- tests/test_command_palette.py (13 tests) PASS
- tests/test_command_palette_sim.py (7 tests) PASS
- tests/test_diff_viewer.py (10 tests) PASS
- tests/test_external_editor.py (16 tests) PASS
- tests/test_external_editor_gui.py (5 tests) PASS
- tests/test_markdown_helper_* (16 tests) PASS
This commit is contained in:
ed
2026-06-17 19:15:51 -04:00
parent a48acb3f85
commit 3616d35a75
6 changed files with 9 additions and 9 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ def _execute(app: Any, command: Command) -> None:
return
try:
command.action(app)
except Exception as e:
except (AttributeError, TypeError, ValueError, OSError) as e:
print(f"[CommandPalette] Action {command.id} raised: {e}")
_close_palette(app)
+3 -3
View File
@@ -113,7 +113,7 @@ def generate_md_only(app: "App") -> None:
app.last_md_path = path
if hasattr(app, "ai_status"):
app.ai_status = f"md written: {path.name}"
except Exception as e:
except (OSError, ValueError, TypeError) as e:
if hasattr(app, "ai_status"):
app.ai_status = f"error: {e}"
@@ -144,7 +144,7 @@ def save_all(app: "App") -> None:
if hasattr(app, "config"):
try:
app.save_config()
except Exception as e:
except (OSError, ValueError) as e:
if hasattr(app, "ai_status"):
app.ai_status = f"save error: {e}"
@@ -268,7 +268,7 @@ def reset_layout(app: "App") -> None:
if os.path.exists(p):
os.remove(p)
if hasattr(app, "ai_status"): app.ai_status = f"layout reset: removed {p}"
except Exception as e:
except OSError as e:
if hasattr(app, "ai_status"): app.ai_status = f"layout reset partial: {e}"
+1 -1
View File
@@ -164,7 +164,7 @@ def apply_patch_to_file(patch_text: str, base_dir: str = ".") -> Tuple[bool, str
f.writelines(new_lines)
results.append(f"Patched: {file_path}")
except Exception as e:
except (OSError, ValueError, IndexError) as e:
return False, f"Error patching {file_path}: {e}"
return True, "\n".join(results)
+1 -1
View File
@@ -79,7 +79,7 @@ def _find_vscode_in_registry() -> Optional[str]:
exe_path = line.strip() + "\\Code.exe"
if os.path.exists(exe_path):
paths.append(exe_path)
except Exception:
except (OSError, subprocess.SubprocessError, subprocess.TimeoutExpired):
pass
if paths:
return paths[0]
+2 -2
View File
@@ -120,7 +120,7 @@ class MarkdownRenderer:
webbrowser.open(str(p.absolute()))
else:
print(f"Link target does not exist: {url}")
except Exception as e:
except (OSError, ValueError) as e:
print(f"Error opening link {url}: {e}")
def render(self, text: str, context_id: str = "default") -> None:
@@ -197,7 +197,7 @@ class MarkdownRenderer:
block = blocks[table_at_line[i]]
try:
render_table(block)
except Exception as e:
except (TypeError, AttributeError, ValueError, IndexError) as e:
# Fallback: if table rendering fails, just append lines to md_buf
for line_idx in range(block.span[0], block.span[1]):
md_buf.append(lines[line_idx])
+1 -1
View File
@@ -146,7 +146,7 @@ def test_execute_runs_command_and_closes() -> None:
id="test_bad",
title="Test Bad",
category="test",
action=lambda app: (_ for _ in ()).throw(RuntimeError("boom")),
action=lambda app: (_ for _ in ()).throw(TypeError("boom")),
)
# Should NOT raise
_execute(bad_app, bad_command)