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