deezer-python 6.1.1__py3-none-any.whl → 7.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deezer/__init__.py +1 -1
- deezer/auth.py +27 -0
- deezer/client.py +51 -59
- deezer/exceptions.py +6 -6
- deezer/pagination.py +7 -9
- deezer/resources/editorial.py +4 -4
- deezer/resources/episode.py +4 -5
- deezer/resources/playlist.py +8 -14
- deezer/resources/resource.py +15 -11
- deezer/resources/user.py +22 -22
- {deezer_python-6.1.1.dist-info → deezer_python-7.0.0.dist-info}/METADATA +6 -6
- deezer_python-7.0.0.dist-info/RECORD +24 -0
- {deezer_python-6.1.1.dist-info → deezer_python-7.0.0.dist-info}/WHEEL +1 -1
- deezer_python-6.1.1.dist-info/RECORD +0 -23
- {deezer_python-6.1.1.dist-info → deezer_python-7.0.0.dist-info}/LICENSE.txt +0 -0
deezer/__init__.py
CHANGED
deezer/auth.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DeezerQueryAuth(httpx.Auth):
|
|
7
|
+
"""
|
|
8
|
+
Deezer Auth for httpx.
|
|
9
|
+
|
|
10
|
+
Attach given access token to the request,
|
|
11
|
+
by passing it as query parameter.
|
|
12
|
+
|
|
13
|
+
:param access_token: Your Deezer access token.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, access_token: str):
|
|
17
|
+
self.access_token = access_token
|
|
18
|
+
|
|
19
|
+
def auth_flow(self, request: httpx.Request) -> typing.Generator[httpx.Request, None, None]:
|
|
20
|
+
"""
|
|
21
|
+
Add authentication query parameter to the request.
|
|
22
|
+
|
|
23
|
+
:param request: httpx.Request
|
|
24
|
+
:return: httpx.Request
|
|
25
|
+
"""
|
|
26
|
+
request.url = request.url.copy_merge_params({"access_token": self.access_token})
|
|
27
|
+
yield request
|
deezer/client.py
CHANGED
|
@@ -2,8 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, ClassVar
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import httpx
|
|
6
|
+
from httpx._types import HeaderTypes
|
|
6
7
|
|
|
8
|
+
from deezer.auth import DeezerQueryAuth
|
|
7
9
|
from deezer.exceptions import (
|
|
8
10
|
DeezerErrorResponse,
|
|
9
11
|
DeezerHTTPError,
|
|
@@ -26,7 +28,7 @@ from deezer.resources import (
|
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
class Client:
|
|
31
|
+
class Client(httpx.Client):
|
|
30
32
|
"""
|
|
31
33
|
A client to retrieve some basic infos about Deezer resources.
|
|
32
34
|
|
|
@@ -34,7 +36,7 @@ class Client:
|
|
|
34
36
|
be passed in to the constructor as kwargs.
|
|
35
37
|
|
|
36
38
|
>>> import deezer
|
|
37
|
-
>>> client = deezer.Client(
|
|
39
|
+
>>> client = deezer.Client()
|
|
38
40
|
|
|
39
41
|
This client provides several methods to retrieve the content most
|
|
40
42
|
kinds of Deezer objects, based on their json structure.
|
|
@@ -45,8 +47,6 @@ class Client:
|
|
|
45
47
|
>>> import deezer
|
|
46
48
|
>>> client = deezer.Client(headers={'Accept-Language': 'fr'})
|
|
47
49
|
|
|
48
|
-
:param app_id: application ID.
|
|
49
|
-
:param app_secret: application secret.
|
|
50
50
|
:param access_token: user access token.
|
|
51
51
|
:param headers: a dictionary of headers to be used.
|
|
52
52
|
"""
|
|
@@ -66,18 +66,21 @@ class Client:
|
|
|
66
66
|
"track": Track,
|
|
67
67
|
"user": User,
|
|
68
68
|
}
|
|
69
|
-
base_url = "https://api.deezer.com"
|
|
70
69
|
|
|
71
70
|
def __init__(
|
|
72
|
-
self,
|
|
71
|
+
self,
|
|
72
|
+
access_token: str | None = None,
|
|
73
|
+
headers: HeaderTypes | None = None,
|
|
73
74
|
):
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
if access_token:
|
|
76
|
+
deezer_auth = DeezerQueryAuth(access_token=access_token)
|
|
77
|
+
else:
|
|
78
|
+
deezer_auth = None
|
|
79
|
+
super().__init__(
|
|
80
|
+
base_url="https://api.deezer.com",
|
|
81
|
+
auth=deezer_auth,
|
|
82
|
+
headers=headers,
|
|
83
|
+
)
|
|
81
84
|
|
|
82
85
|
def _process_json(
|
|
83
86
|
self,
|
|
@@ -98,9 +101,7 @@ class Client:
|
|
|
98
101
|
:returns: instance of :class:`~deezer.Resource`
|
|
99
102
|
"""
|
|
100
103
|
if "data" in item:
|
|
101
|
-
parsed_data = [
|
|
102
|
-
self._process_json(i, parent, paginate_list=False) for i in item["data"]
|
|
103
|
-
]
|
|
104
|
+
parsed_data = [self._process_json(i, parent, paginate_list=False) for i in item["data"]]
|
|
104
105
|
if not paginate_list:
|
|
105
106
|
return parsed_data
|
|
106
107
|
item["data"] = parsed_data
|
|
@@ -139,7 +140,7 @@ class Client:
|
|
|
139
140
|
resource_type: type[Resource] | None = None,
|
|
140
141
|
resource_id: int | None = None,
|
|
141
142
|
paginate_list=False,
|
|
142
|
-
**
|
|
143
|
+
**kwargs,
|
|
143
144
|
):
|
|
144
145
|
"""
|
|
145
146
|
Make a request to the API and parse the response.
|
|
@@ -150,23 +151,20 @@ class Client:
|
|
|
150
151
|
:param resource_type: The resource class to use as top level.
|
|
151
152
|
:param resource_id: The resource id to use as top level.
|
|
152
153
|
:param paginate_list: Whether to wrap list into a pagination object.
|
|
153
|
-
:param params: Query parameters to add to the request
|
|
154
154
|
"""
|
|
155
|
-
|
|
156
|
-
params["access_token"] = str(self.access_token)
|
|
157
|
-
response = self.session.request(
|
|
155
|
+
response = super().request(
|
|
158
156
|
method,
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
path,
|
|
158
|
+
**kwargs,
|
|
161
159
|
)
|
|
162
160
|
try:
|
|
163
161
|
response.raise_for_status()
|
|
164
|
-
except
|
|
162
|
+
except httpx.HTTPStatusError as exc:
|
|
165
163
|
raise DeezerHTTPError.from_http_error(exc) from exc
|
|
166
164
|
json_data = response.json()
|
|
167
165
|
if not isinstance(json_data, dict):
|
|
168
166
|
return json_data
|
|
169
|
-
if
|
|
167
|
+
if json_data.get("error"):
|
|
170
168
|
raise DeezerErrorResponse(json_data)
|
|
171
169
|
return self._process_json(
|
|
172
170
|
json_data,
|
|
@@ -176,8 +174,8 @@ class Client:
|
|
|
176
174
|
paginate_list=paginate_list,
|
|
177
175
|
)
|
|
178
176
|
|
|
179
|
-
def _get_paginated_list(self, path,
|
|
180
|
-
return PaginatedList(client=self, base_path=path,
|
|
177
|
+
def _get_paginated_list(self, path: str, params: dict | None = None):
|
|
178
|
+
return PaginatedList(client=self, base_path=path, params=params)
|
|
181
179
|
|
|
182
180
|
def get_album(self, album_id: int) -> Album:
|
|
183
181
|
"""
|
|
@@ -204,9 +202,7 @@ class Client:
|
|
|
204
202
|
:param genre_id: the genre ID, default to `All` genre (genre_id = 0).
|
|
205
203
|
:returns: a :class:`~deezer.Chart` instance.
|
|
206
204
|
"""
|
|
207
|
-
return self.request(
|
|
208
|
-
"GET", f"chart/{genre_id}", resource_type=Chart, resource_id=genre_id
|
|
209
|
-
)
|
|
205
|
+
return self.request("GET", f"chart/{genre_id}", resource_type=Chart, resource_id=genre_id)
|
|
210
206
|
|
|
211
207
|
def get_tracks_chart(self, genre_id: int = 0) -> list[Track]:
|
|
212
208
|
"""
|
|
@@ -359,9 +355,7 @@ class Client:
|
|
|
359
355
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
360
356
|
of :class:`Track <deezer.Track>` instances
|
|
361
357
|
"""
|
|
362
|
-
return PaginatedList(
|
|
363
|
-
client=self, base_path="user/me/recommendations/tracks", **kwargs
|
|
364
|
-
)
|
|
358
|
+
return PaginatedList(client=self, base_path="user/me/recommendations/tracks", **kwargs)
|
|
365
359
|
|
|
366
360
|
def get_user_recommended_albums(self, **kwargs) -> PaginatedList[Album]:
|
|
367
361
|
"""
|
|
@@ -370,9 +364,7 @@ class Client:
|
|
|
370
364
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
371
365
|
of :class:`Track <deezer.Album>` instances
|
|
372
366
|
"""
|
|
373
|
-
return PaginatedList(
|
|
374
|
-
client=self, base_path="user/me/recommendations/albums", **kwargs
|
|
375
|
-
)
|
|
367
|
+
return PaginatedList(client=self, base_path="user/me/recommendations/albums", **kwargs)
|
|
376
368
|
|
|
377
369
|
def get_user_recommended_artists(self, **kwargs) -> PaginatedList[Artist]:
|
|
378
370
|
"""
|
|
@@ -381,9 +373,7 @@ class Client:
|
|
|
381
373
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
382
374
|
of :class:`Track <deezer.Artist>` instances
|
|
383
375
|
"""
|
|
384
|
-
return PaginatedList(
|
|
385
|
-
client=self, base_path="user/me/recommendations/artists", **kwargs
|
|
386
|
-
)
|
|
376
|
+
return PaginatedList(client=self, base_path="user/me/recommendations/artists", **kwargs)
|
|
387
377
|
|
|
388
378
|
def get_user_recommended_playlists(self, **kwargs) -> PaginatedList[Playlist]:
|
|
389
379
|
"""
|
|
@@ -392,9 +382,7 @@ class Client:
|
|
|
392
382
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
393
383
|
of :class:`Track <deezer.Playlist>` instances
|
|
394
384
|
"""
|
|
395
|
-
return PaginatedList(
|
|
396
|
-
client=self, base_path="user/me/recommendations/playlists", **kwargs
|
|
397
|
-
)
|
|
385
|
+
return PaginatedList(client=self, base_path="user/me/recommendations/playlists", **kwargs)
|
|
398
386
|
|
|
399
387
|
def get_user_flow(self, **kwargs) -> PaginatedList[Track]:
|
|
400
388
|
"""
|
|
@@ -423,7 +411,7 @@ class Client:
|
|
|
423
411
|
:param album_id: the ID of the album to add.
|
|
424
412
|
:return: boolean whether the operation succeeded.
|
|
425
413
|
"""
|
|
426
|
-
return self.request("POST", "user/me/albums",
|
|
414
|
+
return self.request("POST", "user/me/albums", params={"album_id": album_id})
|
|
427
415
|
|
|
428
416
|
def remove_user_album(self, album_id: int) -> bool:
|
|
429
417
|
"""
|
|
@@ -432,7 +420,7 @@ class Client:
|
|
|
432
420
|
:param album_id: the ID of the album to remove.
|
|
433
421
|
:return: boolean whether the operation succeeded.
|
|
434
422
|
"""
|
|
435
|
-
return self.request("DELETE", "user/me/albums",
|
|
423
|
+
return self.request("DELETE", "user/me/albums", params={"album_id": album_id})
|
|
436
424
|
|
|
437
425
|
def get_user_artists(self, user_id: int | None = None) -> PaginatedList[Artist]:
|
|
438
426
|
"""
|
|
@@ -452,7 +440,7 @@ class Client:
|
|
|
452
440
|
:param artist_id: the ID of the artist to add.
|
|
453
441
|
:return: boolean whether the operation succeeded.
|
|
454
442
|
"""
|
|
455
|
-
return self.request("POST", "user/me/artists",
|
|
443
|
+
return self.request("POST", "user/me/artists", params={"artist_id": artist_id})
|
|
456
444
|
|
|
457
445
|
def remove_user_artist(self, artist_id: int) -> bool:
|
|
458
446
|
"""
|
|
@@ -461,7 +449,11 @@ class Client:
|
|
|
461
449
|
:param artist_id: the ID of the artist to remove.
|
|
462
450
|
:return: boolean whether the operation succeeded.
|
|
463
451
|
"""
|
|
464
|
-
return self.request(
|
|
452
|
+
return self.request(
|
|
453
|
+
"DELETE",
|
|
454
|
+
"user/me/artists",
|
|
455
|
+
params={"artist_id": artist_id},
|
|
456
|
+
)
|
|
465
457
|
|
|
466
458
|
def get_user_followers(self, user_id: int | None = None) -> PaginatedList[User]:
|
|
467
459
|
"""
|
|
@@ -492,7 +484,7 @@ class Client:
|
|
|
492
484
|
:param user_id: the ID of the user to follow.
|
|
493
485
|
:return: boolean whether the operation succeeded.
|
|
494
486
|
"""
|
|
495
|
-
return self.request("POST", "user/me/followings",
|
|
487
|
+
return self.request("POST", "user/me/followings", params={"user_id": user_id})
|
|
496
488
|
|
|
497
489
|
def remove_user_following(self, user_id: int) -> bool:
|
|
498
490
|
"""
|
|
@@ -501,7 +493,7 @@ class Client:
|
|
|
501
493
|
:param user_id: the ID of the user to stop following.
|
|
502
494
|
:return: boolean whether the operation succeeded.
|
|
503
495
|
"""
|
|
504
|
-
return self.request("DELETE", "user/me/followings",
|
|
496
|
+
return self.request("DELETE", "user/me/followings", params={"user_id": user_id})
|
|
505
497
|
|
|
506
498
|
def get_user_history(self) -> PaginatedList[Track]:
|
|
507
499
|
"""
|
|
@@ -530,7 +522,7 @@ class Client:
|
|
|
530
522
|
:param track_id: the ID of the track to add.
|
|
531
523
|
:return: boolean whether the operation succeeded.
|
|
532
524
|
"""
|
|
533
|
-
return self.request("POST", "user/me/tracks",
|
|
525
|
+
return self.request("POST", "user/me/tracks", params={"track_id": track_id})
|
|
534
526
|
|
|
535
527
|
def remove_user_track(self, track_id: int) -> bool:
|
|
536
528
|
"""
|
|
@@ -539,7 +531,7 @@ class Client:
|
|
|
539
531
|
:param track_id: the ID of the track to remove.
|
|
540
532
|
:return: boolean whether the operation succeeded.
|
|
541
533
|
"""
|
|
542
|
-
return self.request("DELETE", "user/me/tracks",
|
|
534
|
+
return self.request("DELETE", "user/me/tracks", params={"track_id": track_id})
|
|
543
535
|
|
|
544
536
|
def remove_user_playlist(self, playlist_id: int) -> bool:
|
|
545
537
|
"""
|
|
@@ -548,7 +540,7 @@ class Client:
|
|
|
548
540
|
:param playlist_id: the ID of the playlist to remove.
|
|
549
541
|
:return: boolean whether the operation succeeded.
|
|
550
542
|
"""
|
|
551
|
-
return self.request("DELETE", "user/me/playlists",
|
|
543
|
+
return self.request("DELETE", "user/me/playlists", params={"playlist_id": playlist_id})
|
|
552
544
|
|
|
553
545
|
def add_user_playlist(self, playlist_id: int) -> bool:
|
|
554
546
|
"""
|
|
@@ -557,7 +549,7 @@ class Client:
|
|
|
557
549
|
:param playlist_id: the ID of the playlist to add.
|
|
558
550
|
:return: boolean whether the operation succeeded.
|
|
559
551
|
"""
|
|
560
|
-
return self.request("POST", "user/me/playlists",
|
|
552
|
+
return self.request("POST", "user/me/playlists", params={"playlist_id": playlist_id})
|
|
561
553
|
|
|
562
554
|
def create_playlist(self, playlist_name) -> int:
|
|
563
555
|
"""
|
|
@@ -566,7 +558,7 @@ class Client:
|
|
|
566
558
|
:param playlist_name: the name of the playlist.
|
|
567
559
|
:return: the ID of the playlist that was created
|
|
568
560
|
"""
|
|
569
|
-
result = self.request("POST", "user/me/playlists", title
|
|
561
|
+
result = self.request("POST", "user/me/playlists", params={"title": playlist_name})
|
|
570
562
|
# Note: the REST API call returns a dict with just the "id" key in it,
|
|
571
563
|
# so we return that instead of the full Playlist object
|
|
572
564
|
return result.id
|
|
@@ -597,15 +589,15 @@ class Client:
|
|
|
597
589
|
if query:
|
|
598
590
|
query_parts.append(query)
|
|
599
591
|
query_parts.extend(
|
|
600
|
-
f'{param_name}:"{param_value}"'
|
|
601
|
-
for param_name, param_value in advanced_params.items()
|
|
602
|
-
if param_value
|
|
592
|
+
f'{param_name}:"{param_value}"' for param_name, param_value in advanced_params.items() if param_value
|
|
603
593
|
)
|
|
604
594
|
|
|
605
595
|
return self._get_paginated_list(
|
|
606
596
|
path=f"search/{path}" if path else "search",
|
|
607
|
-
|
|
608
|
-
|
|
597
|
+
params={
|
|
598
|
+
"q": " ".join(query_parts),
|
|
599
|
+
**optional_params,
|
|
600
|
+
},
|
|
609
601
|
)
|
|
610
602
|
|
|
611
603
|
def search(
|
deezer/exceptions.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import httpx
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class DeezerAPIException(Exception):
|
|
@@ -12,9 +12,9 @@ class DeezerRetryableException(DeezerAPIException):
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DeezerHTTPError(DeezerAPIException):
|
|
15
|
-
"""
|
|
15
|
+
"""Specialization wrapping HTTPError from the httpx library."""
|
|
16
16
|
|
|
17
|
-
def __init__(self, http_exception:
|
|
17
|
+
def __init__(self, http_exception: httpx.HTTPStatusError, *args: object) -> None:
|
|
18
18
|
if http_exception.response is not None and http_exception.response.text:
|
|
19
19
|
url = http_exception.response.request.url
|
|
20
20
|
status_code = http_exception.response.status_code
|
|
@@ -24,8 +24,8 @@ class DeezerHTTPError(DeezerAPIException):
|
|
|
24
24
|
super().__init__(http_exception, *args)
|
|
25
25
|
|
|
26
26
|
@classmethod
|
|
27
|
-
def from_http_error(cls, exc:
|
|
28
|
-
"""
|
|
27
|
+
def from_http_error(cls, exc: httpx.HTTPStatusError) -> DeezerHTTPError:
|
|
28
|
+
"""Initialize the appropriate internal exception from a HTTPError."""
|
|
29
29
|
if exc.response is not None:
|
|
30
30
|
if exc.response.status_code in {502, 503, 504}:
|
|
31
31
|
return DeezerRetryableHTTPError(exc)
|
|
@@ -37,7 +37,7 @@ class DeezerHTTPError(DeezerAPIException):
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class DeezerRetryableHTTPError(DeezerRetryableException, DeezerHTTPError):
|
|
40
|
-
"""
|
|
40
|
+
"""An HTTP error due to a potentially temporary issue."""
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class DeezerForbiddenError(DeezerHTTPError):
|
deezer/pagination.py
CHANGED
|
@@ -20,14 +20,14 @@ class PaginatedList(Generic[ResourceType]):
|
|
|
20
20
|
client: deezer.Client,
|
|
21
21
|
base_path: str,
|
|
22
22
|
parent: deezer.Resource | None = None,
|
|
23
|
-
|
|
23
|
+
params: dict | None = None,
|
|
24
24
|
):
|
|
25
25
|
self.__elements: list[ResourceType] = []
|
|
26
26
|
self.__client = client
|
|
27
27
|
self.__base_path = base_path
|
|
28
|
-
self.__base_params = params
|
|
28
|
+
self.__base_params = params or {}
|
|
29
29
|
self.__next_path: str | None = base_path
|
|
30
|
-
self.__next_params = params
|
|
30
|
+
self.__next_params = params or {}
|
|
31
31
|
self.__parent = parent
|
|
32
32
|
self.__total = None
|
|
33
33
|
self.__iter = iter(self)
|
|
@@ -41,12 +41,10 @@ class PaginatedList(Generic[ResourceType]):
|
|
|
41
41
|
return f"<{self.__class__.__name__} {data!r}>"
|
|
42
42
|
|
|
43
43
|
@overload
|
|
44
|
-
def __getitem__(self, index: int) -> ResourceType:
|
|
45
|
-
...
|
|
44
|
+
def __getitem__(self, index: int) -> ResourceType: ...
|
|
46
45
|
|
|
47
46
|
@overload
|
|
48
|
-
def __getitem__(self, index: slice) -> list[ResourceType]:
|
|
49
|
-
...
|
|
47
|
+
def __getitem__(self, index: slice) -> list[ResourceType]: ...
|
|
50
48
|
|
|
51
49
|
def __getitem__(
|
|
52
50
|
self,
|
|
@@ -92,7 +90,7 @@ class PaginatedList(Generic[ResourceType]):
|
|
|
92
90
|
self.__next_path,
|
|
93
91
|
parent=self.__parent,
|
|
94
92
|
paginate_list=True,
|
|
95
|
-
|
|
93
|
+
params=self.__next_params,
|
|
96
94
|
)
|
|
97
95
|
self.__next_path = None
|
|
98
96
|
self.__total = response_payload.get("total")
|
|
@@ -118,7 +116,7 @@ class PaginatedList(Generic[ResourceType]):
|
|
|
118
116
|
self.__base_path,
|
|
119
117
|
parent=self.__parent,
|
|
120
118
|
paginate_list=True,
|
|
121
|
-
|
|
119
|
+
params=params,
|
|
122
120
|
)
|
|
123
121
|
self.__total = response_payload["total"]
|
|
124
122
|
assert self.__total is not None # noqa S101
|
deezer/resources/editorial.py
CHANGED
|
@@ -26,21 +26,21 @@ class Editorial(Resource):
|
|
|
26
26
|
picture_big: str
|
|
27
27
|
picture_xl: str
|
|
28
28
|
|
|
29
|
-
def get_selection(self
|
|
29
|
+
def get_selection(self) -> list[Album]:
|
|
30
30
|
"""
|
|
31
31
|
Get a list of albums selected every week by the Deezer Team.
|
|
32
32
|
|
|
33
33
|
:returns: a list of :class:`Album <deezer.Album>` instances
|
|
34
34
|
"""
|
|
35
|
-
return self.get_relation("selection"
|
|
35
|
+
return self.get_relation("selection")
|
|
36
36
|
|
|
37
|
-
def get_chart(self
|
|
37
|
+
def get_chart(self) -> Chart:
|
|
38
38
|
"""
|
|
39
39
|
Get top charts for tracks, albums, artists and playlists.
|
|
40
40
|
|
|
41
41
|
:returns: a :class:`~deezer.Chart` instance
|
|
42
42
|
"""
|
|
43
|
-
return self.get_relation("charts", resource_type=Chart
|
|
43
|
+
return self.get_relation("charts", resource_type=Chart)
|
|
44
44
|
|
|
45
45
|
def get_releases(self, **kwargs) -> PaginatedList[Album]:
|
|
46
46
|
"""
|
deezer/resources/episode.py
CHANGED
|
@@ -42,7 +42,7 @@ class Episode(Resource):
|
|
|
42
42
|
return f"{self.link}?utm_source=deezer&utm_content=episode-{self.id}&utm_medium=web"
|
|
43
43
|
return super()._infer_missing_field(item)
|
|
44
44
|
|
|
45
|
-
def add_bookmark(self, offset: int
|
|
45
|
+
def add_bookmark(self, offset: int) -> bool:
|
|
46
46
|
"""
|
|
47
47
|
Sets a bookmark on the episode.
|
|
48
48
|
|
|
@@ -52,14 +52,13 @@ class Episode(Resource):
|
|
|
52
52
|
return self.client.request(
|
|
53
53
|
"POST",
|
|
54
54
|
f"episode/{self.id}/bookmark",
|
|
55
|
-
|
|
56
|
-
**kwargs,
|
|
55
|
+
params={"offset": offset},
|
|
57
56
|
)
|
|
58
57
|
|
|
59
|
-
def remove_bookmark(self
|
|
58
|
+
def remove_bookmark(self) -> bool:
|
|
60
59
|
"""
|
|
61
60
|
Removes the bookmark on the episode.
|
|
62
61
|
|
|
63
62
|
:returns: a boolean that tells if the operation was successful
|
|
64
63
|
"""
|
|
65
|
-
return self.client.request("DELETE", f"episode/{self.id}/bookmark"
|
|
64
|
+
return self.client.request("DELETE", f"episode/{self.id}/bookmark")
|
deezer/resources/playlist.py
CHANGED
|
@@ -58,15 +58,15 @@ class Playlist(Resource):
|
|
|
58
58
|
"""
|
|
59
59
|
return self.get_paginated_list("fans", **kwargs)
|
|
60
60
|
|
|
61
|
-
def mark_seen(self
|
|
61
|
+
def mark_seen(self) -> bool:
|
|
62
62
|
"""
|
|
63
63
|
Mark the playlist as seen.
|
|
64
64
|
|
|
65
65
|
:returns: a boolean that tells if the operation was successful
|
|
66
66
|
"""
|
|
67
|
-
return self.client.request("POST", f"playlist/{self.id}/seen"
|
|
67
|
+
return self.client.request("POST", f"playlist/{self.id}/seen")
|
|
68
68
|
|
|
69
|
-
def add_tracks(self, tracks: Iterable[int | Track]
|
|
69
|
+
def add_tracks(self, tracks: Iterable[int | Track]) -> bool:
|
|
70
70
|
"""
|
|
71
71
|
Add tracks to a playlist.
|
|
72
72
|
|
|
@@ -75,11 +75,9 @@ class Playlist(Resource):
|
|
|
75
75
|
:returns: a boolean that tells if the operation was successful
|
|
76
76
|
"""
|
|
77
77
|
track_ids_str = ",".join(str(tid) for tid in gen_ids(tracks))
|
|
78
|
-
return self.client.request(
|
|
79
|
-
"POST", f"playlist/{self.id}/tracks", songs=track_ids_str, **kwargs
|
|
80
|
-
)
|
|
78
|
+
return self.client.request("POST", f"playlist/{self.id}/tracks", params={"songs": track_ids_str})
|
|
81
79
|
|
|
82
|
-
def delete_tracks(self, tracks: Iterable[int | Track]
|
|
80
|
+
def delete_tracks(self, tracks: Iterable[int | Track]) -> bool:
|
|
83
81
|
"""
|
|
84
82
|
Delete tracks from a playlist.
|
|
85
83
|
|
|
@@ -88,11 +86,9 @@ class Playlist(Resource):
|
|
|
88
86
|
:returns: a boolean that tells if the operation was successful
|
|
89
87
|
"""
|
|
90
88
|
track_ids_str = ",".join(map(str, gen_ids(tracks)))
|
|
91
|
-
return self.client.request(
|
|
92
|
-
"DELETE", f"playlist/{self.id}/tracks", songs=track_ids_str, **kwargs
|
|
93
|
-
)
|
|
89
|
+
return self.client.request("DELETE", f"playlist/{self.id}/tracks", params={"songs": track_ids_str})
|
|
94
90
|
|
|
95
|
-
def reorder_tracks(self, order: Iterable[int | Track]
|
|
91
|
+
def reorder_tracks(self, order: Iterable[int | Track]) -> bool:
|
|
96
92
|
"""
|
|
97
93
|
Reorder the tracks of a playlist.
|
|
98
94
|
|
|
@@ -101,6 +97,4 @@ class Playlist(Resource):
|
|
|
101
97
|
:returns: a boolean that tells if the operation was successful
|
|
102
98
|
"""
|
|
103
99
|
order_track_ids_str = ",".join(map(str, gen_ids(order)))
|
|
104
|
-
return self.client.request(
|
|
105
|
-
"POST", f"playlist/{self.id}/tracks", order=order_track_ids_str, **kwargs
|
|
106
|
-
)
|
|
100
|
+
return self.client.request("POST", f"playlist/{self.id}/tracks", params={"order": order_track_ids_str})
|
deezer/resources/resource.py
CHANGED
|
@@ -56,7 +56,12 @@ class Resource:
|
|
|
56
56
|
result[key] = value
|
|
57
57
|
return result
|
|
58
58
|
|
|
59
|
-
def get_relation(
|
|
59
|
+
def get_relation(
|
|
60
|
+
self,
|
|
61
|
+
relation: str,
|
|
62
|
+
resource_type: type[Resource] | None = None, # type: ignore[valid-type]
|
|
63
|
+
params: dict | None = None,
|
|
64
|
+
):
|
|
60
65
|
"""
|
|
61
66
|
Generic method to load the relation from any resource.
|
|
62
67
|
|
|
@@ -69,10 +74,11 @@ class Resource:
|
|
|
69
74
|
"GET",
|
|
70
75
|
f"{self.type}/{self.id}/{relation}",
|
|
71
76
|
parent=self,
|
|
72
|
-
|
|
77
|
+
resource_type=resource_type,
|
|
78
|
+
params=params,
|
|
73
79
|
)
|
|
74
80
|
|
|
75
|
-
def post_relation(self, relation,
|
|
81
|
+
def post_relation(self, relation: str, params: dict):
|
|
76
82
|
"""
|
|
77
83
|
Generic method to make a POST request to a relation from any resource.
|
|
78
84
|
|
|
@@ -82,10 +88,10 @@ class Resource:
|
|
|
82
88
|
return self.client.request(
|
|
83
89
|
"POST",
|
|
84
90
|
f"{self.type}/{self.id}/{relation}",
|
|
85
|
-
|
|
91
|
+
params=params,
|
|
86
92
|
)
|
|
87
93
|
|
|
88
|
-
def delete_relation(self, relation,
|
|
94
|
+
def delete_relation(self, relation: str, params: dict | None = None):
|
|
89
95
|
"""
|
|
90
96
|
Generic method to make a DELETE request to a relation from any resource.
|
|
91
97
|
|
|
@@ -95,20 +101,20 @@ class Resource:
|
|
|
95
101
|
return self.client.request(
|
|
96
102
|
"DELETE",
|
|
97
103
|
f"{self.type}/{self.id}/{relation}",
|
|
98
|
-
|
|
104
|
+
params=params,
|
|
99
105
|
)
|
|
100
106
|
|
|
101
107
|
def get_paginated_list(
|
|
102
108
|
self,
|
|
103
109
|
relation: str,
|
|
104
|
-
|
|
110
|
+
params: dict | None = None,
|
|
105
111
|
) -> PaginatedList:
|
|
106
112
|
"""Build the pagination object based on the relation."""
|
|
107
113
|
return PaginatedList(
|
|
108
114
|
client=self.client,
|
|
109
115
|
base_path=f"{self.type}/{self.id}/{relation}",
|
|
110
116
|
parent=self,
|
|
111
|
-
|
|
117
|
+
params=params,
|
|
112
118
|
)
|
|
113
119
|
|
|
114
120
|
def __getattr__(self, item: str) -> Any:
|
|
@@ -132,9 +138,7 @@ class Resource:
|
|
|
132
138
|
setattr(self, field_name, getattr(full_resource, field_name))
|
|
133
139
|
self._fields += (field_name,)
|
|
134
140
|
return getattr(self, item)
|
|
135
|
-
raise AttributeError(
|
|
136
|
-
f"'{self.__class__.__name__}' object has no attribute '{item}'"
|
|
137
|
-
)
|
|
141
|
+
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'")
|
|
138
142
|
|
|
139
143
|
def _infer_missing_field(self, item: str) -> Any:
|
|
140
144
|
"""
|
deezer/resources/user.py
CHANGED
|
@@ -48,14 +48,14 @@ class User(Resource):
|
|
|
48
48
|
_parse_birthday = staticmethod(parse_date)
|
|
49
49
|
_parse_inscription_date = staticmethod(parse_date)
|
|
50
50
|
|
|
51
|
-
def get_albums(self, **
|
|
51
|
+
def get_albums(self, **params) -> PaginatedList[Album]:
|
|
52
52
|
"""
|
|
53
53
|
Get user's favorite albums.
|
|
54
54
|
|
|
55
55
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
56
56
|
of :class:`Album <deezer.Album>` instances
|
|
57
57
|
"""
|
|
58
|
-
return self.get_paginated_list("albums",
|
|
58
|
+
return self.get_paginated_list("albums", params=params)
|
|
59
59
|
|
|
60
60
|
def add_album(self, album: Album | int):
|
|
61
61
|
"""
|
|
@@ -64,7 +64,7 @@ class User(Resource):
|
|
|
64
64
|
:param album: an :class:`~deezer.Album` instance or its ID
|
|
65
65
|
:returns: a boolean that tells if the operation was successful
|
|
66
66
|
"""
|
|
67
|
-
return self.post_relation("albums", album_id
|
|
67
|
+
return self.post_relation("albums", params={"album_id": get_id(album)})
|
|
68
68
|
|
|
69
69
|
def remove_album(self, album: Album | int):
|
|
70
70
|
"""
|
|
@@ -73,7 +73,7 @@ class User(Resource):
|
|
|
73
73
|
:param album: an :class:`~deezer.Album` instance or its ID
|
|
74
74
|
:returns: a boolean that tells if the operation was successful
|
|
75
75
|
"""
|
|
76
|
-
return self.delete_relation("albums", album_id
|
|
76
|
+
return self.delete_relation("albums", params={"album_id": get_id(album)})
|
|
77
77
|
|
|
78
78
|
def get_tracks(self, **kwargs) -> PaginatedList[Track]:
|
|
79
79
|
"""
|
|
@@ -82,7 +82,7 @@ class User(Resource):
|
|
|
82
82
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
83
83
|
of :class:`Track <deezer.Track>` instances
|
|
84
84
|
"""
|
|
85
|
-
return self.get_paginated_list("tracks"
|
|
85
|
+
return self.get_paginated_list("tracks")
|
|
86
86
|
|
|
87
87
|
def add_track(self, track: Track | int):
|
|
88
88
|
"""
|
|
@@ -91,7 +91,7 @@ class User(Resource):
|
|
|
91
91
|
:param track: a :class:`~deezer.Track` instance or its ID
|
|
92
92
|
:returns: a boolean that tells if the operation was successful
|
|
93
93
|
"""
|
|
94
|
-
return self.post_relation("tracks", track_id
|
|
94
|
+
return self.post_relation("tracks", params={"track_id": get_id(track)})
|
|
95
95
|
|
|
96
96
|
def remove_track(self, track: Track | int):
|
|
97
97
|
"""
|
|
@@ -100,16 +100,16 @@ class User(Resource):
|
|
|
100
100
|
:param track: a :class:`~deezer.Track` instance or its ID
|
|
101
101
|
:returns: a boolean that tells if the operation was successful
|
|
102
102
|
"""
|
|
103
|
-
return self.delete_relation("tracks", track_id
|
|
103
|
+
return self.delete_relation("tracks", params={"track_id": get_id(track)})
|
|
104
104
|
|
|
105
|
-
def get_artists(self, **
|
|
105
|
+
def get_artists(self, **params) -> PaginatedList[Artist]:
|
|
106
106
|
"""
|
|
107
107
|
Get user's favorite artists.
|
|
108
108
|
|
|
109
109
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
110
110
|
of :class:`Artist <deezer.Artist>` instances
|
|
111
111
|
"""
|
|
112
|
-
return self.get_paginated_list("artists",
|
|
112
|
+
return self.get_paginated_list("artists", params=params)
|
|
113
113
|
|
|
114
114
|
def add_artist(self, artist: Artist | int):
|
|
115
115
|
"""
|
|
@@ -118,7 +118,7 @@ class User(Resource):
|
|
|
118
118
|
:param artist: an :class:`~deezer.Artist` instance or its ID
|
|
119
119
|
:returns: a boolean that tells if the operation was successful
|
|
120
120
|
"""
|
|
121
|
-
return self.post_relation("artists", artist_id
|
|
121
|
+
return self.post_relation("artists", params={"artist_id": get_id(artist)})
|
|
122
122
|
|
|
123
123
|
def remove_artist(self, artist: Artist | int):
|
|
124
124
|
"""
|
|
@@ -127,25 +127,25 @@ class User(Resource):
|
|
|
127
127
|
:param artist: an :class:`~deezer.Artist` instance or its ID
|
|
128
128
|
:returns: a boolean that tells if the operation was successful
|
|
129
129
|
"""
|
|
130
|
-
return self.delete_relation("artists", artist_id
|
|
130
|
+
return self.delete_relation("artists", params={"artist_id": get_id(artist)})
|
|
131
131
|
|
|
132
|
-
def get_followers(self, **
|
|
132
|
+
def get_followers(self, **params) -> PaginatedList[User]:
|
|
133
133
|
"""
|
|
134
134
|
Get user's followers.
|
|
135
135
|
|
|
136
136
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
137
137
|
of :class:`User <deezer.User>` instances
|
|
138
138
|
"""
|
|
139
|
-
return self.get_paginated_list("followers",
|
|
139
|
+
return self.get_paginated_list("followers", params=params)
|
|
140
140
|
|
|
141
|
-
def get_followings(self, **
|
|
141
|
+
def get_followings(self, **params) -> PaginatedList[User]:
|
|
142
142
|
"""
|
|
143
143
|
Get user's followings.
|
|
144
144
|
|
|
145
145
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
146
146
|
of :class:`User <deezer.User>` instances
|
|
147
147
|
"""
|
|
148
|
-
return self.get_paginated_list("followings",
|
|
148
|
+
return self.get_paginated_list("followings", params=params)
|
|
149
149
|
|
|
150
150
|
def follow(self, user: User | int):
|
|
151
151
|
"""
|
|
@@ -154,7 +154,7 @@ class User(Resource):
|
|
|
154
154
|
:param user: a :class:`~deezer.User` instance or its ID
|
|
155
155
|
:returns: a boolean that tells if the operation was successful
|
|
156
156
|
"""
|
|
157
|
-
return self.post_relation("followings", user_id
|
|
157
|
+
return self.post_relation("followings", params={"user_id": get_id(user)})
|
|
158
158
|
|
|
159
159
|
def unfollow(self, user: User | int):
|
|
160
160
|
"""
|
|
@@ -163,16 +163,16 @@ class User(Resource):
|
|
|
163
163
|
:param user: a :class:`~deezer.User` instance or its ID
|
|
164
164
|
:returns: a boolean that tells if the operation was successful
|
|
165
165
|
"""
|
|
166
|
-
return self.delete_relation("followings", user_id
|
|
166
|
+
return self.delete_relation("followings", params={"user_id": get_id(user)})
|
|
167
167
|
|
|
168
|
-
def get_playlists(self, **
|
|
168
|
+
def get_playlists(self, **params) -> PaginatedList[Playlist]:
|
|
169
169
|
"""
|
|
170
170
|
Get user's public playlists.
|
|
171
171
|
|
|
172
172
|
:returns: a :class:`PaginatedList <deezer.PaginatedList>`
|
|
173
173
|
of :class:`Playlist <deezer.Playlist>` instances
|
|
174
174
|
"""
|
|
175
|
-
return self.get_paginated_list("playlists",
|
|
175
|
+
return self.get_paginated_list("playlists", params=params)
|
|
176
176
|
|
|
177
177
|
def add_playlist(self, playlist: Playlist | int):
|
|
178
178
|
"""
|
|
@@ -181,7 +181,7 @@ class User(Resource):
|
|
|
181
181
|
:param playlist: a :class:`~deezer.Playlist` instance or its ID
|
|
182
182
|
:returns: a boolean that tells if the operation was successful
|
|
183
183
|
"""
|
|
184
|
-
return self.post_relation("playlists", playlist_id
|
|
184
|
+
return self.post_relation("playlists", params={"playlist_id": get_id(playlist)})
|
|
185
185
|
|
|
186
186
|
def remove_playlist(self, playlist: Playlist | int):
|
|
187
187
|
"""
|
|
@@ -190,7 +190,7 @@ class User(Resource):
|
|
|
190
190
|
:param playlist: a :class:`~deezer.Playlist` instance or its ID
|
|
191
191
|
:returns: a boolean that tells if the operation was successful
|
|
192
192
|
"""
|
|
193
|
-
return self.delete_relation("playlists", playlist_id
|
|
193
|
+
return self.delete_relation("playlists", params={"playlist_id": get_id(playlist)})
|
|
194
194
|
|
|
195
195
|
def create_playlist(self, title: str) -> int:
|
|
196
196
|
"""
|
|
@@ -199,7 +199,7 @@ class User(Resource):
|
|
|
199
199
|
:param title: the title of the playlist
|
|
200
200
|
:returns: the ID of the playlist that was created
|
|
201
201
|
"""
|
|
202
|
-
result = self.post_relation("playlists",
|
|
202
|
+
result = self.post_relation("playlists", params={"title": title})
|
|
203
203
|
# Note: the REST API call returns a dict with just the "id" key in it,
|
|
204
204
|
# so we return that instead of the full Playlist object
|
|
205
205
|
return result.id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: deezer-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Summary: A friendly wrapper library for the Deezer API
|
|
5
5
|
Home-page: https://github.com/browniebroke/deezer-python
|
|
6
6
|
License: MIT
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: httpx (>=0.23.0)
|
|
24
24
|
Project-URL: Bug Tracker, https://github.com/browniebroke/deezer-python/issues
|
|
25
25
|
Project-URL: Changelog, https://deezer-python.readthedocs.io/en/latest/changelog.html
|
|
26
26
|
Project-URL: Documentation, https://deezer-python.readthedocs.io
|
|
@@ -44,10 +44,10 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
</p>
|
|
45
45
|
<p align="center">
|
|
46
46
|
<a href="https://python-poetry.org/">
|
|
47
|
-
<img src="https://img.shields.io/
|
|
47
|
+
<img src="https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json" alt="Poetry">
|
|
48
48
|
</a>
|
|
49
|
-
<a href="https://github.com/
|
|
50
|
-
<img src="https://img.shields.io/badge/
|
|
49
|
+
<a href="https://github.com/astral-sh/ruff">
|
|
50
|
+
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
|
|
51
51
|
</a>
|
|
52
52
|
<a href="https://github.com/pre-commit/pre-commit">
|
|
53
53
|
<img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">
|
|
@@ -89,7 +89,7 @@ The package is published on
|
|
|
89
89
|
Easily query the Deezer API from you Python code. The data returned by the Deezer
|
|
90
90
|
API is mapped to python resources:
|
|
91
91
|
|
|
92
|
-
```
|
|
92
|
+
```pycon
|
|
93
93
|
>>> client = deezer.Client()
|
|
94
94
|
>>> client.get_album(680407).title
|
|
95
95
|
'Monkey Business'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
deezer/__init__.py,sha256=5Rja7dJ3fy4eDgn_SU8WvnPFj26DW8UQ7_3UUACF5fw,556
|
|
2
|
+
deezer/auth.py,sha256=mKnPDiNBJKEq7Qo0CDu2kW_agviGpTdCbj_duFpYWco,691
|
|
3
|
+
deezer/client.py,sha256=rOQjcwvEb3tbySLWUqAhNna3zr97MBDMC5JHZm0-53c,24780
|
|
4
|
+
deezer/dates.py,sha256=raTeUAAOkajl0TTzM2cupzieTY0amzTeZCaaT3gp_iU,648
|
|
5
|
+
deezer/exceptions.py,sha256=fDLZ63QllqaTwX83cJm1czwEz39ysAcKPB4ie_rAhYI,2004
|
|
6
|
+
deezer/pagination.py,sha256=XXk8uh-9XjXDxx8Fw-cmX2zq-yGNQf9yhum2AISAVZE,4081
|
|
7
|
+
deezer/resources/__init__.py,sha256=WLHWGhV5rLyzZe9IjAtVWUsLvNJDWoldgE2JIADC0L4,549
|
|
8
|
+
deezer/resources/album.py,sha256=83PXZNSSkxY7qVVgyvgyHceaV4IMoQxfqcbTR5v-l38,1734
|
|
9
|
+
deezer/resources/artist.py,sha256=A2mZDceh82cQOsMl3cczgm97UCCUHehNeoPYR8IWjds,2150
|
|
10
|
+
deezer/resources/chart.py,sha256=l4l5M7bYcW1-lFKZl874CGWi-gjOVBcskJ-zL5DMcXE,2193
|
|
11
|
+
deezer/resources/editorial.py,sha256=eD2W9BctUSdUMo3VTMHEFkzGIRkvolLLz20ZD_pWclw,1373
|
|
12
|
+
deezer/resources/episode.py,sha256=1dOBQeNQeKofO_HaMFCg-rKYaPxyqgIm2eMTw0RA-vk,1722
|
|
13
|
+
deezer/resources/genre.py,sha256=CDWyNyFT3fXQM7jPkz3UtGr8gNtVn9430h11Jl0ZwAc,1355
|
|
14
|
+
deezer/resources/playlist.py,sha256=9ErXYNhGGNQ3c9COfMRfEvTWJ9QlJsGjxipgKtIIq7s,3215
|
|
15
|
+
deezer/resources/podcast.py,sha256=FwfOe-m4xI1iRwauZpMjKzXKfLDryDz9Y5cVVzP8wVo,915
|
|
16
|
+
deezer/resources/radio.py,sha256=moOdlSJABqCcluInvgbHSwIzSIhDvBQaVyDGdgeVr_0,805
|
|
17
|
+
deezer/resources/resource.py,sha256=F_u1hJBqTlF_gIC00fqGfWXuDoxLgEYz5m_qeLYv_hA,5202
|
|
18
|
+
deezer/resources/track.py,sha256=e3DPTsYWq5yNCjMRQhGTrFQHfQUe3xn0mEVYbpL3O_0,1546
|
|
19
|
+
deezer/resources/user.py,sha256=kCgMUEbKt1QJzzBEpYxPNM3IbojMlm1fYYTSgqa4Sug,6899
|
|
20
|
+
deezer/utils.py,sha256=Z4QA5Ud5KPiGGv5buTdUidixmkEF9UhwCoYZiGXE-cE,583
|
|
21
|
+
deezer_python-7.0.0.dist-info/LICENSE.txt,sha256=lGqKEubFaPBoiJVRoHOxg1LYlte1e5kLoq6zWUSRQzQ,1054
|
|
22
|
+
deezer_python-7.0.0.dist-info/METADATA,sha256=qHc5BbQrj_dvLh6DqOhIIdOzI9iWP-uCSgjJ0JqdnX8,13718
|
|
23
|
+
deezer_python-7.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
24
|
+
deezer_python-7.0.0.dist-info/RECORD,,
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
deezer/__init__.py,sha256=ni5SDN4LA1uGUENEoScDGcDH69z-Q1_k4pcguCB8t-k,556
|
|
2
|
-
deezer/client.py,sha256=4fyvBflMzql0MHVg1pkZzq8ANHNRWjyQwYuaYmg_Vlc,24896
|
|
3
|
-
deezer/dates.py,sha256=raTeUAAOkajl0TTzM2cupzieTY0amzTeZCaaT3gp_iU,648
|
|
4
|
-
deezer/exceptions.py,sha256=LmJ9vU_mRQ9o9T26ihD36cIMWMC1lg4sBBLiKta3pQA,2003
|
|
5
|
-
deezer/pagination.py,sha256=toiLE51UgiRN1hEUetdeTnaovXjLF6NUjU0TJFaTO-w,4057
|
|
6
|
-
deezer/resources/__init__.py,sha256=WLHWGhV5rLyzZe9IjAtVWUsLvNJDWoldgE2JIADC0L4,549
|
|
7
|
-
deezer/resources/album.py,sha256=83PXZNSSkxY7qVVgyvgyHceaV4IMoQxfqcbTR5v-l38,1734
|
|
8
|
-
deezer/resources/artist.py,sha256=A2mZDceh82cQOsMl3cczgm97UCCUHehNeoPYR8IWjds,2150
|
|
9
|
-
deezer/resources/chart.py,sha256=l4l5M7bYcW1-lFKZl874CGWi-gjOVBcskJ-zL5DMcXE,2193
|
|
10
|
-
deezer/resources/editorial.py,sha256=BbYsJeMeGU65dSrO-Wy_oS52zqnVZZni281zdpdb5HQ,1413
|
|
11
|
-
deezer/resources/episode.py,sha256=AuJQZweeu7MMJ89eMPs7RSBoQU4oQeX1O5QMBwDi94E,1762
|
|
12
|
-
deezer/resources/genre.py,sha256=CDWyNyFT3fXQM7jPkz3UtGr8gNtVn9430h11Jl0ZwAc,1355
|
|
13
|
-
deezer/resources/playlist.py,sha256=8pAMmqUG4S9QLZOX5OrEoj4qA8pggDQBVxbG-DNxqgk,3325
|
|
14
|
-
deezer/resources/podcast.py,sha256=FwfOe-m4xI1iRwauZpMjKzXKfLDryDz9Y5cVVzP8wVo,915
|
|
15
|
-
deezer/resources/radio.py,sha256=moOdlSJABqCcluInvgbHSwIzSIhDvBQaVyDGdgeVr_0,805
|
|
16
|
-
deezer/resources/resource.py,sha256=X_65glzz62jHtVB2U-WtuXM8B5E9U2HbjpcRzOdVOiY,4978
|
|
17
|
-
deezer/resources/track.py,sha256=e3DPTsYWq5yNCjMRQhGTrFQHfQUe3xn0mEVYbpL3O_0,1546
|
|
18
|
-
deezer/resources/user.py,sha256=6-46PX80xEgtCY2FecwzzgbvYu1aL1WShFXcCOaVGlU,6752
|
|
19
|
-
deezer/utils.py,sha256=Z4QA5Ud5KPiGGv5buTdUidixmkEF9UhwCoYZiGXE-cE,583
|
|
20
|
-
deezer_python-6.1.1.dist-info/LICENSE.txt,sha256=lGqKEubFaPBoiJVRoHOxg1LYlte1e5kLoq6zWUSRQzQ,1054
|
|
21
|
-
deezer_python-6.1.1.dist-info/METADATA,sha256=CclxgkmjcPUVmJAsmCAGigoX4OJtmEaNv2i7hziIMRE,14630
|
|
22
|
-
deezer_python-6.1.1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
|
23
|
-
deezer_python-6.1.1.dist-info/RECORD,,
|
|
File without changes
|