From cca396e7bdd38108dbd64481936a52ed422f24b2 Mon Sep 17 00:00:00 2001 From: Antti Kettunen Date: Sat, 18 Apr 2026 18:47:54 +0300 Subject: [PATCH] Centralize Hydrabase enablement Move Hydrabase availability checks into metadata_service so source resolution owns the policy. Keep web_server delegating to the centralized helper and add tests for the enabled/disabled cases. --- core/metadata_service.py | 22 +++++++++++++---- tests/test_metadata_service_cache.py | 36 ++++++++++++++++++++++++++++ web_server.py | 12 ++++------ 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/core/metadata_service.py b/core/metadata_service.py index 3b3070a7..fcd516e1 100644 --- a/core/metadata_service.py +++ b/core/metadata_service.py @@ -451,18 +451,32 @@ def get_discogs_client(token: Optional[str] = None): return client -def get_hydrabase_client(allow_fallback: bool = True): - """Return current Hydrabase client if connected. +def is_hydrabase_enabled() -> bool: + """Return True when Hydrabase is connected and allowed for metadata use.""" + try: + import importlib + ws = importlib.import_module('web_server') + client = getattr(ws, 'hydrabase_client', None) + if not client or not client.is_connected(): + return False + return bool(getattr(ws, 'dev_mode_enabled', False)) + except Exception: + return False + + +def get_hydrabase_client(allow_fallback: bool = True, require_enabled: bool = True): + """Return current Hydrabase client if connected and enabled. If allow_fallback is True, return iTunes fallback when Hydrabase is not - connected. If False, return None instead. + connected or not enabled. If False, return None instead. """ try: import importlib ws = importlib.import_module('web_server') client = getattr(ws, 'hydrabase_client', None) if client and client.is_connected(): - return client + if not require_enabled or bool(getattr(ws, 'dev_mode_enabled', False)): + return client except Exception: pass if allow_fallback: diff --git a/tests/test_metadata_service_cache.py b/tests/test_metadata_service_cache.py index e6abecd4..fa7b0400 100644 --- a/tests/test_metadata_service_cache.py +++ b/tests/test_metadata_service_cache.py @@ -105,3 +105,39 @@ def test_deezer_client_cache_tracks_token(monkeypatch): assert first is not second assert calls["deezer"] == 2 + + +class _FakeHydrabaseClient: + def __init__(self, connected=True): + self._connected = connected + + def is_connected(self): + return self._connected + + +def test_hydrabase_enabled_requires_connection_and_dev_mode(monkeypatch): + fake_ws = types.ModuleType("web_server") + fake_ws.hydrabase_client = _FakeHydrabaseClient(connected=True) + fake_ws.dev_mode_enabled = True + monkeypatch.setitem(sys.modules, "web_server", fake_ws) + + assert metadata_service.is_hydrabase_enabled() is True + + fake_ws.dev_mode_enabled = False + assert metadata_service.is_hydrabase_enabled() is False + + fake_ws.dev_mode_enabled = True + fake_ws.hydrabase_client = _FakeHydrabaseClient(connected=False) + assert metadata_service.is_hydrabase_enabled() is False + + +def test_get_client_for_source_hydrabase_requires_enablement(monkeypatch): + fake_ws = types.ModuleType("web_server") + fake_ws.hydrabase_client = _FakeHydrabaseClient(connected=True) + fake_ws.dev_mode_enabled = False + monkeypatch.setitem(sys.modules, "web_server", fake_ws) + + assert metadata_service.get_client_for_source("hydrabase") is None + + fake_ws.dev_mode_enabled = True + assert metadata_service.get_client_for_source("hydrabase") is fake_ws.hydrabase_client diff --git a/web_server.py b/web_server.py index fc498b67..cd8ec568 100644 --- a/web_server.py +++ b/web_server.py @@ -5867,15 +5867,11 @@ _COMPARISON_MAX_ENTRIES = 50 _comparison_lock = threading.Lock() def _is_hydrabase_active(): - """Check if Hydrabase should be used as the PRIMARY metadata source (replaces Spotify). - Only active in dev mode — the legacy 'Hydrabase replaces everything' behavior. - When selected as a fallback source, Hydrabase works through the normal fallback - path (_get_metadata_fallback_client) just like iTunes/Deezer — not as primary.""" + """Check if Hydrabase is connected and enabled for metadata use.""" try: - if hydrabase_client is None or not hydrabase_client.is_connected(): - return False - return dev_mode_enabled - except (NameError, Exception): + from core.metadata_service import is_hydrabase_enabled + return is_hydrabase_enabled() + except Exception: return False def _run_background_comparison(query, hydrabase_counts=None):