Releases: linuxserver/docker-beets
2.9.0-ls325
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/2.9.0-ls325/index.html
LinuxServer Changes:
Full Changelog: 2.9.0-ls324...2.9.0-ls325
Remote Changes:
Updating PIP version of beets to 2.9.0
nightly-bacebe26-ls270
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-bacebe26-ls270/index.html
LinuxServer Changes:
Full Changelog: nightly-bacebe26-ls269...nightly-bacebe26-ls270
Remote Changes:
Add keep_synced option to lyrics plugin (#6538)
lyrics: Add keep_synced option to protect synced lyrics from
being overwritten
Adds a keep_synced config option and --keep-synced CLI flag to the
lyrics plugin. When enabled, tracks that already have synced lyrics are
skipped during fetching — even if force is set.
Motivation: Libraries with a mix of synced and plain lyrics can use
force to fill gaps without risking overwriting the higher-quality
synced entries.
Fixes: #5249
This is another widely requested issue with many reactions from users.
nightly-bacebe26-ls269
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-bacebe26-ls269/index.html
LinuxServer Changes:
Full Changelog: nightly-1d01689a-ls268...nightly-bacebe26-ls269
Remote Changes:
Add keep_synced option to lyrics plugin (#6538)
lyrics: Add keep_synced option to protect synced lyrics from
being overwritten
Adds a keep_synced config option and --keep-synced CLI flag to the
lyrics plugin. When enabled, tracks that already have synced lyrics are
skipped during fetching — even if force is set.
Motivation: Libraries with a mix of synced and plain lyrics can use
force to fill gaps without risking overwriting the higher-quality
synced entries.
Fixes: #5249
This is another widely requested issue with many reactions from users.
nightly-342a7c0e-ls270
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-342a7c0e-ls270/index.html
LinuxServer Changes:
No changes
Remote Changes:
fix(library): pass clutter to move command (#6540)
#This change fixes move and ensures that clutter options are correctly
passed through allowing beets to prune dirs with clutter in them.
Fixes: #5016
nightly-83017c06-ls267
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-83017c06-ls267/index.html
LinuxServer Changes:
Full Changelog: nightly-ff9f93e6-ls266...nightly-83017c06-ls267
Remote Changes:
docs: Added link and description to the beets-aisauce plugin (#6534)
see beetbox/beets#5922
and https://github.com/metasauce/beets-aisauce
nightly-80cd2155-ls268
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-80cd2155-ls268/index.html
LinuxServer Changes:
No changes
Remote Changes:
inline: make the album/item available directly (#5439)
There have been multiple requests, in the past, for the ability to use
plugin fields in inline fields. This has not previously been available.
From what I can tell, it was intentionally left unavailable due to
performance concerns.
The way the item fields are made available to the inline python code
means that all fields are looked up, whether they're actually used by
the code or not. Doing that for all computed fields would be a
performance concern.
I don't believe there's a good way to postpone the field computation, as
python eval and compile requires that globals be a dictionary, not a
mapping. Instead, we can make available the album or item model object
to the code directly, and let the code access the fields it needs via
that object, resulting in postponing the computation of the fields until
they're actually accessed.
This is a simple approach that makes the computed and plugin fields
available to inline python, which allows for more code reuse, as well as
more options for shifting logic out of templates and into python code.
The object is available as db_obj.
Examples:
item_fields:
test_file_size: db_obj.filesize
album_fields:
test_album_path: db_obj.path
# If the missing plugin is enabled
test_album_missing: db_obj.missingnightly-37d60dd2-ls268
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-37d60dd2-ls268/index.html
LinuxServer Changes:
No changes
Remote Changes:
Populate extra artists for discogs (#6509)
Discogs: Populate multi-value contributor fields from artist roles
Fixes: #6380
This PR extends the Discogs plugin to properly populate beets'
remixers, lyricists, composers, and arrangers fields from
Discogs artist role credits.
What changed
beetsplug/discogs/states.py — Core logic change in ValidArtist
and ArtistState:
- The
is_feat: boolfield onValidArtistis replaced withrole: str, preserving the raw Discogs role string rather than discarding it
after a single boolean check. - A new
main_artistsproperty filters to artists with no role or a
featuring role — this replaces the previous filtering that happened at
parse time, sovalid_artistsnow includes all artists regardless of
role. artists,artists_credit, andartists_idsare updated to source
frommain_artistsinstead ofvalid_artists, ensuring non-primary
contributors (e.g. composers, arrangers) no longer appear in artist
identity fields.- New properties —
lyricists,arrangers,remixers,composers—
derive their values fromvalid_artistsby substring-matching on the
rolefield (e.g."lyrics","producer","remix","written-by").
beetsplug/discogs/types.py — ArtistInfo typed dict gains four
optional fields: arrangers, composers, remixers, lyricists.
Test changes
test_anvis refactored from a flat parametrised function into a
TestAnvclass with a sharedalbum_infofixture, splitting the
assertions across focused test methods per field group.test_parse_featured_artistsgains assertions forartists_idsand
composers.- A new
test_parse_extraartist_rolestest covers role-to-field mapping
end-to-end for all four contributor types.
Impact
Discogs imports now populate contributor fields that were previously
only filled by the MusicBrainz plugin.
nightly-1d01689a-ls268
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-1d01689a-ls268/index.html
LinuxServer Changes:
Full Changelog: nightly-83017c06-ls267...nightly-1d01689a-ls268
Remote Changes:
chroma: gate candidates on musicbrainz plugin being enabled (#6532)
Fixes #6212.
Fixes #6441.
Split out from #6522 per @semohr's suggestion.
The chroma plugin unconditionally instantiated its own private
MusicBrainzPlugin instance and called album_for_id /
track_for_id on it regardless of the user's plugin configuration.
This meant MusicBrainz-sourced candidates appeared during tagging even
when the user had not enabled the musicbrainz plugin.
This PR replaces the direct instantiation with a lookup through the
metadata-source registry (get_metadata_source("musicbrainz")).
When the musicbrainz plugin is not loaded, both candidates and
item_candidates short-circuit and return empty. Acoustid
fingerprinting itself is unaffected — acoustid_id and
acoustid_fingerprint fields are still populated as before.
Side-effect fix
The previous cached_property mb = MusicBrainzPlugin() pattern
created a second instance outside the plugin registry. This bypassed
any plugin that swaps the musicbrainz instance at runtime (e.g.
mbpseudo). Routing through get_metadata_source fixes this —
chroma now uses the same shared instance as the rest of beets.
Scope
This PR is intentionally scoped to the gating fix only. The richer
cross-reference routing (extracting Spotify/Discogs/etc. IDs from
MusicBrainz url-relations and dispatching to enabled external
plugins) is being developed separately in #6522.
nightly-ff9f93e6-ls266
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-ff9f93e6-ls266/index.html
LinuxServer Changes:
Full Changelog: nightly-c6409d2e-ls265...nightly-ff9f93e6-ls266
Remote Changes:
Type musicbrainz (#6329)
Add full type coverage to the MusicBrainz plugin
This PR introduces complete static typing for
beetsplug/musicbrainz.py, beetsplug/mbpseudo.py, and
beetsplug/_utils/musicbrainz.py, and enforces it via mypy strict
mode.
Key changes
New TypedDict schema in beetsplug/_utils/musicbrainz.py
A comprehensive set of TypedDict classes now models the full
MusicBrainz API response surface — Release, Recording, Track,
ReleaseGroup, Artist, ArtistCredit, Work, and all relation
types. Public API methods (get_release, get_recording, etc.) now
return these typed shapes instead of the opaque JSONDict.
Key normalization: dash-to-underscore
The internal _normalize_data method (previously _group_relations)
now also converts all hyphenated keys (e.g. artist-credit,
release-group, sort-name) to underscored equivalents (e.g.
artist_credit, release_group, sort_name) at parse time. This makes
the data structure Python-idiomatic and is what allows the TypedDict
definitions to use clean attribute names. All downstream field accesses,
test fixtures, and JSON test resources are updated accordingly.
mypy strict mode enabled for the three affected modules via
setup.cfg.
Impact
- No behaviour change for end users — this is purely an internal
refactor. - Code reading the MusicBrainz response now has IDE completion and
type-checking support. - The normalization boundary is clearly established at
_normalize_data, so callers never see raw hyphenated keys. - Test fixtures and resource JSON files are updated to match the new
normalized shape.
2.9.0-ls324
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/2.9.0-ls324/index.html
LinuxServer Changes:
Full Changelog: 2.8.0-ls323...2.9.0-ls324
Remote Changes:
Updating PIP version of beets to 2.9.0