Unified search string construction between albums and items.

This commit is contained in:
Sebastian Mohr 2025-10-20 13:42:33 +02:00
parent c26c342cc1
commit a27cf64d4f
3 changed files with 68 additions and 21 deletions

View file

@ -236,6 +236,19 @@ def _add_candidate(
)
def _parse_search_terms_with_fallbacks(
*pairs: tuple[str | None, str],
) -> tuple[str, ...]:
"""Given pairs of (search term, fallback), return a tuple of
search terms. If **all** search terms are non-empty, return them. Otherwise,
return the fallback terms.
"""
if all(term for term, _ in pairs):
return tuple(term or default for term, default in pairs)
else:
return tuple(default for _, default in pairs)
def tag_album(
items,
search_artist: str | None = None,
@ -294,23 +307,24 @@ def tag_album(
Proposal(list(candidates.values()), rec),
)
# Search terms.
if not (search_artist and search_album):
# No explicit search terms -- use current metadata.
search_artist, search_album = cur_artist, cur_album
log.debug("Search terms: {} - {}", search_artist, search_album)
# Manually provided search terms or fallbacks.
_search_artist, _search_album = _parse_search_terms_with_fallbacks(
(search_artist, cur_artist),
(search_album, cur_album),
)
log.debug("Search terms: {} - {}", _search_artist, _search_album)
# Is this album likely to be a "various artist" release?
va_likely = (
(not consensus["artist"])
or (search_artist.lower() in VA_ARTISTS)
or (_search_artist.lower() in VA_ARTISTS)
or any(item.comp for item in items)
)
log.debug("Album might be VA: {}", va_likely)
# Get the results from the data sources.
for matched_candidate in metadata_plugins.candidates(
items, search_artist, search_album, va_likely
items, _search_artist, _search_album, va_likely
):
_add_candidate(items, candidates, matched_candidate)
@ -322,7 +336,7 @@ def tag_album(
def tag_item(
item,
item: Item,
search_artist: str | None = None,
search_title: str | None = None,
search_ids: list[str] | None = None,
@ -364,14 +378,18 @@ def tag_item(
else:
return Proposal([], Recommendation.none)
# Search terms.
search_artist = search_artist or item.artist
search_title = search_title or item.title
log.debug("Item search terms: {} - {}", search_artist, search_title)
# Manually provided search terms or fallbacks.
_search_artist, _search_title = _parse_search_terms_with_fallbacks(
(search_artist, item.artist),
(search_title, item.title),
)
log.debug("Item search terms: {} - {}", _search_artist, _search_title)
# Get and evaluate candidate metadata.
for track_info in metadata_plugins.item_candidates(
item, search_artist, search_title
item,
_search_artist,
_search_title,
):
dist = track_distance(item, track_info, incl_artist=True)
candidates[track_info.track_id] = hooks.TrackMatch(dist, track_info)

View file

@ -35,17 +35,35 @@ def find_metadata_source_plugins() -> list[MetadataSourcePlugin]:
@notify_info_yielded("albuminfo_received")
def candidates(*args, **kwargs) -> Iterable[AlbumInfo]:
def candidates(
items: Sequence[Item],
artist: str,
album: str,
va_likely: bool,
) -> Iterable[AlbumInfo]:
"""Return matching album candidates from all metadata source plugins."""
for plugin in find_metadata_source_plugins():
yield from plugin.candidates(*args, **kwargs)
yield from plugin.candidates(
items=items,
artist=artist,
album=album,
va_likely=va_likely,
)
@notify_info_yielded("trackinfo_received")
def item_candidates(*args, **kwargs) -> Iterable[TrackInfo]:
"""Return matching track candidates fromm all metadata source plugins."""
def item_candidates(
item: Item,
artist: str,
title: str,
) -> Iterable[TrackInfo]:
"""Return matching track candidates from all metadata source plugins."""
for plugin in find_metadata_source_plugins():
yield from plugin.item_candidates(*args, **kwargs)
yield from plugin.item_candidates(
item=item,
artist=artist,
title=title,
)
def album_for_id(_id: str) -> AlbumInfo | None:
@ -157,15 +175,22 @@ class MetadataSourcePlugin(BeetsPlugin, metaclass=abc.ABCMeta):
@abc.abstractmethod
def item_candidates(
self, item: Item, artist: str, title: str
self,
item: Item,
artist: str,
title: str,
) -> Iterable[TrackInfo]:
"""Return :py:class:`TrackInfo` candidates that match the given track.
Used in the autotag functionality to search for tracks.
:param item: Track item
:param artist: Track artist
:param title: Track title
:param artist: Track artist, either a search manually provided or
preprocessed from the item. If no metadata is available an empty string
is passed.
:param title: Track title, either a search manually provided or
preprocessed from the item. If no metadata is available an empty string
is passed.
"""
raise NotImplementedError

View file

@ -19,6 +19,10 @@ For packagers:
Other changes:
- Standardized ``search_*`` parameter handling in autotag matchers. Manual album and
singleton searches now behave consistently: when the prompt does not specify a
search query, the system defaults to using the corresponding metadata value.
2.5.1 (October 14, 2025)
------------------------