From 78da6619d45809c9798d09be306360adf7fee004 Mon Sep 17 00:00:00 2001 From: Andrii Yurchuk Date: Sat, 6 Apr 2024 05:56:57 +0200 Subject: [PATCH] Bring back removing playlist item occurrences API --- docs/src/reference/client.rst | 4 ++ docs/src/release_notes.rst | 10 +++- src/tekore/_client/api/playlist/items.py | 68 ++++++++++++++++++++++++ tests/client/playlist.py | 21 ++++++-- 4 files changed, 97 insertions(+), 6 deletions(-) diff --git a/docs/src/reference/client.rst b/docs/src/reference/client.rst index ca3c4cb..e01ad70 100644 --- a/docs/src/reference/client.rst +++ b/docs/src/reference/client.rst @@ -369,6 +369,8 @@ Playlist API Spotify.playlist_add Spotify.playlist_clear Spotify.playlist_remove + Spotify.playlist_remove_indices + Spotify.playlist_remove_occurrences Spotify.playlist_reorder Spotify.playlist_replace @@ -386,6 +388,8 @@ for additional information. .. automethod:: Spotify.playlist_add .. automethod:: Spotify.playlist_clear .. automethod:: Spotify.playlist_remove +.. automethod:: Spotify.playlist_remove_indices +.. automethod:: Spotify.playlist_remove_occurrences .. automethod:: Spotify.playlist_reorder .. automethod:: Spotify.playlist_replace diff --git a/docs/src/release_notes.rst b/docs/src/release_notes.rst index 977a0ed..74bfffb 100644 --- a/docs/src/release_notes.rst +++ b/docs/src/release_notes.rst @@ -3,6 +3,14 @@ Release notes ============= +Unreleased +------------------ +Added +***** +- re-add :class:`SpotifyPlaylistItems` methods ``playlist_remove_indices`` and + ``playlist_remove_occurrences``, removed in :issue:`315`, marking them as + undocumented (:issue:`321`) + 5.4.0 (2024-02-27) ------------------ Fixed @@ -43,7 +51,7 @@ Fixed Added ***** -- Add ``restrictions`` to :class:`FullEpisode ` +- Add ``restrictions`` to :class:`FullEpisode ` (:issue:`310`) - Support HTTPX ``0.26`` (:issue:`311`) - Improve ``UnknownModelAttributeWarning`` to include model name (:issue:`313`) diff --git a/src/tekore/_client/api/playlist/items.py b/src/tekore/_client/api/playlist/items.py index 7e264cf..45b64aa 100644 --- a/src/tekore/_client/api/playlist/items.py +++ b/src/tekore/_client/api/playlist/items.py @@ -1,3 +1,5 @@ +from typing import List, Optional, Tuple + from tekore._auth import scope from ...base import SpotifyBase @@ -139,3 +141,69 @@ def playlist_remove( return self._generic_playlist_remove( playlist_id, {"tracks": items}, snapshot_id ) + + @scopes([scope.playlist_modify_public], [scope.playlist_modify_private]) + @send_and_process(top_item("snapshot_id")) + def playlist_remove_occurrences( + self, + playlist_id: str, + refs: List[Tuple[str, int]], + snapshot_id: Optional[str] = None, + ) -> str: + """ + Remove items by URI and position. + + .. warning:: + This feature is undocumented and may stop working at any time. + + Parameters + ---------- + playlist_id + playlist ID + refs + a list of tuples containing the URI and index of items to remove + snapshot_id + snapshot ID for the playlist + Returns + ------- + str + snapshot ID for the playlist + """ + gathered = {} + for uri, ix in refs: + gathered.setdefault(uri, []).append(ix) + + items = [ + {"uri": uri, "positions": ix_list} for uri, ix_list in gathered.items() + ] + return self._generic_playlist_remove( + playlist_id, {"tracks": items}, snapshot_id + ) + + @scopes([scope.playlist_modify_public], [scope.playlist_modify_private]) + @send_and_process(top_item("snapshot_id")) + def playlist_remove_indices( + self, playlist_id: str, indices: list, snapshot_id: str + ) -> str: + """ + Remove items by position. + + .. warning:: + This feature is undocumented and may stop working at any time. + + Parameters + ---------- + playlist_id + playlist ID + indices + a list of indices of tracks to remove + snapshot_id + snapshot ID for the playlist + Returns + ------- + str + snapshot ID for the playlist + """ + return self._generic_playlist_remove( + playlist_id, {"positions": indices}, snapshot_id + ) diff --git a/tests/client/playlist.py b/tests/client/playlist.py index c57d6d2..3e4ac2c 100644 --- a/tests/client/playlist.py +++ b/tests/client/playlist.py @@ -193,13 +193,24 @@ def test_playlist_modifications(self, user_client, current_user_id): items = user_client.playlist_items(playlist.id) assert items.total == 0 - # Add tracks back with duplicates + # Add tracks back with duplicates and test removing occurrences new_tracks = track_uris + track_uris[::-1] user_client.playlist_replace(playlist.id, new_tracks) - user_client.playlist_remove(playlist.id, track_uris) - # All items removed - items = user_client.playlist_items(playlist.id) - assert items.total == 0 + user_client.playlist_remove_occurrences( + playlist.id, [(uri, ix) for ix, uri in enumerate(track_uris)] + ) + # Occurrences removed + assert_items_equal(user_client, playlist.id, track_uris[::-1]) + + # Add tracks back with duplicates and test removing indices + new_tracks = track_uris + track_uris[::-1] + user_client.playlist_replace(playlist.id, new_tracks) + playlist = user_client.playlist(playlist.id) + user_client.playlist_remove_indices( + playlist.id, list(range(len(track_uris))), playlist.snapshot_id + ) + # Indices removed + assert_items_equal(user_client, playlist.id, track_uris[::-1]) # Tracks cleared user_client.playlist_clear(playlist.id)