-
Notifications
You must be signed in to change notification settings - Fork 2k
Labels
corePull requests that modify the beets core `beets`Pull requests that modify the beets core `beets`pluginPull requests that are plugins relatedPull requests that are plugins related
Description
Hi @semohr! I wanted to create a separate issue but I'll hijack this one.
Just the other day I was experimenting with plugins and
beets[chroma]but could not get it to load up:$ beet config -e ... plugins: musicbrainz missing fetchart embedart lyrics lastgenre chroma ...Then I noticed the
musicbrainzplugin listed twice in the--versioncommand:$ beet -v --version ... plugin paths: [] Loading plugins: chroma, embedart, fetchart, lastgenre, lyrics, missing, musicbrainz ... Sending event: pluginload ... Sending event: library_opened beets version 2.4.0 Python version 3.12.11 plugins: embedart, fetchart, lastgenre, lyrics, missing, musicbrainz, musicbrainz Sending event: cli_exitAfter a dive into
beets/plugins.pyand its_get_pluginI came up with this fix (notice theand obj.__name__ == "MusicBrainzPlugin"line):loadedMusicBrainzOnce = False def _get_plugin(name: str) -> BeetsPlugin | None: """Dynamically load and instantiate a plugin class by name. Attempts to import the plugin module, locate the appropriate plugin class within it, and return an instance. Handles import failures gracefully and logs warnings for missing plugins or loading errors. """ global loadedMusicBrainzOnce try: try: namespace = __import__(f"{PLUGIN_NAMESPACE}.{name}", None, None) except Exception as exc: raise PluginImportError(name) from exc for obj in getattr(namespace, name).__dict__.values(): if ( inspect.isclass(obj) and not isinstance( obj, GenericAlias ) # seems to be needed for python <= 3.9 only and issubclass(obj, BeetsPlugin) and obj != BeetsPlugin and not inspect.isabstract(obj) ): if obj.__name__ == "MusicBrainzPlugin": if loadedMusicBrainzOnce: continue else: loadedMusicBrainzOnce = True return obj() except Exception: log.warning("** error loading plugin {}", name, exc_info=True) return NoneIn other words, it looks like the Chroma plugin file is somehow exporting the MusicBrainz plugin as well, which in turn gets picked first by the loader and loaded twice.
I hope this helps with the real fix.
- btw, using venv with Python 3.12.11 on Ubuntu 24.04.
Edit: updated the code to allow loading the
MusicBrainzPluginonce.
This way my--versioncommand looks like this:$ beet -v --version ... plugin paths: [] Loading plugins: chroma, embedart, fetchart, lastgenre, lyrics, missing, musicbrainz ... Sending event: pluginload ... Sending event: library_opened beets version 2.4.0 Python version 3.12.11 plugins: chroma, embedart, fetchart, lastgenre, lyrics, missing, musicbrainz Sending event: cli_exit
Originally posted by @OancaAndrei in #6023
OancaAndrei
Metadata
Metadata
Assignees
Labels
corePull requests that modify the beets core `beets`Pull requests that modify the beets core `beets`pluginPull requests that are plugins relatedPull requests that are plugins related