mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 01:03:53 +00:00
parent
5928981e3b
commit
f54830e272
@ -4,6 +4,7 @@ import spotipy
|
||||
''' shows the albums and tracks for a given artist.
|
||||
'''
|
||||
|
||||
|
||||
def get_artist(name):
|
||||
results = sp.search(q='artist:' + name, type='artist')
|
||||
items = results['artists']['items']
|
||||
@ -12,6 +13,7 @@ def get_artist(name):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def show_artist_albums(artist):
|
||||
albums = []
|
||||
results = sp.artist_albums(artist['id'], album_type='album')
|
||||
@ -19,7 +21,7 @@ def show_artist_albums(artist):
|
||||
while results['next']:
|
||||
results = sp.next(results)
|
||||
albums.extend(results['items'])
|
||||
seen = set() # to avoid dups
|
||||
seen = set() # to avoid dups
|
||||
albums.sort(key=lambda album: album['name'].lower())
|
||||
for album in albums:
|
||||
name = album['name']
|
||||
@ -27,6 +29,7 @@ def show_artist_albums(artist):
|
||||
print((' ' + name))
|
||||
seen.add(name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sp = spotipy.Spotify()
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import spotipy
|
||||
''' shows the albums and tracks for a given artist.
|
||||
'''
|
||||
|
||||
|
||||
def get_artist(name):
|
||||
results = sp.search(q='artist:' + name, type='artist')
|
||||
items = results['artists']['items']
|
||||
@ -12,6 +13,7 @@ def get_artist(name):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def show_album_tracks(album):
|
||||
tracks = []
|
||||
results = sp.album_tracks(album['id'])
|
||||
@ -24,6 +26,7 @@ def show_album_tracks(album):
|
||||
print()
|
||||
print(track)
|
||||
|
||||
|
||||
def show_artist_albums(id):
|
||||
albums = []
|
||||
results = sp.artist_albums(artist['id'], album_type='album')
|
||||
@ -35,17 +38,19 @@ def show_artist_albums(id):
|
||||
unique = set() # skip duplicate albums
|
||||
for album in albums:
|
||||
name = album['name'].lower()
|
||||
if not name in unique:
|
||||
if name not in unique:
|
||||
print(name)
|
||||
unique.add(name)
|
||||
show_album_tracks(album)
|
||||
|
||||
|
||||
def show_artist(artist):
|
||||
print('====', artist['name'], '====')
|
||||
print('Popularity: ', artist['popularity'])
|
||||
if len(artist['genres']) > 0:
|
||||
print('Genres: ', ','.join(artist['genres']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sp = spotipy.Spotify()
|
||||
sp.trace = False
|
||||
|
||||
@ -7,7 +7,8 @@ import spotipy
|
||||
from spotipy.oauth2 import SpotifyClientCredentials
|
||||
client_credentials_manager = SpotifyClientCredentials()
|
||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||
sp.trace=False
|
||||
sp.trace = False
|
||||
|
||||
|
||||
def get_artist(name):
|
||||
results = sp.search(q='artist:' + name, type='artist')
|
||||
@ -17,11 +18,12 @@ def get_artist(name):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def show_recommendations_for_artist(artist):
|
||||
albums = []
|
||||
results = sp.recommendations(seed_artists=[artist['id']])
|
||||
for track in results['tracks']:
|
||||
print track['name'], '-', track['artists'][0]['name']
|
||||
print(track['name'], '-', track['artists'][0]['name'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
@ -32,4 +34,4 @@ if __name__ == '__main__':
|
||||
if artist:
|
||||
show_recommendations_for_artist(artist)
|
||||
else:
|
||||
print "Can't find that artist", name
|
||||
print("Can't find that artist", name)
|
||||
|
||||
@ -11,7 +11,7 @@ import sys
|
||||
|
||||
client_credentials_manager = SpotifyClientCredentials()
|
||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||
sp.trace=False
|
||||
sp.trace = False
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
artist_name = ' '.join(sys.argv[1:])
|
||||
|
||||
@ -12,7 +12,7 @@ import sys
|
||||
|
||||
client_credentials_manager = SpotifyClientCredentials()
|
||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||
sp.trace=True
|
||||
sp.trace = True
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
tids = sys.argv[1:]
|
||||
|
||||
@ -25,7 +25,7 @@ if len(sys.argv) > 3:
|
||||
|
||||
else:
|
||||
print("Usage: %s username playlist_id name [public collaborative "
|
||||
"description]" % (sys.argv[0]))
|
||||
"description]" % (sys.argv[0]))
|
||||
sys.exit()
|
||||
|
||||
scope = 'playlist-modify-public playlist-modify-private'
|
||||
@ -37,6 +37,6 @@ if token:
|
||||
results = sp.user_playlist_change_details(
|
||||
username, playlist_id, name=name, public=public,
|
||||
collaborative=collaborative, description=description)
|
||||
print results
|
||||
print(results)
|
||||
else:
|
||||
print "Can't get token for", username
|
||||
print("Can't get token for"), username
|
||||
|
||||
@ -12,7 +12,9 @@ if len(sys.argv) > 2:
|
||||
playlist_name = sys.argv[2]
|
||||
playlist_description = sys.argv[3]
|
||||
else:
|
||||
print("Usage: %s username playlist-name playlist-description" % (sys.argv[0],))
|
||||
print(
|
||||
"Usage: %s username playlist-name playlist-description" %
|
||||
(sys.argv[0],))
|
||||
sys.exit()
|
||||
|
||||
scope = "playlist-modify-public"
|
||||
|
||||
@ -7,7 +7,7 @@ import spotipy
|
||||
|
||||
client_credentials_manager = SpotifyClientCredentials()
|
||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||
sp.trace=True
|
||||
sp.trace = True
|
||||
try:
|
||||
print('bad call 0')
|
||||
bad_artist_call = sp.artist('spotify:artist:12341234')
|
||||
@ -17,4 +17,3 @@ except spotipy.client.SpotifyException:
|
||||
print('bad call 1')
|
||||
bad_artist_call = sp.artist('spotify:artist:12341234')
|
||||
print('bad artist', bad_artist_call)
|
||||
|
||||
|
||||
@ -19,6 +19,6 @@ if token:
|
||||
sp.trace = False
|
||||
results = sp.current_user_playlists(limit=50)
|
||||
for i, item in enumerate(results['items']):
|
||||
print("%d %s" %(i, item['name']))
|
||||
print("%d %s" % (i, item['name']))
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
# Shows the top artists for a user
|
||||
|
||||
import pprint
|
||||
import sys
|
||||
|
||||
import spotipy
|
||||
import spotipy.util as util
|
||||
import simplejson as json
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
username = sys.argv[1]
|
||||
@ -21,10 +19,10 @@ if token:
|
||||
sp.trace = False
|
||||
ranges = ['short_term', 'medium_term', 'long_term']
|
||||
for range in ranges:
|
||||
print ("range:", range)
|
||||
print("range:", range)
|
||||
results = sp.current_user_top_artists(time_range=range, limit=50)
|
||||
for i, item in enumerate(results['items']):
|
||||
print (i, item['name'])
|
||||
print ()
|
||||
print(i, item['name'])
|
||||
print()
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
# Shows the top tracks for a user
|
||||
|
||||
import pprint
|
||||
import sys
|
||||
|
||||
import spotipy
|
||||
import spotipy.util as util
|
||||
import simplejson as json
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
username = sys.argv[1]
|
||||
@ -21,11 +19,11 @@ if token:
|
||||
sp.trace = False
|
||||
ranges = ['short_term', 'medium_term', 'long_term']
|
||||
for range in ranges:
|
||||
print ("range:", range)
|
||||
print("range:", range)
|
||||
results = sp.current_user_top_tracks(time_range=range, limit=50)
|
||||
for i, item in enumerate(results['items']):
|
||||
print (i, item['name'], '//', item['artists'][0]['name'])
|
||||
print ()
|
||||
print(i, item['name'], '//', item['artists'][0]['name'])
|
||||
print()
|
||||
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
@ -10,4 +10,4 @@ username = uri.split(':')[2]
|
||||
playlist_id = uri.split(':')[4]
|
||||
|
||||
results = sp.user_playlist(username, playlist_id)
|
||||
print (json.dumps(results, indent=4))
|
||||
print(json.dumps(results, indent=4))
|
||||
|
||||
@ -15,7 +15,9 @@ if len(sys.argv) > 3:
|
||||
tid, pos = t_pos.split(',')
|
||||
track_ids.append({"uri": tid, "positions": [int(pos)]})
|
||||
else:
|
||||
print("Usage: %s username playlist_id track_id,pos track_id,pos ..." % (sys.argv[0],))
|
||||
print(
|
||||
"Usage: %s username playlist_id track_id,pos track_id,pos ..." %
|
||||
(sys.argv[0],))
|
||||
sys.exit()
|
||||
|
||||
scope = 'playlist-modify-public'
|
||||
@ -24,7 +26,8 @@ token = util.prompt_for_user_token(username, scope)
|
||||
if token:
|
||||
sp = spotipy.Spotify(auth=token)
|
||||
sp.trace = False
|
||||
results = sp.user_playlist_remove_specific_occurrences_of_tracks(username, playlist_id, track_ids)
|
||||
results = sp.user_playlist_remove_specific_occurrences_of_tracks(
|
||||
username, playlist_id, track_ids)
|
||||
pprint.pprint(results)
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
@ -20,7 +20,8 @@ token = util.prompt_for_user_token(username, scope)
|
||||
if token:
|
||||
sp = spotipy.Spotify(auth=token)
|
||||
sp.trace = False
|
||||
results = sp.user_playlist_remove_all_occurrences_of_tracks(username, playlist_id, track_ids)
|
||||
results = sp.user_playlist_remove_all_occurrences_of_tracks(
|
||||
username, playlist_id, track_ids)
|
||||
pprint.pprint(results)
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
@ -22,6 +22,5 @@ try:
|
||||
print('Related artists for', name)
|
||||
for artist in related['artists']:
|
||||
print(' ', artist['name'])
|
||||
except:
|
||||
except BaseException:
|
||||
print("usage show_related.py [artist-name]")
|
||||
|
||||
|
||||
@ -19,6 +19,3 @@ if __name__ == '__main__':
|
||||
results = sp.tracks(tids[start: start + max_tracks_per_call])
|
||||
for track in results['tracks']:
|
||||
print(track['name'] + ' - ' + track['artists'][0]['name'])
|
||||
|
||||
|
||||
|
||||
|
||||
@ -14,4 +14,3 @@ sp = spotipy.Spotify()
|
||||
sp.trace = True
|
||||
user = sp.user(username)
|
||||
pprint.pprint(user)
|
||||
|
||||
|
||||
@ -14,4 +14,3 @@ while results['next']:
|
||||
|
||||
for album in albums:
|
||||
print((album['name']))
|
||||
|
||||
|
||||
@ -15,4 +15,3 @@ items = results['artists']['items']
|
||||
if len(items) > 0:
|
||||
artist = items[0]
|
||||
print(artist['name'], artist['images'][0]['url'])
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import spotipy
|
||||
import random
|
||||
import simplejson as json
|
||||
|
||||
'''
|
||||
generates a list of songs where the first word in each subsequent song
|
||||
@ -14,13 +13,14 @@ skiplist = set(['dm', 'remix'])
|
||||
max_offset = 500
|
||||
seen = set()
|
||||
|
||||
|
||||
def find_songs_that_start_with_word(word):
|
||||
max_titles = 20
|
||||
max_offset = 200
|
||||
offset = 0
|
||||
|
||||
out = []
|
||||
while offset < max_offset and len(out) < max_titles:
|
||||
while offset < max_offset and len(out) < max_titles:
|
||||
results = sp.search(q=word, type='track', limit=50, offset=offset)
|
||||
if len(results['tracks']['items']) == 0:
|
||||
break
|
||||
@ -37,27 +37,29 @@ def find_songs_that_start_with_word(word):
|
||||
if '/' in name:
|
||||
continue
|
||||
words = name.split()
|
||||
if len(words) > 1 and words[0] == word and words[-1] not in skiplist:
|
||||
#print " ", name, len(out)
|
||||
if len(words) > 1 and words[0] == word \
|
||||
and words[-1] not in skiplist:
|
||||
# print " ", name, len(out)
|
||||
out.append(item)
|
||||
offset += 50
|
||||
#print "found", len(out), "matches"
|
||||
# print "found", len(out), "matches"
|
||||
return out
|
||||
|
||||
|
||||
def make_chain(word):
|
||||
which = 1
|
||||
while True:
|
||||
songs = find_songs_that_start_with_word(word)
|
||||
if len(songs) > 0:
|
||||
song = random.choice(songs)
|
||||
print which, song['name'] + " by " + song['artists'][0]['name']
|
||||
print(which, song['name'] + " by " + song['artists'][0]['name'])
|
||||
which += 1
|
||||
word = song['name'].lower().split()[-1]
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
title = ' '.join(sys.argv[1:])
|
||||
make_chain(sys.argv[1].lower())
|
||||
|
||||
|
||||
@ -4,10 +4,13 @@ import sys
|
||||
import spotipy
|
||||
import spotipy.util as util
|
||||
|
||||
|
||||
def show_tracks(results):
|
||||
for i, item in enumerate(results['items']):
|
||||
track = item['track']
|
||||
print(" %d %32.32s %s" % (i, track['artists'][0]['name'], track['name']))
|
||||
print(
|
||||
" %d %32.32s %s" %
|
||||
(i, track['artists'][0]['name'], track['name']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -28,7 +31,8 @@ if __name__ == '__main__':
|
||||
print()
|
||||
print(playlist['name'])
|
||||
print(' total tracks', playlist['tracks']['total'])
|
||||
results = sp.user_playlist(username, playlist['id'], fields="tracks,next")
|
||||
results = sp.user_playlist(
|
||||
username, playlist['id'], fields="tracks,next")
|
||||
tracks = results['tracks']
|
||||
show_tracks(tracks)
|
||||
while tracks['next']:
|
||||
@ -36,4 +40,3 @@ if __name__ == '__main__':
|
||||
show_tracks(tracks)
|
||||
else:
|
||||
print("Can't get token for", username)
|
||||
|
||||
|
||||
@ -18,7 +18,13 @@ playlists = sp.user_playlists(user)
|
||||
|
||||
while playlists:
|
||||
for i, playlist in enumerate(playlists['items']):
|
||||
print("%4d %s %s" % (i + 1 + playlists['offset'], playlist['uri'], playlist['name']))
|
||||
print(
|
||||
"%4d %s %s" %
|
||||
(i +
|
||||
1 +
|
||||
playlists['offset'],
|
||||
playlist['uri'],
|
||||
playlist['name']))
|
||||
if playlists['next']:
|
||||
playlists = sp.next(playlists)
|
||||
else:
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
|
||||
"""
|
||||
|
||||
import pprint
|
||||
import sys
|
||||
import json
|
||||
import spotipy
|
||||
import spotipy.util as util
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import spotipy
|
||||
import spotipy.util as util
|
||||
|
||||
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
username = sys.argv[1]
|
||||
else:
|
||||
|
||||
7
setup.py
7
setup.py
@ -1,9 +1,11 @@
|
||||
from setuptools import setup
|
||||
|
||||
desc = """### A light weight Python library for the Spotify Web API"""
|
||||
|
||||
setup(
|
||||
name='spotipy',
|
||||
version='2.5.0',
|
||||
long_description="""### A light weight Python library for the Spotify Web API""",
|
||||
long_description=desc,
|
||||
long_description_content_type='text/markdown',
|
||||
author="@plamere",
|
||||
author_email="paul@echonest.com",
|
||||
@ -12,7 +14,6 @@ setup(
|
||||
'mock>=2.0.0',
|
||||
'requests>=2.3.0',
|
||||
'six>=1.10.0',
|
||||
'simplejson==3.13.2',
|
||||
],
|
||||
],
|
||||
license='LICENSE.txt',
|
||||
packages=['spotipy'])
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
from .client import *
|
||||
from .oauth2 import *
|
||||
from .util import *
|
||||
from .client import * # noqa
|
||||
from .oauth2 import * # noqa
|
||||
from .util import * # noqa
|
||||
|
||||
@ -17,7 +17,6 @@ import requests
|
||||
import six
|
||||
|
||||
|
||||
|
||||
class SpotifyException(Exception):
|
||||
def __init__(self, http_status, code, msg, headers=None):
|
||||
self.http_status = http_status
|
||||
@ -58,7 +57,8 @@ class Spotify(object):
|
||||
max_get_retries = 10
|
||||
|
||||
def __init__(self, auth=None, requests_session=True,
|
||||
client_credentials_manager=None, proxies=None, requests_timeout=None):
|
||||
client_credentials_manager=None, proxies=None,
|
||||
requests_timeout=None):
|
||||
"""
|
||||
Creates a Spotify API client.
|
||||
|
||||
@ -73,7 +73,8 @@ class Spotify(object):
|
||||
:param proxies:
|
||||
Definition of proxies (optional)
|
||||
:param requests_timeout:
|
||||
Tell Requests to stop waiting for a response after a given number of seconds
|
||||
Tell Requests to stop waiting for a response after a given
|
||||
number of seconds
|
||||
"""
|
||||
self.prefix = 'https://api.spotify.com/v1/'
|
||||
self._auth = auth
|
||||
@ -112,26 +113,33 @@ class Spotify(object):
|
||||
|
||||
if self.trace_out:
|
||||
print(url)
|
||||
r = self._session.request(method, url, headers=headers, proxies=self.proxies, **args)
|
||||
r = self._session.request(
|
||||
method,
|
||||
url,
|
||||
headers=headers,
|
||||
proxies=self.proxies,
|
||||
**args)
|
||||
|
||||
if self.trace: # pragma: no cover
|
||||
print()
|
||||
print ('headers', headers)
|
||||
print ('http status', r.status_code)
|
||||
print('headers', headers)
|
||||
print('http status', r.status_code)
|
||||
print(method, r.url)
|
||||
if payload:
|
||||
print("DATA", json.dumps(payload))
|
||||
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except:
|
||||
except BaseException:
|
||||
if r.text and len(r.text) > 0 and r.text != 'null':
|
||||
msg = '%s:\n %s' % (r.url, r.json()['error']['message'])
|
||||
raise SpotifyException(r.status_code,
|
||||
-1, '%s:\n %s' % (r.url, r.json()['error']['message']),
|
||||
headers=r.headers)
|
||||
-1, msg,
|
||||
headers=r.headers)
|
||||
else:
|
||||
raise SpotifyException(r.status_code,
|
||||
-1, '%s:\n %s' % (r.url, 'error'), headers=r.headers)
|
||||
-1, '%s:\n %s' % (r.url, 'error'),
|
||||
headers=r.headers)
|
||||
finally:
|
||||
if hasattr(r, "connection"):
|
||||
r.connection.close()
|
||||
@ -160,21 +168,22 @@ class Spotify(object):
|
||||
if retries < 0:
|
||||
raise
|
||||
else:
|
||||
sleep_seconds = int(e.headers.get('Retry-After', delay))
|
||||
print ('retrying ...' + str(sleep_seconds) + 'secs')
|
||||
sleep_seconds = int(
|
||||
e.headers.get('Retry-After', delay))
|
||||
print('retrying ...' + str(sleep_seconds) + 'secs')
|
||||
time.sleep(sleep_seconds + 1)
|
||||
delay += 1
|
||||
else:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise
|
||||
print ('exception', str(e))
|
||||
print('exception', str(e))
|
||||
# some other exception. Requests have
|
||||
# been know to throw a BadStatusLine exception
|
||||
retries -= 1
|
||||
if retries >= 0:
|
||||
sleep_seconds = int(e.headers.get('Retry-After', delay))
|
||||
print ('retrying ...' + str(delay) + 'secs')
|
||||
print('retrying ...' + str(delay) + 'secs')
|
||||
time.sleep(sleep_seconds + 1)
|
||||
delay += 1
|
||||
else:
|
||||
@ -233,7 +242,7 @@ class Spotify(object):
|
||||
trid = self._get_id('track', track_id)
|
||||
return self._get('tracks/' + trid)
|
||||
|
||||
def tracks(self, tracks, market = None):
|
||||
def tracks(self, tracks, market=None):
|
||||
""" returns a list of tracks given a list of track IDs, URIs, or URLs
|
||||
|
||||
Parameters:
|
||||
@ -242,7 +251,7 @@ class Spotify(object):
|
||||
"""
|
||||
|
||||
tlist = [self._get_id('track', t) for t in tracks]
|
||||
return self._get('tracks/?ids=' + ','.join(tlist), market = market)
|
||||
return self._get('tracks/?ids=' + ','.join(tlist), market=market)
|
||||
|
||||
def artist(self, artist_id):
|
||||
""" returns a single artist given the artist's ID, URI or URL
|
||||
@ -345,9 +354,11 @@ class Spotify(object):
|
||||
- offset - the index of the first item to return
|
||||
- type - the type of item to return. One of 'artist', 'album',
|
||||
'track' or 'playlist'
|
||||
- market - An ISO 3166-1 alpha-2 country code or the string from_token.
|
||||
- market - An ISO 3166-1 alpha-2 country code or the string
|
||||
from_token.
|
||||
"""
|
||||
return self._get('search', q=q, limit=limit, offset=offset, type=type, market=market)
|
||||
return self._get('search', q=q, limit=limit,
|
||||
offset=offset, type=type, market=market)
|
||||
|
||||
def user(self, user):
|
||||
""" Gets basic profile information about a Spotify User
|
||||
@ -394,12 +405,12 @@ class Spotify(object):
|
||||
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.
|
||||
- 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):
|
||||
""" Get full details of the tracks of a playlist owned by a user.
|
||||
@ -417,7 +428,6 @@ class Spotify(object):
|
||||
limit=limit, offset=offset, fields=fields,
|
||||
market=market)
|
||||
|
||||
|
||||
def user_playlist_create(self, user, name, public=True, description=''):
|
||||
""" Creates a playlist for a user
|
||||
|
||||
@ -429,7 +439,6 @@ class Spotify(object):
|
||||
"""
|
||||
data = {'name': name, 'public': public, 'description': description}
|
||||
|
||||
|
||||
return self._post("users/%s/playlists" % (user,), payload=data)
|
||||
|
||||
def user_playlist_change_details(
|
||||
@ -465,7 +474,8 @@ class Spotify(object):
|
||||
- user - the id of the user
|
||||
- name - the name of the playlist
|
||||
"""
|
||||
return self._delete("users/%s/playlists/%s/followers" % (user, playlist_id))
|
||||
return self._delete("users/%s/playlists/%s/followers" %
|
||||
(user, playlist_id))
|
||||
|
||||
def user_playlist_add_tracks(self, user, playlist_id, tracks,
|
||||
position=None):
|
||||
@ -505,8 +515,10 @@ class Spotify(object):
|
||||
- user - the id of the user
|
||||
- playlist_id - the id of the playlist
|
||||
- range_start - the position of the first track to be reordered
|
||||
- range_length - optional the number of tracks to be reordered (default: 1)
|
||||
- insert_before - the position where the tracks should be inserted
|
||||
- range_length - optional the number of tracks to be reordered
|
||||
(default: 1)
|
||||
- insert_before - the position where the tracks should be
|
||||
inserted
|
||||
- snapshot_id - optional playlist's snapshot ID
|
||||
"""
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
@ -575,9 +587,12 @@ class Spotify(object):
|
||||
- playlist_id - the id of the playlist
|
||||
|
||||
"""
|
||||
return self._put("users/{}/playlists/{}/followers".format(playlist_owner_id, playlist_id))
|
||||
return self._put(
|
||||
"users/{}/playlists/{}/followers".format(playlist_owner_id,
|
||||
playlist_id))
|
||||
|
||||
def user_playlist_is_following(self, playlist_owner_id, playlist_id, user_ids):
|
||||
def user_playlist_is_following(
|
||||
self, playlist_owner_id, playlist_id, user_ids):
|
||||
"""
|
||||
Check to see if the given users are following the given playlist
|
||||
|
||||
@ -588,7 +603,10 @@ class Spotify(object):
|
||||
if they follow the playlist. Maximum: 5 ids.
|
||||
|
||||
"""
|
||||
return self._get("users/{}/playlists/{}/followers/contains?ids={}".format(playlist_owner_id, playlist_id, ','.join(user_ids)))
|
||||
endpoint = "users/{}/playlists/{}/followers/contains?ids={}"
|
||||
return self._get(endpoint.format(playlist_owner_id,
|
||||
playlist_id,
|
||||
','.join(user_ids)))
|
||||
|
||||
def me(self):
|
||||
""" Get detailed profile information about the current user.
|
||||
@ -623,7 +641,8 @@ class Spotify(object):
|
||||
|
||||
Parameters:
|
||||
- limit - the number of artists to return
|
||||
- after - the last artist ID retrieved from the previous request
|
||||
- after - the last artist ID retrieved from the previous
|
||||
request
|
||||
|
||||
"""
|
||||
return self._get('me/following', type='artist', limit=limit,
|
||||
@ -858,17 +877,18 @@ class Spotify(object):
|
||||
- seed_tracks - a list of track IDs, URIs or URLs
|
||||
|
||||
- seed_genres - a list of genre names. Available genres for
|
||||
recommendations can be found by calling recommendation_genre_seeds
|
||||
recommendations can be found by calling
|
||||
recommendation_genre_seeds
|
||||
|
||||
- country - An ISO 3166-1 alpha-2 country code. If provided, all
|
||||
results will be playable in this country.
|
||||
- country - An ISO 3166-1 alpha-2 country code. If provided,
|
||||
all results will be playable in this country.
|
||||
|
||||
- limit - The maximum number of items to return. Default: 20.
|
||||
Minimum: 1. Maximum: 100
|
||||
Minimum: 1. Maximum: 100
|
||||
|
||||
- min/max/target_<attribute> - For the tuneable track attributes listed
|
||||
in the documentation, these values provide filters and targeting on
|
||||
results.
|
||||
- min/max/target_<attribute> - For the tuneable track
|
||||
attributes listed in the documentation, these values
|
||||
provide filters and targeting on results.
|
||||
"""
|
||||
params = dict(limit=limit)
|
||||
if seed_artists:
|
||||
@ -928,23 +948,23 @@ class Spotify(object):
|
||||
'''
|
||||
return self._get("me/player/devices")
|
||||
|
||||
def current_playback(self, market = None):
|
||||
def current_playback(self, market=None):
|
||||
''' Get information about user's current playback.
|
||||
|
||||
Parameters:
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
return self._get("me/player", market = market)
|
||||
return self._get("me/player", market=market)
|
||||
|
||||
def currently_playing(self, market = None):
|
||||
def currently_playing(self, market=None):
|
||||
''' Get user's currently playing track.
|
||||
|
||||
Parameters:
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
return self._get("me/player/currently-playing", market = market)
|
||||
return self._get("me/player/currently-playing", market=market)
|
||||
|
||||
def transfer_playback(self, device_id, force_play = True):
|
||||
def transfer_playback(self, device_id, force_play=True):
|
||||
''' Transfer playback to another device.
|
||||
Note that the API accepts a list of device ids, but only
|
||||
actually supports one.
|
||||
@ -960,7 +980,8 @@ class Spotify(object):
|
||||
}
|
||||
return self._put("me/player", payload=data)
|
||||
|
||||
def start_playback(self, device_id = None, context_uri = None, uris = None, offset = None):
|
||||
def start_playback(self, device_id=None,
|
||||
context_uri=None, uris=None, offset=None):
|
||||
''' Start or resume user's playback.
|
||||
|
||||
Provide a `context_uri` to start playback or a album,
|
||||
@ -991,9 +1012,10 @@ class Spotify(object):
|
||||
data['uris'] = uris
|
||||
if offset is not None:
|
||||
data['offset'] = offset
|
||||
return self._put(self._append_device_id("me/player/play", device_id), payload=data)
|
||||
return self._put(self._append_device_id(
|
||||
"me/player/play", device_id), payload=data)
|
||||
|
||||
def pause_playback(self, device_id = None):
|
||||
def pause_playback(self, device_id=None):
|
||||
''' Pause user's playback.
|
||||
|
||||
Parameters:
|
||||
@ -1001,7 +1023,7 @@ class Spotify(object):
|
||||
'''
|
||||
return self._put(self._append_device_id("me/player/pause", device_id))
|
||||
|
||||
def next_track(self, device_id = None):
|
||||
def next_track(self, device_id=None):
|
||||
''' Skip user's playback to next track.
|
||||
|
||||
Parameters:
|
||||
@ -1009,15 +1031,16 @@ class Spotify(object):
|
||||
'''
|
||||
return self._post(self._append_device_id("me/player/next", device_id))
|
||||
|
||||
def previous_track(self, device_id = None):
|
||||
def previous_track(self, device_id=None):
|
||||
''' Skip user's playback to previous track.
|
||||
|
||||
Parameters:
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
return self._post(self._append_device_id("me/player/previous", device_id))
|
||||
return self._post(self._append_device_id(
|
||||
"me/player/previous", device_id))
|
||||
|
||||
def seek_track(self, position_ms, device_id = None):
|
||||
def seek_track(self, position_ms, device_id=None):
|
||||
''' Seek to position in current track.
|
||||
|
||||
Parameters:
|
||||
@ -1027,9 +1050,10 @@ class Spotify(object):
|
||||
if not isinstance(position_ms, int):
|
||||
self._warn('position_ms must be an integer')
|
||||
return
|
||||
return self._put(self._append_device_id("me/player/seek?position_ms=%s" % position_ms, device_id))
|
||||
return self._put(self._append_device_id(
|
||||
"me/player/seek?position_ms=%s" % position_ms, device_id))
|
||||
|
||||
def repeat(self, state, device_id = None):
|
||||
def repeat(self, state, device_id=None):
|
||||
''' Set repeat mode for playback.
|
||||
|
||||
Parameters:
|
||||
@ -1039,9 +1063,12 @@ class Spotify(object):
|
||||
if state not in ['track', 'context', 'off']:
|
||||
self._warn('invalid state')
|
||||
return
|
||||
self._put(self._append_device_id("me/player/repeat?state=%s" % state, device_id))
|
||||
self._put(
|
||||
self._append_device_id(
|
||||
"me/player/repeat?state=%s" %
|
||||
state, device_id))
|
||||
|
||||
def volume(self, volume_percent, device_id = None):
|
||||
def volume(self, volume_percent, device_id=None):
|
||||
''' Set playback volume.
|
||||
|
||||
Parameters:
|
||||
@ -1054,9 +1081,12 @@ class Spotify(object):
|
||||
if volume_percent < 0 or volume_percent > 100:
|
||||
self._warn('volume must be between 0 and 100, inclusive')
|
||||
return
|
||||
self._put(self._append_device_id("me/player/volume?volume_percent=%s" % volume_percent, device_id))
|
||||
self._put(
|
||||
self._append_device_id(
|
||||
"me/player/volume?volume_percent=%s" %
|
||||
volume_percent, device_id))
|
||||
|
||||
def shuffle(self, state, device_id = None):
|
||||
def shuffle(self, state, device_id=None):
|
||||
''' Toggle playback shuffling.
|
||||
|
||||
Parameters:
|
||||
@ -1067,7 +1097,10 @@ class Spotify(object):
|
||||
self._warn('state must be a boolean')
|
||||
return
|
||||
state = str(state).lower()
|
||||
self._put(self._append_device_id("me/player/shuffle?state=%s" % state, device_id))
|
||||
self._put(
|
||||
self._append_device_id(
|
||||
"me/player/shuffle?state=%s" %
|
||||
state, device_id))
|
||||
|
||||
def _append_device_id(self, path, device_id):
|
||||
''' Append device ID to API path.
|
||||
|
||||
@ -27,7 +27,11 @@ class SpotifyOauthError(Exception):
|
||||
|
||||
|
||||
def _make_authorization_headers(client_id, client_secret):
|
||||
auth_header = base64.b64encode(six.text_type(client_id + ':' + client_secret).encode('ascii'))
|
||||
auth_header = base64.b64encode(
|
||||
six.text_type(
|
||||
client_id +
|
||||
':' +
|
||||
client_secret).encode('ascii'))
|
||||
return {'Authorization': 'Basic %s' % auth_header.decode('ascii')}
|
||||
|
||||
|
||||
@ -77,12 +81,14 @@ class SpotifyClientCredentials(object):
|
||||
|
||||
def _request_access_token(self):
|
||||
"""Gets client credentials access token """
|
||||
payload = { 'grant_type': 'client_credentials'}
|
||||
payload = {'grant_type': 'client_credentials'}
|
||||
|
||||
headers = _make_authorization_headers(self.client_id, self.client_secret)
|
||||
headers = _make_authorization_headers(
|
||||
self.client_id, self.client_secret)
|
||||
|
||||
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
|
||||
headers=headers, verify=True, proxies=self.proxies)
|
||||
headers=headers, verify=True,
|
||||
proxies=self.proxies)
|
||||
if response.status_code != 200:
|
||||
raise SpotifyOauthError(response.reason)
|
||||
token_info = response.json()
|
||||
@ -109,7 +115,7 @@ class SpotifyOAuth(object):
|
||||
OAUTH_TOKEN_URL = 'https://accounts.spotify.com/api/token'
|
||||
|
||||
def __init__(self, client_id, client_secret, redirect_uri,
|
||||
state=None, scope=None, cache_path=None, proxies=None):
|
||||
state=None, scope=None, cache_path=None, proxies=None):
|
||||
'''
|
||||
Creates a SpotifyOAuth object
|
||||
|
||||
@ -125,9 +131,9 @@ class SpotifyOAuth(object):
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
self.redirect_uri = redirect_uri
|
||||
self.state=state
|
||||
self.state = state
|
||||
self.cache_path = cache_path
|
||||
self.scope=self._normalize_scope(scope)
|
||||
self.scope = self._normalize_scope(scope)
|
||||
self.proxies = proxies
|
||||
|
||||
def get_cached_token(self):
|
||||
@ -142,11 +148,13 @@ class SpotifyOAuth(object):
|
||||
token_info = json.loads(token_info_string)
|
||||
|
||||
# if scopes don't match, then bail
|
||||
if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
|
||||
if 'scope' not in token_info or not self._is_scope_subset(
|
||||
self.scope, token_info['scope']):
|
||||
return None
|
||||
|
||||
if self.is_token_expired(token_info):
|
||||
token_info = self.refresh_access_token(token_info['refresh_token'])
|
||||
token_info = self.refresh_access_token(
|
||||
token_info['refresh_token'])
|
||||
|
||||
except IOError:
|
||||
pass
|
||||
@ -164,7 +172,8 @@ class SpotifyOAuth(object):
|
||||
|
||||
def _is_scope_subset(self, needle_scope, haystack_scope):
|
||||
needle_scope = set(needle_scope.split()) if needle_scope else set()
|
||||
haystack_scope = set(haystack_scope.split()) if haystack_scope else set()
|
||||
haystack_scope = set(
|
||||
haystack_scope.split()) if haystack_scope else set()
|
||||
return needle_scope <= haystack_scope
|
||||
|
||||
def is_token_expired(self, token_info):
|
||||
@ -222,7 +231,8 @@ class SpotifyOAuth(object):
|
||||
headers = self._make_authorization_headers()
|
||||
|
||||
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
|
||||
headers=headers, verify=True, proxies=self.proxies)
|
||||
headers=headers, verify=True,
|
||||
proxies=self.proxies)
|
||||
if response.status_code != 200:
|
||||
raise SpotifyOauthError(response.reason)
|
||||
token_info = response.json()
|
||||
@ -232,30 +242,29 @@ class SpotifyOAuth(object):
|
||||
|
||||
def _normalize_scope(self, scope):
|
||||
if scope:
|
||||
scopes = scope.split()
|
||||
scopes.sort()
|
||||
scopes = sorted(scope.split())
|
||||
return ' '.join(scopes)
|
||||
else:
|
||||
return None
|
||||
|
||||
def refresh_access_token(self, refresh_token):
|
||||
payload = { 'refresh_token': refresh_token,
|
||||
payload = {'refresh_token': refresh_token,
|
||||
'grant_type': 'refresh_token'}
|
||||
|
||||
headers = self._make_authorization_headers()
|
||||
|
||||
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
|
||||
headers=headers, proxies=self.proxies)
|
||||
headers=headers, proxies=self.proxies)
|
||||
if response.status_code != 200:
|
||||
if False: # debugging code
|
||||
print('headers', headers)
|
||||
print('request', response.url)
|
||||
self._warn("couldn't refresh token: code:%d reason:%s" \
|
||||
% (response.status_code, response.reason))
|
||||
self._warn("couldn't refresh token: code:%d reason:%s"
|
||||
% (response.status_code, response.reason))
|
||||
return None
|
||||
token_info = response.json()
|
||||
token_info = self._add_custom_values_to_token_info(token_info)
|
||||
if not 'refresh_token' in token_info:
|
||||
if 'refresh_token' not in token_info:
|
||||
token_info['refresh_token'] = refresh_token
|
||||
self._save_token_info(token_info)
|
||||
return token_info
|
||||
@ -271,4 +280,3 @@ class SpotifyOAuth(object):
|
||||
|
||||
def _warn(self, msg):
|
||||
print('warning:' + msg, file=sys.stderr)
|
||||
|
||||
|
||||
@ -22,8 +22,10 @@ CLIENT_CREDS_ENV_VARS = {
|
||||
'redirect_uri': 'SPOTIPY_REDIRECT_URI'
|
||||
}
|
||||
|
||||
def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
client_secret = None, redirect_uri = None, cache_path = None):
|
||||
|
||||
def prompt_for_user_token(username, scope=None, client_id=None,
|
||||
client_secret=None, redirect_uri=None,
|
||||
cache_path=None):
|
||||
''' prompts the user to login if necessary and returns
|
||||
the user token suitable for use with the spotipy.Spotify
|
||||
constructor
|
||||
@ -64,7 +66,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
|
||||
cache_path = cache_path or ".cache-" + username
|
||||
sp_oauth = oauth2.SpotifyOAuth(client_id, client_secret, redirect_uri,
|
||||
scope=scope, cache_path=cache_path)
|
||||
scope=scope, cache_path=cache_path)
|
||||
|
||||
# try to get a valid token for this user, from the cache,
|
||||
# if not in the cache, the create a new (this will send
|
||||
@ -87,7 +89,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
import webbrowser
|
||||
webbrowser.open(auth_url)
|
||||
print("Opened %s in your browser" % auth_url)
|
||||
except:
|
||||
except BaseException:
|
||||
print("Please navigate here: %s" % auth_url)
|
||||
|
||||
print()
|
||||
|
||||
@ -14,27 +14,23 @@ following environment variables
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
from pprint import pprint
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import simplejson as json
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
from spotipy import (
|
||||
CLIENT_CREDS_ENV_VARS as CCEV,
|
||||
prompt_for_user_token,
|
||||
Spotify,
|
||||
SpotifyException,
|
||||
)
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
|
||||
class AuthTestSpotipy(unittest.TestCase):
|
||||
"""
|
||||
These tests require user authentication - provide client credentials using the
|
||||
following environment variables
|
||||
These tests require user authentication - provide client credentials using
|
||||
the following environment variables
|
||||
|
||||
::
|
||||
|
||||
@ -47,30 +43,32 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
|
||||
playlist_new_id = "spotify:playlist:7GlxpQjjxRjmbb3RP2rDqI"
|
||||
four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
||||
"4VrWlk8IQxevMvERoX08iC",
|
||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
||||
"4VrWlk8IQxevMvERoX08iC",
|
||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
||||
|
||||
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||
|
||||
other_tracks=["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
||||
other_tracks = ["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
||||
|
||||
album_ids = ["spotify:album:6kL09DaURb7rAoqqaA51KU",
|
||||
"spotify:album:6RTzC0rDbvagTSJLlY7AKl"]
|
||||
|
||||
bad_id = 'BAD_ID'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
|
||||
missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))
|
||||
|
||||
if missing:
|
||||
raise Exception('Please set the client credentials for the test application using the following environment variables: {}'.format(CCEV.values()))
|
||||
raise Exception(
|
||||
('Please set the client credentials for the test application'
|
||||
' using the following environment variables: {}').format(
|
||||
CCEV.values()))
|
||||
|
||||
self.username = os.getenv(CCEV['client_username'])
|
||||
|
||||
@ -121,14 +119,12 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
results = self.spotify.user_playlist_tracks(user, pid)
|
||||
self.assertTrue(len(results['items']) >= 0)
|
||||
|
||||
def user_playlist_tracks(self, user, playlist_id = None, fields=None,
|
||||
limit=100, offset=0):
|
||||
|
||||
# known API issue currently causes this test to fail
|
||||
# the issue is that the API doesn't currently respect the
|
||||
# limit parameter
|
||||
|
||||
self.assertTrue(len(playlists['items']) == 5)
|
||||
# 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):
|
||||
# List
|
||||
@ -139,7 +135,10 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
self.spotify.current_user_saved_albums_add(self.album_ids)
|
||||
|
||||
# Contains
|
||||
self.assertTrue(self.spotify.current_user_saved_albums_contains(self.album_ids) == [True, True])
|
||||
self.assertTrue(
|
||||
self.spotify.current_user_saved_albums_contains(
|
||||
self.album_ids) == [
|
||||
True, True])
|
||||
|
||||
# Remove
|
||||
self.spotify.current_user_saved_albums_delete(self.album_ids)
|
||||
@ -152,14 +151,20 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
self.assertTrue(len(playlists['items']) == 10)
|
||||
|
||||
def test_user_playlist_follow(self):
|
||||
self.spotify.user_playlist_follow_playlist('plamere', '4erXB04MxwRAVqcUEpu30O')
|
||||
follows = self.spotify.user_playlist_is_following('plamere', '4erXB04MxwRAVqcUEpu30O', [self.spotify.current_user()['id']])
|
||||
self.spotify.user_playlist_follow_playlist(
|
||||
'plamere', '4erXB04MxwRAVqcUEpu30O')
|
||||
follows = self.spotify.user_playlist_is_following(
|
||||
'plamere', '4erXB04MxwRAVqcUEpu30O', [
|
||||
self.spotify.current_user()['id']])
|
||||
|
||||
self.assertTrue(len(follows) == 1, 'proper follows length')
|
||||
self.assertTrue(follows[0], 'is following')
|
||||
self.spotify.user_playlist_unfollow('plamere', '4erXB04MxwRAVqcUEpu30O')
|
||||
self.spotify.user_playlist_unfollow(
|
||||
'plamere', '4erXB04MxwRAVqcUEpu30O')
|
||||
|
||||
follows = self.spotify.user_playlist_is_following('plamere', '4erXB04MxwRAVqcUEpu30O', [self.spotify.current_user()['id']])
|
||||
follows = self.spotify.user_playlist_is_following(
|
||||
'plamere', '4erXB04MxwRAVqcUEpu30O', [
|
||||
self.spotify.current_user()['id']])
|
||||
self.assertTrue(len(follows) == 1, 'proper follows length')
|
||||
self.assertFalse(follows[0], 'is no longer following')
|
||||
|
||||
@ -176,7 +181,8 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
new_total = tracks['total']
|
||||
self.assertTrue(new_total - total == len(self.four_tracks))
|
||||
|
||||
tracks = self.spotify.current_user_saved_tracks_delete(self.four_tracks)
|
||||
tracks = self.spotify.current_user_saved_tracks_delete(
|
||||
self.four_tracks)
|
||||
tracks = self.spotify.current_user_saved_tracks()
|
||||
new_total = tracks['total']
|
||||
self.assertTrue(new_total == total)
|
||||
@ -224,37 +230,45 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
if item['name'] == playlist_name:
|
||||
return item['id']
|
||||
playlists = self.spotify.next(playlists)
|
||||
playlist = self.spotify.user_playlist_create(self.username, playlist_name)
|
||||
playlist = self.spotify.user_playlist_create(
|
||||
self.username, playlist_name)
|
||||
playlist_id = playlist['uri']
|
||||
return playlist_id
|
||||
|
||||
def test_user_playlist_ops(self):
|
||||
sp = self.spotify
|
||||
# create empty playlist
|
||||
playlist_id = self.get_or_create_spotify_playlist('spotipy-testing-playlist-1')
|
||||
playlist_id = self.get_or_create_spotify_playlist(
|
||||
'spotipy-testing-playlist-1')
|
||||
|
||||
# remove all tracks from it
|
||||
self.spotify.user_playlist_replace_tracks(self.username, playlist_id,[])
|
||||
playlist = self.spotify.user_playlist(self.username, playlist_id)
|
||||
sp.user_playlist_replace_tracks(
|
||||
self.username, playlist_id, [])
|
||||
playlist = sp.user_playlist(self.username, playlist_id)
|
||||
self.assertTrue(playlist['tracks']['total'] == 0)
|
||||
self.assertTrue(len(playlist['tracks']['items']) == 0)
|
||||
|
||||
# add tracks to it
|
||||
self.spotify.user_playlist_add_tracks(self.username, playlist_id, self.four_tracks)
|
||||
playlist = self.spotify.user_playlist(self.username, playlist_id)
|
||||
sp.user_playlist_add_tracks(
|
||||
self.username, playlist_id, self.four_tracks)
|
||||
playlist = sp.user_playlist(self.username, playlist_id)
|
||||
self.assertTrue(playlist['tracks']['total'] == 4)
|
||||
self.assertTrue(len(playlist['tracks']['items']) == 4)
|
||||
|
||||
# remove two tracks from it
|
||||
self.spotify.user_playlist_remove_all_occurrences_of_tracks (self.username,
|
||||
playlist_id, self.two_tracks)
|
||||
playlist = self.spotify.user_playlist(self.username, playlist_id)
|
||||
|
||||
sp.user_playlist_remove_all_occurrences_of_tracks(self.username,
|
||||
playlist_id,
|
||||
self.two_tracks)
|
||||
playlist = sp.user_playlist(self.username, playlist_id)
|
||||
self.assertTrue(playlist['tracks']['total'] == 2)
|
||||
self.assertTrue(len(playlist['tracks']['items']) == 2)
|
||||
|
||||
# replace with 3 other tracks
|
||||
self.spotify.user_playlist_replace_tracks(self.username,
|
||||
playlist_id, self.other_tracks)
|
||||
playlist = self.spotify.user_playlist(self.username, playlist_id)
|
||||
sp.user_playlist_replace_tracks(self.username,
|
||||
playlist_id,
|
||||
self.other_tracks)
|
||||
playlist = sp.user_playlist(self.username, playlist_id)
|
||||
self.assertTrue(playlist['tracks']['total'] == 3)
|
||||
self.assertTrue(len(playlist['tracks']['items']) == 3)
|
||||
|
||||
@ -293,5 +307,6 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
# Unfollow these 2 users
|
||||
self.spotify.user_unfollow_users(users)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@ -12,25 +12,21 @@ following environment variables
|
||||
'SPOTIPY_REDIRECT_URI'
|
||||
"""
|
||||
|
||||
import os
|
||||
import pprint
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import simplejson as json
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
from spotipy import (
|
||||
Spotify,
|
||||
SpotifyClientCredentials,
|
||||
)
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
|
||||
class AuthTestSpotipy(unittest.TestCase):
|
||||
"""
|
||||
These tests require user authentication - provide client credentials using the
|
||||
following environment variables
|
||||
These tests require user authentication - provide client credentials using
|
||||
the following environment variables
|
||||
|
||||
::
|
||||
|
||||
@ -42,22 +38,23 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
|
||||
playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
|
||||
four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
||||
"4VrWlk8IQxevMvERoX08iC",
|
||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
||||
"4VrWlk8IQxevMvERoX08iC",
|
||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
||||
|
||||
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||
|
||||
other_tracks=["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
||||
other_tracks = ["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
||||
|
||||
bad_id = 'BAD_ID'
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.spotify = Spotify(client_credentials_manager=SpotifyClientCredentials())
|
||||
self.spotify = Spotify(
|
||||
client_credentials_manager=SpotifyClientCredentials())
|
||||
self.spotify.trace = False
|
||||
|
||||
def test_audio_analysis(self):
|
||||
@ -77,15 +74,18 @@ class AuthTestSpotipy(unittest.TestCase):
|
||||
results = self.spotify.audio_features(input)
|
||||
self.assertTrue(len(results) == len(input))
|
||||
for track in results[:-1]:
|
||||
if track != None:
|
||||
if track is not None:
|
||||
assert('speechiness' in track)
|
||||
self.assertTrue(results[-1] == None)
|
||||
self.assertTrue(results[-1] is None)
|
||||
|
||||
def test_recommendations(self):
|
||||
results = self.spotify.recommendations(seed_tracks=self.four_tracks, min_danceability=0, max_loudness=0, target_popularity=50)
|
||||
results = self.spotify.recommendations(
|
||||
seed_tracks=self.four_tracks,
|
||||
min_danceability=0,
|
||||
max_loudness=0,
|
||||
target_popularity=50)
|
||||
self.assertTrue(len(results['tracks']) == 20)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
unittest.main()
|
||||
|
||||
@ -2,22 +2,21 @@
|
||||
|
||||
""" Client Credentials Requests Tests """
|
||||
|
||||
from spotipy import (
|
||||
Spotify,
|
||||
SpotifyClientCredentials,
|
||||
)
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
from spotipy import (
|
||||
Spotify,
|
||||
SpotifyClientCredentials,
|
||||
)
|
||||
|
||||
|
||||
class ClientCredentialsTestSpotipy(unittest.TestCase):
|
||||
"""
|
||||
These tests require user authentication - provide client credentials using the
|
||||
following environment variables
|
||||
These tests require user authentication - provide client credentials using
|
||||
the following environment variables
|
||||
|
||||
::
|
||||
|
||||
@ -29,7 +28,8 @@ class ClientCredentialsTestSpotipy(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.spotify = Spotify(client_credentials_manager=SpotifyClientCredentials())
|
||||
self.spotify = Spotify(
|
||||
client_credentials_manager=SpotifyClientCredentials())
|
||||
self.spotify.trace = False
|
||||
|
||||
muse_urn = 'spotify:artist:12Chz98pHFMPJEknJQMWvI'
|
||||
@ -40,5 +40,4 @@ class ClientCredentialsTestSpotipy(unittest.TestCase):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
unittest.main()
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import six.moves.urllib.parse as urllibparse
|
||||
from spotipy import SpotifyOAuth
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
@ -8,13 +10,11 @@ import unittest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
from spotipy import SpotifyOAuth
|
||||
|
||||
try:
|
||||
import unittest.mock as mock
|
||||
except ImportError:
|
||||
import mock
|
||||
import six.moves.urllib.parse as urllibparse
|
||||
|
||||
patch = mock.patch
|
||||
DEFAULT = mock.DEFAULT
|
||||
|
||||
@ -1,27 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import pprint
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import requests
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
from spotipy import (
|
||||
CLIENT_CREDS_ENV_VARS as CCEV,
|
||||
prompt_for_user_token,
|
||||
Spotify,
|
||||
SpotifyException,
|
||||
)
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import requests
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
|
||||
class TestSpotipy(unittest.TestCase):
|
||||
|
||||
"""
|
||||
These tests require user authentication - provide client credentials using the
|
||||
following environment variables
|
||||
These tests require user authentication - provide client credentials using
|
||||
the following environment variables
|
||||
|
||||
::
|
||||
|
||||
@ -42,7 +40,6 @@ class TestSpotipy(unittest.TestCase):
|
||||
radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
|
||||
angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'
|
||||
|
||||
|
||||
bad_id = 'BAD_ID'
|
||||
|
||||
@classmethod
|
||||
@ -50,7 +47,10 @@ class TestSpotipy(unittest.TestCase):
|
||||
missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))
|
||||
|
||||
if missing:
|
||||
raise Exception('Please set the client credentials for the test application using the following environment variables: {}'.format(CCEV.values()))
|
||||
raise Exception(
|
||||
('Please set the client credentials for the test '
|
||||
'the following environment variables: {}').format(
|
||||
CCEV.values()))
|
||||
|
||||
self.username = os.getenv(CCEV['client_username'])
|
||||
|
||||
@ -82,14 +82,16 @@ class TestSpotipy(unittest.TestCase):
|
||||
tracks = results['items']
|
||||
total, received = results['total'], len(tracks)
|
||||
while received < total:
|
||||
results = self.spotify.album_tracks(self.angeles_haydn_urn, offset=received)
|
||||
results = self.spotify.album_tracks(
|
||||
self.angeles_haydn_urn, offset=received)
|
||||
tracks.extend(results['items'])
|
||||
received = len(tracks)
|
||||
|
||||
self.assertEqual(received, total)
|
||||
|
||||
def test_albums(self):
|
||||
results = self.spotify.albums([self.pinkerton_urn, self.pablo_honey_urn])
|
||||
results = self.spotify.albums(
|
||||
[self.pinkerton_urn, self.pablo_honey_urn])
|
||||
self.assertTrue('albums' in results)
|
||||
self.assertTrue(len(results['albums']) == 2)
|
||||
|
||||
@ -107,7 +109,7 @@ class TestSpotipy(unittest.TestCase):
|
||||
|
||||
def test_track_bad_urn(self):
|
||||
try:
|
||||
track = self.spotify.track(self.el_scorcho_bad_urn)
|
||||
self.spotify.track(self.el_scorcho_bad_urn)
|
||||
self.assertTrue(False)
|
||||
except SpotifyException:
|
||||
self.assertTrue(True)
|
||||
@ -158,17 +160,17 @@ class TestSpotipy(unittest.TestCase):
|
||||
def test_search_timeout(self):
|
||||
sp = Spotify(auth=self.token, requests_timeout=.01)
|
||||
try:
|
||||
results = sp.search(q='my*', type='track')
|
||||
sp.search(q='my*', type='track')
|
||||
self.assertTrue(False, 'unexpected search timeout')
|
||||
except requests.Timeout:
|
||||
self.assertTrue(True, 'expected search timeout')
|
||||
|
||||
|
||||
def test_album_search(self):
|
||||
results = self.spotify.search(q='weezer pinkerton', type='album')
|
||||
self.assertTrue('albums' in results)
|
||||
self.assertTrue(len(results['albums']['items']) > 0)
|
||||
self.assertTrue(results['albums']['items'][0]['name'].find('Pinkerton') >= 0)
|
||||
self.assertTrue(results['albums']['items'][0]
|
||||
['name'].find('Pinkerton') >= 0)
|
||||
|
||||
def test_track_search(self):
|
||||
results = self.spotify.search(q='el scorcho weezer', type='track')
|
||||
@ -182,34 +184,34 @@ class TestSpotipy(unittest.TestCase):
|
||||
|
||||
def test_track_bad_id(self):
|
||||
try:
|
||||
track = self.spotify.track(self.bad_id)
|
||||
self.assertTrue(False)
|
||||
except SpotifyException:
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_track_bad_id(self):
|
||||
try:
|
||||
track = self.spotify.track(self.bad_id)
|
||||
self.spotify.track(self.bad_id)
|
||||
self.assertTrue(False)
|
||||
except SpotifyException:
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_unauthenticated_post_fails(self):
|
||||
with self.assertRaises(SpotifyException) as cm:
|
||||
self.spotify.user_playlist_create("spotify", "Best hits of the 90s")
|
||||
self.spotify.user_playlist_create(
|
||||
"spotify", "Best hits of the 90s")
|
||||
self.assertTrue(cm.exception.http_status == 401 or
|
||||
cm.exception.http_status == 403)
|
||||
cm.exception.http_status == 403)
|
||||
|
||||
def test_custom_requests_session(self):
|
||||
sess = requests.Session()
|
||||
sess.headers["user-agent"] = "spotipy-test"
|
||||
with_custom_session = Spotify(auth=self.token, requests_session=sess)
|
||||
self.assertTrue(with_custom_session.user(user="akx")["uri"] == "spotify:user:akx")
|
||||
self.assertTrue(
|
||||
with_custom_session.user(
|
||||
user="akx")["uri"] == "spotify:user:akx")
|
||||
|
||||
def test_force_no_requests_session(self):
|
||||
with_no_session = Spotify(auth=self.token, requests_session=False)
|
||||
self.assertFalse(isinstance(with_no_session._session, requests.Session))
|
||||
self.assertTrue(with_no_session.user(user="akx")["uri"] == "spotify:user:akx")
|
||||
self.assertFalse(
|
||||
isinstance(
|
||||
with_no_session._session,
|
||||
requests.Session))
|
||||
self.assertTrue(with_no_session.user(user="akx")
|
||||
["uri"] == "spotify:user:akx")
|
||||
|
||||
|
||||
'''
|
||||
@ -220,5 +222,4 @@ class TestSpotipy(unittest.TestCase):
|
||||
'''
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
unittest.main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user