Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #6367 +/- ##
==========================================
+ Coverage 69.18% 69.32% +0.14%
==========================================
Files 140 141 +1
Lines 18686 18786 +100
Branches 3053 3060 +7
==========================================
+ Hits 12927 13024 +97
- Misses 5114 5117 +3
Partials 645 645
🚀 New features to boost your workflow:
|
6f18c92 to
8c0820b
Compare
JOJ0
left a comment
There was a problem hiding this comment.
supported separators in docs correct?
I don't have much to say on the sql implementation except that it works when switching back and forth between this branch and current master and it's super-fast 🤩 👍
There was a problem hiding this comment.
nope, separators are correct, sorry my bad
https://github.com/beetbox/beets/pull/6367/changes#diff-ae385b0e7d1b2ea018b059b900c8d3c44554954bec89513a7ebe54d9c50cd503R90
let's finally get this done! ❤️
8c0820b to
fbf7085
Compare
fbf7085 to
a8101c1
Compare
There was a problem hiding this comment.
Pull request overview
This pull request implements native multi-value genre support in beets by replacing the singular genre field with a plural genres field across the codebase. This addresses long-standing issues with maintaining synchronization between singular and plural fields that caused repeated retagging operations.
Changes:
- Introduces database migration infrastructure to support automatic data migrations across schema changes
- Migrates existing
genrestring values togenresmulti-value field, splitting on common separators (, ; /) - Updates metadata source plugins (MusicBrainz, Beatport, Discogs, LastGenre) to populate
genresas a list rather thangenreas a string - Removes the
separatorconfiguration option from LastGenre plugin since genres are now stored as lists - Updates all tests to use
genresfield instead ofgenre
Reviewed changes
Copilot reviewed 38 out of 40 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| beets/dbcore/db.py | Adds Migration base class and infrastructure for tracking migration state, adds mutate_many for batch operations, adds db_tables cached property for schema introspection |
| beets/dbcore/types.py | Exports MULTI_VALUE_DELIMITER constant for reuse in migrations |
| beets/library/library.py | Registers MultiGenreFieldMigration to run on library initialization |
| beets/library/migrations.py | Implements genre→genres migration logic with automatic separator detection |
| beets/library/models.py | Changes genre field from STRING to genres field with MULTI_VALUE_DSV type in both Item and Album models |
| beets/autotag/hooks.py | Adds deprecation warning for genre parameter in AlbumInfo constructor with automatic conversion to genres list |
| beetsplug/musicbrainz.py | Updates to populate genres list instead of genre string |
| beetsplug/lastgenre/init.py | Refactors to work with genres as lists, removes separator config option, updates type hints |
| beetsplug/discogs/init.py | Updates to populate genres list and simplifies genre/style handling |
| beetsplug/beatport.py | Updates to populate genres list for both releases and tracks |
| beetsplug/bpd/init.py | Maps MPD "Genre" tag type to "genres" field |
| beetsplug/aura.py | Adds mapping for both "genre" and "genres" to "genres" field for compatibility |
| test/* | Updates all tests to use genres field instead of genre, adds migration tests |
| docs/* | Updates documentation to reflect genres field usage and documents migration behavior |
| setup.cfg | Adds follow_untyped_imports = true to mypy configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@JOJ0 given that Copilot also raised a question regarding separators, I've now documented the precedence and the fact that |
151468e to
241d335
Compare
fbe848a to
80d08bc
Compare
03114e1 to
54a46bd
Compare
80d08bc to
ce5214a
Compare
dc2d778 to
d0efc62
Compare
d0efc62 to
a540a81
Compare
|
I think this is now in a good place to be merged in, finally! Thanks, @dunkla ❤️ |
|
I'm having a bit of trouble after upgrading to this commit. |
Hi, can you make a backup copy of your current beets database and then try to reset your database to the pre-migration state? See this post of @snejus: #6367 (comment) Then for your next report here also add debug logging and post what's happening. Question: When you did your print tests, was that possibly after the migration was run? Then the Also some |
I might be mistaken here. Trying hard with the debugger to find out what's going on. I'm not sure anymore what
Maybe my breakpoints are too late and everything happened already. In any case we will need @snejus and I'm sure with some patience we can figure out what's going on. In the meantime I'm investigating more... |
|
@snejus I think I can repro the issue. My last tests were with the Resetting, no genres column: Accessing should trigger migration but doesn't or does it incomplete it seems: I have the genres column but it's empty |
|
Goddammit, I trusted Copilot too much and made a mistake! |
|
Fix is up in #6401 and going to merge it immediately once tests pass. Follow instructions in this comment #6367 (comment) before re-running beets again, apologies! |
I can confirm that it works now: ❤️ |
|
Perfect, that fixes it! Glad I could be your QA! |
|
Actually, not totally perfect. When I run |
|
Could you provide some diff output that you're seeing? |
|
From |
|
Interesting. Are they kept in place using older version of beets? |
|
Yes, going back to version |
|
Would you mind submitting a new issue for this? I will look at it in detail. |
|
Created: #6403. I might have some time to look into this later this weekend |

Add support for a multi-valued
genresfieldgenresinstead ofgenre:musicbrainz,beatport,discogs.separatorconfiguration fromlastgenre.Context
We previously had multiple issues with maintaining both singular and plural fields:
fields must be carefully synchronised, otherwise we see these fields being repeatedly
retagged / rewritten using commands such as
beet write. See related issuesimported as-is could not be fixed. See Stop perpetually writing
mb_artistid,mb_albumartistidandalbumtypesfields #5540, for example.Therefore, this PR replaces a singular
genrefield by pluralgenresfor good:genre->genresimmediately on the firstbeetsinvocationgenrefield is removed andgenresis addedgenrecolumn in the database is left in place - these values will be ignoredby beets.
beets, their
genrevalues are still in place.Migration
This PR creates a new DB table
migrations(name TEXT, table TEXT)CTRL-C during the migration, the migration will continue on the next beets invocation,
see:
Implemented using SQL due to:
genresfield:genrefield is only accessible by querying thedatabase directly.
Supersedes: #6169