- Move pytest setup/teardown into shared `TestHelper` via an autouse
`setup` fixture.
- Collapse old pytest-specific helpers into the main helpers by using
`TestHelper` and `PluginTestHelper` as the standard test base classes.
- Update plugin and library tests to use the new shared lifecycle
instead of custom fixtures or manual `setUp`/`tearDown`.
- Rewrite `test/plugins/test_ftintitle.py` to use `PluginTestHelper` and
`configure_plugin`, which removes manual environment wiring and makes
the test flow match other plugin tests.
- Simplify `test/plugins/test_mbcollection.py` by dropping its local
helper fixture and relying on the shared test setup.
## High-level impact
- Test architecture becomes more consistent: one shared pytest setup
path instead of many local patterns.
- Boilerplate goes down across the test suite, so future tests should be
easier to write and maintain.
- Deprecated helper split is reduced, which makes test utilities simpler
to understand.
- Main behavior change is in test infrastructure, and it fixes the
failing `ftintitle` and `mbcollection` tests without changing production
plugin logic.
### What changed
- Move `Match`, `AlbumMatch`, and `TrackMatch` from
`beets.autotag.hooks` into `beets.autotag.match`.
- Expand `beets.autotag.__init__` to re-export main autotag types and
functions like `Distance`, `Info`, `Match`, `assign_items`, `tag_album`,
and `tag_item`.
- Update internal code, plugins, tests, and docs to import from
`beets.autotag` instead of reaching into deeper modules.
### Architecture impact
- `beets.autotag` now acts as the main public API for autotagging.
- `hooks.py` stays focused on metadata/info structures.
- `match.py` now owns match objects and matching behavior in one place.
### High-level benefit
- Import paths become simpler and more consistent.
- Internal module boundaries are clearer.
- Future refactors inside autotag should be safer because callers depend
on `beets.autotag`, not module internals.
## Description
This PR is a refactor of `test/test_library.py` and replaces the unitest
test cases with a pytest setup. Also replaced capture_log with caplog
fixture.
Needs rebasing after https://github.com/beetbox/beets/pull/6659 is
merged.
TODOs:
- [x] ~~Changelog~~ Not needed as this is an internal refactor only
---
This is related to the multi-step efforts to improve logging in beets
https://github.com/beetbox/beets/issues/6553
This is a follow-up to #6485. Currently `spotifysync`:
- batches Spotify HTTP requests, but still stores each item individually
- writes to the DB before writing tags
- logs Audio features API unavailable, skipping once per remaining item
after a 403
This makes logs noisy and causes unnecessary DB commit overhead.
This PR :
- keeps the existing batched Spotify API fetches
- batches `spotifysync` database persistence into a single outer DB
transaction per run
- aligns `spotifysync` with the normal beets write-before-store pattern
- suppresses repeated per-item audio-features unavailability log spam
Actual logs before fix (masked):
```bash
$ beet -v spotifysync -f album:"ALBUM"
...
spotify: Total 5 tracks
spotify: Processing 1/5 tracks - <Album A> - <Track 1>
spotify: Processing 2/5 tracks - <Album A> - <Track 2>
spotify: Processing 3/5 tracks - <Album A> - <Track 3>
spotify: Processing 4/5 tracks - <Album A> - <Track 4>
spotify: Processing 5/5 tracks - <Album A> - <Track 5>
spotify: Audio features API is unavailable (403 error). Skipping audio features for remaining tracks.
spotify: Audio features API unavailable, skipping
Sending event: database_change
Sending event: write
Sending event: after_write
spotify: Audio features API unavailable, skipping
Sending event: database_change
Sending event: write
Sending event: after_write
spotify: Audio features API unavailable, skipping
Sending event: database_change
Sending event: write
Sending event: after_write
spotify: Audio features API unavailable, skipping
Sending event: database_change
Sending event: write
Sending event: after_write
spotify: Audio features API unavailable, skipping
Sending event: database_change
Sending event: write
Sending event: after_write
```
Logs after fix (masked)):
```bash
$ beet -v spotifysync -f album:"ALBUM"
...
spotify: Total 5 tracks
spotify: Processing 1/5 tracks - <Album A> - <Track 1>
spotify: Processing 2/5 tracks - <Album A> - <Track 2>
spotify: Processing 3/5 tracks - <Album A> - <Track 3>
spotify: Processing 4/5 tracks - <Album A> - <Track 4>
spotify: Processing 5/5 tracks - <Album A> - <Track 5>
spotify: Audio features API is unavailable (403 error). Skipping audio features for remaining tracks.
Sending event: write
Sending event: after_write
Sending event: write
Sending event: after_write
Sending event: write
Sending event: after_write
Sending event: write
Sending event: after_write
Sending event: write
Sending event: after_write
Sending event: database_change
Sending event: database_change
Sending event: database_change
Sending event: database_change
Sending event: database_change
```
- [x] Changelog. (Add an entry to `docs/changelog.rst` to the bottom of
one of the lists near the top of the document.)
- [x] Tests. (Very much encouraged but not strictly required.)