mirror of
https://github.com/beetbox/beets.git
synced 2026-03-23 05:43:54 +01:00
Document new methods
This commit is contained in:
parent
4cccb70921
commit
0670611d7a
5 changed files with 50 additions and 18 deletions
|
|
@ -291,6 +291,12 @@ class IDResponse(TypedDict):
|
|||
|
||||
|
||||
class SearchParams(NamedTuple):
|
||||
"""Bundle normalized search context passed to provider search hooks.
|
||||
|
||||
Shared search orchestration constructs this value so plugin hooks receive
|
||||
one object describing search intent, query text, and provider filters.
|
||||
"""
|
||||
|
||||
query_type: QueryType
|
||||
query: str
|
||||
filters: dict[str, str]
|
||||
|
|
@ -328,6 +334,20 @@ class SearchApiMetadataSourcePlugin(
|
|||
name: str,
|
||||
va_likely: bool,
|
||||
) -> tuple[str, dict[str, str]]:
|
||||
"""Build query text and API filters for a provider search.
|
||||
|
||||
Subclasses can override this hook when their API requires a query format
|
||||
or filter set that differs from the default text-based construction.
|
||||
|
||||
:param query_type: The type of query to perform. Either *album* or *track*
|
||||
:param items: List of items the search is being performed for
|
||||
:param artist: Artist name
|
||||
:param name: Album or track name, depending on ``query_type``
|
||||
:param va_likely: Whether the search is likely to be for various artists
|
||||
:return: Tuple of (``query`` text, ``filters`` dict) to use for the
|
||||
search API call
|
||||
"""
|
||||
|
||||
query = f'album:"{name}"' if query_type == "album" else name
|
||||
if query_type == "track" or not va_likely:
|
||||
query += f' artist:"{artist}"'
|
||||
|
|
@ -336,18 +356,25 @@ class SearchApiMetadataSourcePlugin(
|
|||
|
||||
@abc.abstractmethod
|
||||
def get_search_response(self, params: SearchParams) -> Sequence[R]:
|
||||
"""Fetch raw search results for a provider request.
|
||||
|
||||
Implementations should return records containing source IDs so shared
|
||||
candidate resolution can perform ID-based album and track lookups.
|
||||
|
||||
:param params: :py:namedtuple:`~SearchParams` named tuple
|
||||
:return: Sequence of IDResponse dicts containing at least an "id" key for each
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def _search_api(
|
||||
self, query_type: QueryType, query: str, filters: dict[str, str]
|
||||
) -> Sequence[R]:
|
||||
"""Perform a search on the API.
|
||||
"""Run shared provider search orchestration and return ID-bearing results.
|
||||
|
||||
:param query_type: The type of query to perform.
|
||||
:param filters: A dictionary of filters to apply to the search.
|
||||
:param query_string: Additional query to include in the search.
|
||||
|
||||
Should return a list of identifiers for the requested type (album or track).
|
||||
This path applies optional query normalization and default limits, then
|
||||
delegates API access to provider hooks with consistent logging and
|
||||
failure handling.
|
||||
"""
|
||||
if self.config["search_query_ascii"].get():
|
||||
query = unidecode.unidecode(query)
|
||||
|
|
@ -372,6 +399,8 @@ class SearchApiMetadataSourcePlugin(
|
|||
def _get_candidates(
|
||||
self, query_type: QueryType, *args, **kwargs
|
||||
) -> Sequence[R]:
|
||||
"""Resolve query hooks and execute one provider search request."""
|
||||
|
||||
return self._search_api(
|
||||
query_type,
|
||||
*self.get_search_query_with_filters(query_type, *args, **kwargs),
|
||||
|
|
|
|||
|
|
@ -218,6 +218,8 @@ class DeezerPlugin(SearchApiMetadataSourcePlugin[IDResponse]):
|
|||
)
|
||||
|
||||
def get_search_response(self, params: SearchParams) -> list[IDResponse]:
|
||||
"""Search Deezer and return the raw result payload entries."""
|
||||
|
||||
response = requests.get(
|
||||
f"{self.search_url}{params.query_type}",
|
||||
params={
|
||||
|
|
|
|||
|
|
@ -240,6 +240,12 @@ class DiscogsPlugin(SearchApiMetadataSourcePlugin[IDResponse]):
|
|||
name: str,
|
||||
va_likely: bool,
|
||||
) -> tuple[str, dict[str, str]]:
|
||||
"""Build a Discogs release query and fixed release-type filter.
|
||||
|
||||
The query is normalized to improve hit rates for punctuation-heavy album
|
||||
names and medium suffixes that can reduce recall.
|
||||
"""
|
||||
|
||||
query = f"{artist} {name}" if va_likely else name
|
||||
# Strip non-word characters from query. Things like "!" and "-" can
|
||||
# cause a query to return no results, even if they match the artist or
|
||||
|
|
@ -253,7 +259,7 @@ class DiscogsPlugin(SearchApiMetadataSourcePlugin[IDResponse]):
|
|||
return query, {"type": "release"}
|
||||
|
||||
def get_search_response(self, params: SearchParams) -> Sequence[IDResponse]:
|
||||
"""Returns a list of AlbumInfo objects for a discogs search query."""
|
||||
"""Search Discogs releases and return raw result mappings with IDs."""
|
||||
results = self.discogs_client.search(params.query, **params.filters)
|
||||
results.per_page = params.limit
|
||||
return [r.data for r in results.page(1)]
|
||||
|
|
|
|||
|
|
@ -728,6 +728,8 @@ class MusicBrainzPlugin(
|
|||
name: str,
|
||||
va_likely: bool,
|
||||
) -> tuple[str, dict[str, str]]:
|
||||
"""Build MusicBrainz criteria filters for album and recording search."""
|
||||
|
||||
if query_type == "album":
|
||||
criteria = self.get_album_criteria(items, artist, name, va_likely)
|
||||
else:
|
||||
|
|
@ -738,12 +740,8 @@ class MusicBrainzPlugin(
|
|||
}
|
||||
|
||||
def get_search_response(self, params: SearchParams) -> Sequence[IDResponse]:
|
||||
"""Perform MusicBrainz API search and return results.
|
||||
"""Search MusicBrainz and return release or recording result mappings."""
|
||||
|
||||
Execute a search against the MusicBrainz API for recordings or releases
|
||||
using the provided criteria. Handles API errors by converting them into
|
||||
MusicBrainzAPIError exceptions with contextual information.
|
||||
"""
|
||||
mb_entity: Literal["release", "recording"] = (
|
||||
"release" if params.query_type == "album" else "recording"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -470,13 +470,10 @@ class SpotifyPlugin(
|
|||
def get_search_response(
|
||||
self, params: SearchParams
|
||||
) -> Sequence[SearchResponseAlbums | SearchResponseTracks]:
|
||||
"""Query the Spotify Search API for the specified ``query_string``,
|
||||
applying the provided ``filters``.
|
||||
"""Search Spotify and return raw album or track result items.
|
||||
|
||||
:param query_type: Item type to search across. Valid types are: 'album',
|
||||
'artist', 'playlist', and 'track'.
|
||||
:param filters: Field filters to apply.
|
||||
:param query_string: Additional query to include in the search.
|
||||
Unauthorized responses trigger one token refresh attempt before the
|
||||
method gives up and falls back to an empty result set.
|
||||
"""
|
||||
for _ in range(2):
|
||||
response = requests.get(
|
||||
|
|
|
|||
Loading…
Reference in a new issue