fix: Deezer dropped from hybrid + no green light despite working as primary
Deezer download is_configured()/is_available() returned the raw _authenticated flag, but the ARL auth is LAZY — only is_authenticated() triggers it (post-boot). The primary-source download path calls is_authenticated() so Deezer auths and works; the hybrid-mode source gate (web_server _resolve sources) and the green-light status (orchestrator.get_source_status) both read is_configured(), which never fired the auth — so Deezer looked unauthenticated, got pruned from the hybrid chain, and showed no green dot. Route is_configured()/is_available() through is_authenticated() so all three agree (and the auth still defers cleanly during boot). 4 seam tests: lazy-auth fires post-boot, defers during boot, stays True when already authed, False with no ARL.
This commit is contained in:
parent
fcd768ffee
commit
598a480a0b
2 changed files with 72 additions and 2 deletions
|
|
@ -227,10 +227,14 @@ class DeezerDownloadClient(DownloadSourcePlugin):
|
||||||
self.shutdown_check = check_callable
|
self.shutdown_check = check_callable
|
||||||
|
|
||||||
def is_configured(self) -> bool:
|
def is_configured(self) -> bool:
|
||||||
return self._authenticated
|
# Go through is_authenticated() so the lazy ARL auth fires (post-boot) — otherwise the raw
|
||||||
|
# _authenticated flag is still False until something else triggers it, and the hybrid-mode
|
||||||
|
# gate + the green-light status (both read is_configured) silently drop Deezer even though it
|
||||||
|
# downloads fine as a primary source (that path calls is_authenticated). Keeps the three in sync.
|
||||||
|
return self.is_authenticated()
|
||||||
|
|
||||||
def is_available(self) -> bool:
|
def is_available(self) -> bool:
|
||||||
return self._authenticated
|
return self.is_authenticated()
|
||||||
|
|
||||||
def is_authenticated(self) -> bool:
|
def is_authenticated(self) -> bool:
|
||||||
if self._pending_arl and not self._authenticated:
|
if self._pending_arl and not self._authenticated:
|
||||||
|
|
|
||||||
66
tests/test_deezer_download_is_configured.py
Normal file
66
tests/test_deezer_download_is_configured.py
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
"""Regression: Deezer download client `is_configured()` must fire the lazy ARL auth.
|
||||||
|
|
||||||
|
The hybrid-mode source gate + the green-light status both read `is_configured()`. It used to return
|
||||||
|
the raw `_authenticated` flag, which stays False until something calls `is_authenticated()` (the lazy
|
||||||
|
ARL auth). So Deezer downloaded fine as a *primary* source (that path auths) but was silently dropped
|
||||||
|
from a hybrid chain and showed no green light. The fix routes is_configured()/is_available() through
|
||||||
|
is_authenticated() so the three can't drift.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import core.boot_phase as boot
|
||||||
|
from core.deezer_download_client import DeezerDownloadClient
|
||||||
|
|
||||||
|
|
||||||
|
def _bare_client(authenticated=False, pending_arl=None):
|
||||||
|
"""A client without __init__ (no config/network) — just the auth-state seam we're testing."""
|
||||||
|
c = DeezerDownloadClient.__new__(DeezerDownloadClient)
|
||||||
|
c._authenticated = authenticated
|
||||||
|
c._pending_arl = pending_arl
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_configured_fires_lazy_arl_auth_post_boot(monkeypatch):
|
||||||
|
monkeypatch.setattr(boot, "is_boot_phase", lambda: False)
|
||||||
|
c = _bare_client(authenticated=False, pending_arl="fake-arl")
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
def fake_auth(arl):
|
||||||
|
calls.append(arl)
|
||||||
|
c._authenticated = True
|
||||||
|
|
||||||
|
c._authenticate = fake_auth
|
||||||
|
|
||||||
|
# The hybrid gate / green light call this — it must trigger the deferred auth, not report False.
|
||||||
|
assert c.is_configured() is True
|
||||||
|
assert c.is_available() is True
|
||||||
|
assert calls == ["fake-arl"]
|
||||||
|
assert c._pending_arl is None
|
||||||
|
|
||||||
|
# Idempotent: once authed, no repeat network auth.
|
||||||
|
assert c.is_configured() is True
|
||||||
|
assert calls == ["fake-arl"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_configured_defers_during_boot(monkeypatch):
|
||||||
|
monkeypatch.setattr(boot, "is_boot_phase", lambda: True)
|
||||||
|
c = _bare_client(authenticated=False, pending_arl="fake-arl")
|
||||||
|
|
||||||
|
def boom(arl):
|
||||||
|
raise AssertionError("must not authenticate (network) during boot")
|
||||||
|
|
||||||
|
c._authenticate = boom
|
||||||
|
assert c.is_configured() is False # deferred — stays unauthenticated, but never auths mid-boot
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_configured_true_when_already_authed():
|
||||||
|
c = _bare_client(authenticated=True, pending_arl=None)
|
||||||
|
assert c.is_configured() is True
|
||||||
|
assert c.is_available() is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_configured_false_with_no_arl(monkeypatch):
|
||||||
|
monkeypatch.setattr(boot, "is_boot_phase", lambda: False)
|
||||||
|
c = _bare_client(authenticated=False, pending_arl=None) # no ARL configured at all
|
||||||
|
assert c.is_configured() is False
|
||||||
Loading…
Reference in a new issue