Before:
```
Traceback (most recent call last):
File "/nix/store/yk2m7a9wdmh8fz8ywca0c73sc5ad2zm6-beets-2.3.1/lib/python3.13/site-packages/beetsplug/discogs.py", line 312, in get_album_info
result.refresh()
~~~~~~~~~~~~~~^^
File "/nix/store/007cfg4f295dz064bl9a2cjw10vlpc83-python3.13-discogs-client-2.8/lib/python3.13/site-packages/discogs_client/models.py", line 204, in refresh
data = self.client._get(self.data['resource_url'])
File "/nix/store/007cfg4f295dz064bl9a2cjw10vlpc83-python3.13-discogs-client-2.8/lib/python3.13/site-packages/discogs_client/client.py", line 114, in _get
return self._request('GET', url)
~~~~~~~~~~~~~^^^^^^^^^^^^
File "/nix/store/007cfg4f295dz064bl9a2cjw10vlpc83-python3.13-discogs-client-2.8/lib/python3.13/site-packages/discogs_client/client.py", line 111, in _request
raise HTTPError(body['message'], status_code)
discogs_client.exceptions.HTTPError: 404: That release does not exist or may have been deleted.
```
After:
```
Discogs release not found: <Release 20919814 'Kumi Tanioka, Yae - Final Fantasy Crystal Chronicles Original Soundtrack'>: 404: That release does not exist or may have been deleted.
```
Here's the link to the relevant release, which [shows up in search
results](https://www.discogs.com/search?q=Kumi+Tanioka%2C+Yae+-+Final+Fantasy+Crystal+Chronicles+Original+Soundtrack&type=all)
but 404s if you click on it:
https://www.discogs.com/release/20919814-Kumi-Tanioka-Yae-Final-Fantasy-Crystal-Chronicles-Original-Soundtrack
Add the artist and album information to the item template in the web
plugin.
When searching for an item, Instead of
`` Doo Woop (That Thing)``
the interface now shows
``Lauryn Hill - The Miseducation of Lauryn Hill - Doo Wop (That Thing)``
which is arguably clearer, and matches the default output of `beet ls`
in the cli.
## Summary
See https://github.com/beetbox/beets/discussions/5891 for context.
This PR introduces a deprecation system for module structure changes and
deprecated functionality in the beets codebase:
### Key Changes
**New deprecation infrastructure:**
- Add `deprecate_imports()` utility function to handle deprecated module
imports with warnings
- Implement `__getattr__` hooks in modules to intercept and redirect
deprecated imports
- Deprecate previously removed imports in `beets.library` and
`beets.autotag`
- Deprecate `decargs` function.
## 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.