Ensure that path_formats is set in relevant tests to avoid reliance on
defaults and to clarify test intent. Update Library constructor type hint for
path_formats to use Template type.
This default value was only relevant in tests.
ReadError and WriteError formatted the super() proxy in their f-string, so file read and write failures lost the path and reason.
Use super().__str__() to return the FileOperationError message.
Move path relativization/expansion logic from Item._setitem/__getitem__
into dbcore layer (PathType.to_sql/from_sql and PathQuery), so all
models benefit without per-model overrides.
Propagate contextvars to pipeline and replaygain pool threads so the
library root context variable is available during background processing.
Convert item paths to relative on write and back to absolute on read,
keeping the database free of hardcoded library directory. Fix tests to
account for absolute path return values.
Simplify multi-genre implementation based on maintainer feedback (PR #6169).
Changes:
- Remove multi_value_genres and genre_separator config options
- Replace complex sync_genre_fields() with ensure_first_value('genre', 'genres')
- Update all plugins (Beatport, MusicBrainz, LastGenre) to always write genres as lists
- Add automatic migration for comma/semicolon/slash-separated genre strings
- Add 'beet migrate genres' command for explicit batch migration with --pretend flag
- Update all tests to reflect simplified approach (44 tests passing)
- Update documentation
Implementation aligns with maintainer vision of always using multi-value genres
internally with automatic backward-compatible sync to the genre field via
ensure_first_value(), eliminating configuration complexity.
Migration strategy avoids problems from #5540:
- Automatic lazy migration on item access (no reimport/mbsync needed)
- Optional batch migration command for user control
- No endless rewrite loops due to proper field synchronization
- Use '\␀' as the DB delimiter while formatting lists with '; ' for
templates.
- Update DelimitedString parsing to accept both separators:
* '\␀' for the values from the DB
* '; ' for the rest of parsed values (for example `beet modify genres="eletronic; jazz"`)
- Refresh %first docs and tests to reflect multi-value field behavior.