Commit graph

11897 commits

Author SHA1 Message Date
Šarūnas Nejus
c9702a4c24
windows: do not skip test when hiding file fails 2024-07-18 12:26:17 +01:00
Šarūnas Nejus
370ae43634
art: assume local backend is available 2024-07-18 12:26:17 +01:00
Šarūnas Nejus
31fba03f26
lyrics: assume bs4 is always available 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
6f7174f844
importer: always test .rar archives
unrar is actually not needed here.
2024-07-18 12:26:16 +01:00
Šarūnas Nejus
ec948978b0
ui: always run tests that need bash 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
2a1acb3ba2
artresizer: always run IMBackend tests 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
1d6781d06a
artresizer: always run PILBackend tests 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
06cf9c4ea8
replaygain: separate out r128 tests into a mixin to clarify which backends are tested 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
d716475f3d
Do not skip any replaygain tests
This means that the dependencies must be installed for the tests to
work. Otherwise, why do we have these tests that aren't being run?
2024-07-18 12:26:16 +01:00
Šarūnas Nejus
c2f5a6c19c
Replace has_program with shutil.which 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
c71aceb184
Enable LRCLibIntegrationTest 2024-07-18 12:26:16 +01:00
Šarūnas Nejus
0089fb430a
Enable EmbedartCliTest 2024-07-18 12:26:10 +01:00
Šarūnas Nejus
1163645604
Make sure tests do not leave any temp files behind (#5345)
Fixes #5229, is part of #5361 and relates to #5285.

I have to admit thsi was a fairly tough task - I initially assumed that
the problem lies
with how the tests are setup, and that we're probably missing some
`teardown_beets` calls
here and there.

Unfortunately, it was not so simple. I came across several issues that
gave rise to
leftover temporary files:

1. `fetchart`, `artresizer` and `play` handling of temporary files.
These plugins created
isolated temporary files outside of the directories that tests clean up.
You will find
I added a couple of functions (namely `get_module_tempdir`) that force
these plugins to
create files in directories determined by their module names. This way
we can clean up
   after them using the new `CleanupModulesMixin`.

2. Tests that ran temporary directories setup twice, running
`_common.TestCase.setUp` and
`test.helper.TestHelper.setup_beets`. Both of these ran `self.temp_dir =
mkdtemp()`,
therefore the directories created by the initial setup persisted since
those have been
overridden and thus unreachable in the teardown. Here, I removed the
`setUp` calls, see

   - `test/plugins/test_embedart.py`
   - `test/test_importer.py`
   - and `test/test_plugins.py` where `setup_beets` was called twice

3. `test/test_config_command.py` attempted to manage the temporary
directory by itself,
where I found that `tearDown` failed to remove the directory for four
tests. Could not
figure out the cause, and found that delegating this task to
`TestHelper` fixed the
   issue.

4. Mediafile fixture removal depended on calling
`remove_mediafile_fixtures` method, which
`test/plugins/test_zero.py` failed to do. I made the fixtures to be
created within the
same `temp_dir` directory that gets removed in the teardown, so now they
are taken care
   of automatically.

In summary, see the test modules that left files behind:

```
Temp files created by test/__init__.py
Temp files created by test/plugins/__init__.py
Temp files created by test/plugins/lyrics_download_samples.py
Temp files created by test/plugins/test_acousticbrainz.py
Temp files created by test/plugins/test_advancedrewrite.py
Temp files created by test/plugins/test_albumtypes.py
Temp files created by test/plugins/test_art.py
	/tmp/tmp11nicahe.jpg
	/tmp/tmp1bjmodum.png
	/tmp/tmped7nhls4.jpg
	/tmp/tmpflnzr9wz.jpg
	/tmp/tmpjngkauqs.png
	/tmp/tmpkzy9mn6t.jpg
	/tmp/tmpph_wmuea.jpg
	/tmp/tmps6gk58i_.jpg
	/tmp/tmpz2eji_o4.jpg
Temp files created by test/plugins/test_aura.py
Temp files created by test/plugins/test_bareasc.py
	/tmp/tmphl3kzhug
	/tmp/tmpnh2q6v02
	/tmp/tmpppw5qrhz
Temp files created by test/plugins/test_beatport.py
Temp files created by test/plugins/test_bucket.py
Temp files created by test/plugins/test_convert.py
Temp files created by test/plugins/test_discogs.py
Temp files created by test/plugins/test_edit.py
Temp files created by test/plugins/test_embedart.py
	/tmp/tmp1ayvqzhx
	/tmp/tmp58k6mdfx.jpg
	/tmp/tmp64c2lqiv
	/tmp/tmp6nar4kr5
	/tmp/tmp6u0d5dex
	/tmp/tmpacoq7w_f
	/tmp/tmpajnr_sxr
	/tmp/tmpasj16beh
	/tmp/tmpboyaixb5
	/tmp/tmpcrmcyt5r
	/tmp/tmpdomje5g3
	/tmp/tmplu3o6t6g
	/tmp/tmpns_xvkns
	/tmp/tmpo87o1h6o.jpg
	/tmp/tmpqem39h_j
	/tmp/tmprlzm18pb
	/tmp/tmpt22v4u6x
	/tmp/tmptp3rxdgv
Temp files created by test/plugins/test_embyupdate.py
Temp files created by test/plugins/test_export.py
Temp files created by test/plugins/test_fetchart.py
Temp files created by test/plugins/test_filefilter.py
Temp files created by test/plugins/test_ftintitle.py
Temp files created by test/plugins/test_hook.py
Temp files created by test/plugins/test_ihate.py
Temp files created by test/plugins/test_importadded.py
Temp files created by test/plugins/test_importfeeds.py
Temp files created by test/plugins/test_info.py
Temp files created by test/plugins/test_ipfs.py
Temp files created by test/plugins/test_keyfinder.py
Temp files created by test/plugins/test_lastgenre.py
Temp files created by test/plugins/test_limit.py
Temp files created by test/plugins/test_lyrics.py
Temp files created by test/plugins/test_mbsubmit.py
Temp files created by test/plugins/test_mbsync.py
Temp files created by test/plugins/test_mpdstats.py
Temp files created by test/plugins/test_parentwork.py
Temp files created by test/plugins/test_permissions.py
Temp files created by test/plugins/test_player.py
Temp files created by test/plugins/test_playlist.py
Temp files created by test/plugins/test_play.py
	/tmp/tmp6ohknmve.m3u
	/tmp/tmp8rw2z_j4.m3u
	/tmp/tmp9vi27ypx.m3u
	/tmp/tmpa_s66jh8.m3u
	/tmp/tmpb7h3cn3n.m3u
	/tmp/tmpexbmqvry.m3u
	/tmp/tmpinbqrt80.m3u
	/tmp/tmpql02hax5.m3u
	/tmp/tmpvbdzprsf.m3u
	/tmp/tmpzipim36x.m3u
Temp files created by test/plugins/test_plexupdate.py
Temp files created by test/plugins/test_plugin_mediafield.py
Temp files created by test/plugins/test_random.py
Temp files created by test/plugins/test_replaygain.py
Temp files created by test/plugins/test_smartplaylist.py
Temp files created by test/plugins/test_spotify.py
Temp files created by test/plugins/test_subsonicupdate.py
Temp files created by test/plugins/test_the.py
Temp files created by test/plugins/test_thumbnails.py
Temp files created by test/plugins/test_types_plugin.py
Temp files created by test/plugins/test_web.py
Temp files created by test/plugins/test_zero.py
	/tmp/tmp3ub9xmzy
Temp files created by test/rsrc/beetsplug/test.py
Temp files created by test/rsrc/convert_stub.py
Temp files created by test/testall.py
Temp files created by test/test_art_resize.py
	/tmp/tmp3p7p60ih.jpg
	/tmp/tmp8exclgit.jpg
	/tmp/tmpkrrjsitl.jpg
	/tmp/tmpw6n8ee8e.jpg
	/tmp/tmpygws_0aw.jpg
Temp files created by test/test_autotag.py
Temp files created by test/test_config_command.py
	/tmp/tmp333f0r2j
	/tmp/tmphr356z5r
	/tmp/tmporp4rag2
	/tmp/tmpy7sjqdsw
Temp files created by test/test_datequery.py
Temp files created by test/test_dbcore.py
Temp files created by test/test_files.py
Temp files created by test/test_hidden.py
Temp files created by test/test_importer.py
	/tmp/tmp0m363gfb
	/tmp/tmp2n3i13mc
	/tmp/tmpxk3v304s
Temp files created by test/test_library.py
Temp files created by test/test_logging.py
Temp files created by test/test_m3ufile.py
Temp files created by test/test_mb.py
Temp files created by test/test_metasync.py
Temp files created by test/test_pipeline.py
Temp files created by test/test_plugins.py
	/tmp/tmp6pxhx67u
	/tmp/tmpb8pqi9ui
	/tmp/tmpcx_658g7
	/tmp/tmp_giqb9jz
	/tmp/tmpgm9xk94_
	/tmp/tmpk60l6bt3
	/tmp/tmpqoj4la68
	/tmp/tmptcdu20rp
	/tmp/tmpvr7k5shn
	/tmp/tmpwnfnzs91
Temp files created by test/test_query.py
Temp files created by test/test_sort.py
Temp files created by test/test_template.py
Temp files created by test/test_ui_commands.py
	/tmp/tmpns2u94w6
Temp files created by test/test_ui_importer.py
Temp files created by test/test_ui_init.py
Temp files created by test/test_ui.py
Temp files created by test/test_util.py
Temp files created by test/test_vfs.py
```

And that's what we have right now:

```
Temp files created by test/__init__.py
Temp files created by test/plugins/__init__.py
Temp files created by test/plugins/lyrics_download_samples.py
Temp files created by test/plugins/test_acousticbrainz.py
Temp files created by test/plugins/test_advancedrewrite.py
Temp files created by test/plugins/test_albumtypes.py
Temp files created by test/plugins/test_art.py
Temp files created by test/plugins/test_aura.py
Temp files created by test/plugins/test_bareasc.py
Temp files created by test/plugins/test_beatport.py
Temp files created by test/plugins/test_bucket.py
Temp files created by test/plugins/test_convert.py
Temp files created by test/plugins/test_discogs.py
Temp files created by test/plugins/test_edit.py
Temp files created by test/plugins/test_embedart.py
Temp files created by test/plugins/test_embyupdate.py
Temp files created by test/plugins/test_export.py
Temp files created by test/plugins/test_fetchart.py
Temp files created by test/plugins/test_filefilter.py
Temp files created by test/plugins/test_ftintitle.py
Temp files created by test/plugins/test_hook.py
Temp files created by test/plugins/test_ihate.py
Temp files created by test/plugins/test_importadded.py
Temp files created by test/plugins/test_importfeeds.py
Temp files created by test/plugins/test_info.py
Temp files created by test/plugins/test_ipfs.py
Temp files created by test/plugins/test_keyfinder.py
Temp files created by test/plugins/test_lastgenre.py
Temp files created by test/plugins/test_limit.py
Temp files created by test/plugins/test_lyrics.py
Temp files created by test/plugins/test_mbsubmit.py
Temp files created by test/plugins/test_mbsync.py
Temp files created by test/plugins/test_mpdstats.py
Temp files created by test/plugins/test_parentwork.py
Temp files created by test/plugins/test_permissions.py
Temp files created by test/plugins/test_player.py
Temp files created by test/plugins/test_playlist.py
Temp files created by test/plugins/test_play.py
Temp files created by test/plugins/test_plexupdate.py
Temp files created by test/plugins/test_plugin_mediafield.py
Temp files created by test/plugins/test_random.py
Temp files created by test/plugins/test_replaygain.py
Temp files created by test/plugins/test_smartplaylist.py
Temp files created by test/plugins/test_spotify.py
Temp files created by test/plugins/test_subsonicupdate.py
Temp files created by test/plugins/test_the.py
Temp files created by test/plugins/test_thumbnails.py
Temp files created by test/plugins/test_types_plugin.py
Temp files created by test/plugins/test_web.py
Temp files created by test/plugins/test_zero.py
Temp files created by test/rsrc/beetsplug/test.py
Temp files created by test/rsrc/convert_stub.py
Temp files created by test/testall.py
Temp files created by test/test_art_resize.py
Temp files created by test/test_autotag.py
Temp files created by test/test_config_command.py
Temp files created by test/test_datequery.py
Temp files created by test/test_dbcore.py
Temp files created by test/test_files.py
Temp files created by test/test_hidden.py
Temp files created by test/test_importer.py
Temp files created by test/test_library.py
Temp files created by test/test_logging.py
Temp files created by test/test_m3ufile.py
Temp files created by test/test_mb.py
Temp files created by test/test_metasync.py
Temp files created by test/test_pipeline.py
Temp files created by test/test_plugins.py
Temp files created by test/test_query.py
Temp files created by test/test_sort.py
Temp files created by test/test_template.py
Temp files created by test/test_ui_commands.py
Temp files created by test/test_ui_importer.py
Temp files created by test/test_ui_init.py
Temp files created by test/test_ui.py
Temp files created by test/test_util.py
Temp files created by test/test_vfs.py
```

Note that the command which provides the output is now available through
`poe`.
2024-07-18 12:25:23 +01:00
Šarūnas Nejus
83f101627e
Use common temp_dir for playlist plugin directory 2024-07-17 23:34:16 +01:00
Šarūnas Nejus
f88bb4ed60
Add a shell command which tests for leftover temp files 2024-07-12 20:32:18 +01:00
Šarūnas Nejus
de704125d8
test_ui_commands.py: make sure tearDown is run for FieldsTest 2024-07-12 20:32:18 +01:00
Šarūnas Nejus
3177bc44ba
test_importer.py: do not run _common.TestCase.setUp with setup_beets 2024-07-12 20:32:18 +01:00
Šarūnas Nejus
82b1a0d01f
test_plugins.py: dedupe setUp, tearDown usage
And most importantly, remove a redudant invocation of `setup_beets`
which left temporary directories hanging around without getting cleaned
up.
2024-07-12 20:32:18 +01:00
Serene
61e885c85a
Fix bug #4815 (#5352) 2024-07-11 15:20:01 +10:00
Serene-Arc
79449b0851
Filter ending newlines 2024-07-11 15:15:40 +10:00
Serene-Arc
30106d105c
Add test for lyrics 2024-07-11 15:15:25 +10:00
Serene
9122722283
Rework beets.util.hidden (#5341) 2024-07-11 14:52:36 +10:00
HomerHaddock
bdf9eb2a26 Change changelog to reflect fix to #4815 2024-07-07 23:23:22 -06:00
HomerHaddock
50bfe6a179 Fix bug #4815 2024-07-06 23:10:33 -06:00
Šarūnas Nejus
12730aa8d9
test_config_command: use TestHelper to manage temp dir
Due to some weird race conditions the temporary directories were not
getting torn down for four of the tests. I failed to figure out why, and
I found that using TestHelper to manage the temporary directory somehow
fixes this.
2024-07-02 15:35:24 +01:00
Šarūnas Nejus
0682d0d030
test_play: Remove files generated by play plugin 2024-07-02 15:35:24 +01:00
Šarūnas Nejus
c9045215c1
TestHelper: Create mediafield fixtures within temp_dir
This way they get automatically removed with removal of temp_dir.

After this change `test/plugins/test_zero.py` does not any more leave
any mediafield fixtures hanging around.
2024-07-02 15:35:24 +01:00
Šarūnas Nejus
1fda7b6111
fetchart, artresizer: Create art files in predictable directories
This allows to clean them up in art (1) fetching, (2) resizing and (3)
deinterlace tests.
2024-07-02 15:35:24 +01:00
Šarūnas Nejus
56d9d9670f
test_art, test_embedart: Define FetchImageHelper without _common.TestCase
And move the definition to a shared module.

The problem was that EmbedartCliTest ran `_common.TestCase.setUp`
method which initialised temporary directory for the tests AND ran
`helper.TestHelper.setup_beets` method which initialised another set of
temporary directories. This meant that the first set of directories
could not be tracked down for the cleanup.
2024-07-02 15:35:24 +01:00
Šarūnas Nejus
b80b898ba8
test_bareasc: Add teardown which removes tmp files 2024-07-02 10:39:10 +01:00
Arav K.
2fc501f398 [beets.util.hidden] Disambiguate Win32 attribute logic
See: <https://github.com/beetbox/beets/pull/5341#discussion_r1658172880>
2024-06-28 08:11:10 +02:00
Arav K.
484400f701 [beets.util.hidden] Check for a 'st_flags' field
This check existed in the original implementation, but I had removed it
due to a misinterpretation of the 'os' documentation, thinking that the
field was guaranteed to exist.
2024-06-27 15:16:53 +02:00
Arav K.
3a09335e63 [beets.util.hidden] Note TODO for dropping 'bytes' inputs 2024-06-27 15:06:42 +02:00
Arav K.
b51f4cbd91 [util.hidden] use 'typing.Union' instead of '|' 2024-06-27 15:05:14 +02:00
Arav K.
f9b683225b Rework 'beets.util.hidden'
The implementation was unnecessarily convoluted.  I've rewritten it to
declare fewer functions, and it now uses 'pathlib'.
2024-06-27 14:59:21 +02:00
Serene
240c5fca51
Refactor Candidate class in fetchart.py to improve resizing logic (#5152) 2024-06-25 14:30:49 +10:00
Serene
de0742b9d6
Merge branch 'master' into bug-fetchart-resize-logic-fix 2024-06-25 14:30:39 +10:00
Šarūnas Nejus
4e06b59b60
Filter albums by tracks fields and vice versa (#5327)
Fixes #4360

This PR enables querying albums by track fields and tracks by album
fields, and speeds up querying albums by `path` field.

It originally was part of #5240, however we found that the changes
related to the flexible attributes caused degradation in performance. So
this PR contains the first part of #5240 which joined `items` and
`albums` tables in queries.
2024-06-25 02:04:45 +01:00
Serene
f1c643d573
Use typing_extensions only when needed (#5331) 2024-06-24 14:33:11 +10:00
Arkadiy Illarionov
1c020b8264 Check Python version instead of catching ImportError 2024-06-22 19:55:52 +03:00
Arkadiy Illarionov
89f1bda4e0 Update poetry.lock 2024-06-22 16:18:56 +03:00
Arkadiy Illarionov
859072ee9e Use typing_extensions only when needed
Self was added in Python 3.11
TypeAlias was added in Python 3.10
2024-06-22 16:02:24 +03:00
Šarūnas Nejus
bcc2826000
Make sure we can filter common fields 2024-06-21 15:05:29 +01:00
Šarūnas Nejus
981a61bd56
Add support for filtering relations 2024-06-21 15:05:29 +01:00
Šarūnas Nejus
8e237d62c8
Make LazyClassProperty / cached_classproperty reusable 2024-06-21 08:49:10 +01:00
Serene
a273807569
Revert only fast queries (#5326)
Fixes: #5325 

As @arsaboo underlined, this change makes interaction with `beets`
unbearably slow for systems that have SQLite version below `3.38.0`.
This is what Ubuntu ships with by default.

I have also tested other commands, like `beet update`, and found that
even with up to date SQLite version, this command takes twice as long to
execute as before.

Thus, I think that the performance gain we see using some of the more
complex queries is not worth the performance loss for the most common
operations. Therefore, at least for now, I am reverting this change an
leaving this work on the `only-fast-filtering` branch to be revised.
2024-06-20 14:24:42 +10:00
Šarūnas Nejus
2800a323a2
Revert "Make queries fast, filter all flexible attributes (#5240)"
This reverts commit 143b9202f3, reversing
changes made to 8508a57d77.
2024-06-19 21:51:44 +01:00
Šarūnas Nejus
143b9202f3
Make queries fast, filter all flexible attributes (#5240)
Another and (hopefully) final attempt to improve querying speed.

Fixes #4360 
Fixes #3515
and possibly more issues to do with slow queries.

This PR supersedes #4746.

## What's been done
The `album` and `item` tables are joined, and corresponding data from
`item_attributes` and `album_attributes` is merged and made available
for filtering. This enables to achieve the following:

- [x] Faster album path queries, `beet list -a path::some/path` 
- [x] Faster flexible attributes queries, both albums and tracks, `beet
list play_count:10`
- [x] (New) Ability to filter albums with track-level (and vice-versa)
**db** field queries, `beet list -a title:something`
- [x] (New) Ability to filter tracks with album-level **flexible** field
queries, `beet list artpath:cover`
- [x] (New) Ability to filter albums with track-level **flexible** field
queries, `beet list -a art_source:something`

## Benchmarks

![image](https://github.com/beetbox/beets/assets/16212750/3136bc23-33ea-4f07-b93b-ff768b79fb0d)

You can see that now querying speed is more or less constant regardless
of the query, and the speed is mostly influenced by how many results
need to be printed out

![image](https://github.com/beetbox/beets/assets/16212750/bfb037fb-b8d3-46ca-9c30-f851d2af1887)

Compare this with what we had previously

![image](https://github.com/beetbox/beets/assets/16212750/38108879-a404-4cdf-90cc-5563e4a75f9f)

## Later
https://github.com/beetbox/beets/issues/5318
https://github.com/beetbox/beets/issues/5319
2024-06-17 09:10:47 +01:00
Šarūnas Nejus
2c4b42d167
Keep the same FieldQuery.field interface as before 2024-06-17 08:59:20 +01:00
Serene
8508a57d77
Bring back source files to codecov (#5316) 2024-06-17 09:56:59 +10:00