Support for playlist_tracks,

Closes #335, closes #318
This commit is contained in:
Stéphane Bruckert 2020-01-17 18:12:13 +00:00 committed by GitHub
commit dda55b25df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 73 deletions

View File

@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- Support for `playlist_tracks`
### Changed
- `user_playlist_tracks` doesn't require a user anymore
### Deprecated
- Deprecated `user_playlist` and `user_playlist_tracks`
## [2.6.3] - 2020-01-16 ## [2.6.3] - 2020-01-16
### Fixed ### Fixed

View File

@ -271,7 +271,7 @@ Shows the contents of every playlist owned by a user::
print() print()
print(playlist['name']) print(playlist['name'])
print (' total tracks', playlist['tracks']['total']) print (' total tracks', playlist['tracks']['total'])
results = sp.user_playlist(username, playlist['id'], results = sp.playlist(playlist['id'],
fields="tracks,next") fields="tracks,next")
tracks = results['tracks'] tracks = results['tracks']
show_tracks(tracks) show_tracks(tracks)

View File

@ -5,9 +5,6 @@ import json
client_credentials_manager = SpotifyClientCredentials() client_credentials_manager = SpotifyClientCredentials()
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
uri = 'spotify:user:spotifycharts:playlist:37i9dQZEVXbJiZcmkrIHGU' playlist_id = 'spotify:user:spotifycharts:playlist:37i9dQZEVXbJiZcmkrIHGU'
username = uri.split(':')[2] results = sp.playlist(playlist_id)
playlist_id = uri.split(':')[4]
results = sp.user_playlist(username, playlist_id)
print(json.dumps(results, indent=4)) print(json.dumps(results, indent=4))

View File

@ -31,8 +31,7 @@ if __name__ == '__main__':
print() print()
print(playlist['name']) print(playlist['name'])
print(' total tracks', playlist['tracks']['total']) print(' total tracks', playlist['tracks']['total'])
results = sp.user_playlist( results = sp.playlist(playlist['id'], fields="tracks,next")
username, playlist['id'], fields="tracks,next")
tracks = results['tracks'] tracks = results['tracks']
show_tracks(tracks) show_tracks(tracks)
while tracks['next']: while tracks['next']:

View File

