Commit Graph

4449 Commits

Author SHA1 Message Date
Šarūnas Nejus
f5a949fcf8 modify: fix selecting objects 2026-08-18 19:50:02 +01:00
Šarūnas Nejus
10b176c866 ipfs: fix play command 2026-08-18 10:46:54 +01:00
Šarūnas Nejus
0c05551251 Update events docs 2026-08-18 10:46:33 +01:00
Šarūnas Nejus
cf385e7614 Merge branch 'master' into fix/skip-empty-metadata-search 2026-08-17 09:35:05 +01:00
Šarūnas Nejus
9b16f67af1 Remove bluelet in favor of using asyncio in bpd plugin 2026-08-17 05:05:21 +01:00
Sanjay Santhanam
127a2d8914 docs: keep changelog entry under unreleased 2026-08-15 16:59:28 -07:00
Henry
b7993d19ac fix(discogs): retry malformed search responses #6912 2026-08-15 09:53:26 -07:00
Cohen Karnell
d97d78f830 Fix KeyError in Deezer track conversion when artist is missing
_get_track resolved the artist with track_data.get('contributors', [track_data['artist']]),
whose default is evaluated eagerly, so track_data['artist'] raises KeyError whenever the
artist key is absent, even when contributors is present. Guard the fallback the same way
album_for_id already does. Fixes #4339.
2026-08-14 12:02:07 -04:00
Sebastian Mohr
54b5d41acd Merge branch 'master' into fix/skip-empty-metadata-search 2026-08-12 12:28:20 +02:00
Trey Turner
afd07ce5d3 fix(discogs): retry malformed search responses 2026-08-11 16:04:08 -05:00
Alok Saboo
abacc3aad0 Merge branch 'master' into upgrade2 2026-08-11 08:19:15 -04:00
NoDancing
f6b7e1f761 tidal: Normalize copyright text into a concise label name
_parse_label() used to store Tidal's raw copyright info as the label
name. Add _normalize_label(), a helper that strips leading markers,
years, legal entities, and boilerplate clauses.

Fixes #6796
2026-08-11 00:39:31 +01:00
Sanjay Santhanam
4596bd21d2 docs: reformat changelog entry with docstrfmt 2026-08-06 10:06:50 -07:00
Sanjay Santhanam
0ab54bd44e Simplify empty-search comment and shorten changelog entry 2026-08-06 10:04:57 -07:00
Sanjay Santhanam
6fff0532d6 docs: scope changelog entry to SearchApiMetadataSourcePlugin plugins 2026-08-06 10:04:57 -07:00
Sanjay Santhanam
58bd7ede4c fix: skip metadata source search when query and filters are empty
Items with no artist or title tags produce a search with an empty query
and no filters. The request was still sent to the metadata source API,
and MusicBrainz answers it with a 400 Bad Request, which was logged with
a traceback once per affected file during an import.

Return no candidates instead of issuing a request that cannot match
anything.
2026-08-06 10:04:57 -07:00
Alok Saboo
1ddc95f7a6 address copilot comments 2026-08-05 09:05:51 -04:00
Alok Saboo
cbe300f7ef Merge branch 'master' into upgrade2 2026-08-05 08:57:42 -04:00
Alok Saboo
c19b6b42d8 add interactive upgrade option 2026-08-05 08:47:26 -04:00
Šarūnas Nejus
03045b80e9 Merge branch 'master' into master 2026-08-04 16:45:30 +01:00
Vincent Gao
2fe5dc7a0e Fix storing flex media fields during update 2026-08-04 08:29:44 +02:00
Sebastian Cao
c7a842941d Fix queries for flexible attributes with uppercase names 2026-08-03 20:31:12 +08:00
Mohsin Hirani
205ededdce docs: move changelog entry to Unreleased section 2026-08-02 13:49:13 -04:00
Mohsin Hirani
503830cacb docs: apply docstrfmt formatting to editor section 2026-08-02 13:45:06 -04:00
Mohsin Hirani
a849afb4c1 docs: add editor config option to configuration reference 2026-08-02 13:36:14 -04:00
Mohsin Hirani
441d8f5a96 docs: apply docstrfmt formatting to changelog 2026-08-02 13:35:16 -04:00
Mohsin Hirani
1e88e48e78 docs: add changelog entry for editor config option 2026-08-02 13:34:52 -04:00
Piotr Szpetkowski
681f27feb6 fix(deezer): use free text for singleton searches
Singleton searches built the query as `<title> artist:"<artist>"`. Deezer
discards unquoted free text as soon as a query contains any field:"value"
filter, so that was evaluated as `artist:"<artist>"` alone - every track by
the artist, in Deezer's own relevance order, truncated to `search_limit`
(default 5). Substituting nonsense for the title returns a byte-identical
result set. For any artist with more releases than that window, the track
being imported was simply never among the candidates offered.

Filtering on the title as well (`track:"<title>" artist:"<artist>"`) is not
a fix: `artist:` matches loosely enough to return unrelated artists, so the
two filters can intersect to nothing even for a correctly tagged file.
`track:"Get Lucky" artist:"Daft Punk"` returns zero results, while the plain
free text `Get Lucky Daft Punk` returns the right track first.

Measured over 12 tracks at the default `search_limit`, counting the wanted
track appearing anywhere in the results:

  `<title> artist:"..."`              6/12, mean rank 1.50
  `track:"..." artist:"..."`          7/12, mean rank 1.00
  free text                          10/12, mean rank 1.00

Album searches are unchanged; `album:"<name>"` has no equivalent problem.

