playlist_add_items() to accept only full URIs and URLs (#914)

* updated functionality of playlist_add_items() to accept only uris and urls (ids should not be allowed since 'track' or 'episode' cannot be inferred purely from the id)

* added a check to raise runtime error if any items in playlist_add_items() are not URIs or URLs

* modified change log

* CL format fix

---------

Co-authored-by: Stéphane Bruckert <stephane.bruckert@gmail.com>
This commit is contained in:
oliveraw 2025-01-19 10:33:57 -06:00 committed by GitHub
parent 71fe07a5d1
commit 1caf97296c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 4 deletions

View File

@ -26,6 +26,10 @@ Rebasing master onto v3 doesn't require a changelog update.
- Replaced the `set_auth` and `auth_manager` properties with standard attributes.
- Replaced string concatenations and `str.format()` with f-strings
### Fixed
- Fixed playlist_add_items() to accept only URIs and URLs and not IDs, since 'track' and 'episode' cannot be inferred from ID only
### Removed
- Removed the following deprecated methods from `Spotify`:
@ -52,7 +56,7 @@ Rebasing master onto v3 doesn't require a changelog update.
### Added
- Added examples for audiobooks, shows and episodes methods to examples directory
- Use newer string formatters (https://pyformat.info)
- Use newer string formatters ([https://pyformat.info](https://pyformat.info))
### Fixed

View File

@ -787,10 +787,15 @@ class Spotify:
- items - a list of track/episode URIs or URLs
- position - the position to add the tracks
"""
for item in items:
if not self._is_uri(item) and not self._is_url(item):
raise RuntimeError("playlist_add_items() only accepts URIs and URLs.")
plid = self._get_id("playlist", playlist_id)
ftracks = [self._get_uri("track", tid) for tid in items]
items = [self._url_to_uri(item) if self._is_url(item) else item for item in items]
return self._post(
f"playlists/{plid}/tracks", payload=ftracks, position=position
f"playlists/{plid}/tracks",
payload=items,
position=position,
)
def playlist_replace_items(self, playlist_id, items):
@ -1717,6 +1722,13 @@ class Spotify:
def _is_uri(self, uri):
return re.search(Spotify._regex_spotify_uri, uri) is not None
def _is_url(self, url):
return url.startswith("http")
def _url_to_uri(self, url):
splitted = url.split("/")
return "spotify:" + splitted[-2] + ":" + splitted[-1]
def _search_multiple_markets(self, q, limit, offset, type, markets, total):
if total and limit > total:
limit = total

View File

@ -47,6 +47,14 @@ class SpotipyPlaylistApiTest(unittest.TestCase):
"spotify:episode:7cRcsGYYRUFo1OF3RgRzdx",
]
cls.tracks_and_episodes = [
"spotify:track:3F5CgOj3wFlRv51JsHbxhe",
"http://open.spotify.com/track/5mCPDVBb16L4XQwDdbRUpz",
"spotify:episode:7AY0yaj2k0W3obOSCfm6m4",
"https://open.spotify.com/episode/5AJB2BTp7RExSGpbQlIsXI"
]
scope = (
'playlist-modify-public '
'user-library-read '
@ -112,7 +120,7 @@ class SpotipyPlaylistApiTest(unittest.TestCase):
def test_playlist_replace_items(self):
# add tracks to playlist
self.spotify.playlist_add_items(
self.new_playlist['id'], self.four_tracks)
self.new_playlist['id'], self.tracks_and_episodes)
playlist = self.spotify.playlist(self.new_playlist['id'])
self.assertEqual(playlist['tracks']['total'], 4)
self.assertEqual(len(playlist['tracks']['items']), 4)