diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 121d76596..1c91688a6 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -482,6 +482,13 @@ class LastGenrePlugin(plugins.BeetsPlugin): if obj.genre and self.config["keep_existing"]: if not self.whitelist or self._is_valid(obj.genre.lower()): return obj.genre, "original fallback" + else: + # If the original genre doesn't match a whitelisted genre, check + # if we can canonicalize it to find a matching, whitelisted genre! + if result := _try_resolve_stage( + "original fallback", keep_genres, [] + ): + return result # Return fallback string. if fallback := self.config["fallback"].get(): diff --git a/docs/changelog.rst b/docs/changelog.rst index 50b021bf8..df886700b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -57,6 +57,9 @@ New features: Bug fixes: +- :doc:`/plugins/lastgenre`: Canonicalize genres when ``force`` and + ``keep_existing`` are ``on``, yet no genre info on lastfm could be found. + :bug:`6303` - Handle potential OSError when unlinking temporary files in ArtResizer. :bug:`5615` - :doc:`/plugins/spotify`: Updated Spotify API credentials. :bug:`6270` diff --git a/test/plugins/test_lastgenre.py b/test/plugins/test_lastgenre.py index 026001e38..3de43d197 100644 --- a/test/plugins/test_lastgenre.py +++ b/test/plugins/test_lastgenre.py @@ -541,6 +541,31 @@ class LastGenrePluginTest(PluginTestCase): "keep + album, whitelist", ), ), + # 16 - canonicalization transforms non-whitelisted original genres to canonical + # forms and deduplication works, **even** when no new genres are found online. + # + # "Cosmic Disco" is not in the default whitelist, thus gets resolved "up" in the + # tree to "Disco" and "Electronic". + ( + { + "force": True, + "keep_existing": True, + "source": "album", + "whitelist": True, + "canonical": True, + "prefer_specific": False, + "count": 10, + }, + "Cosmic Disco", + { + "album": [], + "artist": [], + }, + ( + "Disco, Electronic", + "keep + original fallback, whitelist", + ), + ), ], ) def test_get_genre(config_values, item_genre, mock_genres, expected_result):