deezer-python 7.3.0__tar.gz → 8.0.0__tar.gz
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_python-7.3.0 → deezer_python-8.0.0}/CHANGELOG.md +13 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/CONTRIBUTING.md +5 -11
- {deezer_python-7.3.0 → deezer_python-8.0.0}/PKG-INFO +6 -6
- {deezer_python-7.3.0 → deezer_python-8.0.0}/README.md +2 -2
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/usage.md +5 -5
- {deezer_python-7.3.0 → deezer_python-8.0.0}/pyproject.toml +12 -12
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/__init__.py +1 -1
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/_mixin.py +5 -4
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/client.py +4 -4
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/auth.py +6 -6
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/client.py +4 -4
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/exceptions.py +4 -4
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer_python.egg-info/PKG-INFO +6 -6
- deezer_python-8.0.0/src/deezer_python.egg-info/requires.txt +1 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/tests/test_exceptions.py +4 -4
- deezer_python-7.3.0/src/deezer_python.egg-info/requires.txt +0 -1
- {deezer_python-7.3.0 → deezer_python-8.0.0}/LICENSE.txt +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/MANIFEST.in +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/Makefile +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/_static/.placeholder +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_client.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_pagination.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/album.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/artist.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/chart.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/editorial.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/episode.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/genre.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/playlist.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/podcast.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/radio.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/track.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/user.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/client.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/pagination.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/album.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/artist.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/chart.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/editorial.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/episode.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/genre.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/playlist.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/podcast.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/radio.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/track.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources/user.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/resources.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/toc.rst +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/async.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/changelog.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/conf.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/contributing.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/index.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/installation.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/make.bat +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/docs/pagination.md +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/setup.cfg +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/__init__.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/pagination.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/__init__.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/album.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/artist.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/chart.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/editorial.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/episode.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/genre.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/playlist.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/podcast.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/radio.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/resource.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/track.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/asyncio/resources/user.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/dates.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/pagination.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/__init__.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/album.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/artist.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/chart.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/editorial.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/episode.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/genre.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/playlist.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/podcast.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/radio.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/resource.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/track.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/resources/user.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer/utils.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer_python.egg-info/SOURCES.txt +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer_python.egg-info/dependency_links.txt +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/src/deezer_python.egg-info/top_level.txt +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/tests/test_client.py +0 -0
- {deezer_python-7.3.0 → deezer_python-8.0.0}/tests/test_pagination.py +0 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v8.0.0 (2026-11-07)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Migrate from httpx to httpx2 ([`685382b`](https://github.com/browniebroke/deezer-python/commit/685382bafb4c53f821af9360ba0d6265d9ada82b))
|
|
8
|
+
- Drop support for python 3.10 ([`d32a37b`](https://github.com/browniebroke/deezer-python/commit/d32a37b459c6f7605a78a25721b82a6d05c95fc7))
|
|
9
|
+
|
|
10
|
+
## v7.4.0 (2026-08-07)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- Add support for python 3.15 ([`5de06d6`](https://github.com/browniebroke/deezer-python/commit/5de06d645a7b5fa92bdcb6c53687b8d2f7ea0f55))
|
|
15
|
+
|
|
3
16
|
## v7.3.0 (2026-04-06)
|
|
4
17
|
|
|
5
18
|
### Features
|
|
@@ -65,25 +65,19 @@ Ready to contribute? Here's how to set up `deezer-python` for local development.
|
|
|
65
65
|
$ uv run pytest
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
6.
|
|
68
|
+
6. Linting is done through [prek](https://prek.j178.dev/). Provided you have the tool installed globally, you can run them all as one-off:
|
|
69
69
|
|
|
70
70
|
```shell
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
7. Linting is done through [pre-commit](https://pre-commit.com). Provided you have the tool installed globally, you can run them all as one-off:
|
|
75
|
-
|
|
76
|
-
```shell
|
|
77
|
-
$ pre-commit run -a
|
|
71
|
+
$ prek run -a
|
|
78
72
|
```
|
|
79
73
|
|
|
80
74
|
Or better, install the hooks once and have them run automatically each time you commit:
|
|
81
75
|
|
|
82
76
|
```shell
|
|
83
|
-
$
|
|
77
|
+
$ prek install -f
|
|
84
78
|
```
|
|
85
79
|
|
|
86
|
-
|
|
80
|
+
7. Commit your changes, quoting GitHub issue in the commit message, if applicable, and push your branch to GitHub:
|
|
87
81
|
|
|
88
82
|
```shell
|
|
89
83
|
$ git add .
|
|
@@ -93,7 +87,7 @@ Ready to contribute? Here's how to set up `deezer-python` for local development.
|
|
|
93
87
|
|
|
94
88
|
Note: the commit message should follow [the conventional commits](https://www.conventionalcommits.org). We run [`commitlint` on CI](https://github.com/marketplace/actions/commit-linter) to validate it, and if you've installed pre-commit hooks at the previous step, the message will be checked at commit time.
|
|
95
89
|
|
|
96
|
-
|
|
90
|
+
8. Submit a pull request on GitHub.
|
|
97
91
|
|
|
98
92
|
## Obtain an API token
|
|
99
93
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deezer-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: A friendly wrapper library for the Deezer API
|
|
5
5
|
Author-email: Bruno Alla <alla.brunoo@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,16 +16,16 @@ Classifier: Intended Audience :: Developers
|
|
|
16
16
|
Classifier: Natural Language :: English
|
|
17
17
|
Classifier: Operating System :: OS Independent
|
|
18
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
24
24
|
Classifier: Topic :: Software Development :: Libraries
|
|
25
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE.txt
|
|
28
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: httpx2>=2
|
|
29
29
|
Dynamic: license-file
|
|
30
30
|
|
|
31
31
|
# Deezer Python Client
|
|
@@ -48,8 +48,8 @@ Dynamic: license-file
|
|
|
48
48
|
<a href="https://github.com/astral-sh/ruff">
|
|
49
49
|
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
|
|
50
50
|
</a>
|
|
51
|
-
<a href="https://github.com/
|
|
52
|
-
<img src="https://img.shields.io/
|
|
51
|
+
<a href="https://github.com/j178/prek">
|
|
52
|
+
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json" alt="prek">
|
|
53
53
|
</a>
|
|
54
54
|
</p>
|
|
55
55
|
<p align="center">
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
<a href="https://github.com/astral-sh/ruff">
|
|
19
19
|
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
|
|
20
20
|
</a>
|
|
21
|
-
<a href="https://github.com/
|
|
22
|
-
<img src="https://img.shields.io/
|
|
21
|
+
<a href="https://github.com/j178/prek">
|
|
22
|
+
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json" alt="prek">
|
|
23
23
|
</a>
|
|
24
24
|
</p>
|
|
25
25
|
<p align="center">
|
|
@@ -15,12 +15,12 @@ with deezer.Client() as client:
|
|
|
15
15
|
...
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
This is [the recommended way to use it by `
|
|
18
|
+
This is [the recommended way to use it by `httpx2`](https://pydantic.dev/docs/httpx2/advanced/clients/#usage), which is the library we use under the hood.
|
|
19
19
|
|
|
20
20
|
From there, you can search for some terms:
|
|
21
21
|
|
|
22
22
|
```pycon
|
|
23
|
-
>>> client.search(
|
|
23
|
+
>>> client.search("Daft Punk")
|
|
24
24
|
<PaginatedList [
|
|
25
25
|
<Track: One More Time>,
|
|
26
26
|
<Track: I Feel It Coming>,
|
|
@@ -35,7 +35,7 @@ The above returned a lot of tracks, wrapped in a {class}`PaginatedList <deezer.P
|
|
|
35
35
|
If you wanted to search for artists instead, you may use the {meth}`Client.search_artists() <deezer.Client.search_artists>` method:
|
|
36
36
|
|
|
37
37
|
```pycon
|
|
38
|
-
>>> client.search_artists(
|
|
38
|
+
>>> client.search_artists("Daft Punk")
|
|
39
39
|
<PaginatedList [
|
|
40
40
|
<Artist: Daft Punk>,
|
|
41
41
|
<Artist: Daft Punk - Stardust>,
|
|
@@ -77,7 +77,7 @@ For example, when you get an {class}`Artist <deezer.Artist>`, you may call one o
|
|
|
77
77
|
Let's try from the initial example:
|
|
78
78
|
|
|
79
79
|
```pycon
|
|
80
|
-
>>> daft_punk = client.search_artists(
|
|
80
|
+
>>> daft_punk = client.search_artists("Daft Punk")[0]
|
|
81
81
|
>>> daft_punk.get_albums()[:4]
|
|
82
82
|
[<Album: Random Access Memories>,
|
|
83
83
|
<Album: TRON: Legacy Reconfigured>,
|
|
@@ -156,7 +156,7 @@ To integrate the OAuth flow in your application, we recommend looking at other l
|
|
|
156
156
|
Once the OAuth2 flow is complete, Deezer should give you a token which can be passed to the {class}`Client <deezer.Client>` class:
|
|
157
157
|
|
|
158
158
|
```python
|
|
159
|
-
client = deezer.Client(access_token=
|
|
159
|
+
client = deezer.Client(access_token="your-super-secret-token")
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
From there, you should be able to perform authenticated requests.
|
|
@@ -4,7 +4,7 @@ requires = [ "setuptools>=77.0.3" ]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deezer-python"
|
|
7
|
-
version = "
|
|
7
|
+
version = "8.0.0"
|
|
8
8
|
description = "A friendly wrapper library for the Deezer API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [
|
|
@@ -17,22 +17,22 @@ license = "MIT"
|
|
|
17
17
|
authors = [
|
|
18
18
|
{ name = "Bruno Alla", email = "alla.brunoo@gmail.com" },
|
|
19
19
|
]
|
|
20
|
-
requires-python = ">=3.
|
|
20
|
+
requires-python = ">=3.11"
|
|
21
21
|
classifiers = [
|
|
22
22
|
"Development Status :: 5 - Production/Stable",
|
|
23
23
|
"Intended Audience :: Developers",
|
|
24
24
|
"Natural Language :: English",
|
|
25
25
|
"Operating System :: OS Independent",
|
|
26
26
|
"Programming Language :: Python :: 3 :: Only",
|
|
27
|
-
"Programming Language :: Python :: 3.10",
|
|
28
27
|
"Programming Language :: Python :: 3.11",
|
|
29
28
|
"Programming Language :: Python :: 3.12",
|
|
30
29
|
"Programming Language :: Python :: 3.13",
|
|
31
30
|
"Programming Language :: Python :: 3.14",
|
|
31
|
+
"Programming Language :: Python :: 3.15",
|
|
32
32
|
"Topic :: Software Development :: Libraries",
|
|
33
33
|
]
|
|
34
34
|
dependencies = [
|
|
35
|
-
"
|
|
35
|
+
"httpx2>=2",
|
|
36
36
|
]
|
|
37
37
|
urls."Bug Tracker" = "https://github.com/browniebroke/deezer-python/issues"
|
|
38
38
|
urls.Changelog = "https://deezer-python.readthedocs.io/en/latest/changelog.html"
|
|
@@ -44,15 +44,15 @@ urls.Twitter = "https://twitter.com/_BrunoAlla"
|
|
|
44
44
|
[dependency-groups]
|
|
45
45
|
dev = [
|
|
46
46
|
"coverage>=7,<8",
|
|
47
|
-
"deezer-oauth-cli>=
|
|
47
|
+
"deezer-oauth-cli>=2,<3",
|
|
48
48
|
"environs>=15,<16",
|
|
49
49
|
"pytest>=9,<10",
|
|
50
50
|
"pytest-asyncio",
|
|
51
51
|
"pytest-cov>=7,<8",
|
|
52
52
|
"pytest-mock>=3.6,<4",
|
|
53
53
|
"pytest-vcr>=1,<2",
|
|
54
|
-
"ty
|
|
55
|
-
"vcrpy>=
|
|
54
|
+
"ty==0.0.99",
|
|
55
|
+
"vcrpy>=9,<10",
|
|
56
56
|
]
|
|
57
57
|
docs = [
|
|
58
58
|
"furo>=2023.5.20; python_version>='3.11'",
|
|
@@ -97,16 +97,16 @@ lint.per-file-ignores."tests/**/*" = [
|
|
|
97
97
|
lint.isort.known-first-party = [ "deezer" ]
|
|
98
98
|
|
|
99
99
|
[tool.pyproject-fmt]
|
|
100
|
-
max_supported_python = "3.
|
|
100
|
+
max_supported_python = "3.15"
|
|
101
101
|
|
|
102
102
|
[tool.pytest]
|
|
103
|
-
minversion = "9.0"
|
|
104
103
|
addopts = [ "-v", "-Wdefault", "--cov=deezer" ]
|
|
104
|
+
minversion = "9.0"
|
|
105
105
|
pythonpath = [ "src" ]
|
|
106
106
|
|
|
107
107
|
[tool.coverage]
|
|
108
|
-
run.branch = true
|
|
109
108
|
run.source = [ "deezer" ]
|
|
109
|
+
run.branch = true
|
|
110
110
|
report.exclude_lines = [
|
|
111
111
|
"@overload",
|
|
112
112
|
"if TYPE_CHECKING",
|
|
@@ -116,10 +116,10 @@ report.exclude_lines = [
|
|
|
116
116
|
report.ignore_errors = true
|
|
117
117
|
|
|
118
118
|
[tool.semantic_release]
|
|
119
|
-
version_toml = [ "pyproject.toml:project.version" ]
|
|
120
119
|
version_variables = [
|
|
121
120
|
"src/deezer/__init__.py:__version__",
|
|
122
121
|
]
|
|
122
|
+
version_toml = [ "pyproject.toml:project.version" ]
|
|
123
123
|
build_command = """
|
|
124
124
|
pip install uv
|
|
125
125
|
uv lock
|
|
@@ -130,9 +130,9 @@ branches.main.match = "main"
|
|
|
130
130
|
branches.noop.match = "(?!main$)"
|
|
131
131
|
branches.noop.prerelease = true
|
|
132
132
|
branches.stable.match = "(?!stable/*$)"
|
|
133
|
+
changelog.environment.keep_trailing_newline = true
|
|
133
134
|
changelog.exclude_commit_patterns = [
|
|
134
135
|
"chore.*",
|
|
135
136
|
"ci.*",
|
|
136
137
|
"Merge pull request .*",
|
|
137
138
|
]
|
|
138
|
-
changelog.environment.keep_trailing_newline = true
|
|
@@ -22,9 +22,9 @@ from deezer.resources import (
|
|
|
22
22
|
class DeezerMixin:
|
|
23
23
|
"""Mixin providing shared logic for both sync and async Deezer clients."""
|
|
24
24
|
|
|
25
|
-
_resource_base_class: ClassVar[type[
|
|
25
|
+
_resource_base_class: ClassVar[type[Any]] = Resource
|
|
26
26
|
|
|
27
|
-
objects_types: ClassVar[dict[str, type[
|
|
27
|
+
objects_types: ClassVar[dict[str, type[Any] | None]] = {
|
|
28
28
|
"album": Album,
|
|
29
29
|
"artist": Artist,
|
|
30
30
|
"chart": Chart,
|
|
@@ -75,8 +75,9 @@ class DeezerMixin:
|
|
|
75
75
|
if "id" not in result and resource_id is not None:
|
|
76
76
|
result["id"] = resource_id
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
resource_type_name = result.get("type")
|
|
79
|
+
if isinstance(resource_type_name, str) and resource_type_name in self.objects_types:
|
|
80
|
+
object_class = self.objects_types[resource_type_name]
|
|
80
81
|
elif "type" in result or (not resource_type and "id" in result):
|
|
81
82
|
object_class = self._resource_base_class
|
|
82
83
|
elif resource_type:
|
|
@@ -2,8 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import ClassVar
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
from
|
|
5
|
+
import httpx2
|
|
6
|
+
from httpx2._types import HeaderTypes
|
|
7
7
|
|
|
8
8
|
from deezer._mixin import DeezerMixin
|
|
9
9
|
from deezer.auth import DeezerQueryAuth
|
|
@@ -30,7 +30,7 @@ from .resources import (
|
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class AsyncClient(DeezerMixin,
|
|
33
|
+
class AsyncClient(DeezerMixin, httpx2.AsyncClient):
|
|
34
34
|
"""
|
|
35
35
|
An async client to retrieve some basic infos about Deezer resources.
|
|
36
36
|
|
|
@@ -111,7 +111,7 @@ class AsyncClient(DeezerMixin, httpx.AsyncClient):
|
|
|
111
111
|
)
|
|
112
112
|
try:
|
|
113
113
|
response.raise_for_status()
|
|
114
|
-
except
|
|
114
|
+
except httpx2.HTTPStatusError as exc:
|
|
115
115
|
raise DeezerHTTPError.from_http_error(exc) from exc
|
|
116
116
|
json_data = response.json()
|
|
117
117
|
if not isinstance(json_data, dict):
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import httpx2
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class DeezerQueryAuth(
|
|
6
|
+
class DeezerQueryAuth(httpx2.Auth):
|
|
7
7
|
"""
|
|
8
|
-
Deezer Auth for
|
|
8
|
+
Deezer Auth for httpx2.
|
|
9
9
|
|
|
10
10
|
Attach given access token to the request,
|
|
11
11
|
by passing it as query parameter.
|
|
@@ -16,12 +16,12 @@ class DeezerQueryAuth(httpx.Auth):
|
|
|
16
16
|
def __init__(self, access_token: str):
|
|
17
17
|
self.access_token = access_token
|
|
18
18
|
|
|
19
|
-
def auth_flow(self, request:
|
|
19
|
+
def auth_flow(self, request: httpx2.Request) -> typing.Generator[httpx2.Request, httpx2.Response, None]:
|
|
20
20
|
"""
|
|
21
21
|
Add authentication query parameter to the request.
|
|
22
22
|
|
|
23
|
-
:param request:
|
|
24
|
-
:return:
|
|
23
|
+
:param request: httpx2.Request
|
|
24
|
+
:return: httpx2.Request
|
|
25
25
|
"""
|
|
26
26
|
request.url = request.url.copy_merge_params({"access_token": self.access_token})
|
|
27
27
|
yield request
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from
|
|
3
|
+
import httpx2
|
|
4
|
+
from httpx2._types import HeaderTypes
|
|
5
5
|
|
|
6
6
|
from deezer._mixin import DeezerMixin
|
|
7
7
|
from deezer.auth import DeezerQueryAuth
|
|
@@ -26,7 +26,7 @@ from deezer.resources import (
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class Client(DeezerMixin,
|
|
29
|
+
class Client(DeezerMixin, httpx2.Client):
|
|
30
30
|
"""
|
|
31
31
|
A client to retrieve some basic infos about Deezer resources.
|
|
32
32
|
|
|
@@ -91,7 +91,7 @@ class Client(DeezerMixin, httpx.Client):
|
|
|
91
91
|
)
|
|
92
92
|
try:
|
|
93
93
|
response.raise_for_status()
|
|
94
|
-
except
|
|
94
|
+
except httpx2.HTTPStatusError as exc:
|
|
95
95
|
raise DeezerHTTPError.from_http_error(exc) from exc
|
|
96
96
|
json_data = response.json()
|
|
97
97
|
if not isinstance(json_data, dict):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import httpx2
|
|
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
|
-
"""Specialization wrapping HTTPError from the
|
|
15
|
+
"""Specialization wrapping HTTPError from the httpx2 library."""
|
|
16
16
|
|
|
17
|
-
def __init__(self, http_exception:
|
|
17
|
+
def __init__(self, http_exception: httpx2.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,7 +24,7 @@ class DeezerHTTPError(DeezerAPIException):
|
|
|
24
24
|
super().__init__(http_exception, *args)
|
|
25
25
|
|
|
26
26
|
@classmethod
|
|
27
|
-
def from_http_error(cls, exc:
|
|
27
|
+
def from_http_error(cls, exc: httpx2.HTTPStatusError) -> DeezerHTTPError:
|
|
28
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}:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deezer-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: A friendly wrapper library for the Deezer API
|
|
5
5
|
Author-email: Bruno Alla <alla.brunoo@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,16 +16,16 @@ Classifier: Intended Audience :: Developers
|
|
|
16
16
|
Classifier: Natural Language :: English
|
|
17
17
|
Classifier: Operating System :: OS Independent
|
|
18
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
24
24
|
Classifier: Topic :: Software Development :: Libraries
|
|
25
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE.txt
|
|
28
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: httpx2>=2
|
|
29
29
|
Dynamic: license-file
|
|
30
30
|
|
|
31
31
|
# Deezer Python Client
|
|
@@ -48,8 +48,8 @@ Dynamic: license-file
|
|
|
48
48
|
<a href="https://github.com/astral-sh/ruff">
|
|
49
49
|
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
|
|
50
50
|
</a>
|
|
51
|
-
<a href="https://github.com/
|
|
52
|
-
<img src="https://img.shields.io/
|
|
51
|
+
<a href="https://github.com/j178/prek">
|
|
52
|
+
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json" alt="prek">
|
|
53
53
|
</a>
|
|
54
54
|
</p>
|
|
55
55
|
<p align="center">
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx2>=2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import httpx2
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
6
|
from deezer.exceptions import (
|
|
@@ -21,10 +21,10 @@ from deezer.exceptions import (
|
|
|
21
21
|
],
|
|
22
22
|
)
|
|
23
23
|
def test_deezer_http_error(status_code, expected_exception):
|
|
24
|
-
response =
|
|
25
|
-
http_error =
|
|
24
|
+
response = httpx2.Response(status_code=status_code)
|
|
25
|
+
http_error = httpx2.HTTPStatusError(
|
|
26
26
|
message="",
|
|
27
|
-
request=
|
|
27
|
+
request=httpx2.Request("GET", "https://example.com"),
|
|
28
28
|
response=response,
|
|
29
29
|
)
|
|
30
30
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
httpx>=0.23
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deezer_python-7.3.0 → deezer_python-8.0.0}/docs/api_reference/async_resources/editorial.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|