deezer-python-gql 0.21.0__tar.gz → 0.22.1__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.
Files changed (104) hide show
  1. {deezer_python_gql-0.21.0/deezer_python_gql.egg-info → deezer_python_gql-0.22.1}/PKG-INFO +5 -5
  2. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/base_client.py +5 -1
  3. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/__init__.py +26 -0
  4. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/base_client.py +5 -1
  5. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/client.py +37 -0
  6. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/enums.py +14 -0
  7. deezer_python_gql-0.22.1/deezer_python_gql/generated/input_types.py +62 -0
  8. deezer_python_gql-0.22.1/deezer_python_gql/generated/push_queue_state.py +39 -0
  9. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1/deezer_python_gql.egg-info}/PKG-INFO +5 -5
  10. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql.egg-info/SOURCES.txt +1 -0
  11. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql.egg-info/requires.txt +4 -4
  12. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/pyproject.toml +6 -6
  13. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/tests/test_client.py +73 -1
  14. deezer_python_gql-0.21.0/deezer_python_gql/generated/input_types.py +0 -3
  15. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/LICENSE +0 -0
  16. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/MANIFEST.in +0 -0
  17. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/README.md +0 -0
  18. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/__init__.py +0 -0
  19. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_album_to_favorite.py +0 -0
  20. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_artist_to_favorite.py +0 -0
  21. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_audiobook_to_favorite.py +0 -0
  22. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_playlist_to_favorite.py +0 -0
  23. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_podcast_to_favorite.py +0 -0
  24. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_track_to_favorite.py +0 -0
  25. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/add_tracks_to_playlist.py +0 -0
  26. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/ban_artist_from_recommendation.py +0 -0
  27. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/ban_track_from_recommendation.py +0 -0
  28. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/base_model.py +0 -0
  29. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/bookmark_podcast_episode.py +0 -0
  30. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/create_playlist.py +0 -0
  31. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/delete_playlist.py +0 -0
  32. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/fragments.py +0 -0
  33. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_album.py +0 -0
  34. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_artist.py +0 -0
  35. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_artist_mix.py +0 -0
  36. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_audiobook.py +0 -0
  37. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_audiobook_chapter.py +0 -0
  38. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_banned_artists.py +0 -0
  39. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_banned_tracks.py +0 -0
  40. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_charts.py +0 -0
  41. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_family.py +0 -0
  42. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_albums.py +0 -0
  43. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_artists.py +0 -0
  44. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_audiobooks.py +0 -0
  45. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_playlists.py +0 -0
  46. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_podcasts.py +0 -0
  47. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_favorite_tracks.py +0 -0
  48. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_flow.py +0 -0
  49. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_flow_batch.py +0 -0
  50. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_flow_config_tracks.py +0 -0
  51. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_flow_configs.py +0 -0
  52. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_flow_tuner.py +0 -0
  53. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_infinite_track_mix.py +0 -0
  54. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_latest_podcast_episodes.py +0 -0
  55. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_livestream.py +0 -0
  56. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_made_for_me.py +0 -0
  57. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_me.py +0 -0
  58. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_music_together_affinity.py +0 -0
  59. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_music_together_group.py +0 -0
  60. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_music_together_groups.py +0 -0
  61. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_personal_tracks.py +0 -0
  62. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_playlist.py +0 -0
  63. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_podcast.py +0 -0
  64. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_podcast_episode.py +0 -0
  65. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_podcast_episode_bookmarks.py +0 -0
  66. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_podcast_episodes_by_ids.py +0 -0
  67. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_recently_played.py +0 -0
  68. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_recommendations.py +0 -0
  69. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_similar_artists.py +0 -0
  70. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_similar_tracks.py +0 -0
  71. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_smart_tracklist.py +0 -0
  72. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_track.py +0 -0
  73. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_track_mix.py +0 -0
  74. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_tracks_by_ids.py +0 -0
  75. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_user_charts.py +0 -0
  76. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/get_user_playlists.py +0 -0
  77. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/mark_as_not_played_podcast_episode.py +0 -0
  78. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/mark_as_played_podcast_episode.py +0 -0
  79. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/move_track_in_playlist.py +0 -0
  80. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_create_group.py +0 -0
  81. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_generate_group_name.py +0 -0
  82. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_join_group.py +0 -0
  83. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_leave_group.py +0 -0
  84. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_refresh_suggested_tracklist.py +0 -0
  85. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/music_together_update_group_settings.py +0 -0
  86. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_album_from_favorite.py +0 -0
  87. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_artist_from_favorite.py +0 -0
  88. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_audiobook_from_favorite.py +0 -0
  89. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_playlist_from_favorite.py +0 -0
  90. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_podcast_from_favorite.py +0 -0
  91. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_track_from_favorite.py +0 -0
  92. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/remove_tracks_from_playlist.py +0 -0
  93. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/search.py +0 -0
  94. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/search_flows.py +0 -0
  95. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/set_flow_discovery_tuner.py +0 -0
  96. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/unban_artist_from_recommendation.py +0 -0
  97. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/unban_track_from_recommendation.py +0 -0
  98. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/unbookmark_podcast_episode.py +0 -0
  99. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/generated/update_playlist.py +0 -0
  100. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql/py.typed +0 -0
  101. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql.egg-info/dependency_links.txt +0 -0
  102. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql.egg-info/not-zip-safe +0 -0
  103. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/deezer_python_gql.egg-info/top_level.txt +0 -0
  104. {deezer_python_gql-0.21.0 → deezer_python_gql-0.22.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deezer-python-gql
3
- Version: 0.21.0
3
+ Version: 0.22.1
4
4
  Summary: Async typed Python client for Deezer's Pipe GraphQL API.
5
5
  Author-email: Julian Daberkow <jdaberkow@users.noreply.github.com>
6
6
  License: Apache-2.0
@@ -16,13 +16,13 @@ Requires-Dist: pydantic>=2.0.0
16
16
  Requires-Dist: yarl>=1.22.0
17
17
  Provides-Extra: test
18
18
  Requires-Dist: codespell==2.4.3; extra == "test"
19
- Requires-Dist: mypy==2.4.0; extra == "test"
19
+ Requires-Dist: mypy==2.4.1; extra == "test"
20
20
  Requires-Dist: pre-commit==4.7.0; extra == "test"
21
21
  Requires-Dist: pre-commit-hooks==6.0.0; extra == "test"
22
- Requires-Dist: pytest==9.1.1; extra == "test"
23
- Requires-Dist: pytest-asyncio==1.4.1; extra == "test"
22
+ Requires-Dist: pytest==9.2.0; extra == "test"
23
+ Requires-Dist: pytest-asyncio==1.4.1.post1; extra == "test"
24
24
  Requires-Dist: pytest-cov==7.1.0; extra == "test"
25
- Requires-Dist: ruff==0.17.2; extra == "test"
25
+ Requires-Dist: ruff==0.17.3; extra == "test"
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: ariadne-codegen[subscriptions]; extra == "dev"
28
28
  Dynamic: license-file
@@ -11,6 +11,7 @@ from dataclasses import dataclass
11
11
  from typing import TYPE_CHECKING, Any, ClassVar, Self, cast
12
12
 
13
13
  from aiohttp import ClientSession, ClientTimeout
14
+ from pydantic_core import to_jsonable_python
14
15
  from yarl import URL
15
16
 
16
17
  if TYPE_CHECKING:
@@ -227,8 +228,11 @@ class DeezerBaseClient:
227
228
  # Inline import avoids depending on generated code at module level.
228
229
  from deezer_python_gql.generated.base_model import UnsetType # noqa: PLC0415
229
230
 
231
+ # input types are pydantic models, sent under their GraphQL field names
230
232
  payload["variables"] = {
231
- k: v for k, v in variables.items() if not isinstance(v, UnsetType)
233
+ k: to_jsonable_python(v, by_alias=True)
234
+ for k, v in variables.items()
235
+ if not isinstance(v, UnsetType)
232
236
  }
233
237
 
234
238
  session = self._get_session()
@@ -63,10 +63,12 @@ from .enums import (
63
63
  AudiobookContributorRoles,
64
64
  DiscoveryTuner,
65
65
  DiscoveryTunerInput,
66
+ MediaTypeInput,
66
67
  MusicTogetherRefreshSuggestedTracklistMoodInput,
67
68
  MusicTogetherSuggestedTracklistMoodInput,
68
69
  PodcastEpisodeOrder,
69
70
  PodcastType,
71
+ RepeatModeInput,
70
72
  TrackContributorRoles,
71
73
  )
72
74
  from .fragments import (
@@ -551,6 +553,12 @@ from .get_user_playlists import (
551
553
  GetUserPlaylistsMePlaylistsEdgesNode,
552
554
  GetUserPlaylistsMePlaylistsPageInfo,
553
555
  )
556
+ from .input_types import (
557
+ PushQueueContextInput,
558
+ PushQueueMediaInput,
559
+ PushQueueStateClientDetailsInput,
560
+ PushQueueStateInput,
561
+ )
554
562
  from .mark_as_not_played_podcast_episode import (
555
563
  MarkAsNotPlayedPodcastEpisode,
556
564
  MarkAsNotPlayedPodcastEpisodeMarkAsNotPlayedPodcastEpisode,
@@ -599,6 +607,13 @@ from .music_together_update_group_settings import (
599
607
  MusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsOutput,
600
608
  MusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsOutputGroup,
601
609
  )
610
+ from .push_queue_state import (
611
+ PushQueueState,
612
+ PushQueueStatePushQueueStatePushQueueStateError,
613
+ PushQueueStatePushQueueStatePushQueueStateErrorConflict,
614
+ PushQueueStatePushQueueStatePushQueueStateErrorConflictCurrent,
615
+ PushQueueStatePushQueueStatePushQueueStateOutput,
616
+ )
602
617
  from .remove_album_from_favorite import (
603
618
  RemoveAlbumFromFavorite,
604
619
  RemoveAlbumFromFavoriteRemoveAlbumFromFavorite,
@@ -1147,6 +1162,7 @@ __all__ = [
1147
1162
  "MarkAsPlayedPodcastEpisode",
1148
1163
  "MarkAsPlayedPodcastEpisodeMarkAsPlayedPodcastEpisode",
1149
1164
  "MarkAsPlayedPodcastEpisodeMarkAsPlayedPodcastEpisodeBookmark",
1165
+ "MediaTypeInput",
1150
1166
  "MoveTrackInPlaylist",
1151
1167
  "MoveTrackInPlaylistMoveTrackInPlaylist",
1152
1168
  "MusicTogetherCreateGroup",
@@ -1185,6 +1201,15 @@ __all__ = [
1185
1201
  "PodcastFields",
1186
1202
  "PodcastFieldsCover",
1187
1203
  "PodcastType",
1204
+ "PushQueueContextInput",
1205
+ "PushQueueMediaInput",
1206
+ "PushQueueState",
1207
+ "PushQueueStateClientDetailsInput",
1208
+ "PushQueueStateInput",
1209
+ "PushQueueStatePushQueueStatePushQueueStateError",
1210
+ "PushQueueStatePushQueueStatePushQueueStateErrorConflict",
1211
+ "PushQueueStatePushQueueStatePushQueueStateErrorConflictCurrent",
1212
+ "PushQueueStatePushQueueStatePushQueueStateOutput",
1188
1213
  "RemoveAlbumFromFavorite",
1189
1214
  "RemoveAlbumFromFavoriteRemoveAlbumFromFavorite",
1190
1215
  "RemoveAlbumFromFavoriteRemoveAlbumFromFavoriteAlbum",
@@ -1204,6 +1229,7 @@ __all__ = [
1204
1229
  "RemoveTrackFromFavoriteRemoveTrackFromFavoriteTrack",
1205
1230
  "RemoveTracksFromPlaylist",
1206
1231
  "RemoveTracksFromPlaylistRemoveTracksFromPlaylist",
1232
+ "RepeatModeInput",
1207
1233
  "Search",
1208
1234
  "SearchFlows",
1209
1235
  "SearchFlowsSearch",
@@ -13,6 +13,7 @@ from dataclasses import dataclass
13
13
  from typing import TYPE_CHECKING, Any, ClassVar, Self, cast
14
14
 
15
15
  from aiohttp import ClientSession, ClientTimeout
16
+ from pydantic_core import to_jsonable_python
16
17
  from yarl import URL
17
18
 
18
19
  if TYPE_CHECKING:
@@ -229,8 +230,11 @@ class DeezerBaseClient:
229
230
  # Inline import avoids depending on generated code at module level.
230
231
  from deezer_python_gql.generated.base_model import UnsetType # noqa: PLC0415
231
232
 
233
+ # input types are pydantic models, sent under their GraphQL field names
232
234
  payload["variables"] = {
233
- k: v for k, v in variables.items() if not isinstance(v, UnsetType)
235
+ k: to_jsonable_python(v, by_alias=True)
236
+ for k, v in variables.items()
237
+ if not isinstance(v, UnsetType)
234
238
  }
235
239
 
236
240
  session = self._get_session()
@@ -119,6 +119,7 @@ from .get_track_mix import GetTrackMix, GetTrackMixTrackMix
119
119
  from .get_tracks_by_ids import GetTracksByIds, GetTracksByIdsTracksByIds
120
120
  from .get_user_charts import GetUserCharts, GetUserChartsMe
121
121
  from .get_user_playlists import GetUserPlaylists, GetUserPlaylistsMe
122
+ from .input_types import PushQueueStateInput
122
123
  from .mark_as_not_played_podcast_episode import (
123
124
  MarkAsNotPlayedPodcastEpisode,
124
125
  MarkAsNotPlayedPodcastEpisodeMarkAsNotPlayedPodcastEpisode,
@@ -160,6 +161,11 @@ from .music_together_update_group_settings import (
160
161
  MusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsError,
161
162
  MusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsMusicTogetherUpdateGroupSettingsOutput,
162
163
  )
164
+ from .push_queue_state import (
165
+ PushQueueState,
166
+ PushQueueStatePushQueueStatePushQueueStateError,
167
+ PushQueueStatePushQueueStatePushQueueStateOutput,
168
+ )
163
169
  from .remove_album_from_favorite import (
164
170
  RemoveAlbumFromFavorite,
165
171
  RemoveAlbumFromFavoriteRemoveAlbumFromFavorite,
@@ -4469,6 +4475,37 @@ class DeezerGQLClient(DeezerBaseClient):
4469
4475
  data = self.get_data(response)
4470
4476
  return MoveTrackInPlaylist.model_validate(data).move_track_in_playlist
4471
4477
 
4478
+ async def push_queue_state(
4479
+ self, input: PushQueueStateInput, **kwargs: Any
4480
+ ) -> Union[
4481
+ PushQueueStatePushQueueStatePushQueueStateOutput,
4482
+ PushQueueStatePushQueueStatePushQueueStateError,
4483
+ ]:
4484
+ query = gql("""
4485
+ mutation PushQueueState($input: PushQueueStateInput!) {
4486
+ pushQueueState(input: $input) {
4487
+ __typename
4488
+ ... on PushQueueStateOutput {
4489
+ version
4490
+ }
4491
+ ... on PushQueueStateError {
4492
+ isBadRequest
4493
+ conflict {
4494
+ current {
4495
+ version
4496
+ }
4497
+ }
4498
+ }
4499
+ }
4500
+ }
4501
+ """)
4502
+ variables: dict[str, object] = {"input": input}
4503
+ response = await self.execute(
4504
+ query=query, operation_name="PushQueueState", variables=variables, **kwargs
4505
+ )
4506
+ data = self.get_data(response)
4507
+ return PushQueueState.model_validate(data).push_queue_state
4508
+
4472
4509
  async def ban_track_from_recommendation(
4473
4510
  self, track_id: str, **kwargs: Any
4474
4511
  ) -> BanTrackFromRecommendationBanTrackFromRecommendation:
@@ -46,6 +46,20 @@ class PodcastEpisodeOrder(str, Enum):
46
46
  LATEST = "LATEST"
47
47
 
48
48
 
49
+ class MediaTypeInput(str, Enum):
50
+ TRACK = "TRACK"
51
+ EPISODE = "EPISODE"
52
+ CHAPTER = "CHAPTER"
53
+ LIVE = "LIVE"
54
+ RAW_URL = "RAW_URL"
55
+
56
+
57
+ class RepeatModeInput(str, Enum):
58
+ NONE = "NONE"
59
+ ONE = "ONE"
60
+ ALL = "ALL"
61
+
62
+
49
63
  class DiscoveryTuner(str, Enum):
50
64
  DEFAULT = "DEFAULT"
51
65
  DISCOVERY = "DISCOVERY"
@@ -0,0 +1,62 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: schema.graphql
3
+
4
+ from typing import Optional
5
+
6
+ from pydantic import Field
7
+
8
+ from .base_model import BaseModel
9
+ from .enums import MediaTypeInput, RepeatModeInput
10
+
11
+
12
+ class PushQueueStateInput(BaseModel):
13
+ client_details: "PushQueueStateClientDetailsInput" = Field(alias="clientDetails")
14
+ "Details about the client pushing the queue state"
15
+ media_list: list["PushQueueMediaInput"] = Field(alias="mediaList")
16
+ "List of all media in the queue in playing order"
17
+ position: int
18
+ "Zero based index of the current playback position in the queue"
19
+ progress_ms: Optional[int] = Field(alias="progressMS", default=None)
20
+ "Progress in the current media in ms"
21
+ previous_version: Optional[str] = Field(alias="previousVersion", default=None)
22
+ "Previous known queue state version\nNote: Except when there is no queue state available, this version MUST be provided otherwise you'll get a conflict error"
23
+ queue_configuration: str = Field(alias="queueConfiguration")
24
+ "Queue's configuration"
25
+ repeat_mode: RepeatModeInput = Field(alias="repeatMode")
26
+ "Queue repeat mode"
27
+ contexts: Optional[list["PushQueueContextInput"]] = None
28
+ "The list of unique contexts referenced by mediaList.contextId"
29
+
30
+
31
+ class PushQueueMediaInput(BaseModel):
32
+ """Details of media that belongs to the pushed queue"""
33
+
34
+ id: str
35
+ "The media id"
36
+ type_: MediaTypeInput = Field(alias="type")
37
+ "The media type"
38
+ context_id: Optional[str] = Field(alias="contextId", default=None)
39
+ 'The context identifier, it should correspond to an entry in "PushQueueStateInput.contexts"\nEach media can have its own context or share multiple time the same context by using the same contextId'
40
+ local_queue_item_id: Optional[str] = Field(alias="localQueueItemId", default=None)
41
+ "Item identifier used on client side"
42
+ unshuffled_position: int = Field(alias="unshuffledPosition")
43
+ "The position within the unshuffled version of the queue"
44
+
45
+
46
+ class PushQueueContextInput(BaseModel):
47
+ id: str
48
+ "Context identifier"
49
+ content: str
50
+ "The context content itself"
51
+
52
+
53
+ class PushQueueStateClientDetailsInput(BaseModel):
54
+ """Details about the client that wants to push the queue state"""
55
+
56
+ local_queue_id: str = Field(alias="localQueueID")
57
+ "Identifier of the client's local queue, doesn't necessarily match a real queue id"
58
+ locally_updated_at: str = Field(alias="locallyUpdatedAt")
59
+ "Date in ISO-8601 format including milliseconds when update was made on client"
60
+
61
+
62
+ PushQueueStateInput.model_rebuild()
@@ -0,0 +1,39 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: queries
3
+
4
+ from typing import Literal, Optional, Union
5
+
6
+ from pydantic import Field
7
+
8
+ from .base_model import BaseModel
9
+
10
+
11
+ class PushQueueState(BaseModel):
12
+ push_queue_state: Union[
13
+ "PushQueueStatePushQueueStatePushQueueStateOutput",
14
+ "PushQueueStatePushQueueStatePushQueueStateError",
15
+ ] = Field(alias="pushQueueState", discriminator="typename__")
16
+
17
+
18
+ class PushQueueStatePushQueueStatePushQueueStateOutput(BaseModel):
19
+ typename__: Literal["PushQueueStateOutput"] = Field(alias="__typename")
20
+ version: str
21
+
22
+
23
+ class PushQueueStatePushQueueStatePushQueueStateError(BaseModel):
24
+ typename__: Literal["PushQueueStateError"] = Field(alias="__typename")
25
+ is_bad_request: bool = Field(alias="isBadRequest")
26
+ conflict: Optional["PushQueueStatePushQueueStatePushQueueStateErrorConflict"]
27
+
28
+
29
+ class PushQueueStatePushQueueStatePushQueueStateErrorConflict(BaseModel):
30
+ current: Optional["PushQueueStatePushQueueStatePushQueueStateErrorConflictCurrent"]
31
+
32
+
33
+ class PushQueueStatePushQueueStatePushQueueStateErrorConflictCurrent(BaseModel):
34
+ version: str
35
+
36
+
37
+ PushQueueState.model_rebuild()
38
+ PushQueueStatePushQueueStatePushQueueStateError.model_rebuild()
39
+ PushQueueStatePushQueueStatePushQueueStateErrorConflict.model_rebuild()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deezer-python-gql
3
- Version: 0.21.0
3
+ Version: 0.22.1
4
4
  Summary: Async typed Python client for Deezer's Pipe GraphQL API.
5
5
  Author-email: Julian Daberkow <jdaberkow@users.noreply.github.com>
6
6
  License: Apache-2.0
@@ -16,13 +16,13 @@ Requires-Dist: pydantic>=2.0.0
16
16
  Requires-Dist: yarl>=1.22.0
17
17
  Provides-Extra: test
18
18
  Requires-Dist: codespell==2.4.3; extra == "test"
19
- Requires-Dist: mypy==2.4.0; extra == "test"
19
+ Requires-Dist: mypy==2.4.1; extra == "test"
20
20
  Requires-Dist: pre-commit==4.7.0; extra == "test"
21
21
  Requires-Dist: pre-commit-hooks==6.0.0; extra == "test"
22
- Requires-Dist: pytest==9.1.1; extra == "test"
23
- Requires-Dist: pytest-asyncio==1.4.1; extra == "test"
22
+ Requires-Dist: pytest==9.2.0; extra == "test"
23
+ Requires-Dist: pytest-asyncio==1.4.1.post1; extra == "test"
24
24
  Requires-Dist: pytest-cov==7.1.0; extra == "test"
25
- Requires-Dist: ruff==0.17.2; extra == "test"
25
+ Requires-Dist: ruff==0.17.3; extra == "test"
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: ariadne-codegen[subscriptions]; extra == "dev"
28
28
  Dynamic: license-file
@@ -83,6 +83,7 @@ deezer_python_gql/generated/music_together_join_group.py
83
83
  deezer_python_gql/generated/music_together_leave_group.py
84
84
  deezer_python_gql/generated/music_together_refresh_suggested_tracklist.py
85
85
  deezer_python_gql/generated/music_together_update_group_settings.py
86
+ deezer_python_gql/generated/push_queue_state.py
86
87
  deezer_python_gql/generated/remove_album_from_favorite.py
87
88
  deezer_python_gql/generated/remove_artist_from_favorite.py
88
89
  deezer_python_gql/generated/remove_audiobook_from_favorite.py
@@ -7,10 +7,10 @@ ariadne-codegen[subscriptions]
7
7
 
8
8
  [test]
9
9
  codespell==2.4.3
10
- mypy==2.4.0
10
+ mypy==2.4.1
11
11
  pre-commit==4.7.0
12
12
  pre-commit-hooks==6.0.0
13
- pytest==9.1.1
14
- pytest-asyncio==1.4.1
13
+ pytest==9.2.0
14
+ pytest-asyncio==1.4.1.post1
15
15
  pytest-cov==7.1.0
16
- ruff==0.17.2
16
+ ruff==0.17.3
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "deezer-python-gql"
3
- version = "0.21.0"
3
+ version = "0.22.1"
4
4
  description = "Async typed Python client for Deezer's Pipe GraphQL API."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -24,13 +24,13 @@ text = "Apache-2.0"
24
24
  [project.optional-dependencies]
25
25
  test = [
26
26
  "codespell==2.4.3",
27
- "mypy==2.4.0",
27
+ "mypy==2.4.1",
28
28
  "pre-commit==4.7.0",
29
29
  "pre-commit-hooks==6.0.0",
30
- "pytest==9.1.1",
31
- "pytest-asyncio==1.4.1",
30
+ "pytest==9.2.0",
31
+ "pytest-asyncio==1.4.1.post1",
32
32
  "pytest-cov==7.1.0",
33
- "ruff==0.17.2",
33
+ "ruff==0.17.3",
34
34
  ]
35
35
  dev = [
36
36
  "ariadne-codegen[subscriptions]",
@@ -182,5 +182,5 @@ asyncio_mode = "auto"
182
182
 
183
183
  [tool.uv]
184
184
  override-dependencies = [
185
- "ruff==0.17.2",
185
+ "ruff==0.17.3",
186
186
  ]
@@ -48,7 +48,7 @@ from deezer_python_gql.generated.ban_track_from_recommendation import (
48
48
  from deezer_python_gql.generated.bookmark_podcast_episode import BookmarkPodcastEpisode
49
49
  from deezer_python_gql.generated.create_playlist import CreatePlaylist
50
50
  from deezer_python_gql.generated.delete_playlist import DeletePlaylist
51
- from deezer_python_gql.generated.enums import PodcastType
51
+ from deezer_python_gql.generated.enums import MediaTypeInput, PodcastType, RepeatModeInput
52
52
  from deezer_python_gql.generated.get_album import GetAlbum
53
53
  from deezer_python_gql.generated.get_artist import GetArtist
54
54
  from deezer_python_gql.generated.get_artist_mix import GetArtistMix
@@ -99,6 +99,11 @@ from deezer_python_gql.generated.get_track_mix import GetTrackMix
99
99
  from deezer_python_gql.generated.get_tracks_by_ids import GetTracksByIds
100
100
  from deezer_python_gql.generated.get_user_charts import GetUserCharts
101
101
  from deezer_python_gql.generated.get_user_playlists import GetUserPlaylists
102
+ from deezer_python_gql.generated.input_types import (
103
+ PushQueueMediaInput,
104
+ PushQueueStateClientDetailsInput,
105
+ PushQueueStateInput,
106
+ )
102
107
  from deezer_python_gql.generated.mark_as_not_played_podcast_episode import (
103
108
  MarkAsNotPlayedPodcastEpisode,
104
109
  )
@@ -114,6 +119,11 @@ from deezer_python_gql.generated.music_together_generate_group_name import (
114
119
  )
115
120
  from deezer_python_gql.generated.music_together_join_group import MusicTogetherJoinGroup
116
121
  from deezer_python_gql.generated.music_together_leave_group import MusicTogetherLeaveGroup
122
+ from deezer_python_gql.generated.push_queue_state import (
123
+ PushQueueState,
124
+ PushQueueStatePushQueueStatePushQueueStateError,
125
+ PushQueueStatePushQueueStatePushQueueStateOutput,
126
+ )
117
127
  from deezer_python_gql.generated.remove_album_from_favorite import RemoveAlbumFromFavorite
118
128
  from deezer_python_gql.generated.remove_artist_from_favorite import RemoveArtistFromFavorite
119
129
  from deezer_python_gql.generated.remove_audiobook_from_favorite import (
@@ -378,6 +388,7 @@ def test_client_has_generated_methods() -> None:
378
388
  "get_latest_podcast_episodes",
379
389
  "get_tracks_by_ids",
380
390
  "set_flow_discovery_tuner",
391
+ "push_queue_state",
381
392
  ]
382
393
  for method in expected_methods:
383
394
  assert hasattr(client, method), f"Missing method: {method}"
@@ -2030,3 +2041,64 @@ def test_smoke_get_family() -> None:
2030
2041
  ("2002", True),
2031
2042
  ("3003", False),
2032
2043
  ]
2044
+
2045
+
2046
+ def test_smoke_push_queue_state() -> None:
2047
+ """Verify PushQueueState fixture parses the new queue state version."""
2048
+ data = _load_fixture("push_queue_state.json")
2049
+ result = PushQueueState.model_validate(data).push_queue_state
2050
+ assert isinstance(result, PushQueueStatePushQueueStatePushQueueStateOutput)
2051
+ assert result.version == "01a1a613-c68c-731f-8677-15d9c535adbb"
2052
+
2053
+
2054
+ def test_smoke_push_queue_state_conflict() -> None:
2055
+ """Verify a PushQueueState conflict parses the version it conflicts with."""
2056
+ data = _load_fixture("push_queue_state_conflict.json")
2057
+ result = PushQueueState.model_validate(data).push_queue_state
2058
+ assert isinstance(result, PushQueueStatePushQueueStatePushQueueStateError)
2059
+ assert result.is_bad_request is False
2060
+ assert result.conflict is not None
2061
+ assert result.conflict.current is not None
2062
+ assert result.conflict.current.version == "01a1a63d-1f5b-7d29-ae26-099eb9c20ab7"
2063
+
2064
+
2065
+ @pytest.mark.asyncio
2066
+ async def test_execute_sends_input_types_by_their_graphql_names() -> None:
2067
+ """Verify an input type variable is sent as JSON with the API's field names."""
2068
+ client = DeezerGQLClient(arl="test_arl")
2069
+ client._jwt = _make_jwt(exp=time.time() + 600) # noqa: SLF001
2070
+ client._jwt_expires_at = time.time() + 600 # noqa: SLF001
2071
+ state = PushQueueStateInput(
2072
+ clientDetails=PushQueueStateClientDetailsInput(
2073
+ localQueueID="queue", locallyUpdatedAt="2026-11-04T10:21:16.223Z"
2074
+ ),
2075
+ mediaList=[PushQueueMediaInput(id="1", type=MediaTypeInput.TRACK, unshuffledPosition=0)],
2076
+ position=0,
2077
+ queueConfiguration="{}",
2078
+ repeatMode=RepeatModeInput.NONE,
2079
+ )
2080
+ gql_cm = _mock_post_context_manager(
2081
+ json.dumps({"data": _load_fixture("push_queue_state.json")}).encode()
2082
+ )
2083
+
2084
+ # the generated client runs on the generated copy of the base client
2085
+ with patch("deezer_python_gql.generated.base_client.ClientSession") as mock_cls:
2086
+ mock_instance = MagicMock()
2087
+ mock_instance.post = MagicMock(return_value=gql_cm)
2088
+ mock_instance.close = AsyncMock()
2089
+ mock_cls.return_value = mock_instance
2090
+
2091
+ await client.push_queue_state(input=state)
2092
+
2093
+ sent = mock_instance.post.call_args.kwargs["json"]["variables"]["input"]
2094
+ assert sent["clientDetails"]["localQueueID"] == "queue"
2095
+ assert sent["mediaList"] == [
2096
+ {
2097
+ "id": "1",
2098
+ "type": "TRACK",
2099
+ "contextId": None,
2100
+ "localQueueItemId": None,
2101
+ "unshuffledPosition": 0,
2102
+ }
2103
+ ]
2104
+ assert sent["repeatMode"] == "NONE"
@@ -1,3 +0,0 @@
1
- # Generated by ariadne-codegen
2
- # Source: schema.graphql
3
-