mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +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 re
|
||||
import warnings
|
||||
from functools import cache
|
||||
from typing import TYPE_CHECKING, Generic, Literal, Sequence, TypedDict, TypeVar
|
||||
|
||||
import unidecode
|
||||
|
|
@ -29,30 +29,11 @@ if TYPE_CHECKING:
|
|||
from .autotag.hooks import AlbumInfo, Item, TrackInfo
|
||||
|
||||
|
||||
@cache
|
||||
def find_metadata_source_plugins() -> list[MetadataSourcePlugin]:
|
||||
"""Returns a list of MetadataSourcePlugin subclass instances
|
||||
|
||||
Resolved from all currently loaded beets plugins.
|
||||
"""
|
||||
|
||||
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]
|
||||
"""Return a list of all loaded metadata source plugins."""
|
||||
# TODO: Make this an isinstance(MetadataSourcePlugin, ...) check in v3.0.0
|
||||
return [p for p in find_plugins() if hasattr(p, "data_source")] # type: ignore[misc]
|
||||
|
||||
|
||||
@notify_info_yielded("albuminfo_received")
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import abc
|
|||
import inspect
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from functools import wraps
|
||||
from importlib import import_module
|
||||
|
|
@ -160,19 +161,46 @@ class BeetsPlugin(metaclass=abc.ABCMeta):
|
|||
import_stages: list[ImportStageFunc]
|
||||
|
||||
def __init_subclass__(cls) -> None:
|
||||
# Dynamically copy methods to BeetsPlugin for legacy support
|
||||
# TODO: Remove this in the future major release, v3.0.0
|
||||
"""Enable legacy metadata‐source plugins to work with the new interface.
|
||||
|
||||
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):
|
||||
return
|
||||
|
||||
from beets.metadata_plugins import MetadataSourcePlugin
|
||||
|
||||
abstractmethods = MetadataSourcePlugin.__abstractmethods__
|
||||
for name, method in inspect.getmembers(
|
||||
MetadataSourcePlugin, predicate=inspect.isfunction
|
||||
if issubclass(cls, MetadataSourcePlugin) or not hasattr(
|
||||
cls, "data_source"
|
||||
):
|
||||
if name not in abstractmethods and not hasattr(cls, name):
|
||||
setattr(cls, name, method)
|
||||
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__)
|
||||
),
|
||||
):
|
||||
setattr(cls, name, method)
|
||||
|
||||
def __init__(self, name: str | None = None):
|
||||
"""Perform one-time plugin setup."""
|
||||
|
|
|
|||
Loading…
Reference in a new issue