Skip to content

Commit 256a8a1

Browse files
committed
lastgenre: _filter_valid forbids genres via helper
- Helper _is_forbidden (similar to _is_valid) checks whether a genre and artist combination is forbidden. - A special artist name "*" can be included in blacklist.yaml to support kicking out via the blacklist (and not only the whitelist). TODO: Is that redundant or convenient?
1 parent 017e71a commit 256a8a1

1 file changed

Lines changed: 47 additions & 7 deletions

File tree

beetsplug/lastgenre/__init__.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def setup(self):
156156
if bl_filename:
157157
bl_filename = normpath(bl_filename)
158158
try:
159-
with codecs.open(bl_filename, 'r', encoding='utf-8') as f:
159+
with codecs.open(bl_filename, "r", encoding="utf-8") as f:
160160
self.blacklist = yaml.safe_load(f)
161161
self._log.debug("Loaded genre blacklist from {0}", bl_filename)
162162
except Exception as exc:
@@ -265,10 +265,19 @@ def fetch_genre(self, lastfm_obj):
265265
min_weight = self.config["min_weight"].get(int)
266266
return self._tags_for(lastfm_obj, min_weight)
267267

268-
def _filter_valid_genres(self, genres: list[str]) -> list[str]:
269-
"""Filter list of genres, only keep valid."""
268+
def _filter_valid_genres(
269+
self, genres: list[str], artist: str = None
270+
) -> list[str]:
271+
"""Filter list of genres, only keep valid.
272+
First applies blacklist filtering if enabled, then whitelist filtering."""
270273
if not genres:
271274
return []
275+
276+
# First remove forbidden genres if we have an artist
277+
if artist:
278+
genres = [g for g in genres if not self._is_forbidden(g, artist)]
279+
280+
# Then apply whitelist filter
272281
return [x for x in genres if self._is_valid(x)]
273282

274283
def _is_valid(self, genre: str) -> bool:
@@ -281,6 +290,33 @@ def _is_valid(self, genre: str) -> bool:
281290
return True
282291
return False
283292

293+
def _is_forbidden(self, genre: str, artist: str) -> bool:
294+
"""Return True if the genre is forbidden for the artist.
295+
296+
Supports a special '*' key in the blacklist YAML file for
297+
global forbidden genres.
298+
299+
Example:
300+
"Artist Name":
301+
- "pop"
302+
"*":
303+
- "spoken word"
304+
"""
305+
if not self.blacklist:
306+
return False
307+
308+
forbidden = set()
309+
# Add global forbidden genres
310+
if "*" in self.blacklist:
311+
forbidden.update(g.lower() for g in self.blacklist["*"] or [])
312+
# Add artist-specific forbidden genres
313+
if artist:
314+
for bl_artist, blocked_genres in self.blacklist.items():
315+
if bl_artist != "*" and bl_artist.lower() == artist.lower():
316+
forbidden.update(g.lower() for g in blocked_genres or [])
317+
318+
return genre.lower() in forbidden
319+
284320
# Cached last.fm entity lookups.
285321

286322
def _last_lookup(self, entity, method, *args):
@@ -311,25 +347,29 @@ def fetch_album_genre(self, obj):
311347
return self._filter_valid_genres(
312348
self._last_lookup(
313349
"album", LASTFM.get_album, obj.albumartist, obj.album
314-
)
350+
),
351+
obj.albumartist,
315352
)
316353

317354
def fetch_album_artist_genre(self, obj):
318355
"""Return the album artist genre for this Item or Album."""
319356
return self._filter_valid_genres(
320-
self._last_lookup("artist", LASTFM.get_artist, obj.albumartist)
357+
self._last_lookup("artist", LASTFM.get_artist, obj.albumartist),
358+
obj.albumartist,
321359
)
322360

323361
def fetch_artist_genre(self, item):
324362
"""Returns the track artist genre for this Item."""
325363
return self._filter_valid_genres(
326-
self._last_lookup("artist", LASTFM.get_artist, item.artist)
364+
self._last_lookup("artist", LASTFM.get_artist, item.artist),
365+
item.artist,
327366
)
328367

329368
def fetch_track_genre(self, obj):
330369
"""Returns the track genre for this Item."""
331370
return self._filter_valid_genres(
332-
self._last_lookup("track", LASTFM.get_track, obj.artist, obj.title)
371+
self._last_lookup("track", LASTFM.get_track, obj.artist, obj.title),
372+
obj.artist,
333373
)
334374

335375
# Main processing: _get_genre() and helpers.

0 commit comments

Comments
 (0)