mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 16:42:42 +01:00
Cache found metadata source plugins
This commit is contained in:
parent
01e2eb4665
commit
96670cf971
2 changed files with 40 additions and 31 deletions
|
|
@ -9,7 +9,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import re
|
import re
|
||||||
import warnings
|
from functools import cache
|
||||||
from typing import TYPE_CHECKING, Generic, Literal, Sequence, TypedDict, TypeVar
|
from typing import TYPE_CHECKING, Generic, Literal, Sequence, TypedDict, TypeVar
|
||||||
|
|
||||||
import unidecode
|
import unidecode
|
||||||
|
|
@ -29,30 +29,11 @@ if TYPE_CHECKING:
|
||||||
from .autotag.hooks import AlbumInfo, Item, TrackInfo
|
from .autotag.hooks import AlbumInfo, Item, TrackInfo
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
def find_metadata_source_plugins() -> list[MetadataSourcePlugin]:
|
def find_metadata_source_plugins() -> list[MetadataSourcePlugin]:
|
||||||
"""Returns a list of MetadataSourcePlugin subclass instances
|
"""Return a list of all loaded metadata source plugins."""
|
||||||
|
# TODO: Make this an isinstance(MetadataSourcePlugin, ...) check in v3.0.0
|
||||||
Resolved from all currently loaded beets plugins.
|
return [p for p in find_plugins() if hasattr(p, "data_source")] # type: ignore[misc]
|
||||||
"""
|
|
||||||
|
|
||||||
all_plugins = find_plugins()
|
|
||||||
metadata_plugins: list[MetadataSourcePlugin | BeetsPlugin] = []
|
|
||||||
for plugin in all_plugins:
|
|
||||||
if isinstance(plugin, MetadataSourcePlugin):
|
|
||||||
metadata_plugins.append(plugin)
|
|
||||||
elif hasattr(plugin, "data_source"):
|
|
||||||
# TODO: Remove this in the future major release, v3.0.0
|
|
||||||
warnings.warn(
|
|
||||||
f"{plugin.__class__.__name__} is used as a legacy metadata source. "
|
|
||||||
"It should extend MetadataSourcePlugin instead of BeetsPlugin. "
|
|
||||||
"Support for this will be removed in the v3.0.0 release!",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
metadata_plugins.append(plugin)
|
|
||||||
|
|
||||||
# typeignore: BeetsPlugin is not a MetadataSourcePlugin (legacy support)
|
|
||||||
return metadata_plugins # type: ignore[return-value]
|
|
||||||
|
|
||||||
|
|
||||||
@notify_info_yielded("albuminfo_received")
|
@notify_info_yielded("albuminfo_received")
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import abc
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
@ -160,18 +161,45 @@ class BeetsPlugin(metaclass=abc.ABCMeta):
|
||||||
import_stages: list[ImportStageFunc]
|
import_stages: list[ImportStageFunc]
|
||||||
|
|
||||||
def __init_subclass__(cls) -> None:
|
def __init_subclass__(cls) -> None:
|
||||||
# Dynamically copy methods to BeetsPlugin for legacy support
|
"""Enable legacy metadata‐source plugins to work with the new interface.
|
||||||
# TODO: Remove this in the future major release, v3.0.0
|
|
||||||
|
When a plugin subclass of BeetsPlugin defines a `data_source` attribute
|
||||||
|
but does not inherit from MetadataSourcePlugin, this hook:
|
||||||
|
|
||||||
|
1. Skips abstract classes.
|
||||||
|
2. Warns that the class should extend MetadataSourcePlugin (deprecation).
|
||||||
|
3. Copies any nonabstract methods from MetadataSourcePlugin onto the
|
||||||
|
subclass to provide the full plugin API.
|
||||||
|
|
||||||
|
This compatibility layer will be removed in the v3.0.0 release.
|
||||||
|
"""
|
||||||
|
# TODO: Remove in v3.0.0
|
||||||
if inspect.isabstract(cls):
|
if inspect.isabstract(cls):
|
||||||
return
|
return
|
||||||
|
|
||||||
from beets.metadata_plugins import MetadataSourcePlugin
|
from beets.metadata_plugins import MetadataSourcePlugin
|
||||||
|
|
||||||
abstractmethods = MetadataSourcePlugin.__abstractmethods__
|
if issubclass(cls, MetadataSourcePlugin) or not hasattr(
|
||||||
for name, method in inspect.getmembers(
|
cls, "data_source"
|
||||||
MetadataSourcePlugin, predicate=inspect.isfunction
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
f"{cls.__name__} is used as a legacy metadata source. "
|
||||||
|
"It should extend MetadataSourcePlugin instead of BeetsPlugin. "
|
||||||
|
"Support for this will be removed in the v3.0.0 release!",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=3,
|
||||||
|
)
|
||||||
|
|
||||||
|
for name, method in inspect.getmembers(
|
||||||
|
MetadataSourcePlugin,
|
||||||
|
predicate=lambda f: (
|
||||||
|
inspect.isfunction(f)
|
||||||
|
and f.__name__ not in MetadataSourcePlugin.__abstractmethods__
|
||||||
|
and not hasattr(cls, f.__name__)
|
||||||
|
),
|
||||||
):
|
):
|
||||||
if name not in abstractmethods and not hasattr(cls, name):
|
|
||||||
setattr(cls, name, method)
|
setattr(cls, name, method)
|
||||||
|
|
||||||
def __init__(self, name: str | None = None):
|
def __init__(self, name: str | None = None):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue