-
Notifications
You must be signed in to change notification settings - Fork 2k
Add support multi-value album/track fields in discogs plugin #6214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,7 +27,7 @@ | |||||||
| import traceback | ||||||||
| from functools import cache | ||||||||
| from string import ascii_lowercase | ||||||||
| from typing import TYPE_CHECKING, cast | ||||||||
| from typing import TYPE_CHECKING, NamedTuple, cast | ||||||||
|
|
||||||||
| import confuse | ||||||||
| from discogs_client import Client, Master, Release | ||||||||
|
|
@@ -121,6 +121,18 @@ | |||||||
| super().__init__(**kwargs) | ||||||||
|
|
||||||||
|
|
||||||||
| class ArtistCreditParts(NamedTuple): | ||||||||
| name: str | ||||||||
| artist_id: str | None | ||||||||
| names: tuple[str, ...] | ||||||||
| ids: tuple[str, ...] | ||||||||
|
|
||||||||
|
|
||||||||
| class ArtistCreditData(NamedTuple): | ||||||||
| default: ArtistCreditParts | ||||||||
| anv: ArtistCreditParts | ||||||||
|
|
||||||||
|
|
||||||||
| class DiscogsPlugin(MetadataSourcePlugin): | ||||||||
| def __init__(self): | ||||||||
| super().__init__() | ||||||||
|
|
@@ -343,24 +355,48 @@ | |||||||
|
|
||||||||
| return media, albumtype | ||||||||
|
|
||||||||
| def get_artist_with_anv( | ||||||||
| self, artists: list[Artist], use_anv: bool = False | ||||||||
| ) -> tuple[str, str | None]: | ||||||||
| """Iterates through a discogs result, fetching data | ||||||||
| if the artist anv is to be used, maps that to the name. | ||||||||
| Calls the parent class get_artist method.""" | ||||||||
| artist_list: list[dict[str | int, str]] = [] | ||||||||
| def _artist_credit_parts( | ||||||||
| self, | ||||||||
| artists: list[Artist], | ||||||||
| *, | ||||||||
| use_anv: bool, | ||||||||
| ) -> ArtistCreditParts: | ||||||||
| if not artists: | ||||||||
| return ArtistCreditParts("", None, tuple(), tuple()) | ||||||||
|
|
||||||||
| formatted: list[dict[str | int, str | None]] = [] | ||||||||
| names: list[str] = [] | ||||||||
| ids: list[str] = [] | ||||||||
|
|
||||||||
| for artist_data in artists: | ||||||||
| a: dict[str | int, str] = { | ||||||||
| "name": artist_data["name"], | ||||||||
| "id": artist_data["id"], | ||||||||
| "join": artist_data.get("join", ""), | ||||||||
| } | ||||||||
| if use_anv and (anv := artist_data.get("anv", "")): | ||||||||
| a["name"] = anv | ||||||||
| artist_list.append(a) | ||||||||
| artist, artist_id = self.get_artist(artist_list, join_key="join") | ||||||||
| return self.strip_disambiguation(artist), artist_id | ||||||||
| name = artist_data.get("anv") if use_anv else None | ||||||||
| if not name: | ||||||||
| name = artist_data["name"] | ||||||||
|
|
||||||||
| stripped_name = self.strip_disambiguation(name) | ||||||||
| artist_id = artist_data.get("id") | ||||||||
| str_id = str(artist_id) if artist_id is not None else None | ||||||||
| formatted.append( | ||||||||
| { | ||||||||
| "name": stripped_name, | ||||||||
| "id": str_id, | ||||||||
| "join": artist_data.get("join", ""), | ||||||||
| } | ||||||||
| ) | ||||||||
| names.append(stripped_name) | ||||||||
| if str_id is not None: | ||||||||
| ids.append(str_id) | ||||||||
|
|
||||||||
| artist, artist_id = self.get_artist(formatted, join_key="join") | ||||||||
| return ArtistCreditParts(artist, artist_id, tuple(names), tuple(ids)) | ||||||||
|
|
||||||||
| def _build_artist_credit_data( | ||||||||
| self, artists: list[Artist] | ||||||||
| ) -> ArtistCreditData: | ||||||||
| return ArtistCreditData( | ||||||||
| default=self._artist_credit_parts(artists, use_anv=False), | ||||||||
| anv=self._artist_credit_parts(artists, use_anv=True), | ||||||||
| ) | ||||||||
|
|
||||||||
| def get_album_info(self, result: Release) -> AlbumInfo | None: | ||||||||
| """Returns an AlbumInfo object for a discogs Release object.""" | ||||||||
|
|
@@ -391,11 +427,18 @@ | |||||||
| return None | ||||||||
|
|
||||||||
| artist_data = [a.data for a in result.artists] | ||||||||
| album_artist, album_artist_id = self.get_artist_with_anv(artist_data) | ||||||||
| album_artist_anv, _ = self.get_artist_with_anv( | ||||||||
| artist_data, use_anv=True | ||||||||
| ) | ||||||||
| artist_credit = album_artist_anv | ||||||||
| album_artist_data = self._build_artist_credit_data(artist_data) | ||||||||
| album_artist_default = album_artist_data.default | ||||||||
| album_artist_anv = album_artist_data.anv | ||||||||
|
|
||||||||
| album_artist = album_artist_default.name | ||||||||
| album_artist_id = album_artist_default.artist_id | ||||||||
| album_artists = list(album_artist_default.names) | ||||||||
| album_artists_sort = list(album_artists) | ||||||||
| album_artists_ids = list(album_artist_default.ids) | ||||||||
|
|
||||||||
| artist_credit = album_artist_anv.name | ||||||||
| album_artists_credit = list(album_artist_anv.names) | ||||||||
|
|
||||||||
| album = re.sub(r" +", " ", result.title) | ||||||||
| album_id = result.data["id"] | ||||||||
|
|
@@ -405,14 +448,17 @@ | |||||||
| # each make an API call just to get the same data back. | ||||||||
| tracks = self.get_tracks( | ||||||||
| result.data["tracklist"], | ||||||||
| (album_artist, album_artist_anv, album_artist_id), | ||||||||
| album_artist_data, | ||||||||
| ) | ||||||||
|
|
||||||||
| # Assign ANV to the proper fields for tagging | ||||||||
| if not self.config["anv"]["artist_credit"]: | ||||||||
| artist_credit = album_artist | ||||||||
| artist_credit = album_artist_default.name | ||||||||
| album_artists_credit = list(album_artist_default.names) | ||||||||
| if self.config["anv"]["album_artist"]: | ||||||||
| album_artist = album_artist_anv | ||||||||
| album_artist = album_artist_anv.name | ||||||||
| album_artists = list(album_artist_anv.names) | ||||||||
| album_artists_sort = list(album_artist_anv.names) | ||||||||
|
|
||||||||
| # Extract information for the optional AlbumInfo fields, if possible. | ||||||||
| va = result.data["artists"][0].get("name", "").lower() == "various" | ||||||||
|
|
@@ -432,9 +478,12 @@ | |||||||
|
|
||||||||
| # Extract information for the optional AlbumInfo fields that are | ||||||||
| # contained on nested discogs fields. | ||||||||
| media, albumtype = self.get_media_and_albumtype( | ||||||||
| result.data.get("formats") | ||||||||
| ) | ||||||||
| formats = result.data.get("formats") | ||||||||
| media, albumtype = self.get_media_and_albumtype(formats) | ||||||||
| albumtypes_list: list[str] = [] | ||||||||
| if formats and (first_format := formats[0]): | ||||||||
| if descriptions := first_format.get("descriptions"): | ||||||||
| albumtypes_list = list(descriptions) | ||||||||
|
|
||||||||
| label = catalogno = labelid = None | ||||||||
| if result.data.get("labels"): | ||||||||
|
|
@@ -452,6 +501,9 @@ | |||||||
| va_name = config["va_name"].as_str() | ||||||||
| album_artist = va_name | ||||||||
| artist_credit = va_name | ||||||||
| album_artists = [va_name] | ||||||||
| album_artists_credit = [va_name] | ||||||||
| album_artists_sort = [va_name] | ||||||||
|
||||||||
| album_artists_sort = [va_name] | |
| album_artists_sort = [va_name] | |
| album_artists_ids = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The albumtypes extraction logic is duplicated. The method
get_media_and_albumtypealready extracts descriptions from formats, but then lines 483-486 extract the same information again separately. Consider either:get_media_and_albumtypeto return a third value (the list of descriptions), orget_media_and_albumtypeby splitting on ", ".