Adds test/plugins/test_deezer.py, which did not exist.
2026-07-30 21:18:59 +02:00
Alok Saboo
7a49cc4882 Merge branch 'master' into upgrade 2026-07-30 09:11:46 -04:00
Sebastian Mohr
f421079eaf Moved changelog entry into unreleased section. 2026-07-30 13:05:31 +02:00
Sai Asish Y
9667d0fcf7 lyrics: treat missing lyrics body as empty text instead of crashing
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
2026-07-30 13:04:58 +02:00
Sebastian Mohr
b5019fb180 Moved changelog entry into unreleased section. 2026-07-30 12:58:31 +02:00
chuenchen309
8518a13f3d docs: reflow changelog entry to satisfy docstrfmt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 12:58:16 +02:00
chuenchen309
69772cdc6d fix(autotag): "featuring" pattern in string_dist matches mid-word "ft"
SD_PATTERNS' featuring/feat/ft regex has no word boundary before the
alternation, so it matches "ft" embedded in ordinary words like
"draft", "left", "gift", "craft" and treats everything after it as a
low-weight suffix. "Draft Beer" vs. "Draft Whiskey" scores 0.05
(near-identical) instead of correctly registering as very different.
2026-07-30 12:58:16 +02:00
Sebastian Mohr
5d2d3993a7 Moved changelog entry to the current unreleased section. 2026-07-30 12:53:21 +02:00
Qalipso
a8439e2d07 Fix unique_path counter for names ending in two or more digits
unique_path parses a trailing counter so it can continue from it, but the
pattern is `\.(\d)+$` -- a single-digit group repeated, not a multi-digit
group. group(1) is therefore the last digit only, and the counter restarts
from it:

    track.10.mp3 -> track.1.mp3   (expected track.11.mp3)
    track.12.mp3 -> track.3.mp3
    track.123.mp3 -> track.4.mp3

The returned path still does not exist, so nothing is overwritten, but the
new name sorts before the file it was derived from, and the scan restarts
from a low number when the neighbours are already taken.

Use `\.(\d+)$`. Existing coverage only exercised a single-digit counter
(`x.1.mp3`), which is why this held.
2026-07-30 12:52:03 +02:00
TowyTowy
348b87dd3e Normalise reversed date ranges instead of crashing
A date range query whose start lies after its end, such as
`beet ls added:2024..2020`, crashed with an uncaught ValueError
raised by DateInterval's endpoint-order check:

    ValueError: start date 2024-01-01 00:00:00 is not before end date
    2021-01-01 00:00:00

Only InvalidQueryArgumentValueError is converted into a user-facing
InvalidQueryError by Library._get_results, so the plain ValueError
escaped all the way up as a traceback.

Rather than reporting an error, accept the range and swap its two
endpoints, so `added:2024..2020` means the same as `added:2020..2024`.

The swap lives in `DateInterval.from_periods`, which is the only place
where the two user-supplied endpoints are still available as `Period`
objects. Swapping further down, in `DateInterval.__init__`, would swap
the already-derived datetimes, and those are derived asymmetrically:
the start contributes `Period.date` while the end contributes
`Period.open_right_endpoint()`. For `2024..2020` that would yield
[2021-01-01, 2024-01-01), which excludes both 2020 and 2024 -- not the
interval the user asked for. Swapping the periods first yields
[2020-01-01, 2025-01-01), which is exactly `2020..2024`.

`DateInterval.__init__` keeps raising ValueError, since it remains the
invariant guard for callers constructing an interval from datetimes
directly, where there is no notion of the order the user typed.

The swap only triggers when the interval would otherwise be empty, so
partially overlapping mixed-precision ranges that are valid today, such
as `2000-06..2000`, are unaffected. Genuinely malformed input such as
`added:notadate` still raises InvalidQueryArgumentValueError from
`Period.parse` as before.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-30 12:36:04 +02:00
Alok Saboo
c44f517edf Merge branch 'master' into upgrade 2026-07-29 12:16:14 -04:00
snejus
b795229994 Increment version to 2.13.1 2026-07-29 10:44:53 +00:00
Sebastian Mohr
0234e38f78 Removed unused doc sections. Preparing for hotfix. 2026-07-29 12:05:52 +02:00
Sebastian Mohr
87a07553fd Changelog entry 2026-07-29 12:05:52 +02:00
Alok Saboo
9a5d00ceda update changelog 2026-07-28 19:52:45 -04:00
Alok Saboo
6fb5e62e40 Resolve upgrade target per-album when duplicates span multiple albums 2026-07-28 19:51:30 -04:00
Alok Saboo
789c13e4f7 Add bitrate-based upgrade duplicate_action 2026-07-28 19:51:30 -04:00
Alok Saboo
a486f92693 reformat beatport/bpsync docs 2026-07-28 15:28:32 -04:00
snejus
48d44d15ed Increment version to 2.13.0 2026-07-27 19:07:11 +00:00
Alok Saboo
d392729b64 Merge branch 'master' into spotify 2026-07-24 10:14:31 -04:00
Alok Saboo
3909065ad5 Add changelog 2026-07-24 09:57:44 -04:00
Alok Saboo
801fe8f6d9 improve 503 error handling 2026-07-24 09:56:24 -04:00
Sebastian Cao
d3f36f678b docs: mention terminal emulator for Windows (#6866)
## Description

Fixes #2848.

The classic Windows console (`cmd.exe`) doesn't render beets' output
(special characters, colors) correctly. Added a note in the Windows
installation guide pointing people at a terminal emulator like Windows
Terminal or cmder, or a Unix-like shell such as Git Bash.
2026-07-23 20:02:25 +02:00