Add before_album_info_emitted for metadata plugins

This commit is contained in:
asardaes 2025-11-22 17:56:04 +01:00 committed by Alexis Sardá
parent 5ff1c7b17f
commit 264e7430c8
5 changed files with 34 additions and 15 deletions

View file

@ -39,7 +39,10 @@ def candidates(items, *args, **kwargs) -> Iterable[AlbumInfo]:
"""Return matching album candidates from all metadata source plugins."""
for plugin in find_metadata_source_plugins():
for info in plugin.candidates(items, *args, **kwargs):
send("albuminfo_received", info=info, items=items)
send(
"albuminfo_received",
info=plugin.before_album_info_emitted(items, info),
)
yield info
@ -60,7 +63,10 @@ def album_for_id(
"""
for plugin in find_metadata_source_plugins():
if info := plugin.album_for_id(album_id=_id):
send("albuminfo_received", info=info, items=items)
send(
"albuminfo_received",
info=plugin.before_album_info_emitted(items, info),
)
return info
return None
@ -132,6 +138,18 @@ class MetadataSourcePlugin(BeetsPlugin, metaclass=abc.ABCMeta):
found."""
raise NotImplementedError
def before_album_info_emitted(
self,
items: Iterable[Item],
album_info: AlbumInfo,
) -> AlbumInfo:
"""Called after an :py:class:`AlbumInfo` object has been found for a set
of :py:class:`Item` objects but before the ``albuminfo_received``
:py:type:`plugins.EventType` has been sent. The returned instance will
be the payload of the event.
"""
return album_info
@abc.abstractmethod
def track_for_id(self, track_id: str) -> TrackInfo | None:
"""Return a :py:class:`TrackInfo` object or None if no matching release was

View file

@ -100,9 +100,6 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
pass
self.register_listener("pluginload", self._on_plugins_loaded)
self.register_listener(
"albuminfo_received", self._on_album_info_received
)
self.register_listener("album_matched", self._adjust_final_album_match)
# noinspection PyMethodMayBeStatic
@ -116,12 +113,13 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
" the mbpseudo plugin"
)
def _on_album_info_received(
@override
def before_album_info_emitted(
self,
info: AlbumInfo,
items: Iterable[Item],
album_info: AlbumInfo,
):
if isinstance(info, PseudoAlbumInfo):
if isinstance(album_info, PseudoAlbumInfo):
for item in items:
# particularly relevant for reimport but could also happen during import
if "mb_albumid" in item:
@ -131,10 +129,12 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
self._log.debug(
"Using {0} release for distance calculations for album {1}",
info.determine_best_ref(list(items)),
info.album_id,
album_info.determine_best_ref(list(items)),
album_info.album_id,
)
return album_info
@override
def candidates(
self,

View file

@ -57,8 +57,9 @@ Bug fixes:
For plugin developers:
- The plugin event ``albuminfo_received`` now has a second argument ``items``
with the files that were used in the corresponding search.
- Metadata plugins can now implement a ``before_album_info_emitted`` method to
modify ``AlbumInfo`` objects before they are emitted as part of the
``albuminfo_received`` event.
- A new plugin event, ``album_matched``, is sent when an album that is being
imported has been matched to its metadata and the corresponding distance has
been calculated.

View file

@ -175,7 +175,7 @@ registration process in this case:
or adjustments (e.g., ``mbsync``).
``albuminfo_received``
:Parameters: ``info`` (|AlbumInfo|), ``items`` (iterable of |Item|)
:Parameters: ``info`` (|AlbumInfo|)
:Description: Like ``trackinfo_received`` but for album-level metadata.
``album_matched``

View file

@ -141,7 +141,7 @@ class TestMBPseudoPlugin(PluginMixin):
item["title"] = "百花繚乱"
# if items don't have mb_*, they are not modified
mbpseudo_plugin._on_album_info_received(pseudo_info, [item])
mbpseudo_plugin.before_album_info_emitted([item], pseudo_info)
assert pseudo_info.album == item.title
pseudo_info.use_pseudo_as_ref()
@ -153,7 +153,7 @@ class TestMBPseudoPlugin(PluginMixin):
assert item.get("mb_trackid") == "mb_tid"
# if items have mb_*, they are deleted
mbpseudo_plugin._on_album_info_received(pseudo_info, [item])
mbpseudo_plugin.before_album_info_emitted([item], pseudo_info)
assert pseudo_info.album == item.title
assert item.get("mb_albumid") == ""
assert item.get("mb_trackid") == ""