@ -1,30 +0,0 @@
# shows a user's starred playlist
import sys
import spotipy
import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print("Whoops, need your username!")
print("usage: python user_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
if token:
sp = spotipy.Spotify(auth=token)
results = sp.user_playlist(username)
tracks = results['tracks']
which = 1
while tracks:
for item in tracks['items']:
track = item['track']
print(which, track['name'], ' --', track['artists'][0]['name'])
which += 1
tracks = sp.next(tracks)
else:
print("Can't get token for", username)

View File

@ -15,6 +15,7 @@ import time
import requests import requests
import six import six
import warnings
class SpotifyException(Exception): class SpotifyException(Exception):
@ -371,43 +372,57 @@ class Spotify(object):
""" """
return self._get("me/playlists", limit=limit, offset=offset) return self._get("me/playlists", limit=limit, offset=offset)
def user_playlists(self, user, limit=50, offset=0): def playlist(self, playlist_id, fields=None, market=None):
""" Gets playlists of a user """ Gets playlist by id.
Parameters: Parameters:
- user - the id of the usr - playlist - the id of the playlist
- limit - the number of items to return - fields - which fields to return
- offset - the index of the first item to return - market - An ISO 3166-1 alpha-2 country code or the
string from_token.
""" """
return self._get("users/%s/playlists" % user, limit=limit, plid = self._get_id('playlist', playlist_id)
offset=offset) return self._get("playlists/%s" % (plid), fields=fields, market=market)
def playlist_tracks(self, playlist_id, fields=None,
limit=100, offset=0, market=None):
""" Get full details of the tracks of a playlist.
Parameters:
- playlist_id - the id of the playlist
- fields - which fields to return
- limit - the maximum number of tracks to return
- offset - the index of the first track to return
- market - an ISO 3166-1 alpha-2 country code.
"""
plid = self._get_id('playlist', playlist_id)
return self._get("playlists/%s/tracks" % (plid),
limit=limit, offset=offset, fields=fields,
market=market)
def user_playlist(self, user, playlist_id=None,
fields=None, market=None):
warnings.warn(
"You should use `playlist(playlist_id)` instead",
DeprecationWarning)
def user_playlist(self, user, playlist_id=None, fields=None):
""" Gets playlist of a user """ Gets playlist of a user
Parameters: Parameters:
- user - the id of the user - user - the id of the user
- playlist_id - the id of the playlist - playlist_id - the id of the playlist
- fields - which fields to return - fields - which fields to return
""" """
if playlist_id is None: if playlist_id is None:
return self._get("users/%s/starred" % (user), fields=fields) return self._get("users/%s/starred" % user)
plid = self._get_id('playlist', playlist_id) return self.playlist(playlist_id, fields=fields, market=market)
return self._get("users/%s/playlists/%s" % (user, plid), fields=fields)
def playlist(self, playlist_id, fields=None, market=None): def user_playlist_tracks(self, user=None, playlist_id=None, fields=None,
""" Gets playlist by id
Parameters:
- playlist - the id of the playlist
- fields - which fields to return
- market - An ISO 3166-1 alpha-2 country code or the string
from_token.
"""
plid = self._get_id('playlist', playlist_id)
return self._get("playlists/%s" % (plid), fields=fields)
def user_playlist_tracks(self, user, playlist_id=None, fields=None,
limit=100, offset=0, market=None): limit=100, offset=0, market=None):
warnings.warn(
"You should use `playlist_tracks(playlist_id)` instead",
DeprecationWarning)
""" Get full details of the tracks of a playlist owned by a user. """ Get full details of the tracks of a playlist owned by a user.
Parameters: Parameters:
@ -418,10 +433,19 @@ class Spotify(object):
- offset - the index of the first track to return - offset - the index of the first track to return
- market - an ISO 3166-1 alpha-2 country code. - market - an ISO 3166-1 alpha-2 country code.
""" """
plid = self._get_id('playlist', playlist_id) return self.playlist_tracks(playlist_id, limit=limit, offset=offset,
return self._get("users/%s/playlists/%s/tracks" % (user, plid), fields=fields, market=market)
limit=limit, offset=offset, fields=fields,
market=market) def user_playlists(self, user, limit=50, offset=0):
""" Gets playlists of a user
Parameters:
- user - the id of the usr
- limit - the number of items to return
- offset - the index of the first item to return
"""
return self._get("users/%s/playlists" % user, limit=limit,
offset=offset)
def user_playlist_create(self, user, name, public=True, description=''): def user_playlist_create(self, user, name, public=True, description=''):
""" Creates a playlist for a user """ Creates a playlist for a user

View File

@ -23,6 +23,7 @@ from spotipy import (
import os import os
import sys import sys
import unittest import unittest
import warnings
sys.path.insert(0, os.path.abspath(os.pardir)) sys.path.insert(0, os.path.abspath(os.pardir))
@ -61,6 +62,12 @@ class AuthTestSpotipy(unittest.TestCase):
@classmethod @classmethod
def setUpClass(self): def setUpClass(self):
if sys.version_info >= (3, 2):
# >= Python3.2 only
warnings.filterwarnings(
"ignore",
category=ResourceWarning,
message="unclosed.*<ssl.SSLSocket.*>")
missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV)) missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))
@ -119,13 +126,6 @@ class AuthTestSpotipy(unittest.TestCase):
results = self.spotify.user_playlist_tracks(user, pid) results = self.spotify.user_playlist_tracks(user, pid)
self.assertTrue(len(results['items']) >= 0) self.assertTrue(len(results['items']) >= 0)
# known API issue currently causes this test to fail
# the issue is that the API doesn't currently respect the
# limit parameter
# def user_playlist_tracks(self, user, playlist_id=None, fields=None,
# limit=100, offset=0):
# self.assertTrue(len(playlists['items']) == 5)
def test_current_user_saved_albums(self): def test_current_user_saved_albums(self):
# List # List
albums = self.spotify.current_user_saved_albums() albums = self.spotify.current_user_saved_albums()
@ -281,6 +281,17 @@ class AuthTestSpotipy(unittest.TestCase):
pl = self.spotify.playlist(self.playlist) pl = self.spotify.playlist(self.playlist)
self.assertTrue(pl["tracks"]["total"] > 0) self.assertTrue(pl["tracks"]["total"] > 0)
def test_playlist_tracks(self):
# New playlist ID
pl = self.spotify.playlist_tracks(self.playlist_new_id, limit=2)
self.assertTrue(len(pl["items"]) == 2)
self.assertTrue(pl["total"] > 0)
# Old playlist ID
pl = self.spotify.playlist_tracks(self.playlist, limit=2)
self.assertTrue(len(pl["items"]) == 2)
self.assertTrue(pl["total"] > 0)
def test_user_follows_and_unfollows_artist(self): def test_user_follows_and_unfollows_artist(self):
# Initially follows 1 artist # Initially follows 1 artist
res = self.spotify.current_user_followed_artists() res = self.spotify.current_user_followed_artists()
@ -307,6 +318,24 @@ class AuthTestSpotipy(unittest.TestCase):
# Unfollow these 2 users # Unfollow these 2 users
self.spotify.user_unfollow_users(users) self.spotify.user_unfollow_users(users)
def test_deprecated_starred(self):
pl = self.spotify.user_playlist(self.username)
self.assertTrue(pl["tracks"] is None)
self.assertTrue(pl["owner"] is None)
def test_deprecated_user_playlist(self):
# Test without user due to change from
# https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/
pl = self.spotify.user_playlist(None, self.playlist)
self.assertTrue(pl["tracks"]["total"] > 0)
def test_deprecated_user_playlis(self):
# Test without user due to change from
# https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/
pl = self.spotify.user_playlist_tracks(None, self.playlist, limit=2)
self.assertTrue(len(pl["items"]) == 2)
self.assertTrue(pl["total"] > 0)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()