From 9be006a79dd15ca43814924182d4c0ffdfb483e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0ar=C5=ABnas=20Nejus?= Date: Sat, 24 Jan 2026 22:36:56 +0000 Subject: [PATCH] Refactor parsing genre --- beetsplug/musicbrainz.py | 34 +++++++++++++++------------ test/plugins/factories/musicbrainz.py | 11 +++++++++ test/plugins/test_musicbrainz.py | 16 +++++++++---- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/beetsplug/musicbrainz.py b/beetsplug/musicbrainz.py index b62537524..ba534e1a8 100644 --- a/beetsplug/musicbrainz.py +++ b/beetsplug/musicbrainz.py @@ -16,7 +16,7 @@ from __future__ import annotations -from collections import Counter +from collections import defaultdict from contextlib import suppress from functools import cached_property from itertools import product @@ -434,6 +434,23 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): original_day=day, ) + def _parse_genre(self, release: Release) -> str | None: + if self.config["genres"]: + genres = [ + *release["release_group"][self.genres_field], + *release.get(self.genres_field, []), + ] + count_by_genre: dict[str, int] = defaultdict(int) + for genre in genres: + count_by_genre[genre["name"]] += int(genre["count"]) + + return "; ".join( + g + for g, _ in sorted(count_by_genre.items(), key=lambda g: -g[1]) + ) + + return None + def album_info(self, release: Release) -> beets.autotag.hooks.AlbumInfo: """Takes a MusicBrainz release result dictionary and returns a beets AlbumInfo object containing the interesting data about that release. @@ -522,6 +539,7 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): data_source=self.data_source, data_url=urljoin(BASE_URL, f"release/{release['id']}"), barcode=release.get("barcode"), + genre=genre if (genre := self._parse_genre(release)) else None, **self._parse_release_group(release["release_group"]), ) info.va = info.artist_id == VARIOUS_ARTISTS_ID @@ -569,20 +587,6 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): else: info.media = "Media" - if self.config["genres"]: - sources = [ - release["release_group"][self.genres_field], - release.get(self.genres_field, []), - ] - genres: Counter[str] = Counter() - for source in sources: - for genreitem in source: - genres[genreitem["name"]] += int(genreitem["count"]) - info.genre = "; ".join( - genre - for genre, _count in sorted(genres.items(), key=lambda g: -g[1]) - ) - # We might find links to external sources (Discogs, Bandcamp, ...) external_ids = self.config["external_ids"].get() wanted_sources: set[UrlSource] = { diff --git a/test/plugins/factories/musicbrainz.py b/test/plugins/factories/musicbrainz.py index 36549d953..1a7cfa72b 100644 --- a/test/plugins/factories/musicbrainz.py +++ b/test/plugins/factories/musicbrainz.py @@ -115,3 +115,14 @@ class ReleaseGroupFactory(_IdFactory): secondary_types = factory.List([]) tags = factory.List([]) title = "Release Group" + + +class GenreFactory(factory.DictFactory): + id = factory.Faker("uuid4") + count = 1 + disambiguation = "" + name = "Genre" + + +class TagFactory(GenreFactory): + name = "Tag" diff --git a/test/plugins/test_musicbrainz.py b/test/plugins/test_musicbrainz.py index 529f2d4b3..dd1594756 100644 --- a/test/plugins/test_musicbrainz.py +++ b/test/plugins/test_musicbrainz.py @@ -60,6 +60,14 @@ def release_group_factory(**kwargs) -> mb.ReleaseGroup: return factories.ReleaseGroupFactory.build(**kwargs) +def genre_factory(**kwargs) -> mb.Genre: + return factories.GenreFactory.build(**kwargs) + + +def tag_factory(**kwargs) -> mb.Tag: + return factories.TagFactory.build(**kwargs) + + class MusicBrainzTestCase(BeetsTestCase): def setUp(self): super().setUp() @@ -85,8 +93,8 @@ class MusicBrainzTestCase(BeetsTestCase): "artist_credit": [artist_credit_factory(artist__id_base=10)], "date": "3001", "media": [], - "genres": [{"count": 1, "name": "GENRE"}], - "tags": [{"count": 1, "name": "TAG"}], + "genres": [genre_factory()], + "tags": [tag_factory()], "label_info": [ { "catalog_number": "CATALOG NUMBER", @@ -520,14 +528,14 @@ class MBAlbumInfoTest(MusicBrainzTestCase): config["musicbrainz"]["genres_tag"] = "genre" release = self._make_release() d = self.mb.album_info(release) - assert d.genre == "GENRE" + assert d.genre == "Genre" def test_tags(self): config["musicbrainz"]["genres"] = True config["musicbrainz"]["genres_tag"] = "tag" release = self._make_release() d = self.mb.album_info(release) - assert d.genre == "TAG" + assert d.genre == "Tag" def test_no_genres(self): config["musicbrainz"]["genres"] = False