Commit graph

2785 commits

Author SHA1 Message Date
Šarūnas Nejus
06dd2738bb
Remove never used replacements paramater from item.destination 2025-05-04 12:23:25 +01:00
Šarūnas Nejus
52951bf719
Fix legalize_path types
Background
  The `_legalize_stage` function was causing issues with Mypy due to
  inconsistent type usage between the `path` and `extension` parameters.
  This inconsistency stemmed from the `fragment` parameter influencing the
  types of these variables.

Key issues
  1. `path` was defined as `str`, while `extension` was `bytes`.
  2. Depending on `fragment`, `extension` could be either `str` or `bytes`.
  3. `path` was sometimes converted to `bytes` within `_legalize_stage`.

Item.destination` method
  - The `fragment` parameter determined the output format:
    - `False`: Returned absolute path as bytes (default)
    - `True`: Returned path relative to library directory as str

Thus
  - Rename `fragment` parameter to `relative_to_libdir` for clarity
  - Ensure `Item.destination` returns `bytes` in all cases
  - Code expecting strings now converts the output to `str`
  - Use only `str` type in `_legalize_stage` and `_legalize_path`
    functions
  - These functions are no longer dependent on `relative_to_libdir`
2025-05-04 12:23:22 +01:00
Šarūnas Nejus
9acfa3c175
Remove arg_encoding 2025-04-21 12:41:57 +01:00
Šarūnas Nejus
179ed13e09
Say bye to util._fsencoding 2025-04-21 12:41:57 +01:00
Sebastian Mohr
b4a634a443
Allow to pickle db models by removing the current connection. (#5641)
## Description

This might be a quick one, depending on how you feel about it... It
allows you to pickle DB model objects. I don't think this is used
directly in Beets, but it might be useful in general. For instance, we
encountered an issue where we wanted to quickly pickle an Item or Album.
This sometimes worked and other times failed, which seemed quite
inconsistent.

Some DB model methods and properties have the side effect of attaching
an SQLite connection to self (._db), which prevents serialization. The
fix is quite straightforward, so I thought we might want to integrate
this into beets directly.

## To Do

- [x] Changelog
- [x] Tests
2025-04-15 11:43:36 +02:00
Šarūnas Nejus
d1d681c1ff
mbsync: support other data sources 2025-04-14 02:28:43 +01:00
Šarūnas Nejus
4c1f217ce0
missing: support non-musicbrainz data sources 2025-04-14 02:28:42 +01:00
Skia
225c21b90f plugins/thumbnails: fix FFI with GIO on s390x
Using the correct function signature for g_file_new_for_path fixes the
tests on s390x.
I do not have the full story on why this failed consistently only on
s390x, but I guess the big endian might have something to play with
this.

Here is how the tests were failing:
```
169s ___________________________ ThumbnailsTest.test_uri ____________________________
169s
169s self = <test.plugins.test_thumbnails.ThumbnailsTest testMethod=test_uri>
169s
169s     def test_uri(self):
169s         gio = GioURI()
169s         if not gio.available:
169s             self.skipTest("GIO library not found")
169s
169s >       assert gio.uri("/foo") == "file:///"  # silent fail
169s E       AssertionError: assert '' == 'file:///'
169s E
169s E         - file:///
169s
169s test/plugins/test_thumbnails.py:268: AssertionError
```
You can see a full log here [1] and a history of consistent failure
here [2]. Both links are bound to expire at some point, sorry future
archeologist 🤷.

[1]: https://autopkgtest.ubuntu.com/results/autopkgtest-plucky/plucky/s390x/b/beets/20250403_162414_5d1da@/log.gz#S5
[2]: https://autopkgtest.ubuntu.com/packages/beets/plucky/s390x
2025-04-14 02:19:10 +01:00
J0J0 Todos
eb83491788 lastgenre: Fix "original fallback" conditions
This was not thought through clearly before. It now behaves as follows
which I suppose is least surprising to a user:

- force is on, keep_existing is on, but the whitelist is DISABLED
- no stage found anything on last.fm
- fall back to the original genre

If in this example the whitelist would be ENABLED, the behaviour
changes: Only if the existing genre passes the whitelist test the
original is kept.
2025-04-09 22:52:07 +02:00
J0J0 Todos
de9020055d lastgenre: Add test ensuring next stage is hit
If no album was found the next stage (artist) should be entered, the
original genre kicked out (not whitelisted) and artist genre accepted.
The log message is slightly misleading since it tried to keep existing
genres but they were not whitelisted, thus kicked out. This is expected.
2025-04-09 22:52:07 +02:00
J0J0 Todos
e20cf7f20b lastgenre: Rework combine, stringify, count reduction
- Rename method from _combine_genres() to _combine_resolve_and_log() to
  make clear that it not only combines new and old genres but also
  resolves them (which in this plugin's wording means "do the magic" of
  canonicalizationm, whitelist checking and reducing to a configured
  genre count).

- Clarify in _resolve docstring that a possible outcome might be all
  genres being removed.

- Add an additional log message telling which existing genres are taken
  into account BEFORE "the magic happens".

- Rename _to_delimited_genre_string() to _format_and_stringify()

- Move count reduction logic to _resolve_genres()

- Fix and rename a test
2025-04-09 22:52:07 +02:00
Jack Wilsdon
5c1817c780 Fix IMBackend#compare on ImageMagick 7.1.1-44 2025-02-27 01:03:16 +00:00
Šarūnas Nejus
b713d72612
translations: use a more distinctive separator
I found that the translator would sometimes replace the pipe character
with another symbol (maybe it got confused thinking the character is
part of the text?).

Added spaces around the pipe to make it more clear that it's definitely
the separator.
2025-02-20 03:47:04 +00:00
Šarūnas Nejus
43032f7bc7
translations: make sure we do not re-translate 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
7893766e4c
Improve flags structure and add tests 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
c95156adcd
Refactor writing rest files 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
d7201062a8
Resurrect translation functionality 2025-02-20 03:47:04 +00:00
Sebastian Mohr
918fd863f3
Merge branch 'master' into importer-typehints-and-refactor 2025-02-17 23:02:00 +01:00
J0J0 Todos
2286511ebe
Merge branch 'master' into smartplaylist-attr-url-encoding 2025-02-17 21:16:09 +01:00
Sebastian Mohr
b46dbb93f7
Merge branch 'master' into importer-typehints-and-refactor 2025-02-08 17:43:31 +01:00
Šarūnas Nejus
5685cf43cf
Align musica lyrics source expected lyrics with whats returned 2025-02-08 09:09:24 +00:00
valrus
99d2da66dc use actual value of matcher, not typo'd one 2025-02-03 19:32:27 -08:00
valrus
f520790713 s/macthin/matching/ 2025-02-03 19:32:27 -08:00
Sebastian Mohr
ed92f9b997 Do not skip tests in ci.
The return type of the stage decorator should in theory be `T|None`
but the return of task types is not consistent in its usage. Would need
some bigger changes for which I'm not ready at the moment.
2025-02-03 11:37:33 +01:00
Sebastian Mohr
04aa1b8ddb Added last missing typehints in importer and fixed some typehint issues
in util. Also run poe format
2025-02-01 15:52:11 +01:00
Sebastian Mohr
c81a2c9b18 Using 3.9 unions instead of new 3.10 style unions for typehints 2025-02-01 13:25:25 +01:00
Max Goltzsche
5d96509cfe
smartplaylist: change encoding of additional field
URL-encode additional item `fields` within generated EXTM3U playlists instead of JSON-encoding them.
This is because JSON-encoding additional fields/attributes made it difficult to parse the `EXTINF` line but using URL-encoding for these values makes parsing easy (because URL-encoded values cannot contain commas, quotation marks and spaces).

I introduced the generation of additional EXTM3U item fields earlier this year and I want to correct that now.

**Design/definition background:**
Unfortunately, I didn't find a clear definition of how additional playlist item attributes should be encoded - apparently there is none.
Given that item URIs within an M3U playlist can be URL-encoded already, defining the values of additional attributes to be URL-encoded is consistent design.
I didn't find examples of additional EXTM3U item attributes in the web where the attribute value contains a comma, space or quotation mark but examples that specified numeric IDs and URLs as attribute values.
Because the URL attribute examples I found didn't contain URL-encoded characters and because it is more readable and unproblematic for parsing, I've let the attribute URL encoding treat `:` and `/` as safe characters.

**Breaking change:**
While this is a breaking change in theory, in practice it is not since afaik all integrations of the smartplaylist plugin's additional EXTM3U item attribute generation feature (beets-webm3u) work with simple attribute values such as the item ID (numeric) whose formatting/encoding is not affected when changing from JSON to URL-encoding.
In other words the change is backward-compatible with the beets-webm3u plugin (which I'll adjust correspondingly after this beets PR was merged).
2025-02-01 01:14:27 +01:00
Šarūnas Nejus
7389f241f4
Do not search for Various Artists, split titles by ' / ' 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
39c479fcab
Google: add support for dainuzodziai.lt 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
858c13558c
Xfail Songlyrics source 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
734bcc28a8
Append source to the lyrics 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
bdc564a573
Tidy up handling of backends 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
70554640e5
Create Html class for cleaning up the html text
Additionally, improve HTML pre-processing:

* Ensure a new line between blocks of lyrics text from letras.mus.br.
* Parse a missing last block of lyrics text from lacocinelle.net.
* Parse a missing last block of lyrics text from paroles.net.
* Fix encoding issues with AZLyrics by setting response encoding to
  None, allowing `requests` to handle it.
2025-01-27 10:56:52 +00:00
Šarūnas Nejus
c5c4138d66
Google: Refactor and improve
* Type the response data that Google Custom Search API return.
* Exclude some 'letras.mus.br' pages that do not contain lyric.
* Exclude results from Musixmatch as we cannot access their pages.
* Improve parsing of the URL title:
  - Handle long URL titles that get truncated (end with ellipsis) for
    long searches
  - Remove domains starting with 'www'
  - Parse the title AND the artist. Previously this would only parse the
    title, and fetch lyrics even when the artist did not match.
* Remove now redundant credits cleanup and checks for valid lyrics.
2025-01-27 10:56:52 +00:00
Šarūnas Nejus
12c5eaae5e
Unite Genius, Tekstowo and Google backends under the same interface 2025-01-27 10:56:52 +00:00
Šarūnas Nejus
745c5eb9f0
Genius: refactor and simplify 2025-01-27 10:56:52 +00:00
Šarūnas Nejus
f94d2767f9
Use a single slug implementation
Tidy up 'Google.is_page_candidate' method and remove 'Google.sluggify'
method which was a duplicate of 'slug'.

Since 'GeniusFetchTest' only tested whether the artist name is cleaned
up (the rest of the functionality is patched), remove it and move its
test cases to the 'test_slug' test.
2025-01-27 08:50:50 +00:00
Šarūnas Nejus
dd9f178fff
Do not try to strip cruft from the parsed lyrics text.
Having removed it I fuond that only the Genius lyrics changed: it had en
extra new line. Thus I defined a function 'collapse_newlines' which now
gets called for the Genius lyrics.
2025-01-27 08:50:50 +00:00
Šarūnas Nejus
7c2fb31136
Leave a single chef in the kitchen 2025-01-27 08:50:50 +00:00
Šarūnas Nejus
cb29605bfd
Include class name in the log messages 2025-01-27 08:50:50 +00:00
Šarūnas Nejus
283c513c72
Centralise request error handling 2025-01-27 08:50:49 +00:00
Šarūnas Nejus
2ff57505d8
Apply dist_thresh to Genius and Google backends
This commit introduces a distance threshold mechanism for the Genius and
Google backends.

- Create a new `SearchBackend` base class with a method `check_match`
  that performs checking.
- Start using undocumented `dist_thresh` configuration option for good,
  and mention it in the docs. This controls the maximum allowable
  distance for matching artist and title names.

These changes aim to improve the accuracy of lyrics matching, especially
when there are slight variations in artist or title names, see #4791.
2025-01-27 08:50:48 +00:00
J0J0 Todos
5d9d8840ae Fix a lastgenre test 2025-01-22 18:20:41 +01:00
J0J0 Todos
261379f395 Add test_get_genre case proving no-force keeps any
because _get_existing_genres does not rely on configured separator.
2025-01-22 18:07:43 +01:00
J0J0 Todos
34b9021772 Fix test_get_genrer - configure first
otherwise self.whitelist is "set up" before the test cases config is
set.
2025-01-22 18:07:43 +01:00
J0J0 Todos
1219b43af4 Fix a test: no-force always early returns 2025-01-21 17:48:21 +01:00
J0J0 Todos
d703a7f712 Fix tests for log-label changes 2025-01-21 17:14:15 +01:00
J0J0 Todos
6e3f5b3127 Fix type hints, Refactor existing genres method
- Rename method _dedup_genre, since it's only used for
  finalizing/polishing existing genres.
- Return separator-delimited string already.
- Decide on not passing "separator" to methods, it's a config
  setting available throughout the plugin. Assign to variable where
  useful for readability though.
- In the force branch, remove re-assigning keep_genres to empty list.
- Fix a test. Existing genres are "polished" now, which means:
  configured title_case is applied.
- Fix/add type hints on all touched and new methods
2025-01-21 17:04:03 +01:00
J0J0 Todos
6cd000750a _resolve_genre as list tests, add test_to_delimited_string
- Adapt tests to _resolve_genres returning a list with not yet formatted genres.
- Rename and adapt test_count -> test_to_delimited_string. Note that the
  new function does not apply whitelist, prefer anything. It just cuts
  to count and formats!
2025-01-21 17:04:02 +01:00
J0J0 Todos
dd3a74ca4d Fix lastgenre limit to count test
- No idea where a missing separator (which is default) could
  happen...just set it explicitely.
- Since we now refactored fetch_genre to returning a list we can add
  mock multiple fetched gernes easier.
2025-01-21 17:04:02 +01:00