## Fix dynamic plugin type and query registration
This PR refactors the plugin system to properly handle dynamic type and
query registration by converting static class attributes to cached class
properties.
**Problem**: Plugin types and queries were stored as mutable class
attributes that were manually updated during plugin loading/unloading.
This caused issues where:
- Plugin types weren't properly registered in test environments
- Shared mutable state between test runs caused inconsistent behavior
- Manual cleanup was error-prone and incomplete
See https://github.com/beetbox/beets/pull/5833 and specifically
https://github.com/beetbox/beets/pull/5833#issuecomment-3016635209 for
the context.
**Solution**:
- Convert `_types` and `_queries` from static dictionaries to
`@cached_classproperty` decorators
- Types and queries are now dynamically computed from loaded plugins
when accessed
- Eliminates manual mutation of class attributes during plugin loading
- Properly clears cached properties when plugins are loaded/unloaded
- Ensures plugin types are available immediately after registration
**Key Changes**:
- `Model._types` and `LibModel._queries` now use `@cached_classproperty`
- Removed manual `_types.update()` calls in plugin loading code
- Added proper cache clearing in test infrastructure
- Plugin types are now inherited through the class hierarchy correctly
This fixes the developer's issue where `item_types` weren't being
registered properly in tests - the new dynamic property approach ensures
plugin types are available as soon as plugins are loaded.
Convert _queries from mutable class attributes to cached class properties
that dynamically fetch plugin queries. This eliminates the need for manual
query registration and cleanup in plugin loading/unloading logic.
Convert static _types dictionaries to dynamic cached class properties to
enable proper plugin type inheritance and avoid mutating shared state.
Key changes:
- Replace static _types dicts with @cached_classproperty decorators
- Update cached_classproperty to support proper caching with class names
- Remove manual _types mutation in plugin loading/unloading
- Add pluginload event and cache clearing for proper plugin integration
- Fix test to trigger type checking during item creation
This ensures plugin types are properly inherited through the class
hierarchy and eliminates issues with shared mutable state between
test runs.
**Bug Fixes**:
- Wrong `raw_seconds_short` module in `DurationQuery`.
- Missing `byte_paths` variable in `import_func`.
Otherwise
- Addressed all static type checking errors in the codebase (except
`spotify` plugin which has already been fixed in a separate PR)
- Removed `continue-on-error` from in `mypy` CI job, which means any
errors in type checking will now fail the CI job.
Remove 'files' configuration from the config to make sure that mypy runs
quicker when invoked from the editor (where ideally it should only check
the file being edited).
Remove 'disallow_any_generics' from the config since we already have
this configured centrally.
And finally, do not allow variable redefinitions.
At the moment the `MetaDataSourcePlugin` has multiple responsibilities:
- fetch data via `_search` api
- defines contract for interaction within the beets autotag lookup
I propose splitting these responsibilities, as it would enable us to use
the `MetaDataSourcePlugin` baseclass with plugins that use external
packages to fetch data.
This follows from discussion in #5761 and
https://github.com/beetbox/beets/pull/5748#discussion_r2075070638.
Feedback is highly appreciated, as this is mainly architectural decision
and I would prefer if the new behavior is a shared consensus.
## To Do
- [x] Opt in plugins into the new `MetaDataSourcePlugin`
- [x] Spotify
- [x] Musicbrainz
- [x] Deezer
- [x] Beatport
- [x] Chroma
- [x] Disccogs
- [x] Remove old MetaDataSourcePlugin and related functions
- [x] Documentation on the ontology of plugins
- [x] Changelog
This PR was initially #5764 and was accidentally closed as the target
branch was deleted. Wasn't able to recover the original PR.