From fe863602e3dca17291df26114824f2efa344e26d Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Mon, 20 Jul 2026 15:29:25 +0000 Subject: [PATCH] Catch InvalidVersion specifically in plugin update comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review feedback: the version comparison caught a blind `except Exception` (ruff BLE001). Split the two failure modes and catch each specifically — ImportError for a missing `packaging` (a core dependency) and InvalidVersion for an unparseable version string — while preserving the existing "surface the mismatch" fallback behavior. Added a test for the unparseable-version path. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012EW8yDbsk8EceDpq6Hjgqj --- test/test_web_api.py | 3 +++ web_interface/blueprints/api_v3.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/test_web_api.py b/test/test_web_api.py index 91cdd3bd..e8f57bea 100644 --- a/test/test_web_api.py +++ b/test/test_web_api.py @@ -433,6 +433,9 @@ class TestPluginsAPI: # Missing either side yields no signal. assert _is_plugin_update_available('', '1.0.0') is False assert _is_plugin_update_available('1.0.0', '') is False + # Unparseable version differing from the installed one surfaces the + # mismatch rather than hiding a possible update. + assert _is_plugin_update_available('1.0.0', 'not-a-semver') is True def test_get_plugin_health(self, client, mock_plugin_manager): """Test getting plugin health information.""" diff --git a/web_interface/blueprints/api_v3.py b/web_interface/blueprints/api_v3.py index 73d16ade..41631ef1 100644 --- a/web_interface/blueprints/api_v3.py +++ b/web_interface/blueprints/api_v3.py @@ -134,9 +134,15 @@ def _is_plugin_update_available(installed_version: str, latest_version: str) -> if installed_version == latest_version: return False try: - from packaging.version import parse as _parse_version + from packaging.version import parse as _parse_version, InvalidVersion + except ImportError: + # packaging is a core dependency, but if it's somehow unavailable we + # can't compare semantically — surface the mismatch we already know + # exists (the two strings differ). + return True + try: return _parse_version(latest_version) > _parse_version(installed_version) - except Exception: + except InvalidVersion: # Unparseable version string: we can't tell direction, so surface the # mismatch rather than silently hiding a potential update. return True