diff --git a/beets/plugins.py b/beets/plugins.py index d8d465183..c0dd12e5b 100644 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -22,6 +22,7 @@ import re import sys from collections import defaultdict from functools import wraps +from importlib import import_module from pathlib import Path from types import GenericAlias from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypeVar @@ -365,11 +366,11 @@ def _get_plugin(name: str) -> BeetsPlugin | None: """ try: try: - namespace = __import__(f"{PLUGIN_NAMESPACE}.{name}", None, None) + namespace = import_module(f"{PLUGIN_NAMESPACE}.{name}") except Exception as exc: raise PluginImportError(name) from exc - for obj in getattr(namespace, name).__dict__.values(): + for obj in namespace.__dict__.values(): if ( inspect.isclass(obj) and not isinstance( @@ -378,6 +379,12 @@ def _get_plugin(name: str) -> BeetsPlugin | None: and issubclass(obj, BeetsPlugin) and obj != BeetsPlugin and not inspect.isabstract(obj) + # Only consider this plugin's module or submodules to avoid + # conflicts when plugins import other BeetsPlugin classes + and ( + obj.__module__ == namespace.__name__ + or obj.__module__.startswith(f"{namespace.__name__}.") + ) ): return obj() diff --git a/docs/changelog.rst b/docs/changelog.rst index cbcfe73f0..52e935445 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -32,6 +32,8 @@ Bug fixes: extraartists field. - :doc:`plugins/spotify` Fixed an issue where candidate lookup would not find matches due to query escaping (single vs double quotes). +- :doc:`plugins/chroma` :doc:`plugins/bpsync` Fix plugin loading issue caused by + an import of another :class:`beets.plugins.BeetsPlugin` class. :bug:`6033` For packagers: