feat: add async Deezer client and resources in deezer.asyncio#1565
Merged
browniebroke merged 42 commits intomainfrom Apr 6, 2026
Merged
feat: add async Deezer client and resources in deezer.asyncio#1565browniebroke merged 42 commits intomainfrom
deezer.asyncio#1565browniebroke merged 42 commits intomainfrom
Conversation
Extract shared client logic (objects_types, _process_json) into a DeezerMixin class, then create an AsyncClient inheriting from both DeezerMixin and httpx.AsyncClient. Includes get_album() method and async tests with VCR cassettes. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Move test_async_client.py to tests/asyncio/test_client.py and cassettes to tests/asyncio/cassettes/ to match the deezer.asyncio package layout. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Replace manual vcr.use_cassette() context managers with pytestmark = pytest.mark.vcr, matching the pattern used by the sync tests. Add async_client fixture in conftest and per-test cassette files. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
…tist Create deezer.asyncio.resources sub-package mirroring the sync resources layout. AsyncResource provides async get_relation(). AsyncAlbum has async get_artist() and get_tracks() methods. AsyncClient now returns async resource types via overridden objects_types. Add _resource_base_class to DeezerMixin so the async client falls back to AsyncResource for unknown types. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
AsyncArtist now has get_top(), get_related(), get_radio(), get_albums(), and get_playlists() async methods. Add post_relation/delete_relation to AsyncResource base. Add get_artist() to AsyncClient. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Contributor
There was a problem hiding this comment.
Sorry @browniebroke, your pull request is larger than the review limit of 150000 diff characters
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1565 +/- ##
==========================================
+ Coverage 99.86% 99.92% +0.06%
==========================================
Files 20 37 +17
Lines 723 1332 +609
Branches 46 71 +25
==========================================
+ Hits 722 1331 +609
Partials 1 1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Implements AsyncPlaylist with get_tracks, get_fans, mark_seen, add_tracks, delete_tracks, and reorder_tracks methods. Adds get_playlist to AsyncClient. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Implements AsyncUser with get/add/remove methods for albums, tracks, artists, playlists, followers, followings, and create_playlist. Adds get_user to AsyncClient and async_client_token fixture for authenticated async tests. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Clean up cassette copies that don't match any async test names. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Implements AsyncPaginatedList with async iteration (__aiter__/__anext__), total(), length(), get() for indexed access, and collect() to fetch all pages. Mirrors the sync PaginatedList but uses async methods throughout. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Adds get_paginated_list() to AsyncResource for building AsyncPaginatedList from relation methods, and _get_paginated_list() to AsyncClient as a convenience for client-level paginated queries. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
- resource.py: Move AsyncPaginatedList import to top level (no circular dep) - editorial.py: Move AsyncChart import to top level (no circular dep) - album.py: Remove empty TYPE_CHECKING block and unused typing import https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Updates all async resource methods that correspond to sync methods returning PaginatedList to now return AsyncPaginatedList instead of plain lists. Affected resources: Album, Artist, Chart, Editorial, Genre, Playlist, Podcast, User. Methods like get_radio, get_selection, get_artists (on Genre) that use get_relation in sync are left unchanged. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Adds all remaining sync Client methods to AsyncClient: - Search: search, search_albums, search_artists, search_playlists - Lists: list_editorials, list_genres, list_radios, get_radios_top - User recommendations: get_user_recommended_tracks/albums/artists/playlists - User favorites: get_user_albums/artists/tracks with add/remove variants - User social: get_user_followers/followings with add/remove_user_following - User misc: get_user_flow, get_user_history - Playlists: create_playlist, delete_playlist, add/remove_user_playlist All paginated methods return AsyncPaginatedList, matching sync behavior. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
- Use ty: ignore syntax for invalid-method-override on AsyncClient.request - Widen type annotations on AsyncClient.request to accept AsyncResource types - Use Any for parent/resource_type params in DeezerMixin._process_json since it's shared between sync (Resource) and async (AsyncResource) clients https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
3e4ccc3 to
5cf2c45
Compare
Cover previously untested lines in AsyncPaginatedList: - __repr__ method (lines 35-39) - __anext__ raising StopAsyncIteration (line 69) https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
…aylist reorder_tracks Cover previously untested lines: - AsyncEditorial.get_chart (line 29) - AsyncGenre.get_podcasts (line 28) - AsyncPlaylist.reorder_tracks (lines 60-61) https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
- Add advanced search test (no query, only artist param) for _search branch - Add second __anext__ call after exhaustion to cover _could_grow() False branch All asyncio code now at 100% line and branch coverage. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
- Add docs/async.md covering AsyncClient, async resources, and AsyncPaginatedList usage with practical examples - Add API reference pages for AsyncClient, AsyncPaginatedList, and all 11 async resource classes using autodoc - Update index.md to include async guide after pagination page - Update API reference TOC to include async sections https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
…t page fetch AsyncPaginatedList now fetches the first page eagerly via a new `create()` classmethod factory. All methods on AsyncClient and async resources that return an AsyncPaginatedList are now async and must be awaited, matching user expectations for async code. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
All tests now await paginated list creation calls, matching the new behavior where methods returning AsyncPaginatedList are async and eagerly fetch the first page. Updated AsyncPaginatedList fixture to use the create() classmethod factory. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
- Remove unreachable _could_grow() guard in create() factory - Remove dead total() fallback that fetched with limit=1 since total is always available from the first page - Add cross-page __anext__ test for full iterator coverage - Update docs/async.md to reflect awaitable pagination behavior https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Since AsyncPaginatedList eagerly fetches the first page, total is always available synchronously. Replace async total() method with a property and replace length() with __len__ to match the sync API. https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Align with the sync PaginatedList convention of using name-mangled private attributes (e.g. self.__elements instead of self._elements). https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
deezer.asyncio
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DeezerMixinclass, and create anAsyncClientinheriting from bothDeezerMixinandhttpx.AsyncClient.https://claude.ai/code/session_011tWs29w53Yg2dmkQqUV79b
Fix #1339
Ref #804