Skip to content

Commit 88483c4

Browse files
authored
Add method to get several artists (#473)
1 parent ce63565 commit 88483c4

File tree

6 files changed

+287
-56
lines changed

6 files changed

+287
-56
lines changed

poetry.lock

Lines changed: 23 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/spotifyaio/models.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,19 @@ class PlayedTrack(DataClassORJSONMixin):
233233

234234

235235
@dataclass
236-
class ArtistResponse(DataClassORJSONMixin):
236+
class FollowedArtistResponse(DataClassORJSONMixin):
237237
"""Artist response model."""
238238

239239
artists: ArtistResponseItem
240240

241241

242+
@dataclass
243+
class ArtistResponse(DataClassORJSONMixin):
244+
"""Artist response model."""
245+
246+
artists: list[Artist]
247+
248+
242249
@dataclass
243250
class ArtistResponseItem(DataClassORJSONMixin):
244251
"""Artist response model."""

src/spotifyaio/spotify.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@
1212
import orjson
1313
from yarl import URL
1414

15-
from spotifyaio.exceptions import (
16-
SpotifyConnectionError,
17-
SpotifyNotFoundError,
18-
SpotifyRateLimitError,
19-
)
15+
from spotifyaio.exceptions import SpotifyConnectionError, SpotifyNotFoundError
2016
from spotifyaio.models import (
2117
Album,
2218
AlbumsResponse,
@@ -36,6 +32,7 @@
3632
Devices,
3733
Episode,
3834
FeaturedPlaylistResponse,
35+
FollowedArtistResponse,
3936
NewReleasesResponse,
4037
NewReleasesResponseInner,
4138
PlaybackState,
@@ -136,10 +133,6 @@ async def _request(
136133
msg = f"Resource not found: {uri}"
137134
raise SpotifyNotFoundError(msg)
138135

139-
if '"status": 429' in text:
140-
msg = "Ratelimit exceeded"
141-
raise SpotifyRateLimitError(msg)
142-
143136
return text
144137

145138
async def _get(self, uri: str, params: dict[str, Any] | None = None) -> str:
@@ -254,7 +247,18 @@ async def get_artist(self, artist_id: str) -> Artist:
254247
response = await self._get(f"v1/artists/{identifier}")
255248
return Artist.from_json(response)
256249

257-
# Get several artists
250+
async def get_artists(self, artist_ids: list[str]) -> list[Artist]:
251+
"""Get several artists."""
252+
if not artist_ids:
253+
return []
254+
if len(artist_ids) > 50:
255+
msg = "Maximum of 50 artists can be requested at once"
256+
raise ValueError(msg)
257+
params: dict[str, Any] = {
258+
"ids": ",".join([get_identifier(i) for i in artist_ids])
259+
}
260+
response = await self._get("v1/artists", params=params)
261+
return ArtistResponse.from_json(response).artists
258262

259263
async def get_artist_albums(self, artist_id: str) -> list[SimplifiedAlbum]:
260264
"""Get artist albums."""
@@ -569,7 +573,7 @@ async def get_followed_artists(self) -> list[Artist]:
569573
"""Get followed artists."""
570574
params: dict[str, Any] = {"limit": 48, "type": "artist"}
571575
response = await self._get("v1/me/following", params=params)
572-
return ArtistResponse.from_json(response).artists.items
576+
return FollowedArtistResponse.from_json(response).artists.items
573577

574578
# Follow an artist or user
575579

tests/__snapshots__/test_spotify.ambr

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18367,6 +18367,81 @@
1836718367
}),
1836818368
])
1836918369
# ---
18370+
# name: test_get_several_artists
18371+
list([
18372+
dict({
18373+
'artist_id': '2CIMQHirSU0MQqyYHq0eOx',
18374+
'images': list([
18375+
dict({
18376+
'height': 640,
18377+
'url': 'https://i.scdn.co/image/ab6761610000e5eb89ffabe57a25cedeca3309e7',
18378+
'width': 640,
18379+
}),
18380+
dict({
18381+
'height': 320,
18382+
'url': 'https://i.scdn.co/image/ab6761610000517489ffabe57a25cedeca3309e7',
18383+
'width': 320,
18384+
}),
18385+
dict({
18386+
'height': 160,
18387+
'url': 'https://i.scdn.co/image/ab6761610000f17889ffabe57a25cedeca3309e7',
18388+
'width': 160,
18389+
}),
18390+
]),
18391+
'name': 'deadmau5',
18392+
'uri': 'spotify:artist:2CIMQHirSU0MQqyYHq0eOx',
18393+
}),
18394+
dict({
18395+
'artist_id': '57dN52uHvrHOxijzpIgu3E',
18396+
'images': list([
18397+
dict({
18398+
'height': 693,
18399+
'url': 'https://i.scdn.co/image/2f0c6c465a83cd196e651e3d4e7625ba799a6f60',
18400+
'width': 1000,
18401+
}),
18402+
dict({
18403+
'height': 444,
18404+
'url': 'https://i.scdn.co/image/4e3e13c8b993bde9898e49509fb9ae121636e05f',
18405+
'width': 640,
18406+
}),
18407+
dict({
18408+
'height': 139,
18409+
'url': 'https://i.scdn.co/image/dc68dd24b45b74ecce9d4ed486423673d683ced3',
18410+
'width': 200,
18411+
}),
18412+
dict({
18413+
'height': 44,
18414+
'url': 'https://i.scdn.co/image/4e55ca05d4f336a2fa0e3062a7ec9778a201e8bc',
18415+
'width': 63,
18416+
}),
18417+
]),
18418+
'name': 'Ratatat',
18419+
'uri': 'spotify:artist:57dN52uHvrHOxijzpIgu3E',
18420+
}),
18421+
dict({
18422+
'artist_id': '1vCWHaC5f2uS3yhpwWbIA6',
18423+
'images': list([
18424+
dict({
18425+
'height': 640,
18426+
'url': 'https://i.scdn.co/image/ab6761610000e5ebae07171f989fb39736674113',
18427+
'width': 640,
18428+
}),
18429+
dict({
18430+
'height': 320,
18431+
'url': 'https://i.scdn.co/image/ab67616100005174ae07171f989fb39736674113',
18432+
'width': 320,
18433+
}),
18434+
dict({
18435+
'height': 160,
18436+
'url': 'https://i.scdn.co/image/ab6761610000f178ae07171f989fb39736674113',
18437+
'width': 160,
18438+
}),
18439+
]),
18440+
'name': 'Avicii',
18441+
'uri': 'spotify:artist:1vCWHaC5f2uS3yhpwWbIA6',
18442+
}),
18443+
])
18444+
# ---
1837018445
# name: test_get_show
1837118446
dict({
1837218447
'description': 'Safety Third is a weekly show hosted by William Osman, NileRed, The Backyard Scientist, Allen Pan, and a couple other YouTube "Scientists". Sometimes we have guests, sometimes it\'s just us, but always: safety is our number three priority.',

0 commit comments

Comments
 (0)