Skip to content

Commit d4175f7

Browse files
committed
Implement multi-tag genres field
1 parent d3c6296 commit d4175f7

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

beets/autotag/hooks.py

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def __init__(
109109
country: Optional[str] = None,
110110
style: Optional[str] = None,
111111
genre: Optional[str] = None,
112+
genres: Optional[str] = None,
112113
albumstatus: Optional[str] = None,
113114
media: Optional[str] = None,
114115
albumdisambig: Optional[str] = None,
@@ -152,6 +153,7 @@ def __init__(
152153
self.country = country
153154
self.style = style
154155
self.genre = genre
156+
self.genres = genres
155157
self.albumstatus = albumstatus
156158
self.media = media
157159
self.albumdisambig = albumdisambig
@@ -221,6 +223,7 @@ def __init__(
221223
bpm: Optional[str] = None,
222224
initial_key: Optional[str] = None,
223225
genre: Optional[str] = None,
226+
genres: Optional[str] = None,
224227
album: Optional[str] = None,
225228
**kwargs,
226229
):
@@ -255,6 +258,7 @@ def __init__(
255258
self.bpm = bpm
256259
self.initial_key = initial_key
257260
self.genre = genre
261+
self.genres = genres
258262
self.album = album
259263
self.update(kwargs)
260264

beets/library.py

+3
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ class Item(LibModel):
531531
"albumartist_credit": types.STRING,
532532
"albumartists_credit": types.MULTI_VALUE_DSV,
533533
"genre": types.STRING,
534+
"genres": types.MULTI_VALUE_DSV,
534535
"style": types.STRING,
535536
"discogs_albumid": types.INTEGER,
536537
"discogs_artistid": types.INTEGER,
@@ -1173,6 +1174,7 @@ class Album(LibModel):
11731174
"albumartists_credit": types.MULTI_VALUE_DSV,
11741175
"album": types.STRING,
11751176
"genre": types.STRING,
1177+
"genres": types.MULTI_VALUE_DSV,
11761178
"style": types.STRING,
11771179
"discogs_albumid": types.INTEGER,
11781180
"discogs_artistid": types.INTEGER,
@@ -1229,6 +1231,7 @@ class Album(LibModel):
12291231
"albumartists_credit",
12301232
"album",
12311233
"genre",
1234+
"genres",
12321235
"style",
12331236
"discogs_albumid",
12341237
"discogs_artistid",

docs/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ New features:
2020
* :doc:`plugins/autobpm`: Add new configuration option ``beat_track_kwargs``
2121
which enables adjusting keyword arguments supplied to librosa's
2222
``beat_track`` function call.
23+
* New multi-value `genres` tag
2324

2425
Bug fixes:
2526

test/test_library.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -708,13 +708,13 @@ def test_if_def_false_complete(self):
708708
self._assert_dest(b"/base/not_played")
709709

710710
def test_first(self):
711-
self.i.genres = "Pop; Rock; Classical Crossover"
712-
self._setf("%first{$genres}")
711+
self.i.semicolon_delimited_field = "Pop; Rock; Classical Crossover"
712+
self._setf("%first{$semicolon_delimited_field}")
713713
self._assert_dest(b"/base/Pop")
714714

715715
def test_first_skip(self):
716-
self.i.genres = "Pop; Rock; Classical Crossover"
717-
self._setf("%first{$genres,1,2}")
716+
self.i.semicolon_delimited_field = "Pop; Rock; Classical Crossover"
717+
self._setf("%first{$semicolon_delimited_field,1,2}")
718718
self._assert_dest(b"/base/Classical Crossover")
719719

720720
def test_first_different_sep(self):
@@ -1306,6 +1306,28 @@ def test_write_date_field(self):
13061306
item.write()
13071307
assert MediaFile(syspath(item.path)).year == clean_year
13081308

1309+
def test_write_multi_genres(self):
1310+
item = self.add_item_fixture(genre="old genre")
1311+
item.write(
1312+
tags={"genres": ["g1", "g2"]},
1313+
)
1314+
1315+
# Ensure it reads all genres
1316+
assert MediaFile(syspath(item.path)).genres == ["g1", "g2"]
1317+
1318+
# Ensure reading single genre outputs the first of the genres
1319+
assert MediaFile(syspath(item.path)).genre == "g1"
1320+
1321+
def test_write_multi_genres_both_single_and_multi(self):
1322+
item = self.add_item_fixture(genre="old genre 1")
1323+
item.write(
1324+
tags={"genre": "single genre", "genres": ["multi genre"]},
1325+
)
1326+
1327+
# Ensure the multi takes precedence
1328+
assert MediaFile(syspath(item.path)).genre == "multi genre"
1329+
assert MediaFile(syspath(item.path)).genres == ["multi genre"]
1330+
13091331

13101332
class ItemReadTest(unittest.TestCase):
13111333
def test_unreadable_raise_read_error(self):

0 commit comments

Comments
 (0)