Skip to content

Commit 9328bd7

Browse files
committed
Tidy up handling of backends
1 parent 3f62d04 commit 9328bd7

File tree

2 files changed

+29
-29
lines changed

2 files changed

+29
-29
lines changed

beetsplug/lyrics.py

+24-28
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,14 @@ def handle_request(self) -> Iterator[None]:
241241
self.warn("Request error: {}", exc)
242242

243243

244-
class Backend(RequestHandler):
244+
class BackendClass(type):
245+
@property
246+
def name(cls) -> str:
247+
"""Return lowercase name of the backend class."""
248+
return cls.__name__.lower()
249+
250+
251+
class Backend(RequestHandler, metaclass=BackendClass):
245252
def __init__(self, config, log):
246253
self._log = log
247254
self.config = config
@@ -736,15 +743,21 @@ def scrape(cls, html: str) -> str | None:
736743

737744

738745
class LyricsPlugin(RequestHandler, plugins.BeetsPlugin):
739-
SOURCES = ["lrclib", "google", "musixmatch", "genius", "tekstowo"]
740-
SOURCE_BACKENDS = {
741-
"google": Google,
742-
"musixmatch": MusiXmatch,
743-
"genius": Genius,
744-
"tekstowo": Tekstowo,
745-
"lrclib": LRCLib,
746+
BACKEND_BY_NAME = {
747+
b.name: b for b in [LRCLib, Google, Genius, Tekstowo, MusiXmatch]
746748
}
747749

750+
@cached_property
751+
def backends(self) -> list[Backend]:
752+
user_sources = self.config["sources"].get()
753+
754+
chosen = plugins.sanitize_choices(user_sources, self.BACKEND_BY_NAME)
755+
if "google" in chosen and not self.config["google_API_key"].get():
756+
self.warn("Disabling Google source: no API key configured.")
757+
chosen.remove("google")
758+
759+
return [self.BACKEND_BY_NAME[c](self.config, self._log) for c in chosen]
760+
748761
def __init__(self):
749762
super().__init__()
750763
self.import_stages = [self.imported]
@@ -767,7 +780,9 @@ def __init__(self):
767780
"synced": False,
768781
# Musixmatch is disabled by default as they are currently blocking
769782
# requests with the beets user agent.
770-
"sources": [s for s in self.SOURCES if s != "musixmatch"],
783+
"sources": [
784+
n for n in self.BACKEND_BY_NAME if n != "musixmatch"
785+
],
771786
}
772787
)
773788
self.config["bing_client_secret"].redact = True
@@ -784,29 +799,10 @@ def __init__(self):
784799
# open yet.
785800
self.rest = None
786801

787-
available_sources = list(self.SOURCES)
788-
sources = plugins.sanitize_choices(
789-
self.config["sources"].as_str_seq(), available_sources
790-
)
791-
792-
if "google" in sources:
793-
if not self.config["google_API_key"].get():
794-
# We log a *debug* message here because the default
795-
# configuration includes `google`. This way, the source
796-
# is silent by default but can be enabled just by
797-
# setting an API key.
798-
self.debug("Disabling google source: " "no API key configured.")
799-
sources.remove("google")
800-
801802
self.config["bing_lang_from"] = [
802803
x.lower() for x in self.config["bing_lang_from"].as_str_seq()
803804
]
804805

805-
self.backends = [
806-
self.SOURCE_BACKENDS[s](self.config, self._log.getChild(s))
807-
for s in sources
808-
]
809-
810806
@cached_property
811807
def bing_access_token(self) -> str | None:
812808
params = {

test/plugins/test_lyrics.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ class TestGoogleLyrics(LyricsBackendTest):
294294
def backend_name(self):
295295
return "google"
296296

297-
@pytest.fixture(scope="class")
297+
@pytest.fixture
298298
def plugin_config(self):
299299
return {"google_API_key": "test"}
300300

@@ -306,6 +306,10 @@ def file_name(self):
306306
def search_item(self, url_title, url):
307307
return {"title": url_title, "link": url}
308308

309+
@pytest.mark.parametrize("plugin_config", [{}])
310+
def test_disabled_without_api_key(self, lyrics_plugin):
311+
assert not lyrics_plugin.backends
312+
309313
def test_mocked_source_ok(self, backend, lyrics_html):
310314
"""Test that lyrics of the mocked page are correctly scraped"""
311315
result = backend.scrape(lyrics_html).lower()

0 commit comments

Comments
 (0)