mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
Testing and implemented anv method, also added Featuring customizable string
This commit is contained in:
parent
533aa6379b
commit
5a43d6add4
2 changed files with 135 additions and 135 deletions
|
|
@ -97,8 +97,12 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
"user_token": "",
|
||||
"separator": ", ",
|
||||
"index_tracks": False,
|
||||
"featured_label": "Feat.",
|
||||
"append_style_genre": False,
|
||||
"strip_disambiguation": True,
|
||||
"album_artist_anv": False,
|
||||
"track_artist_anv": False,
|
||||
"artist_credit_anv": True
|
||||
}
|
||||
)
|
||||
self.config["apikey"].redact = True
|
||||
|
|
@ -302,6 +306,19 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
|
||||
return media, albumtype
|
||||
|
||||
def get_artist(self, artists, use_anv=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_data = []
|
||||
for artist in artists:
|
||||
if use_anv and (anv := artist.get("anv", "")):
|
||||
artist["name"] = anv
|
||||
artist_data.append(artist)
|
||||
artist, artist_id = super().get_artist(
|
||||
artist_data, join_key="join")
|
||||
return self.strip_disambiguation(artist), artist_id
|
||||
|
||||
def get_album_info(self, result):
|
||||
"""Returns an AlbumInfo object for a discogs Release object."""
|
||||
# Explicitly reload the `Release` fields, as they might not be yet
|
||||
|
|
@ -330,8 +347,12 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
self._log.warning("Release does not contain the required fields")
|
||||
return None
|
||||
|
||||
artist, artist_id = self.get_artist(
|
||||
[a.data for a in result.artists], join_key="join"
|
||||
artist_data = [a.data for a in result.artists]
|
||||
album_artist, album_artist_id = self.get_artist(artist_data,
|
||||
self.config["album_artist_anv"]
|
||||
)
|
||||
artist_credit, _ = self.get_artist(artist_data,
|
||||
self.config["artist_credit_anv"]
|
||||
)
|
||||
album = re.sub(r" +", " ", result.title)
|
||||
album_id = result.data["id"]
|
||||
|
|
@ -339,7 +360,8 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
# convenient `.tracklist` property, which will strip out useful artist
|
||||
# information and leave us with skeleton `Artist` objects that will
|
||||
# each make an API call just to get the same data back.
|
||||
tracks = self.get_tracks(result.data["tracklist"], artist, artist_id)
|
||||
tracks = self.get_tracks(result.data["tracklist"], (album_artist, album_artist_id,
|
||||
artist_credit))
|
||||
|
||||
# Extract information for the optional AlbumInfo fields, if possible.
|
||||
va = result.data["artists"][0].get("name", "").lower() == "various"
|
||||
|
|
@ -376,9 +398,7 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
# Additional cleanups
|
||||
# (various artists name, catalog number, media, disambiguation).
|
||||
if va:
|
||||
artist = config["va_name"].as_str()
|
||||
else:
|
||||
artist = self.strip_disambiguation(artist)
|
||||
album_artist, artist_credit = config["va_name"].as_str()
|
||||
if catalogno == "none":
|
||||
catalogno = None
|
||||
# Explicitly set the `media` for the tracks, since it is expected by
|
||||
|
|
@ -401,9 +421,9 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
return AlbumInfo(
|
||||
album=album,
|
||||
album_id=album_id,
|
||||
artist=artist,
|
||||
artist_credit=artist,
|
||||
artist_id=artist_id,
|
||||
artist=album_artist,
|
||||
artist_credit=artist_credit,
|
||||
artist_id=album_artist_id,
|
||||
tracks=tracks,
|
||||
albumtype=albumtype,
|
||||
va=va,
|
||||
|
|
@ -421,7 +441,7 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
data_url=data_url,
|
||||
discogs_albumid=discogs_albumid,
|
||||
discogs_labelid=labelid,
|
||||
discogs_artistid=artist_id,
|
||||
discogs_artistid=album_artist_id,
|
||||
cover_art_url=cover_art_url,
|
||||
)
|
||||
|
||||
|
|
@ -443,7 +463,7 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
else:
|
||||
return None
|
||||
|
||||
def get_tracks(self, tracklist, album_artist, album_artist_id):
|
||||
def get_tracks(self, tracklist, album_artist_data):
|
||||
"""Returns a list of TrackInfo objects for a discogs tracklist."""
|
||||
try:
|
||||
clean_tracklist = self.coalesce_tracks(tracklist)
|
||||
|
|
@ -469,7 +489,7 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
divisions += next_divisions
|
||||
del next_divisions[:]
|
||||
track_info = self.get_track_info(
|
||||
track, index, divisions, album_artist, album_artist_id
|
||||
track, index, divisions, album_artist_data
|
||||
)
|
||||
track_info.track_alt = track["position"]
|
||||
tracks.append(track_info)
|
||||
|
|
@ -638,9 +658,11 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
return DISAMBIGUATION_RE.sub("", text)
|
||||
|
||||
def get_track_info(
|
||||
self, track, index, divisions, album_artist, album_artist_id
|
||||
self, track, index, divisions, album_artist_data
|
||||
):
|
||||
"""Returns a TrackInfo object for a discogs track."""
|
||||
album_artist, album_artist_id, artist_credit = album_artist_data
|
||||
|
||||
title = track["title"]
|
||||
if self.config["index_tracks"]:
|
||||
prefix = ", ".join(divisions)
|
||||
|
|
@ -648,28 +670,39 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
title = f"{prefix}: {title}"
|
||||
track_id = None
|
||||
medium, medium_index, _ = self.get_track_index(track["position"])
|
||||
artist, artist_id = self.get_artist(
|
||||
track.get("artists", []), join_key="join"
|
||||
)
|
||||
# If no artist and artist is returned, set to match album artist
|
||||
if not artist:
|
||||
artist = album_artist
|
||||
artist_id = album_artist_id
|
||||
|
||||
artist = album_artist
|
||||
artist_credit = album_artist
|
||||
artist_id = album_artist_id
|
||||
|
||||
# If artists are found on the track, we will use those instead
|
||||
if (artists := track.get("artists", [])):
|
||||
artist, artist_id = self.get_artist(artists,
|
||||
self.config["track_artist_anv"]
|
||||
)
|
||||
artist_credit, _ = self.get_artist(artists,
|
||||
self.config["artist_credit_anv"]
|
||||
)
|
||||
length = self.get_track_length(track["duration"])
|
||||
|
||||
# Add featured artists
|
||||
extraartists = track.get("extraartists", [])
|
||||
featured = [
|
||||
artist["name"]
|
||||
for artist in extraartists
|
||||
if "Featuring" in artist["role"]
|
||||
]
|
||||
if featured:
|
||||
artist = f"{artist} feat. {', '.join(featured)}"
|
||||
artist = self.strip_disambiguation(artist)
|
||||
if (extraartists := track.get("extraartists", [])):
|
||||
featured_list = [
|
||||
artist for artist
|
||||
in extraartists
|
||||
if "Featuring"
|
||||
in artist["role"]]
|
||||
featured, _ = self.get_artist(featured_list,
|
||||
self.config["track_artist_anv"])
|
||||
featured_credit, _ = self.get_artist(featured_list,
|
||||
self.config["artist_credit_anv"])
|
||||
if featured:
|
||||
artist = f"{artist} {self.config['featured_label']} {featured}"
|
||||
artist_credit = f"{artist_credit} {self.config['featured_label']} {featured_credit}"
|
||||
return TrackInfo(
|
||||
title=title,
|
||||
track_id=track_id,
|
||||
artist_credit=artist,
|
||||
artist_credit=artist_credit,
|
||||
artist=artist,
|
||||
artist_id=artist_id,
|
||||
length=length,
|
||||
|
|
|
|||
|
|
@ -452,6 +452,72 @@ class DGAlbumInfoTest(BeetsTestCase):
|
|||
assert d.label == "LABEL NAME (5)"
|
||||
config["discogs"]["strip_disambiguation"] = True
|
||||
|
||||
def test_use_anv(self):
|
||||
test_cases = [
|
||||
({
|
||||
"track_artist": False,
|
||||
"album_artist": False,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTIST NAME & SOLOIST",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTIST Feat. PERFORMER",
|
||||
"track_artist_credit": "ARTIST Feat. PERFORMER"
|
||||
}),
|
||||
({
|
||||
"track_artist": True,
|
||||
"album_artist": False,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTIST NAME & SOLOIST",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTY Feat. FORMER",
|
||||
"track_artist_credit": "ARTIST Feat. PERFORMER"
|
||||
})]
|
||||
data = {
|
||||
"id": 123,
|
||||
"uri": "https://www.discogs.com/release/123456-something",
|
||||
"tracklist": [{
|
||||
"title": "track",
|
||||
"position": "A",
|
||||
"type_": "track",
|
||||
"duration": "5:44",
|
||||
"artists": [{
|
||||
"name": "ARTIST",
|
||||
"tracks": "",
|
||||
"anv": "ARTY",
|
||||
"id": 11146
|
||||
}],
|
||||
"extraartists": [{
|
||||
"name": "PERFORMER",
|
||||
"role": "Featuring",
|
||||
"anv": "FORMER",
|
||||
"id": 787
|
||||
}],
|
||||
}],
|
||||
"artists": [
|
||||
{"name": "ARTIST NAME", "anv": "ARTISTIC", "id": 321, "join": "&"},
|
||||
{"name": "SOLOIST", "anv": "SOLO", "id": 445, "join": ""},
|
||||
],
|
||||
"title": "title",
|
||||
}
|
||||
release = Bag(
|
||||
data=data,
|
||||
title=data["title"],
|
||||
artists=[Bag(data=d) for d in data["artists"]],
|
||||
)
|
||||
for test_case in test_cases:
|
||||
config_input, expected_output = test_case
|
||||
r = DiscogsPlugin().get_album_info(release)
|
||||
config["album_artist_anv"] = config_input["album_artist"]
|
||||
config["track_artist_anv"] = config_input["track_artist"]
|
||||
config["artist_credit_anv"] = config_input["artist_credit"]
|
||||
assert r.artist == expected_output["album_artist"]
|
||||
assert r.artist_credit == expected_output["album_artist_credit"]
|
||||
assert r.tracks[0].artist == expected_output["track_artist"]
|
||||
assert r.tracks[0].artist_credit == expected_output["track_artist_credit"]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"track, expected_artist",
|
||||
|
|
@ -469,23 +535,27 @@ class DGAlbumInfoTest(BeetsTestCase):
|
|||
"extraartists": [
|
||||
{
|
||||
"name": "SOLOIST",
|
||||
"id": 3,
|
||||
"role": "Featuring",
|
||||
},
|
||||
{
|
||||
"name": "PERFORMER (1)",
|
||||
"id": 5,
|
||||
"role": "Other Role, Featuring",
|
||||
},
|
||||
{
|
||||
"name": "RANDOM",
|
||||
"id": 8,
|
||||
"role": "Written-By",
|
||||
},
|
||||
{
|
||||
"name": "MUSICIAN",
|
||||
"id": 10,
|
||||
"role": "Featuring [Uncredited]",
|
||||
},
|
||||
],
|
||||
},
|
||||
"NEW ARTIST, VOCALIST feat. SOLOIST, PERFORMER, MUSICIAN",
|
||||
"NEW ARTIST, VOCALIST Feat. SOLOIST, PERFORMER, MUSICIAN",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
@ -494,7 +564,7 @@ def test_parse_featured_artists(track, expected_artist):
|
|||
"""Tests the plugins ability to parse a featured artist.
|
||||
Initial check with one featured artist, two featured artists,
|
||||
and three. Ignores artists that are not listed as featured."""
|
||||
t = DiscogsPlugin().get_track_info(track, 1, 1, "ARTIST", 2)
|
||||
t = DiscogsPlugin().get_track_info(track, 1, 1, ("ARTIST", 2, "ARTIST CREDIT"))
|
||||
assert t.artist == expected_artist
|
||||
|
||||
|
||||
|
|
@ -520,109 +590,6 @@ def test_get_media_and_albumtype(formats, expected_media, expected_albumtype):
|
|||
|
||||
assert result == (expected_media, expected_albumtype)
|
||||
|
||||
@patch("beetsplug.discogs.DiscogsPlugin.setup", Mock())
|
||||
@pytest.mark.parametrize(
|
||||
"config_input, expected_output",
|
||||
[
|
||||
({
|
||||
"track_artist": False,
|
||||
"album_artist": False,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTIST NAME & SOLOIST",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTIST feat. PERFORMER",
|
||||
"track_artist_credit": "ARTIST feat. PERFORMER"
|
||||
}),
|
||||
({
|
||||
"album_artist": False,
|
||||
"track_artist": True,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTIST NAME & SOLOIST",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTY feat. FORMER",
|
||||
"track_artist_credit": "ARTIST feat. PERFORMER"
|
||||
}),
|
||||
({
|
||||
"album_artist": True,
|
||||
"track_artist": False,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTY & SOLO",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTIST feat. PERFORMER",
|
||||
"track_artist_credit": "ARTIST feat. PERFORMER"
|
||||
}),
|
||||
({
|
||||
"album_artist": True,
|
||||
"track_artist": False,
|
||||
"artist_credit": False
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTY & SOLO",
|
||||
"album_artist_credit": "ARTIST NAME & SOLOIST",
|
||||
"track_artist": "ARTIST feat. PERFORMER",
|
||||
"track_artist_credit": "ARTIST Feat. PERFORMER"
|
||||
}),
|
||||
({
|
||||
"album_artist": False,
|
||||
"track_artist": False,
|
||||
"artist_credit": True
|
||||
},
|
||||
{
|
||||
"album_artist": "ARTIST NAME & SOLOIST",
|
||||
"album_artist_credit": "ARTY & SOLO",
|
||||
"track_artist": "ARTIST feat. PERFORMER",
|
||||
"track_artist_credit": "ARTY Feat. FORMER"
|
||||
})
|
||||
|
||||
])
|
||||
def test_use_anv(config_input, expected_output):
|
||||
d = DiscogsPlugin()
|
||||
d.config["album_artist_anv"] = config_input["album_artist"]
|
||||
d.config["track_artist_anv"] = config_input["track_artist"]
|
||||
d.config["artist_credit_anv"] = config_input["artist_credit"]
|
||||
data = {
|
||||
"id": 123,
|
||||
"uri": "https://www.discogs.com/release/123456-something",
|
||||
"tracklist": [{
|
||||
"title": "track",
|
||||
"position": "A",
|
||||
"type_": "track",
|
||||
"duration": "5:44",
|
||||
"artists": [{
|
||||
"name": "ARTIST",
|
||||
"tracks": "",
|
||||
"anv": "ARTY",
|
||||
"id": 11146
|
||||
}],
|
||||
"extraartists": [{
|
||||
"name": "PERFORMER",
|
||||
"role": "Featuring",
|
||||
"anv": "FORMER",
|
||||
"id": 787
|
||||
}],
|
||||
}],
|
||||
"artists": [
|
||||
{"name": "ARTIST NAME", "anv": "ARTY", "id": 321, "join": "&"},
|
||||
{"name": "SOLOIST", "anv": "SOLO", "id": 445, "join": ""},
|
||||
],
|
||||
"title": "title",
|
||||
}
|
||||
release = Bag(
|
||||
data=data,
|
||||
title=data["title"],
|
||||
artists=[Bag(data=d) for d in data["artists"]],
|
||||
)
|
||||
r = d.get_album_info(release)
|
||||
assert r.artist == expected_output["album_artist"]
|
||||
assert r.artist_credit == expected_output["album_artist_credit"]
|
||||
assert r.tracks[0].artist == expected_output["track_artist"]
|
||||
assert r.tracks[0].artist_credit == expected_output["track_artist_credit"]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"position, medium, index, subindex",
|
||||
|
|
|
|||
Loading…
Reference in a new issue