From 702ddf493e37a58c4380c61464e8e830adbd5737 Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Fri, 28 Mar 2025 07:51:48 +0100 Subject: [PATCH] lastgenre: Early validate genres, new debug option - Revert/fix last.fm fetcher methods to validate genres. - In past versions (<=2.2) _resolve_genres which included whitelist checks ran instantly after fetching last.fm tags which made sure the next stage is hit when nothing worthwhile was found (e.g fallback album -> artist). - Bring back this behavior but don't run a full _resolve_genres but a quick valid (whitelist) check only! - Introduce an extended config/CLI option that allows to really log what each stage fetches (prior to validation/whitelist filtering). - Since this potentially is verbose especially with VA albums (a lot of artist tag fetches) for performance and debug log clutter reasons this is disabled by default. - Clarify final last.fm tags debug log message to "valid last.fm genres" --- beetsplug/lastgenre/__init__.py | 39 +++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 1f2f01cb0..f0c13c496 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -104,6 +104,7 @@ class LastGenrePlugin(plugins.BeetsPlugin): "separator": ", ", "prefer_specific": False, "title_case": True, + "extended_debug": False, } ) self.setup() @@ -241,7 +242,7 @@ class LastGenrePlugin(plugins.BeetsPlugin): # c14n only adds allowed genres but we may have had forbidden genres in # the original tags list - valid_tags = [x for x in tags if self._is_valid(x)] + valid_tags = self._filter_valid_genres(tags) return valid_tags[: self.config["count"].get(int)] def fetch_genre(self, lastfm_obj): @@ -251,6 +252,10 @@ class LastGenrePlugin(plugins.BeetsPlugin): min_weight = self.config["min_weight"].get(int) return self._tags_for(lastfm_obj, min_weight) + def _filter_valid_genres(self, genres: list[str]) -> list[str]: + """Filter list of genres, only keep valid.""" + return [x for x in genres if self._is_valid(x)] + def _is_valid(self, genre: str) -> bool: """Check if the genre is valid. @@ -281,26 +286,35 @@ class LastGenrePlugin(plugins.BeetsPlugin): args = [a.replace("\u2010", "-") for a in args] self._genre_cache[key] = self.fetch_genre(method(*args)) - return self._genre_cache[key] + genre = self._genre_cache[key] + if self.config["extended_debug"]: + self._log.debug(f"last.fm (unfiltered) {entity} tags: {genre}") + return genre def fetch_album_genre(self, obj): """Return the album genre for this Item or Album.""" - return self._last_lookup( - "album", LASTFM.get_album, obj.albumartist, obj.album + return self._filter_valid_genres( + self._last_lookup( + "album", LASTFM.get_album, obj.albumartist, obj.album + ) ) def fetch_album_artist_genre(self, obj): """Return the album artist genre for this Item or Album.""" - return self._last_lookup("artist", LASTFM.get_artist, obj.albumartist) + return self._filter_valid_genres( + self._last_lookup("artist", LASTFM.get_artist, obj.albumartist) + ) def fetch_artist_genre(self, item): """Returns the track artist genre for this Item.""" - return self._last_lookup("artist", LASTFM.get_artist, item.artist) + return self._filter_valid_genres( + self._last_lookup("artist", LASTFM.get_artist, item.artist) + ) def fetch_track_genre(self, obj): """Returns the track genre for this Item.""" - return self._last_lookup( - "track", LASTFM.get_track, obj.artist, obj.title + return self._filter_valid_genres( + self._last_lookup("track", LASTFM.get_track, obj.artist, obj.title) ) # Main processing: _get_genre() and helpers. @@ -330,7 +344,7 @@ class LastGenrePlugin(plugins.BeetsPlugin): self, old: list[str], new: list[str] ) -> list[str]: """Combine old and new genres and process via _resolve_genres.""" - self._log.debug(f"fetched last.fm tags: {new}") + self._log.debug(f"valid last.fm tags: {new}") self._log.debug(f"existing genres taken into account: {old}") combined = old + new return self._resolve_genres(combined) @@ -489,6 +503,13 @@ class LastGenrePlugin(plugins.BeetsPlugin): dest="album", help="match albums instead of items (default)", ) + lastgenre_cmd.parser.add_option( + "-d", + "--debug", + action="store_true", + dest="extended_debug", + help="extended last.fm debug logging", + ) lastgenre_cmd.parser.set_defaults(album=True) def lastgenre_func(lib, opts, args):