Add linter, solves #348 (#415)

This commit is contained in:
Stéphane Bruckert 2020-01-12 13:19:40 +00:00 committed by GitHub
parent 5928981e3b
commit f54830e272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 324 additions and 248 deletions

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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:])

View File

@ -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:]

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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)

View File

@ -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]")

View File

@ -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'])

View File

@ -14,4 +14,3 @@ sp = spotipy.Spotify()
sp.trace = True
user = sp.user(username)
pprint.pprint(user)

View File

@ -14,4 +14,3 @@ while results['next']:
for album in albums:
print((album['name']))

View File

@ -15,4 +15,3 @@ items = results['artists']['items']
if len(items) > 0:
artist = items[0]
print(artist['name'], artist['images'][0]['url'])

View File

@ -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())

View File

@ -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)

View File

@ -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:

View File

@ -3,9 +3,7 @@
"""
import pprint
import sys
import json
import spotipy
import spotipy.util as util

View File

@ -5,7 +5,6 @@ import spotipy
import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:

View File

@ -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'])

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -7,3 +7,8 @@ deps=
six
py27: mock
commands=python -m unittest discover -v tests
[flake8]
exclude=
.git,
dist,
docs