Merge pull request #56 from joohoi/python3

Python3 support
This commit is contained in:
Paul Lamere 2015-06-08 14:36:17 +02:00
commit fd9441a1e7
33 changed files with 140 additions and 114 deletions

View File

@ -42,8 +42,8 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'spotipy'
copyright = u'2014, Paul Lamere'
project = 'spotipy'
copyright = '2014, Paul Lamere'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -185,8 +185,8 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'spotipy.tex', u'spotipy Documentation',
u'Paul Lamere', 'manual'),
('index', 'spotipy.tex', 'spotipy Documentation',
'Paul Lamere', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@ -215,8 +215,8 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'spotipy', u'spotipy Documentation',
[u'Paul Lamere'], 1)
('index', 'spotipy', 'spotipy Documentation',
['Paul Lamere'], 1)
]
# If true, show URL addresses after external links.
@ -229,8 +229,8 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'spotipy', u'spotipy Documentation',
u'Paul Lamere', 'spotipy', 'One line description of project.',
('index', 'spotipy', 'spotipy Documentation',
'Paul Lamere', 'spotipy', 'One line description of project.',
'Miscellaneous'),
]

View File

@ -13,7 +13,7 @@ if len(sys.argv) > 2:
username = sys.argv[1]
tids = sys.argv[2:]
else:
print "Usage: %s username track-id ..." % (sys.argv[0],)
print("Usage: %s username track-id ..." % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
@ -24,4 +24,4 @@ if token:
results = sp.current_user_saved_tracks_add(tracks=tids)
pprint.pprint(results)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -12,7 +12,7 @@ if len(sys.argv) > 3:
playlist_id = sys.argv[2]
track_ids = sys.argv[3:]
else:
print "Usage: %s username playlist_id track_id ..." % (sys.argv[0],)
print("Usage: %s username playlist_id track_id ..." % (sys.argv[0],))
sys.exit()
scope = 'playlist-modify-public'
@ -22,6 +22,6 @@ if token:
sp = spotipy.Spotify(auth=token)
sp.trace = False
results = sp.user_playlist_add_tracks(username, playlist_id, track_ids)
print results
print(results)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -24,14 +24,14 @@ def show_artist_albums(artist):
for album in albums:
name = album['name']
if name not in seen:
print(' ' + name)
print((' ' + name))
seen.add(name)
if __name__ == '__main__':
sp = spotipy.Spotify()
if len(sys.argv) < 2:
print('Usage: {0} artist name'.format(sys.argv[0]))
print(('Usage: {0} artist name'.format(sys.argv[0])))
else:
name = ' '.join(sys.argv[1:])
artist = get_artist(name)

View File

@ -20,9 +20,9 @@ def show_album_tracks(album):
results = sp.next(results)
tracks.extend(results['items'])
for track in tracks:
print ' ', track['name']
print
print track
print(' ', track['name'])
print()
print(track)
def show_artist_albums(id):
albums = []
@ -31,27 +31,27 @@ def show_artist_albums(id):
while results['next']:
results = sp.next(results)
albums.extend(results['items'])
print 'Total albums:', len(albums)
print('Total albums:', len(albums))
unique = set() # skip duplicate albums
for album in albums:
name = album['name']
if not name in unique:
print name
print(name)
unique.add(name)
show_album_tracks(album)
def show_artist(artist):
print '====', artist['name'], '===='
print 'Popularity: ', artist['popularity']
print('====', artist['name'], '====')
print('Popularity: ', artist['popularity'])
if len(artist['genres']) > 0:
print 'Genres: ', ','.join(artist['genres'])
print('Genres: ', ','.join(artist['genres']))
if __name__ == '__main__':
sp = spotipy.Spotify()
sp.trace = False
if len(sys.argv) < 2:
print('Usage: {0} artist name'.format(sys.argv[0]))
print(('Usage: {0} artist name'.format(sys.argv[0])))
else:
name = ' '.join(sys.argv[1:])
artist = get_artist(name)

View File

@ -10,7 +10,7 @@ if len(sys.argv) > 2:
username = sys.argv[1]
tids = sys.argv[2:]
else:
print "Usage: %s username track-id ..." % (sys.argv[0],)
print("Usage: %s username track-id ..." % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
@ -21,4 +21,4 @@ if token:
results = sp.current_user_saved_tracks_contains(tracks=tids)
pprint.pprint(results)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -13,7 +13,7 @@ if len(sys.argv) > 2:
username = sys.argv[1]
playlist_name = sys.argv[2]
else:
print "Usage: %s username playlist-name" % (sys.argv[0],)
print("Usage: %s username playlist-name" % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username)
@ -24,4 +24,4 @@ if token:
playlists = sp.user_playlist_create(username, playlist_name)
pprint.pprint(playlists)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -12,7 +12,7 @@ if len(sys.argv) > 2:
username = sys.argv[1]
tids = sys.argv[2:]
else:
print "Usage: %s username track-id ..." % (sys.argv[0],)
print("Usage: %s username track-id ..." % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
@ -23,4 +23,4 @@ if token:
results = sp.current_user_saved_tracks_delete(tracks=tids)
pprint.pprint(results)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -16,7 +16,7 @@ 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'
@ -28,4 +28,4 @@ if token:
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
print("Can't get token for", username)

View File

@ -12,7 +12,7 @@ if len(sys.argv) > 3:
playlist_id = sys.argv[2]
track_ids = sys.argv[3:]
else:
print "Usage: %s username playlist_id track_id ..." % (sys.argv[0],)
print("Usage: %s username playlist_id track_id ..." % (sys.argv[0],))
sys.exit()
scope = 'playlist-modify-public'
@ -24,4 +24,4 @@ if token:
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
print("Can't get token for", username)

View File

@ -12,7 +12,7 @@ if len(sys.argv) > 3:
playlist_id = sys.argv[2]
track_ids = sys.argv[3:]
else:
print "Usage: %s username playlist_id track_id ..." % (sys.argv[0],)
print("Usage: %s username playlist_id track_id ..." % (sys.argv[0],))
sys.exit()
scope = 'playlist-modify-public'
@ -24,4 +24,4 @@ if token:
results = sp.user_playlist_replace_tracks(username, playlist_id, track_ids)
pprint.pprint(results)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -13,4 +13,4 @@ sp = spotipy.Spotify()
response = sp.artist_top_tracks(urn)
for track in response['tracks']:
print track['name']
print(track['name'])

View File

@ -8,8 +8,8 @@ import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Whoops, need your username!"
print "usage: python featured_playlists.py [username]"
print("Whoops, need your username!")
print("usage: python featured_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
@ -18,16 +18,16 @@ if token:
sp = spotipy.Spotify(auth=token)
response = sp.featured_playlists()
print response['message']
print(response['message'])
while response:
playlists = response['playlists']
for i, item in enumerate(playlists['items']):
print playlists['offset'] + i, item['name']
print(playlists['offset'] + i, item['name'])
if playlists['next']:
response = sp.next(playlists)
else:
response = None
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -10,7 +10,7 @@ scope = 'user-library-read'
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Usage: %s username" % (sys.argv[0],)
print("Usage: %s username" % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
@ -20,6 +20,6 @@ if token:
results = sp.current_user_saved_tracks()
for item in results['items']:
track = item['track']
print track['name'] + ' - ' + track['artists'][0]['name']
print(track['name'] + ' - ' + track['artists'][0]['name'])
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -8,8 +8,8 @@ import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Whoops, need your username!"
print "usage: python new_releases.py [username]"
print("Whoops, need your username!")
print("usage: python new_releases.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
@ -22,11 +22,11 @@ if token:
while response:
albums = response['albums']
for i, item in enumerate(albums['items']):
print albums['offset'] + i,item['name']
print(albums['offset'] + i,item['name'])
if albums['next']:
response = sp.next(albums)
else:
response = None
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -17,9 +17,9 @@ try:
uri = result['artists']['items'][0]['uri']
related = sp.artist_related_artists(uri)
print 'Related artists for', name
print('Related artists for', name)
for artist in related['artists']:
print ' ', artist['name']
print(' ', artist['name'])
except:
print "usage show_related.py [artist-name]"
print("usage show_related.py [artist-name]")

View File

@ -15,10 +15,10 @@ if __name__ == '__main__':
tids = file.read().split()
sp = spotipy.Spotify()
for start in xrange(0, len(tids), max_tracks_per_call):
for start in range(0, len(tids), max_tracks_per_call):
results = sp.tracks(tids[start: start + max_tracks_per_call])
for track in results['tracks']:
print track['name'] + ' - ' + track['artists'][0]['name']
print(track['name'] + ' - ' + track['artists'][0]['name'])

View File

@ -3,4 +3,4 @@ sp = spotipy.Spotify()
results = sp.search(q='weezer', limit=20)
for i, t in enumerate(results['tracks']['items']):
print ' ', i, t['name']
print(' ', i, t['name'])

View File

@ -12,5 +12,5 @@ while results['next']:
albums.extend(results['items'])
for album in albums:
print(album['name'])
print((album['name']))

View File

@ -9,7 +9,7 @@ spotify = spotipy.Spotify()
results = spotify.artist_top_tracks(lz_uri)
for track in results['tracks'][:10]:
print 'track : ' + track['name']
print 'audio : ' + track['preview_url']
print 'cover art: ' + track['album']['images'][0]['url']
print
print('track : ' + track['name'])
print('audio : ' + track['preview_url'])
print('cover art: ' + track['album']['images'][0]['url'])
print()

View File

@ -12,5 +12,5 @@ results = spotify.search(q='artist:' + name, type='artist')
items = results['artists']['items']
if len(items) > 0:
artist = items[0]
print artist['name'], artist['images'][0]['url']
print(artist['name'], artist['images'][0]['url'])

View File

@ -1,6 +1,6 @@
# shows tracks for the given artist
from __future__ import print_function
import spotipy
import sys
sp = spotipy.Spotify()

View File

@ -13,8 +13,8 @@ import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Whoops, need your username!"
print "usage: python user_playlists.py [username]"
print("Whoops, need your username!")
print("usage: python user_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
@ -23,6 +23,6 @@ if token:
sp = spotipy.Spotify(auth=token)
playlists = sp.user_playlists(username)
for playlist in playlists['items']:
print playlist['name']
print(playlist['name'])
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -8,15 +8,15 @@ import spotipy.util as util
def show_tracks(results):
for i, item in enumerate(tracks['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__':
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Whoops, need your username!"
print "usage: python user_playlists.py [username]"
print("Whoops, need your username!")
print("usage: python user_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
@ -27,9 +27,9 @@ if __name__ == '__main__':
playlists = sp.user_playlists(username)
for playlist in playlists['items']:
if playlist['owner']['id'] == username:
print
print playlist['name']
print ' total tracks', playlist['tracks']['total']
print()
print(playlist['name'])
print(' total tracks', playlist['tracks']['total'])
results = sp.user_playlist(username, playlist['id'], fields="tracks,next")
tracks = results['tracks']
show_tracks(tracks)
@ -37,5 +37,5 @@ if __name__ == '__main__':
tracks = sp.next(tracks)
show_tracks(tracks)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -9,8 +9,8 @@ import spotipy.util as util
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Whoops, need your username!"
print "usage: python user_playlists.py [username]"
print("Whoops, need your username!")
print("usage: python user_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
@ -23,9 +23,9 @@ if token:
while tracks:
for item in tracks['items']:
track = item['track']
print which, track['name' ], ' --', track['artists'][0]['name']
print(which, track['name' ], ' --', track['artists'][0]['name'])
which += 1
tracks = sp.next(tracks)
else:
print "Can't get token for", username
print("Can't get token for", username)

View File

@ -1,2 +1,2 @@
VERSION='2.0.1'
from client import Spotify, SpotifyException
from .client import Spotify, SpotifyException

View File

@ -1,7 +1,7 @@
# coding: utf-8
from __future__ import print_function
from __future__ import print_function
import sys
import base64
import requests
@ -18,7 +18,7 @@ class SpotifyException(Exception):
self.msg = msg
def __str__(self):
return u'http status: {0}, code:{1} - {2}'.format(
return 'http status: {0}, code:{1} - {2}'.format(
self.http_status, self.code, self.msg)
class Spotify(object):
@ -101,7 +101,9 @@ class Spotify(object):
r.raise_for_status()
except:
raise SpotifyException(r.status_code,
-1, u'%s:\n %s' % (r.url, r.json()['error']['message']))
-1, '%s:\n %s' % (r.url, r.json()['error']['message']))
finally:
r.connection.close()
if len(r.text) > 0:
results = r.json()
if self.trace: # pragma: no cover

View File

@ -1,12 +1,20 @@
from __future__ import print_function
import base64
import urllib
import requests
import os
import json
import time
import sys
# Workaround to support both python 2 & 3
try:
import urllib.request, urllib.error
import urllib.parse as urllibparse
except ImportError:
import urllib as urllibparse
class SpotifyOauthError(Exception):
pass
@ -54,6 +62,10 @@ class SpotifyClientCredentials(object):
"""Gets client credentials access token """
payload = { 'grant_type': 'client_credentials'}
if sys.version_info[0] >= 3: # Python 3
auth_header = base64.b64encode(str(self.client_id + ':' + self.client_secret).encode())
headers = {'Authorization': 'Basic %s' % auth_header.decode()}
else: # Python 2
auth_header = base64.b64encode(self.client_id + ':' + self.client_secret)
headers = {'Authorization': 'Basic %s' % auth_header}
@ -154,7 +166,7 @@ class SpotifyOAuth(object):
if self.state:
payload['state'] = self.state
urlparams = urllib.urlencode(payload)
urlparams = urllibparse.urlencode(payload)
return "%s?%s" % (self.OAUTH_AUTHORIZE_URL, urlparams)
@ -185,10 +197,13 @@ class SpotifyOAuth(object):
if self.state:
payload['state'] = self.state
if sys.version_info[0] >= 3: # Python 3
auth_header = base64.b64encode(str(self.client_id + ':' + self.client_secret).encode())
headers = {'Authorization': 'Basic %s' % auth_header.decode()}
else: # Python 2
auth_header = base64.b64encode(self.client_id + ':' + self.client_secret)
headers = {'Authorization': 'Basic %s' % auth_header}
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
headers=headers, verify=True)
if response.status_code is not 200:
@ -210,6 +225,10 @@ class SpotifyOAuth(object):
payload = { 'refresh_token': refresh_token,
'grant_type': 'refresh_token'}
if sys.version_info[0] >= 3: # Python 3
auth_header = base64.b64encode(str(self.client_id + ':' + self.client_secret).encode())
headers = {'Authorization': 'Basic %s' % auth_header.decode()}
else: # Python 2
auth_header = base64.b64encode(self.client_id + ':' + self.client_secret)
headers = {'Authorization': 'Basic %s' % auth_header}

View File

@ -1,9 +1,10 @@
# shows a user's playlists (need to be authenticated via oauth)
from __future__ import print_function
import os
import subprocess
import oauth2
from . import oauth2
import spotipy
def prompt_for_user_token(username, scope=None, client_id = None,
@ -32,7 +33,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
redirect_uri = os.getenv('SPOTIPY_REDIRECT_URI')
if not client_id:
print '''
print('''
You need to set your Spotify API credentials. You can do this by
setting environment variables like so:
@ -42,7 +43,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
Get your credentials at
https://developer.spotify.com/my-applications
'''
''')
raise spotipy.SpotifyException(550, -1, 'no credentials set')
sp_oauth = oauth2.SpotifyOAuth(client_id, client_secret, redirect_uri,
@ -55,7 +56,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
token_info = sp_oauth.get_cached_token()
if not token_info:
print '''
print('''
User authentication requires interaction with your
web browser. Once you enter your credentials and
@ -63,19 +64,23 @@ def prompt_for_user_token(username, scope=None, client_id = None,
a url. Paste that url you were directed to to
complete the authorization.
'''
''')
auth_url = sp_oauth.get_authorize_url()
try:
subprocess.call(["open", auth_url])
print "Opening %s in your browser" % auth_url
print("Opening %s in your browser" % auth_url)
except:
print "Please navigate here: %s" % auth_url
print("Please navigate here: %s" % auth_url)
print
print
print()
print()
try:
response = raw_input("Enter the URL you were redirected to: ")
print
print
except NameError:
response = input("Enter the URL you were redirected to: ")
print()
print()
code = sp_oauth.parse_response_code(response)
token_info = sp_oauth.get_access_token(code)

View File

@ -57,11 +57,6 @@ class AuthTestSpotipy(unittest.TestCase):
def test_user_playlists(self):
playlists = spotify.user_playlists(username, limit=5)
self.assertTrue('items' in playlists)
# known API issue currently causes this test to fail
# the issue is that the API doesn't currently respect the
# limit paramter
self.assertTrue(len(playlists['items']) == 5)
def test_user_playlist_tracks(self):
@ -174,4 +169,4 @@ if __name__ == '__main__':
spotify.trace = False
unittest.main()
else:
print "Usage: %s username" % (sys.argv[0],)
print("Usage: %s username" % (sys.argv[0],))

View File

@ -17,7 +17,7 @@ class ClientCredentialsTestSpotipy(unittest.TestCase):
def test_request_with_token(self):
artist = spotify.artist(self.muse_urn)
self.assertTrue(artist['name'] == u'Muse')
self.assertTrue(artist['name'] == 'Muse')
if __name__ == '__main__':

View File

@ -25,7 +25,7 @@ class TestSpotipy(unittest.TestCase):
def test_artist_urn(self):
artist = self.spotify.artist(self.radiohead_urn)
self.assertTrue(artist['name'] == u'Radiohead')
self.assertTrue(artist['name'] == 'Radiohead')
def test_artists(self):
results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
@ -34,7 +34,7 @@ class TestSpotipy(unittest.TestCase):
def test_album_urn(self):
album = self.spotify.album(self.pinkerton_urn)
self.assertTrue(album['name'] == u'Pinkerton')
self.assertTrue(album['name'] == 'Pinkerton')
def test_album_tracks(self):
results = self.spotify.album_tracks(self.pinkerton_urn)
@ -58,15 +58,15 @@ class TestSpotipy(unittest.TestCase):
def test_track_urn(self):
track = self.spotify.track(self.creep_urn)
self.assertTrue(track['name'] == u'Creep')
self.assertTrue(track['name'] == 'Creep')
def test_track_id(self):
track = self.spotify.track(self.creep_id)
self.assertTrue(track['name'] == u'Creep')
self.assertTrue(track['name'] == 'Creep')
def test_track_url(self):
track = self.spotify.track(self.creep_url)
self.assertTrue(track['name'] == u'Creep')
self.assertTrue(track['name'] == 'Creep')
def test_tracks(self):
results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])

5
tox.ini Normal file
View File

@ -0,0 +1,5 @@
[tox]
envlist = py27,py34
[testenv]
deps=requests
commands=python -m unittest discover tests