Releases: linuxserver/docker-beets
nightly-a35bb419-ls274
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-a35bb419-ls274/index.html
LinuxServer Changes:
Full Changelog: nightly-7edf27bf-ls273...nightly-a35bb419-ls274
Remote Changes:
Regression: #6547 main needs default (#6571)
Fix regression error from #6547.
Default value None is needed for main function, was removed
accidentally.
nightly-e5504825-ls273
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-e5504825-ls273/index.html
LinuxServer Changes:
No changes
Remote Changes:
Replace old cover art instead of creating suffixed new entries / fetchart (#6554)
Summary
- Fix duplicate album art files (
cover.2.jpg,cover.3.jpg, ...)
accumulating when re-importing albums with the fetchart plugin enabled. ImportTask.remove_duplicatesnow operates at the album level and
explicitly deletes album art files from disk when removing duplicate
albums during import.Album.set_artnow unconditionally removes old art and any existing
file at the destination, instead of appending a numeric suffix via
unique_path. This matches the method's documented behavior of
"replacing any existing art".SingletonImportTaskgets its ownremove_duplicatesoverride
preserving the original item-level behavior, sincefind_duplicates
returns items (not albums) for singletons.
Root cause
Two issues contributed to the bug:
1. remove_duplicates never deleted album art files.
When a user imports a duplicate album and chooses "Remove old",
remove_duplicates iterated over items and called item.remove(). When
the last item was removed, this cascaded to
Album.remove(delete=False), which skipped art deletion due to
delete=False. The old cover.jpg remained on disk as an orphan.
2. set_art created unique paths instead of replacing.
set_art only removed the old art file when oldart == artdest (exact
byte equality). When oldart was None (new album, no inherited
artpath) or pointed to a different path (e.g. different extension), the
existing file was left in place and unique_path generated
cover.2.jpg.
Fixes #6205
nightly-7edf27bf-ls273
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-7edf27bf-ls273/index.html
LinuxServer Changes:
Full Changelog: nightly-406db7cc-ls272...nightly-7edf27bf-ls273
Remote Changes:
Handle TEXT path values when migrating to relative paths (#6562)
Handle TEXT paths in library path migration
Fixes a crash during library migration for users who manually edited
their beets SQLite database and stored item or album-art paths as TEXT
instead of BLOB/bytes.
Changes
migrations.py: The relative-to-portable path migration now skips
NULLrows (avoids unnecessary work) and wraps each path value with
os.fsencode()before passing it tonormalize_path_for_db(). This
ensuresTEXTpaths are coerced tobytesbefore the update, matching
the expected storage format.test_migrations.py: The migration test now inserts both a
bytespath and astrpath, asserting both are correctly migrated to
relativebytesposix paths.
Impact
Low-risk, targeted fix. No changes to the happy path for users with
well-formed databases — os.fsencode() on bytes is a no-op, so
existing behaviour is preserved.
Fixes: #6561
2.10.0-ls326
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/2.10.0-ls326/index.html
LinuxServer Changes:
Full Changelog: 2.9.0-ls325...2.10.0-ls326
Remote Changes:
Updating PIP version of beets to 2.10.0
nightly-c9cee0d1-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-c9cee0d1-ls272/index.html
LinuxServer Changes:
No changes
Remote Changes:
fromfilename: Support 'track' prefix when parsing track number (#6557)
fromfilename: Support "track" prefix in track number parsing
The fromfilename plugin's filename-matching regex is extended to
recognise filenames like track01.m4a or track 2.m4a, where a literal
"track" prefix precedes the track number.
nightly-b13a4fa7-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-b13a4fa7-ls272/index.html
LinuxServer Changes:
No changes
Remote Changes:
Tidal Metadata Plugin (#6520)
Description
This PR introduces tidal as metadatasource. It add both an minimal api
layer and the typical metadata source plugin capabilities.
Details
The implementation provides a small API layer consisting of TidalAPI
for high-level album and track fetching, and TidalSession which
extends requests.Session with token authentication, automatic rate
limiting (~4 req/s via RateLimitAdapter), and pagination resolution
following the JSON:API spec.
Authentication is handled through an OAuth2 PKCE flow accessible via
beet tidal --auth, with automatic token refresh when the access token
expires.
Metadata parsing handles Tidal's JSON:API response format, extracting
album and track information including ISO 8601 duration conversion,
artist relationships, and copyright/label data.
Input wanted
The API layer currently lacks comprehensive test coverage. Setting up
proper tests would require either mocking all outgoing requests or
creating a dedicated test token (which necessitates an account and might
require read/write to github secrets).
Are we comfortable with the current approach of unit testing the plugin
itself while mocking all requests?
TODOs
- Documentation
-
candidateanditem_candidateslookup - It should be possible to optimize batched lookups
- Add tests for candidates and item_candidates
- Implement batching for more than 20 filters
Refs
thanks to @jcjordyn130 for his initial implementations in #5637 and
#4641
nightly-61a4ba9a-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-61a4ba9a-ls272/index.html
LinuxServer Changes:
No changes
Remote Changes:
smartplaylist: Enrich original "Creating output" with track counts; CLI output overhaul (#6493)
Description
- The per-playlist summary now includes a track count (
Creating playlist X: N tracks.) atINFOlevel. - The
--pretendflag produces the same output but reports "N
playlists would be updated" instead of "N playlists updated". - Per-track details are shown only in
DEBUGlog level. - The
--formatoption allows customizing the track line format. - The
__apply_opts_to_confighelper was removed and instead defaults
provided when defining CLI options - Fix a tiny bug: Deduplicate playlist entries by URI and only increment
matched counts when a new entry is added. - The
--pretend-pathsoption was removed since now the per-track log
format is configurable anyway.
nightly-5f6b2d35-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-5f6b2d35-ls272/index.html
LinuxServer Changes:
Full Changelog: nightly-06f5e14b-ls271...nightly-5f6b2d35-ls272
Remote Changes:
Increment version to 2.10.0
nightly-44ffbdf6-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-44ffbdf6-ls272/index.html
LinuxServer Changes:
No changes
Remote Changes:
Remove archive on import during move mode (#6551)
Fixes #1663.
This modifies the cleanup method on the ArchiveImportTask to remove
the original archive file on successful import when move: yes.
I decided to do this such that partial imports do not destructively
remove the archive. Perhaps this would be better as a configuration
option, but I think that may go beyond the scope for this initial
feature.
I am unsure whether my method for "complete import" is strictly correct,
I reasoned that we would check that all files had been moved out, but
surely this data exists more concretely somewhere. Let me know if this
should be polished, or there's more nuance I'm not seeing!
Additionally, I added unit tests for this behavior under the old test
framework since existing helpers are present for the archive backend
setup. This way we minimize the diff and maximize probability that my
test is behaving correctly. I will gladly port this entire archive test
section to pytest in a future PR if this is a dealbreaker.
nightly-406db7cc-ls272
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-406db7cc-ls272/index.html
LinuxServer Changes:
No changes
Remote Changes:
Filter out zero penalty for cli display (#6556)
Fixes #6555
generic_penalty_keys at beets/autotag/distance.py:145 returns all
keys in _penalties without filtering for non-zero values.
I think this is a regression.