mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 09:13:53 +00:00
Merge pull request #414 from plamere/main-fork-progress
Harrison97 fork progress
This commit is contained in:
commit
4595b29bd5
1
.gitignore
vendored
1
.gitignore
vendored
@ -52,6 +52,5 @@ coverage.xml
|
|||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
|
|
||||||
.*
|
.*
|
||||||
archive
|
archive
|
||||||
37
CHANGELOG.md
Normal file
37
CHANGELOG.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
- 1.0 - 04/05/2014 - Initial release
|
||||||
|
- 1.1 - 05/18/2014 - Repackaged for saner imports
|
||||||
|
- 1.4.1 - 06/17/2014 - Updates to match released API
|
||||||
|
- 1.4.2 - 06/21/2014 - Added support for retrieving starred playlists
|
||||||
|
- v1.40, June 12, 2014 -- Initial public release.
|
||||||
|
- v1.42, June 19, 2014 -- Removed dependency on simplejson
|
||||||
|
- v1.43, June 27, 2014 -- Fixed JSON handling issue
|
||||||
|
- v1.44, July 3, 2014 -- Added show tracks.py example
|
||||||
|
- v1.45, July 7, 2014 -- Support for related artists endpoint. Don't use cache auth codes when scope changes
|
||||||
|
- v1.49, July 23, 2014 -- Support for "Your Music" tracks (add, delete, get), with examples
|
||||||
|
- v1.50, August 14, 2014 -- Refactored util out of examples and into the main package
|
||||||
|
- v1.301, August 19, 2014 -- Upgraded version number to take precedence over previously botched release (sigh)
|
||||||
|
- v1.310, August 20, 2014 -- Added playlist replace and remove methods. Added auth tests. Improved API docs
|
||||||
|
- v2.0 - August 22, 2014 -- Upgraded APIs and docs to make it be a real library
|
||||||
|
- v2.0.2 - August 25, 2014 -- Moved to spotipy at pypi
|
||||||
|
- v2.1.0 - October 25, 2014 -- Added support for new_releases and featured_playlists
|
||||||
|
- v2.2.0 - November 15, 2014 -- Added support for user_playlist_tracks
|
||||||
|
- v2.3.0 - January 5, 2015 -- Added session support added by akx.
|
||||||
|
- v2.3.2 - March 31, 2015 -- Added auto retry logic
|
||||||
|
- v2.3.3 - April 1, 2015 -- added client credential flow
|
||||||
|
- v2.3.5 - April 28, 2015 -- Fixed bug in auto retry logic
|
||||||
|
- v2.3.6 - June 3, 2015 -- Support for offset/limit with album_tracks API
|
||||||
|
- v2.3.7 - August 10, 2015 -- Added current_user_followed_artists
|
||||||
|
- v2.3.8 - March 30, 2016 -- Added recs, audio features, user top lists
|
||||||
|
- v2.4.0 - December 31, 2016 -- Incorporated a number of PRs
|
||||||
|
- v2.4.1 - January 2, 2017 -- Incorporated proxy support
|
||||||
|
- v2.4.2 - January 2, 2017 -- support getting audio features for a single track
|
||||||
|
- v2.4.3 - January 2, 2017 -- fixed proxy issue in standard auth flow
|
||||||
|
- v2.4.4 - January 4, 2017 -- python 3 fix
|
||||||
|
- v2.5.0 - January 11, 2020 -- Added follow and player endpoints
|
||||||
|
- Unreleased
|
||||||
|
- Added:
|
||||||
|
- support for `playlist()`
|
||||||
|
- support for `current_user_saved_albums_delete()`
|
||||||
|
- support for `current_user_saved_albums_contains()`
|
||||||
|
- support for `user_unfollow_artists()`
|
||||||
|
- support for `user_unfollow_users()`
|
||||||
16
CHANGES.txt
16
CHANGES.txt
@ -1,16 +0,0 @@
|
|||||||
v1.40, June 12, 2014 -- Initial public release.
|
|
||||||
v1.42, June 19, 2014 -- Removed dependency on simplejson
|
|
||||||
v1.43, June 27, 2014 -- Fixed JSON handling issue
|
|
||||||
v1.44, July 3, 2014 -- Added show_tracks.py exampole
|
|
||||||
v1.45, July 7, 2014 -- Support for related artists endpoint. Don't use
|
|
||||||
cache auth codes when scope changes
|
|
||||||
v1.50, August 14, 2014 -- Refactored util out of examples and into the main
|
|
||||||
package
|
|
||||||
v2.301, August 19, 2014 -- Upgraded version number to take precedence over
|
|
||||||
previously botched release (sigh)
|
|
||||||
v2.310, August 20, 2014 -- Added playlist replace and remove methods. Added auth
|
|
||||||
tests. Improved API docs
|
|
||||||
v2.310, January 5, 2015 -- Added session support
|
|
||||||
v2.3.1, March 28, 2015 -- Auto retry support
|
|
||||||
v2.3.5, April 28, 2015 -- Fixed bug in auto retry support
|
|
||||||
v2.3.6, June 3, 2015 -- Support for offset/limit with album_tracks API
|
|
||||||
33
README.md
33
README.md
@ -52,36 +52,3 @@ A full set of examples can be found in the [online documentation](http://spotipy
|
|||||||
## Reporting Issues
|
## Reporting Issues
|
||||||
|
|
||||||
If you have suggestions, bugs or other issues specific to this library, file them [here](https://github.com/plamere/spotipy/issues). Or just send me a pull request.
|
If you have suggestions, bugs or other issues specific to this library, file them [here](https://github.com/plamere/spotipy/issues). Or just send me a pull request.
|
||||||
|
|
||||||
## Version
|
|
||||||
|
|
||||||
- 1.0 - 04/05/2014 - Initial release
|
|
||||||
- 1.1 - 05/18/2014 - Repackaged for saner imports
|
|
||||||
- 1.4.1 - 06/17/2014 - Updates to match released API
|
|
||||||
- 1.4.2 - 06/21/2014 - Added support for retrieving starred playlists
|
|
||||||
- v1.40, June 12, 2014 -- Initial public release.
|
|
||||||
- v1.42, June 19, 2014 -- Removed dependency on simplejson
|
|
||||||
- v1.43, June 27, 2014 -- Fixed JSON handling issue
|
|
||||||
- v1.44, July 3, 2014 -- Added show tracks.py example
|
|
||||||
- v1.45, July 7, 2014 -- Support for related artists endpoint. Don't use cache auth codes when scope changes
|
|
||||||
- v1.49, July 23, 2014 -- Support for "Your Music" tracks (add, delete, get), with examples
|
|
||||||
- v1.50, August 14, 2014 -- Refactored util out of examples and into the main package
|
|
||||||
- v1.301, August 19, 2014 -- Upgraded version number to take precedence over previously botched release (sigh)
|
|
||||||
- v1.310, August 20, 2014 -- Added playlist replace and remove methods. Added auth tests. Improved API docs
|
|
||||||
- v2.0 - August 22, 2014 -- Upgraded APIs and docs to make it be a real library
|
|
||||||
- v2.0.2 - August 25, 2014 -- Moved to spotipy at pypi
|
|
||||||
- v2.1.0 - October 25, 2014 -- Added support for new_releases and featured_playlists
|
|
||||||
- v2.2.0 - November 15, 2014 -- Added support for user_playlist_tracks
|
|
||||||
- v2.3.0 - January 5, 2015 -- Added session support added by akx.
|
|
||||||
- v2.3.2 - March 31, 2015 -- Added auto retry logic
|
|
||||||
- v2.3.3 - April 1, 2015 -- added client credential flow
|
|
||||||
- v2.3.5 - April 28, 2015 -- Fixed bug in auto retry logic
|
|
||||||
- v2.3.6 - June 3, 2015 -- Support for offset/limit with album_tracks API
|
|
||||||
- v2.3.7 - August 10, 2015 -- Added current_user_followed_artists
|
|
||||||
- v2.3.8 - March 30, 2016 -- Added recs, audio features, user top lists
|
|
||||||
- v2.4.0 - December 31, 2016 -- Incorporated a number of PRs
|
|
||||||
- v2.4.1 - January 2, 2017 -- Incorporated proxy support
|
|
||||||
- v2.4.2 - January 2, 2017 -- support getting audio features for a single track
|
|
||||||
- v2.4.3 - January 2, 2017 -- fixed proxy issue in standard auth flow
|
|
||||||
- v2.4.4 - January 4, 2017 -- python 3 fix
|
|
||||||
- v2.5.0 - January 11, 2020 -- Added follow and player endpoints
|
|
||||||
1
deploy
1
deploy
@ -16,4 +16,3 @@
|
|||||||
# http://spotipy.readthedocs.org/en/latest/
|
# http://spotipy.readthedocs.org/en/latest/
|
||||||
|
|
||||||
sudo python setup.py sdist upload
|
sudo python setup.py sdist upload
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ released by the artist 'Birdy'::
|
|||||||
Here's another example showing how to get 30 second samples and cover art
|
Here's another example showing how to get 30 second samples and cover art
|
||||||
for the top 10 tracks for Led Zeppelin::
|
for the top 10 tracks for Led Zeppelin::
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
lz_uri = 'spotify:artist:36QJpDe2go2KgaRleHCDTp'
|
lz_uri = 'spotify:artist:36QJpDe2go2KgaRleHCDTp'
|
||||||
@ -35,14 +36,15 @@ for the top 10 tracks for Led Zeppelin::
|
|||||||
results = spotify.artist_top_tracks(lz_uri)
|
results = spotify.artist_top_tracks(lz_uri)
|
||||||
|
|
||||||
for track in results['tracks'][:10]:
|
for track in results['tracks'][:10]:
|
||||||
print 'track : ' + track['name']
|
print('track : ' + track['name'])
|
||||||
print 'audio : ' + track['preview_url']
|
print('audio : ' + track['preview_url'])
|
||||||
print 'cover art: ' + track['album']['images'][0]['url']
|
print('cover art: ' + track['album']['images'][0]['url'])
|
||||||
print
|
print()
|
||||||
|
|
||||||
Finally, here's an example that will get the URL for an artist image given the
|
Finally, here's an example that will get the URL for an artist image given the
|
||||||
artist's name::
|
artist's name::
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import spotipy
|
import spotipy
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ artist's name::
|
|||||||
items = results['artists']['items']
|
items = results['artists']['items']
|
||||||
if len(items) > 0:
|
if len(items) > 0:
|
||||||
artist = items[0]
|
artist = items[0]
|
||||||
print artist['name'], artist['images'][0]['url']
|
print(artist['name'], artist['images'][0]['url'])
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
@ -87,10 +89,11 @@ Non-Authorized requests
|
|||||||
For methods that do not require authorization, simply create a Spotify object
|
For methods that do not require authorization, simply create a Spotify object
|
||||||
and start making method calls like so::
|
and start making method calls like so::
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import spotipy
|
import spotipy
|
||||||
spotify = spotipy.Spotify()
|
spotify = spotipy.Spotify()
|
||||||
results = spotify.search(q='artist:' + name, type='artist')
|
results = spotify.search(q='artist:' + name, type='artist')
|
||||||
print results
|
print(results)
|
||||||
|
|
||||||
Authorized requests
|
Authorized requests
|
||||||
=======================
|
=======================
|
||||||
@ -127,7 +130,7 @@ To support the **Authorization Code Flow** *Spotipy* provides a
|
|||||||
utility method ``util.prompt_for_user_token`` that will attempt to authorize the
|
utility method ``util.prompt_for_user_token`` that will attempt to authorize the
|
||||||
user. You can pass your app credentials directly into the method as arguments::
|
user. You can pass your app credentials directly into the method as arguments::
|
||||||
|
|
||||||
util.prompt_for_user_token(username,scope,client_id='your-app-redirect-url',client_secret='your-app-redirect-url',redirect_uri='your-app-redirect-url')
|
util.prompt_for_user_token(username,scope,client_id='your-spotify-client-id',client_secret='your-spotify-client-secret',redirect_uri='your-app-redirect-url')
|
||||||
|
|
||||||
or if you are reluctant to immortalize your app credentials in your source code,
|
or if you are reluctant to immortalize your app credentials in your source code,
|
||||||
you can set environment variables like so::
|
you can set environment variables like so::
|
||||||
@ -146,6 +149,7 @@ are used to automatically re-authorized expired tokens.
|
|||||||
|
|
||||||
Here's an example of getting user authorization to read a user's saved tracks::
|
Here's an example of getting user authorization to read a user's saved tracks::
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
@ -155,7 +159,7 @@ Here's an example of getting user authorization to read a user's saved tracks::
|
|||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
username = sys.argv[1]
|
username = sys.argv[1]
|
||||||
else:
|
else:
|
||||||
print "Usage: %s username" % (sys.argv[0],)
|
print("Usage: %s username" % (sys.argv[0],))
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
token = util.prompt_for_user_token(username, scope)
|
token = util.prompt_for_user_token(username, scope)
|
||||||
@ -165,9 +169,9 @@ Here's an example of getting user authorization to read a user's saved tracks::
|
|||||||
results = sp.current_user_saved_tracks()
|
results = sp.current_user_saved_tracks()
|
||||||
for item in results['items']:
|
for item in results['items']:
|
||||||
track = item['track']
|
track = item['track']
|
||||||
print track['name'] + ' - ' + track['artists'][0]['name']
|
print(track['name'] + ' - ' + track['artists'][0]['name'])
|
||||||
else:
|
else:
|
||||||
print "Can't get token for", username
|
print("Can't get token for", username)
|
||||||
|
|
||||||
Client Credentials Flow
|
Client Credentials Flow
|
||||||
=======================
|
=======================
|
||||||
@ -217,6 +221,7 @@ Here are a few more examples of using *Spotipy*.
|
|||||||
|
|
||||||
Add tracks to a playlist::
|
Add tracks to a playlist::
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -228,7 +233,7 @@ Add tracks to a playlist::
|
|||||||
playlist_id = sys.argv[2]
|
playlist_id = sys.argv[2]
|
||||||
track_ids = sys.argv[3:]
|
track_ids = sys.argv[3:]
|
||||||
else:
|
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()
|
sys.exit()
|
||||||
|
|
||||||
scope = 'playlist-modify-public'
|
scope = 'playlist-modify-public'
|
||||||
@ -238,15 +243,16 @@ Add tracks to a playlist::
|
|||||||
sp = spotipy.Spotify(auth=token)
|
sp = spotipy.Spotify(auth=token)
|
||||||
sp.trace = False
|
sp.trace = False
|
||||||
results = sp.user_playlist_add_tracks(username, playlist_id, track_ids)
|
results = sp.user_playlist_add_tracks(username, playlist_id, track_ids)
|
||||||
print results
|
print(results)
|
||||||
else:
|
else:
|
||||||
print "Can't get token for", username
|
print("Can't get token for", username)
|
||||||
|
|
||||||
|
|
||||||
Shows the contents of every playlist owned by a user::
|
Shows the contents of every playlist owned by a user::
|
||||||
|
|
||||||
# shows a user's playlists (need to be authenticated via oauth)
|
# shows a user's playlists (need to be authenticated via oauth)
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
@ -254,16 +260,16 @@ Shows the contents of every playlist owned by a user::
|
|||||||
def show_tracks(tracks):
|
def show_tracks(tracks):
|
||||||
for i, item in enumerate(tracks['items']):
|
for i, item in enumerate(tracks['items']):
|
||||||
track = item['track']
|
track = item['track']
|
||||||
print " %d %32.32s %s" % (i, track['artists'][0]['name'],
|
print(" %d %32.32s %s" % (i, track['artists'][0]['name'],
|
||||||
track['name'])
|
track['name']))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
username = sys.argv[1]
|
username = sys.argv[1]
|
||||||
else:
|
else:
|
||||||
print "Whoops, need your username!"
|
print("Whoops, need your username!")
|
||||||
print "usage: python user_playlists.py [username]"
|
print("usage: python user_playlists.py [username]")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
token = util.prompt_for_user_token(username)
|
token = util.prompt_for_user_token(username)
|
||||||
@ -273,9 +279,9 @@ Shows the contents of every playlist owned by a user::
|
|||||||
playlists = sp.user_playlists(username)
|
playlists = sp.user_playlists(username)
|
||||||
for playlist in playlists['items']:
|
for playlist in playlists['items']:
|
||||||
if playlist['owner']['id'] == username:
|
if playlist['owner']['id'] == username:
|
||||||
print
|
print()
|
||||||
print playlist['name']
|
print(playlist['name'])
|
||||||
print ' total tracks', playlist['tracks']['total']
|
print (' total tracks', playlist['tracks']['total'])
|
||||||
results = sp.user_playlist(username, playlist['id'],
|
results = sp.user_playlist(username, playlist['id'],
|
||||||
fields="tracks,next")
|
fields="tracks,next")
|
||||||
tracks = results['tracks']
|
tracks = results['tracks']
|
||||||
@ -284,7 +290,7 @@ Shows the contents of every playlist owned by a user::
|
|||||||
tracks = sp.next(tracks)
|
tracks = sp.next(tracks)
|
||||||
show_tracks(tracks)
|
show_tracks(tracks)
|
||||||
else:
|
else:
|
||||||
print "Can't get token for", username
|
print("Can't get token for", username)
|
||||||
|
|
||||||
|
|
||||||
More Examples
|
More Examples
|
||||||
@ -356,6 +362,7 @@ Spotipy authored by Paul Lamere (plamere) with contributions by:
|
|||||||
- corycorycory // corycorycory
|
- corycorycory // corycorycory
|
||||||
- Nathan Coleman // nathancoleman
|
- Nathan Coleman // nathancoleman
|
||||||
- Michael Birtwell // mbirtwell
|
- Michael Birtwell // mbirtwell
|
||||||
|
- Harrison Hayes // Harrison97
|
||||||
|
|
||||||
License
|
License
|
||||||
=======
|
=======
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Shows the top artists for a user
|
# Shows a user's playlists
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@ -21,10 +21,10 @@ if token:
|
|||||||
sp.trace = False
|
sp.trace = False
|
||||||
ranges = ['short_term', 'medium_term', 'long_term']
|
ranges = ['short_term', 'medium_term', 'long_term']
|
||||||
for range in ranges:
|
for range in ranges:
|
||||||
print "range:", range
|
print ("range:", range)
|
||||||
results = sp.current_user_top_artists(time_range=range, limit=50)
|
results = sp.current_user_top_artists(time_range=range, limit=50)
|
||||||
for i, item in enumerate(results['items']):
|
for i, item in enumerate(results['items']):
|
||||||
print i, item['name']
|
print (i, item['name'])
|
||||||
print
|
print ()
|
||||||
else:
|
else:
|
||||||
print("Can't get token for", username)
|
print("Can't get token for", username)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Adds tracks to a playlist
|
# Shows the top tracks for a user
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
@ -21,11 +21,11 @@ if token:
|
|||||||
sp.trace = False
|
sp.trace = False
|
||||||
ranges = ['short_term', 'medium_term', 'long_term']
|
ranges = ['short_term', 'medium_term', 'long_term']
|
||||||
for range in ranges:
|
for range in ranges:
|
||||||
print "range:", range
|
print ("range:", range)
|
||||||
results = sp.current_user_top_tracks(time_range=range, limit=50)
|
results = sp.current_user_top_tracks(time_range=range, limit=50)
|
||||||
for i, item in enumerate(results['items']):
|
for i, item in enumerate(results['items']):
|
||||||
print i, item['name'], '//', item['artists'][0]['name']
|
print (i, item['name'], '//', item['artists'][0]['name'])
|
||||||
print
|
print ()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("Can't get token for", username)
|
print("Can't get token for", username)
|
||||||
|
|||||||
@ -10,4 +10,4 @@ username = uri.split(':')[2]
|
|||||||
playlist_id = uri.split(':')[4]
|
playlist_id = uri.split(':')[4]
|
||||||
|
|
||||||
results = sp.user_playlist(username, playlist_id)
|
results = sp.user_playlist(username, playlist_id)
|
||||||
print json.dumps(results, indent=4)
|
print (json.dumps(results, indent=4))
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
|
# removes tracks from a playlist
|
||||||
# Adds tracks to a playlist
|
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
|
# removes tracks to a playlist
|
||||||
# Adds tracks to a playlist
|
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Replaces all tracks in a playlist
|
# Replaces all tracks in a playlist
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
# shows album info for a URN or URL
|
# shows album info for a URN or URL
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ else:
|
|||||||
urn = 'spotify:album:5yTx83u3qerZF7GRJu7eFk'
|
urn = 'spotify:album:5yTx83u3qerZF7GRJu7eFk'
|
||||||
|
|
||||||
|
|
||||||
sp = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
album = sp.album(urn)
|
album = sp.album(urn)
|
||||||
pprint.pprint(album)
|
pprint.pprint(album)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# shows artist info for a URN or URL
|
# shows artist info for a URN or URL
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
@ -9,7 +10,8 @@ if len(sys.argv) > 1:
|
|||||||
else:
|
else:
|
||||||
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
||||||
|
|
||||||
sp = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
|
|
||||||
artist = sp.artist(urn)
|
artist = sp.artist(urn)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# shows artist info for a URN or URL
|
# shows artist info for a URN or URL
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
@ -9,7 +10,8 @@ if len(sys.argv) > 1:
|
|||||||
else:
|
else:
|
||||||
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
||||||
|
|
||||||
sp = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
response = sp.artist_top_tracks(urn)
|
response = sp.artist_top_tracks(urn)
|
||||||
|
|
||||||
for track in response['tracks']:
|
for track in response['tracks']:
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
# shows related artists for the given seed artist
|
# shows related artists for the given seed artist
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
@ -10,7 +11,9 @@ if len(sys.argv) > 1:
|
|||||||
else:
|
else:
|
||||||
artist_name = 'weezer'
|
artist_name = 'weezer'
|
||||||
|
|
||||||
sp = spotipy.Spotify()
|
|
||||||
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
result = sp.search(q='artist:' + artist_name, type='artist')
|
result = sp.search(q='artist:' + artist_name, type='artist')
|
||||||
try:
|
try:
|
||||||
name = result['artists']['items'][0]['name']
|
name = result['artists']['items'][0]['name']
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# shows track info for a URN or URL
|
# shows track info for a URN or URL
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ if len(sys.argv) > 1:
|
|||||||
else:
|
else:
|
||||||
urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
|
urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
|
||||||
|
|
||||||
sp = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
track = sp.track(urn)
|
track = sp.track(urn)
|
||||||
pprint.pprint(track)
|
pprint.pprint(track)
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import spotipy
|
import spotipy
|
||||||
sp = spotipy.Spotify()
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
|
|
||||||
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
|
|
||||||
results = sp.search(q='weezer', limit=20)
|
results = sp.search(q='weezer', limit=20)
|
||||||
for i, t in enumerate(results['tracks']['items']):
|
for i, t in enumerate(results['tracks']['items']):
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
|
|
||||||
birdy_uri = 'spotify:artist:2WX2uTcsvV5OnS0inACecP'
|
birdy_uri = 'spotify:artist:2WX2uTcsvV5OnS0inACecP'
|
||||||
|
|
||||||
spotify = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
|
|
||||||
results = spotify.artist_albums(birdy_uri, album_type='album')
|
results = sp.artist_albums(birdy_uri, album_type='album')
|
||||||
albums = results['items']
|
albums = results['items']
|
||||||
while results['next']:
|
while results['next']:
|
||||||
results = spotify.next(results)
|
results = sp.next(results)
|
||||||
albums.extend(results['items'])
|
albums.extend(results['items'])
|
||||||
|
|
||||||
for album in albums:
|
for album in albums:
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
|
|
||||||
|
|
||||||
lz_uri = 'spotify:artist:36QJpDe2go2KgaRleHCDTp'
|
lz_uri = 'spotify:artist:36QJpDe2go2KgaRleHCDTp'
|
||||||
|
|
||||||
spotify = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
|
|
||||||
results = spotify.artist_top_tracks(lz_uri)
|
results = sp.artist_top_tracks(lz_uri)
|
||||||
|
|
||||||
for track in results['tracks'][:10]:
|
for track in results['tracks'][:10]:
|
||||||
print('track : ' + track['name'])
|
print('track : ' + track['name'])
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
import spotipy
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
spotify = spotipy.Spotify()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
name = ' '.join(sys.argv[1:])
|
name = ' '.join(sys.argv[1:])
|
||||||
else:
|
else:
|
||||||
name = 'Radiohead'
|
name = 'Radiohead'
|
||||||
|
|
||||||
results = spotify.search(q='artist:' + name, type='artist')
|
results = sp.search(q='artist:' + name, type='artist')
|
||||||
items = results['artists']['items']
|
items = results['artists']['items']
|
||||||
if len(items) > 0:
|
if len(items) > 0:
|
||||||
artist = items[0]
|
artist = items[0]
|
||||||
|
|||||||
30
examples/user_saved_albums_delete.py
Normal file
30
examples/user_saved_albums_delete.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
"""
|
||||||
|
Deletes user saved album
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pprint
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import spotipy
|
||||||
|
import spotipy.util as util
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
username = sys.argv[1]
|
||||||
|
else:
|
||||||
|
print("Usage: %s username" % (sys.argv[0],))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
scope = 'user-library-modify'
|
||||||
|
token = util.prompt_for_user_token(username, scope)
|
||||||
|
|
||||||
|
if token:
|
||||||
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.trace = False
|
||||||
|
uris = input("input a list of album URIs, URLs or IDs: ")
|
||||||
|
uris = list(map(str, uris.split()))
|
||||||
|
deleted = sp.current_user_saved_albums_delete(uris)
|
||||||
|
print("Deletion successful.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Can't get token for", username)
|
||||||
@ -1,2 +1,4 @@
|
|||||||
|
mock==2.0.0
|
||||||
requests==2.3.0
|
requests==2.3.0
|
||||||
|
simplejson==3.13.2
|
||||||
six==1.10.0
|
six==1.10.0
|
||||||
4
setup.py
4
setup.py
@ -9,8 +9,10 @@ setup(
|
|||||||
author_email="paul@echonest.com",
|
author_email="paul@echonest.com",
|
||||||
url='http://spotipy.readthedocs.org/',
|
url='http://spotipy.readthedocs.org/',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
'mock>=2.0.0',
|
||||||
'requests>=2.3.0',
|
'requests>=2.3.0',
|
||||||
'six>=1.10.0',
|
'six>=1.10.0',
|
||||||
],
|
'simplejson==3.13.2',
|
||||||
|
],
|
||||||
license='LICENSE.txt',
|
license='LICENSE.txt',
|
||||||
packages=['spotipy'])
|
packages=['spotipy'])
|
||||||
|
|||||||
@ -1,2 +1,5 @@
|
|||||||
VERSION='2.0.1'
|
VERSION='2.4.5'
|
||||||
from .client import Spotify, SpotifyException
|
|
||||||
|
from .client import *
|
||||||
|
from .oauth2 import *
|
||||||
|
from .util import *
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
# coding: utf-8
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
""" A simple and thin Python library for the Spotify Web API """
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
|
||||||
import requests
|
__all__ = [
|
||||||
|
'Spotify',
|
||||||
|
'SpotifyException'
|
||||||
|
]
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
import six
|
import six
|
||||||
|
|
||||||
""" A simple and thin Python library for the Spotify Web API
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class SpotifyException(Exception):
|
class SpotifyException(Exception):
|
||||||
@ -55,7 +60,7 @@ class Spotify(object):
|
|||||||
def __init__(self, auth=None, requests_session=True,
|
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):
|
||||||
"""
|
"""
|
||||||
Create a Spotify API object.
|
Creates a Spotify API client.
|
||||||
|
|
||||||
:param auth: An authorization token (optional)
|
:param auth: An authorization token (optional)
|
||||||
:param requests_session:
|
:param requests_session:
|
||||||
@ -382,6 +387,18 @@ class Spotify(object):
|
|||||||
plid = self._get_id('playlist', playlist_id)
|
plid = self._get_id('playlist', playlist_id)
|
||||||
return self._get("users/%s/playlists/%s" % (user, plid), fields=fields)
|
return self._get("users/%s/playlists/%s" % (user, plid), fields=fields)
|
||||||
|
|
||||||
|
def playlist(self, playlist_id, fields=None, market=None):
|
||||||
|
""" Gets playlist by id
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- playlist - the id of the playlist
|
||||||
|
- fields - which fields to return
|
||||||
|
- market - An ISO 3166-1 alpha-2 country code or the string from_token.
|
||||||
|
"""
|
||||||
|
plid = self._get_id('playlist', playlist_id)
|
||||||
|
return self._get("playlists/%s" % (plid), fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def user_playlist_tracks(self, user, playlist_id=None, fields=None,
|
def user_playlist_tracks(self, user, playlist_id=None, fields=None,
|
||||||
limit=100, offset=0, market=None):
|
limit=100, offset=0, market=None):
|
||||||
""" Get full details of the tracks of a playlist owned by a user.
|
""" Get full details of the tracks of a playlist owned by a user.
|
||||||
@ -507,7 +524,7 @@ class Spotify(object):
|
|||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
- tracks - the list of track ids to add to the playlist
|
- tracks - the list of track ids to remove from the playlist
|
||||||
- snapshot_id - optional id of the playlist snapshot
|
- snapshot_id - optional id of the playlist snapshot
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -527,9 +544,11 @@ class Spotify(object):
|
|||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
- tracks - an array of objects containing Spotify URIs of the tracks to remove with their current positions in the playlist. For example:
|
- tracks - an array of objects containing Spotify URIs of the
|
||||||
[ { "uri":"4iV5W9uYEdYUVa79Axb7Rh", "positions":[2] },
|
tracks to remove with their current positions in the
|
||||||
{ "uri":"1301WleyT98MSxVHPZCA6M", "positions":[7] } ]
|
playlist. For example:
|
||||||
|
[ { "uri":"4iV5W9uYEdYUVa79Axb7Rh", "positions":[2] },
|
||||||
|
{ "uri":"1301WleyT98MSxVHPZCA6M", "positions":[7] } ]
|
||||||
- snapshot_id - optional id of the playlist snapshot
|
- snapshot_id - optional id of the playlist snapshot
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -564,7 +583,8 @@ class Spotify(object):
|
|||||||
Parameters:
|
Parameters:
|
||||||
- playlist_owner_id - the user id of the playlist owner
|
- playlist_owner_id - the user id of the playlist owner
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
- user_ids - the ids of the users that you want to check to see if they follow the playlist. Maximum: 5 ids.
|
- user_ids - the ids of the users that you want to check to see
|
||||||
|
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)))
|
return self._get("users/{}/playlists/{}/followers/contains?ids={}".format(playlist_owner_id, playlist_id, ','.join(user_ids)))
|
||||||
@ -586,17 +606,6 @@ class Spotify(object):
|
|||||||
'''
|
'''
|
||||||
return self._get('me/player/currently-playing')
|
return self._get('me/player/currently-playing')
|
||||||
|
|
||||||
def current_user_saved_albums(self, limit=20, offset=0):
|
|
||||||
""" Gets a list of the albums saved in the current authorized user's
|
|
||||||
"Your Music" library
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
- limit - the number of albums to return
|
|
||||||
- offset - the index of the first album to return
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self._get('me/albums', limit=limit, offset=offset)
|
|
||||||
|
|
||||||
def current_user_saved_tracks(self, limit=20, offset=0):
|
def current_user_saved_tracks(self, limit=20, offset=0):
|
||||||
""" Gets a list of the tracks saved in the current authorized user's
|
""" Gets a list of the tracks saved in the current authorized user's
|
||||||
"Your Music" library
|
"Your Music" library
|
||||||
@ -612,8 +621,8 @@ class Spotify(object):
|
|||||||
""" Gets a list of the artists followed by the current authorized user
|
""" Gets a list of the artists followed by the current authorized user
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- limit - the number of tracks to return
|
- limit - the number of artists to return
|
||||||
- after - ghe 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,
|
return self._get('me/following', type='artist', limit=limit,
|
||||||
@ -689,6 +698,27 @@ class Spotify(object):
|
|||||||
'''
|
'''
|
||||||
return self._get('me/player/recently-played', limit=limit)
|
return self._get('me/player/recently-played', limit=limit)
|
||||||
|
|
||||||
|
def current_user_saved_albums(self, limit=20, offset=0):
|
||||||
|
""" Gets a list of the albums saved in the current authorized user's
|
||||||
|
"Your Music" library
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- limit - the number of albums to return
|
||||||
|
- offset - the index of the first album to return
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._get('me/albums', limit=limit, offset=offset)
|
||||||
|
|
||||||
|
def current_user_saved_albums_contains(self, albums=[]):
|
||||||
|
""" Check if one or more albums is already saved in
|
||||||
|
the current Spotify user’s “Your Music” library.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- albums - a list of album URIs, URLs or IDs
|
||||||
|
"""
|
||||||
|
alist = [self._get_id('album', a) for a in albums]
|
||||||
|
return self._get('me/albums/contains?ids=' + ','.join(alist))
|
||||||
|
|
||||||
def current_user_saved_albums_add(self, albums=[]):
|
def current_user_saved_albums_add(self, albums=[]):
|
||||||
""" Add one or more albums to the current user's
|
""" Add one or more albums to the current user's
|
||||||
"Your Music" library.
|
"Your Music" library.
|
||||||
@ -696,8 +726,17 @@ class Spotify(object):
|
|||||||
- albums - a list of album URIs, URLs or IDs
|
- albums - a list of album URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
alist = [self._get_id('album', a) for a in albums]
|
alist = [self._get_id('album', a) for a in albums]
|
||||||
r = self._put('me/albums?ids=' + ','.join(alist))
|
return self._put('me/albums?ids=' + ','.join(alist))
|
||||||
return r
|
|
||||||
|
def current_user_saved_albums_delete(self, albums=[]):
|
||||||
|
""" Remove one or more albums from the current user's
|
||||||
|
"Your Music" library.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- albums - a list of album URIs, URLs or IDs
|
||||||
|
"""
|
||||||
|
alist = [self._get_id('album', a) for a in albums]
|
||||||
|
return self._delete('me/albums/?ids=' + ','.join(alist))
|
||||||
|
|
||||||
def user_follow_artists(self, ids=[]):
|
def user_follow_artists(self, ids=[]):
|
||||||
''' Follow one or more artists
|
''' Follow one or more artists
|
||||||
@ -713,6 +752,20 @@ class Spotify(object):
|
|||||||
'''
|
'''
|
||||||
return self._put('me/following?type=user&ids=' + ','.join(ids))
|
return self._put('me/following?type=user&ids=' + ','.join(ids))
|
||||||
|
|
||||||
|
def user_unfollow_artists(self, ids=[]):
|
||||||
|
''' Unfollow one or more artists
|
||||||
|
Parameters:
|
||||||
|
- ids - a list of artist IDs
|
||||||
|
'''
|
||||||
|
return self._delete('me/following?type=artist&ids=' + ','.join(ids))
|
||||||
|
|
||||||
|
def user_unfollow_users(self, ids=[]):
|
||||||
|
''' Unfollow one or more users
|
||||||
|
Parameters:
|
||||||
|
- ids - a list of user IDs
|
||||||
|
'''
|
||||||
|
return self._delete('me/following?type=user&ids=' + ','.join(ids))
|
||||||
|
|
||||||
def featured_playlists(self, locale=None, country=None, timestamp=None,
|
def featured_playlists(self, locale=None, country=None, timestamp=None,
|
||||||
limit=20, offset=0):
|
limit=20, offset=0):
|
||||||
""" Get a list of Spotify featured playlists
|
""" Get a list of Spotify featured playlists
|
||||||
@ -869,14 +922,6 @@ class Spotify(object):
|
|||||||
else:
|
else:
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def audio_analysis(self, id):
|
|
||||||
""" Get audio analysis for a track based upon its Spotify ID
|
|
||||||
Parameters:
|
|
||||||
- id - a track URIs, URLs or IDs
|
|
||||||
"""
|
|
||||||
id = self._get_id('track', id)
|
|
||||||
return self._get('audio-analysis/'+id)
|
|
||||||
|
|
||||||
def devices(self):
|
def devices(self):
|
||||||
''' Get a list of user's available devices.
|
''' Get a list of user's available devices.
|
||||||
'''
|
'''
|
||||||
@ -1040,15 +1085,15 @@ class Spotify(object):
|
|||||||
fields = id.split(':')
|
fields = id.split(':')
|
||||||
if len(fields) >= 3:
|
if len(fields) >= 3:
|
||||||
if type != fields[-2]:
|
if type != fields[-2]:
|
||||||
self._warn('expected id of type %s but found type %s %s',
|
self._warn('expected id of type %s but found type %s %s' %
|
||||||
type, fields[-2], id)
|
(type, fields[-2], id))
|
||||||
return fields[-1]
|
return fields[-1]
|
||||||
fields = id.split('/')
|
fields = id.split('/')
|
||||||
if len(fields) >= 3:
|
if len(fields) >= 3:
|
||||||
itype = fields[-2]
|
itype = fields[-2]
|
||||||
if type != itype:
|
if type != itype:
|
||||||
self._warn('expected id of type %s but found type %s %s',
|
self._warn('expected id of type %s but found type %s %s' %
|
||||||
type, itype, id)
|
(type, itype, id))
|
||||||
return fields[-1]
|
return fields[-1]
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'is_token_expired',
|
||||||
|
'SpotifyClientCredentials',
|
||||||
|
'SpotifyOAuth',
|
||||||
|
'SpotifyOauthError'
|
||||||
|
]
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import requests
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import time
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
# Workaround to support both python 2 & 3
|
# Workaround to support both python 2 & 3
|
||||||
import six
|
import six
|
||||||
|
|||||||
@ -1,11 +1,27 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# shows a user's playlists (need to be authenticated via oauth)
|
""" Shows a user's playlists (need to be authenticated via oauth) """
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'CLIENT_CREDS_ENV_VARS',
|
||||||
|
'prompt_for_user_token'
|
||||||
|
]
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from . import oauth2
|
from . import oauth2
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
|
CLIENT_CREDS_ENV_VARS = {
|
||||||
|
'client_id': 'SPOTIPY_CLIENT_ID',
|
||||||
|
'client_secret': 'SPOTIPY_CLIENT_SECRET',
|
||||||
|
'client_username': 'SPOTIPY_CLIENT_USERNAME',
|
||||||
|
'redirect_uri': 'SPOTIPY_REDIRECT_URI'
|
||||||
|
}
|
||||||
|
|
||||||
def prompt_for_user_token(username, scope=None, client_id = None,
|
def prompt_for_user_token(username, scope=None, client_id = None,
|
||||||
client_secret = None, redirect_uri = None, cache_path = None):
|
client_secret = None, redirect_uri = None, cache_path = None):
|
||||||
''' prompts the user to login if necessary and returns
|
''' prompts the user to login if necessary and returns
|
||||||
|
|||||||
@ -1,222 +0,0 @@
|
|||||||
# -*- coding: latin-1 -*-
|
|
||||||
|
|
||||||
import spotipy
|
|
||||||
from spotipy import util
|
|
||||||
import unittest
|
|
||||||
import pprint
|
|
||||||
import sys
|
|
||||||
import simplejson as json
|
|
||||||
|
|
||||||
'''
|
|
||||||
Since these tests require authentication they are maintained
|
|
||||||
separately from the other tests.
|
|
||||||
|
|
||||||
These tests try to be benign and leave your collection and
|
|
||||||
playlists in a relatively stable state.
|
|
||||||
'''
|
|
||||||
|
|
||||||
class AuthTestSpotipy(unittest.TestCase):
|
|
||||||
'''
|
|
||||||
These tests require user authentication
|
|
||||||
'''
|
|
||||||
|
|
||||||
playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
|
|
||||||
four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
|
||||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
|
||||||
"4VrWlk8IQxevMvERoX08iC",
|
|
||||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
|
||||||
|
|
||||||
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
|
||||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
|
||||||
|
|
||||||
other_tracks=["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
|
||||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
|
||||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
|
||||||
|
|
||||||
bad_id = 'BAD_ID'
|
|
||||||
|
|
||||||
def test_track_bad_id(self):
|
|
||||||
try:
|
|
||||||
track = spotify.track(self.bad_id)
|
|
||||||
self.assertTrue(False)
|
|
||||||
except spotipy.SpotifyException:
|
|
||||||
self.assertTrue(True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_basic_user_profile(self):
|
|
||||||
user = spotify.user(username)
|
|
||||||
self.assertTrue(user['id'] == username)
|
|
||||||
|
|
||||||
def test_current_user(self):
|
|
||||||
user = spotify.current_user()
|
|
||||||
self.assertTrue(user['id'] == username)
|
|
||||||
|
|
||||||
def test_me(self):
|
|
||||||
user = spotify.me()
|
|
||||||
self.assertTrue(user['id'] == username)
|
|
||||||
|
|
||||||
def test_user_playlists(self):
|
|
||||||
playlists = spotify.user_playlists(username, limit=5)
|
|
||||||
self.assertTrue('items' in playlists)
|
|
||||||
self.assertTrue(len(playlists['items']) == 5)
|
|
||||||
|
|
||||||
def test_user_playlist_tracks(self):
|
|
||||||
playlists = spotify.user_playlists(username, limit=5)
|
|
||||||
self.assertTrue('items' in playlists)
|
|
||||||
for playlist in playlists['items']:
|
|
||||||
user = playlist['owner']['id']
|
|
||||||
pid = playlist['id']
|
|
||||||
results = 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 paramter
|
|
||||||
|
|
||||||
self.assertTrue(len(playlists['items']) == 5)
|
|
||||||
|
|
||||||
def test_current_user_saved_tracks(self):
|
|
||||||
tracks = spotify.current_user_saved_tracks()
|
|
||||||
self.assertTrue(len(tracks['items']) > 0)
|
|
||||||
|
|
||||||
def test_current_user_saved_albums(self):
|
|
||||||
albums = spotify.current_user_saved_albums()
|
|
||||||
self.assertTrue(len(albums['items']) > 0)
|
|
||||||
|
|
||||||
def test_current_user_playlists(self):
|
|
||||||
playlists = spotify.current_user_playlists(limit=10)
|
|
||||||
self.assertTrue('items' in playlists)
|
|
||||||
self.assertTrue(len(playlists['items']) == 10)
|
|
||||||
|
|
||||||
def test_user_playlist_follow(self):
|
|
||||||
spotify.user_playlist_follow_playlist('plamere', '4erXB04MxwRAVqcUEpu30O')
|
|
||||||
follows = spotify.user_playlist_is_following('plamere', '4erXB04MxwRAVqcUEpu30O', ['plamere'])
|
|
||||||
|
|
||||||
self.assertTrue(len(follows) == 1, 'proper follows length')
|
|
||||||
self.assertTrue(follows[0], 'is following')
|
|
||||||
spotify.user_playlist_unfollow('plamere', '4erXB04MxwRAVqcUEpu30O')
|
|
||||||
|
|
||||||
follows = spotify.user_playlist_is_following('plamere', '4erXB04MxwRAVqcUEpu30O', ['plamere'])
|
|
||||||
self.assertTrue(len(follows) == 1, 'proper follows length')
|
|
||||||
self.assertFalse(follows[0], 'is no longer following')
|
|
||||||
|
|
||||||
|
|
||||||
def test_current_user_save_and_unsave_tracks(self):
|
|
||||||
tracks = spotify.current_user_saved_tracks()
|
|
||||||
total = tracks['total']
|
|
||||||
|
|
||||||
spotify.current_user_saved_tracks_add(self.four_tracks)
|
|
||||||
|
|
||||||
tracks = spotify.current_user_saved_tracks()
|
|
||||||
new_total = tracks['total']
|
|
||||||
self.assertTrue(new_total - total == len(self.four_tracks))
|
|
||||||
|
|
||||||
tracks = spotify.current_user_saved_tracks_delete(self.four_tracks)
|
|
||||||
tracks = spotify.current_user_saved_tracks()
|
|
||||||
new_total = tracks['total']
|
|
||||||
self.assertTrue(new_total == total)
|
|
||||||
|
|
||||||
|
|
||||||
def test_categories(self):
|
|
||||||
response = spotify.categories()
|
|
||||||
self.assertTrue(len(response['categories']) > 0)
|
|
||||||
|
|
||||||
def test_category_playlists(self):
|
|
||||||
response = spotify.categories()
|
|
||||||
for cat in response['categories']['items']:
|
|
||||||
cat_id = cat['id']
|
|
||||||
response = spotify.category_playlists(category_id=cat_id)
|
|
||||||
self.assertTrue(len(response['playlists']["items"]) > 0)
|
|
||||||
|
|
||||||
def test_new_releases(self):
|
|
||||||
response = spotify.new_releases()
|
|
||||||
self.assertTrue(len(response['albums']) > 0)
|
|
||||||
|
|
||||||
def test_featured_releases(self):
|
|
||||||
response = spotify.featured_playlists()
|
|
||||||
self.assertTrue(len(response['playlists']) > 0)
|
|
||||||
|
|
||||||
def test_current_user_follows(self):
|
|
||||||
response = spotify.current_user_followed_artists()
|
|
||||||
artists = response['artists']
|
|
||||||
self.assertTrue(len(artists['items']) > 0)
|
|
||||||
|
|
||||||
def test_current_user_top_tracks(self):
|
|
||||||
response = spotify.current_user_top_tracks()
|
|
||||||
items = response['items']
|
|
||||||
self.assertTrue(len(items) > 0)
|
|
||||||
|
|
||||||
def test_current_user_top_artists(self):
|
|
||||||
response = spotify.current_user_top_artists()
|
|
||||||
items = response['items']
|
|
||||||
self.assertTrue(len(items) > 0)
|
|
||||||
|
|
||||||
def get_or_create_spotify_playlist(self, username, playlist_name):
|
|
||||||
playlists = spotify.user_playlists(username)
|
|
||||||
while playlists:
|
|
||||||
for item in playlists['items']:
|
|
||||||
if item['name'] == playlist_name:
|
|
||||||
return item['id']
|
|
||||||
playlists = spotify.next(playlists)
|
|
||||||
playlist = spotify.user_playlist_create(username, playlist_name)
|
|
||||||
playlist_id = playlist['uri']
|
|
||||||
return playlist_id
|
|
||||||
|
|
||||||
def test_user_playlist_ops(self):
|
|
||||||
# create empty playlist
|
|
||||||
playlist_id = self.get_or_create_spotify_playlist(username,
|
|
||||||
'spotipy-testing-playlist-1')
|
|
||||||
|
|
||||||
# remove all tracks from it
|
|
||||||
|
|
||||||
spotify.user_playlist_replace_tracks(username, playlist_id,[])
|
|
||||||
|
|
||||||
playlist = spotify.user_playlist(username, playlist_id)
|
|
||||||
self.assertTrue(playlist['tracks']['total'] == 0)
|
|
||||||
self.assertTrue(len(playlist['tracks']['items']) == 0)
|
|
||||||
|
|
||||||
# add tracks to it
|
|
||||||
|
|
||||||
spotify.user_playlist_add_tracks(username, playlist_id, self.four_tracks)
|
|
||||||
playlist = spotify.user_playlist(username, playlist_id)
|
|
||||||
self.assertTrue(playlist['tracks']['total'] == 4)
|
|
||||||
self.assertTrue(len(playlist['tracks']['items']) == 4)
|
|
||||||
|
|
||||||
# remove two tracks from it
|
|
||||||
|
|
||||||
spotify.user_playlist_remove_all_occurrences_of_tracks (username,
|
|
||||||
playlist_id, self.two_tracks)
|
|
||||||
|
|
||||||
playlist = spotify.user_playlist(username, playlist_id)
|
|
||||||
self.assertTrue(playlist['tracks']['total'] == 2)
|
|
||||||
self.assertTrue(len(playlist['tracks']['items']) == 2)
|
|
||||||
|
|
||||||
# replace with 3 other tracks
|
|
||||||
spotify.user_playlist_replace_tracks(username,
|
|
||||||
playlist_id, self.other_tracks)
|
|
||||||
|
|
||||||
playlist = spotify.user_playlist(username, playlist_id)
|
|
||||||
self.assertTrue(playlist['tracks']['total'] == 3)
|
|
||||||
self.assertTrue(len(playlist['tracks']['items']) == 3)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
username = sys.argv[1]
|
|
||||||
del sys.argv[1]
|
|
||||||
|
|
||||||
scope = 'playlist-modify-public '
|
|
||||||
scope += 'user-library-read '
|
|
||||||
scope += 'user-follow-read '
|
|
||||||
scope += 'user-library-modify '
|
|
||||||
scope += 'user-read-private '
|
|
||||||
scope += 'user-top-read'
|
|
||||||
|
|
||||||
token = util.prompt_for_user_token(username, scope)
|
|
||||||
spotify = spotipy.Spotify(auth=token)
|
|
||||||
spotify.trace = False
|
|
||||||
unittest.main()
|
|
||||||
else:
|
|
||||||
print("Usage: %s username" % (sys.argv[0],))
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
# -*- coding: latin-1 -*-
|
|
||||||
|
|
||||||
import spotipy
|
|
||||||
from spotipy import util
|
|
||||||
import unittest
|
|
||||||
import pprint
|
|
||||||
import sys
|
|
||||||
import simplejson as json
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
|
||||||
|
|
||||||
'''
|
|
||||||
Since these tests require authentication they are maintained
|
|
||||||
separately from the other tests.
|
|
||||||
|
|
||||||
These tests try to be benign and leave your collection and
|
|
||||||
playlists in a relatively stable state.
|
|
||||||
'''
|
|
||||||
|
|
||||||
class AuthTestSpotipy(unittest.TestCase):
|
|
||||||
'''
|
|
||||||
These tests require user authentication
|
|
||||||
'''
|
|
||||||
|
|
||||||
playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
|
|
||||||
four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
|
||||||
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
|
||||||
"4VrWlk8IQxevMvERoX08iC",
|
|
||||||
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
|
||||||
|
|
||||||
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
|
||||||
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
|
||||||
|
|
||||||
other_tracks=["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
|
|
||||||
"spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
|
|
||||||
"spotify:track:1PB7gRWcvefzu7t3LJLUlf"]
|
|
||||||
|
|
||||||
bad_id = 'BAD_ID'
|
|
||||||
|
|
||||||
|
|
||||||
def test_audio_analysis(self):
|
|
||||||
result = spotify.audio_analysis(self.four_tracks[0])
|
|
||||||
assert('beats' in result)
|
|
||||||
|
|
||||||
def test_audio_features(self):
|
|
||||||
results = spotify.audio_features(self.four_tracks)
|
|
||||||
self.assertTrue(len(results) == len(self.four_tracks))
|
|
||||||
for track in results:
|
|
||||||
assert('speechiness' in track)
|
|
||||||
|
|
||||||
def test_audio_features_with_bad_track(self):
|
|
||||||
bad_tracks = []
|
|
||||||
bad_tracks = ['spotify:track:bad']
|
|
||||||
input = self.four_tracks + bad_tracks
|
|
||||||
results = spotify.audio_features(input)
|
|
||||||
self.assertTrue(len(results) == len(input))
|
|
||||||
for track in results[:-1]:
|
|
||||||
if track != None:
|
|
||||||
assert('speechiness' in track)
|
|
||||||
self.assertTrue(results[-1] == None)
|
|
||||||
|
|
||||||
def test_recommendations(self):
|
|
||||||
results = 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__':
|
|
||||||
client_credentials_manager = SpotifyClientCredentials()
|
|
||||||
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
|
||||||
spotify.trace = False
|
|
||||||
unittest.main()
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
# -*- coding: latin-1 -*-
|
|
||||||
|
|
||||||
import spotipy
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
'''
|
|
||||||
Client Credentials Requests Tests
|
|
||||||
'''
|
|
||||||
|
|
||||||
class ClientCredentialsTestSpotipy(unittest.TestCase):
|
|
||||||
'''
|
|
||||||
These tests require user authentication
|
|
||||||
'''
|
|
||||||
|
|
||||||
muse_urn = 'spotify:artist:12Chz98pHFMPJEknJQMWvI'
|
|
||||||
|
|
||||||
def test_request_with_token(self):
|
|
||||||
artist = spotify.artist(self.muse_urn)
|
|
||||||
self.assertTrue(artist['name'] == 'Muse')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
spotify_cc = SpotifyClientCredentials()
|
|
||||||
spotify = spotipy.Spotify(client_credentials_manager=spotify_cc)
|
|
||||||
spotify.trace = False
|
|
||||||
unittest.main()
|
|
||||||
297
tests/test_auth.py
Normal file
297
tests/test_auth.py
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
These tests require user authentication - provide client credentials using the
|
||||||
|
following environment variables
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'SPOTIPY_REDIRECT_URI'
|
||||||
|
"""
|
||||||
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTestSpotipy(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
These tests require user authentication - provide client credentials using the
|
||||||
|
following environment variables
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'SPOTIPY_REDIRECT_URI'
|
||||||
|
"""
|
||||||
|
|
||||||
|
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"]
|
||||||
|
|
||||||
|
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||||
|
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||||
|
|
||||||
|
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()))
|
||||||
|
|
||||||
|
self.username = os.getenv(CCEV['client_username'])
|
||||||
|
|
||||||
|
self.scope = (
|
||||||
|
'playlist-modify-public '
|
||||||
|
'user-library-read '
|
||||||
|
'user-follow-read '
|
||||||
|
'user-library-modify '
|
||||||
|
'user-read-private '
|
||||||
|
'user-top-read '
|
||||||
|
'user-follow-modify'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.token = prompt_for_user_token(self.username, scope=self.scope)
|
||||||
|
|
||||||
|
self.spotify = Spotify(auth=self.token)
|
||||||
|
|
||||||
|
def test_track_bad_id(self):
|
||||||
|
try:
|
||||||
|
self.spotify.track(self.bad_id)
|
||||||
|
self.assertTrue(False)
|
||||||
|
except SpotifyException:
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_basic_user_profile(self):
|
||||||
|
user = self.spotify.user(self.username)
|
||||||
|
self.assertTrue(user['id'] == self.username.lower())
|
||||||
|
|
||||||
|
def test_current_user(self):
|
||||||
|
user = self.spotify.current_user()
|
||||||
|
self.assertTrue(user['id'] == self.username.lower())
|
||||||
|
|
||||||
|
def test_me(self):
|
||||||
|
user = self.spotify.me()
|
||||||
|
self.assertTrue(user['id'] == self.username.lower())
|
||||||
|
|
||||||
|
def test_user_playlists(self):
|
||||||
|
playlists = self.spotify.user_playlists(self.username, limit=5)
|
||||||
|
self.assertTrue('items' in playlists)
|
||||||
|
self.assertTrue(len(playlists['items']) == 5)
|
||||||
|
|
||||||
|
def test_user_playlist_tracks(self):
|
||||||
|
playlists = self.spotify.user_playlists(self.username, limit=5)
|
||||||
|
self.assertTrue('items' in playlists)
|
||||||
|
for playlist in playlists['items']:
|
||||||
|
user = playlist['owner']['id']
|
||||||
|
pid = playlist['id']
|
||||||
|
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)
|
||||||
|
|
||||||
|
def test_current_user_saved_albums(self):
|
||||||
|
# List
|
||||||
|
albums = self.spotify.current_user_saved_albums()
|
||||||
|
self.assertTrue(len(albums['items']) == 1)
|
||||||
|
|
||||||
|
# Add
|
||||||
|
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])
|
||||||
|
|
||||||
|
# Remove
|
||||||
|
self.spotify.current_user_saved_albums_delete(self.album_ids)
|
||||||
|
albums = self.spotify.current_user_saved_albums()
|
||||||
|
self.assertTrue(len(albums['items']) == 1)
|
||||||
|
|
||||||
|
def test_current_user_playlists(self):
|
||||||
|
playlists = self.spotify.current_user_playlists(limit=10)
|
||||||
|
self.assertTrue('items' in playlists)
|
||||||
|
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.assertTrue(len(follows) == 1, 'proper follows length')
|
||||||
|
self.assertTrue(follows[0], 'is following')
|
||||||
|
self.spotify.user_playlist_unfollow('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.assertFalse(follows[0], 'is no longer following')
|
||||||
|
|
||||||
|
def test_current_user_saved_tracks(self):
|
||||||
|
tracks = self.spotify.current_user_saved_tracks()
|
||||||
|
self.assertTrue(len(tracks['items']) > 0)
|
||||||
|
|
||||||
|
def test_current_user_save_and_unsave_tracks(self):
|
||||||
|
tracks = self.spotify.current_user_saved_tracks()
|
||||||
|
total = tracks['total']
|
||||||
|
self.spotify.current_user_saved_tracks_add(self.four_tracks)
|
||||||
|
|
||||||
|
tracks = self.spotify.current_user_saved_tracks()
|
||||||
|
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()
|
||||||
|
new_total = tracks['total']
|
||||||
|
self.assertTrue(new_total == total)
|
||||||
|
|
||||||
|
def test_categories(self):
|
||||||
|
response = self.spotify.categories()
|
||||||
|
self.assertTrue(len(response['categories']) > 0)
|
||||||
|
|
||||||
|
def test_category_playlists(self):
|
||||||
|
response = self.spotify.categories()
|
||||||
|
for cat in response['categories']['items']:
|
||||||
|
cat_id = cat['id']
|
||||||
|
response = self.spotify.category_playlists(category_id=cat_id)
|
||||||
|
if len(response['playlists']["items"]) > 0:
|
||||||
|
break
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_new_releases(self):
|
||||||
|
response = self.spotify.new_releases()
|
||||||
|
self.assertTrue(len(response['albums']) > 0)
|
||||||
|
|
||||||
|
def test_featured_releases(self):
|
||||||
|
response = self.spotify.featured_playlists()
|
||||||
|
self.assertTrue(len(response['playlists']) > 0)
|
||||||
|
|
||||||
|
def test_current_user_follows(self):
|
||||||
|
response = self.spotify.current_user_followed_artists()
|
||||||
|
artists = response['artists']
|
||||||
|
self.assertTrue(len(artists['items']) > 0)
|
||||||
|
|
||||||
|
def test_current_user_top_tracks(self):
|
||||||
|
response = self.spotify.current_user_top_tracks()
|
||||||
|
items = response['items']
|
||||||
|
self.assertTrue(len(items) > 0)
|
||||||
|
|
||||||
|
def test_current_user_top_artists(self):
|
||||||
|
response = self.spotify.current_user_top_artists()
|
||||||
|
items = response['items']
|
||||||
|
self.assertTrue(len(items) > 0)
|
||||||
|
|
||||||
|
def get_or_create_spotify_playlist(self, playlist_name):
|
||||||
|
playlists = self.spotify.user_playlists(self.username)
|
||||||
|
while playlists:
|
||||||
|
for item in playlists['items']:
|
||||||
|
if item['name'] == playlist_name:
|
||||||
|
return item['id']
|
||||||
|
playlists = self.spotify.next(playlists)
|
||||||
|
playlist = self.spotify.user_playlist_create(self.username, playlist_name)
|
||||||
|
playlist_id = playlist['uri']
|
||||||
|
return playlist_id
|
||||||
|
|
||||||
|
def test_user_playlist_ops(self):
|
||||||
|
# create empty playlist
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
self.assertTrue(playlist['tracks']['total'] == 3)
|
||||||
|
self.assertTrue(len(playlist['tracks']['items']) == 3)
|
||||||
|
|
||||||
|
def test_playlist(self):
|
||||||
|
# New playlist ID
|
||||||
|
pl = self.spotify.playlist(self.playlist_new_id)
|
||||||
|
self.assertTrue(pl["tracks"]["total"] > 0)
|
||||||
|
|
||||||
|
# Old playlist ID
|
||||||
|
pl = self.spotify.playlist(self.playlist)
|
||||||
|
self.assertTrue(pl["tracks"]["total"] > 0)
|
||||||
|
|
||||||
|
def test_user_follows_and_unfollows_artist(self):
|
||||||
|
# Initially follows 1 artist
|
||||||
|
res = self.spotify.current_user_followed_artists()
|
||||||
|
self.assertTrue(res['artists']['total'] == 1)
|
||||||
|
|
||||||
|
# Follow 2 more artists
|
||||||
|
artists = ["6DPYiyq5kWVQS4RGwxzPC7", "0NbfKEOTQCcwd6o7wSDOHI"]
|
||||||
|
self.spotify.user_follow_artists(artists)
|
||||||
|
res = self.spotify.current_user_followed_artists()
|
||||||
|
self.assertTrue(res['artists']['total'] == 3)
|
||||||
|
|
||||||
|
# Unfollow these 2 artists
|
||||||
|
self.spotify.user_unfollow_artists(artists)
|
||||||
|
res = self.spotify.current_user_followed_artists()
|
||||||
|
self.assertTrue(res['artists']['total'] == 1)
|
||||||
|
|
||||||
|
def test_user_follows_and_unfollows_user(self):
|
||||||
|
# TODO improve after implementing `me/following/contains`
|
||||||
|
users = ["11111204", "xlqeojt6n7on0j7coh9go8ifd"]
|
||||||
|
|
||||||
|
# Follow 2 more users
|
||||||
|
self.spotify.user_follow_users(users)
|
||||||
|
|
||||||
|
# Unfollow these 2 users
|
||||||
|
self.spotify.user_unfollow_users(users)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
91
tests/test_auth2.py
Normal file
91
tests/test_auth2.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
These tests require user authentication - provide client credentials using the
|
||||||
|
following environment variables
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTestSpotipy(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
These tests require user authentication - provide client credentials using the
|
||||||
|
following environment variables
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'SPOTIPY_REDIRECT_URI'
|
||||||
|
"""
|
||||||
|
|
||||||
|
playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
|
||||||
|
four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||||
|
"spotify:track:7IHOIqZUUInxjVkko181PB",
|
||||||
|
"4VrWlk8IQxevMvERoX08iC",
|
||||||
|
"http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]
|
||||||
|
|
||||||
|
two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
|
||||||
|
"spotify:track:7IHOIqZUUInxjVkko181PB"]
|
||||||
|
|
||||||
|
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.trace = False
|
||||||
|
|
||||||
|
def test_audio_analysis(self):
|
||||||
|
result = self.spotify.audio_analysis(self.four_tracks[0])
|
||||||
|
assert('beats' in result)
|
||||||
|
|
||||||
|
def test_audio_features(self):
|
||||||
|
results = self.spotify.audio_features(self.four_tracks)
|
||||||
|
self.assertTrue(len(results) == len(self.four_tracks))
|
||||||
|
for track in results:
|
||||||
|
assert('speechiness' in track)
|
||||||
|
|
||||||
|
def test_audio_features_with_bad_track(self):
|
||||||
|
bad_tracks = []
|
||||||
|
bad_tracks = ['spotify:track:bad']
|
||||||
|
input = self.four_tracks + bad_tracks
|
||||||
|
results = self.spotify.audio_features(input)
|
||||||
|
self.assertTrue(len(results) == len(input))
|
||||||
|
for track in results[:-1]:
|
||||||
|
if track != None:
|
||||||
|
assert('speechiness' in track)
|
||||||
|
self.assertTrue(results[-1] == None)
|
||||||
|
|
||||||
|
def test_recommendations(self):
|
||||||
|
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()
|
||||||
44
tests/test_client_credentials.py
Normal file
44
tests/test_client_credentials.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
""" Client Credentials Requests Tests """
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'SPOTIPY_REDIRECT_URI'
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(self):
|
||||||
|
self.spotify = Spotify(client_credentials_manager=SpotifyClientCredentials())
|
||||||
|
self.spotify.trace = False
|
||||||
|
|
||||||
|
muse_urn = 'spotify:artist:12Chz98pHFMPJEknJQMWvI'
|
||||||
|
|
||||||
|
def test_request_with_token(self):
|
||||||
|
artist = self.spotify.artist(self.muse_urn)
|
||||||
|
self.assertTrue(artist['name'] == 'Muse')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
unittest.main()
|
||||||
@ -1,8 +1,15 @@
|
|||||||
from spotipy.oauth2 import SpotifyOAuth
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
|
||||||
import io
|
import io
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||||
|
|
||||||
|
from spotipy import SpotifyOAuth
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import unittest.mock as mock
|
import unittest.mock as mock
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -166,4 +173,5 @@ class TestSpotifyOAuth(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@ -1,13 +1,36 @@
|
|||||||
# -*- coding: latin-1 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import spotipy
|
|
||||||
import unittest
|
import os
|
||||||
import pprint
|
import pprint
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from spotipy.client import SpotifyException
|
|
||||||
|
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||||
|
|
||||||
|
from spotipy import (
|
||||||
|
CLIENT_CREDS_ENV_VARS as CCEV,
|
||||||
|
prompt_for_user_token,
|
||||||
|
Spotify,
|
||||||
|
SpotifyException,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestSpotipy(unittest.TestCase):
|
class TestSpotipy(unittest.TestCase):
|
||||||
|
|
||||||
|
"""
|
||||||
|
These tests require user authentication - provide client credentials using the
|
||||||
|
following environment variables
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'SPOTIPY_CLIENT_USERNAME'
|
||||||
|
'SPOTIPY_CLIENT_ID'
|
||||||
|
'SPOTIPY_CLIENT_SECRET'
|
||||||
|
'SPOTIPY_REDIRECT_URI'
|
||||||
|
"""
|
||||||
|
|
||||||
creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42'
|
creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42'
|
||||||
creep_id = '3HfB5hBU0dmBt8T0iCmH42'
|
creep_id = '3HfB5hBU0dmBt8T0iCmH42'
|
||||||
creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42'
|
creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42'
|
||||||
@ -22,8 +45,20 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
|
|
||||||
bad_id = 'BAD_ID'
|
bad_id = 'BAD_ID'
|
||||||
|
|
||||||
def setUp(self):
|
@classmethod
|
||||||
self.spotify = spotipy.Spotify()
|
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()))
|
||||||
|
|
||||||
|
self.username = os.getenv(CCEV['client_username'])
|
||||||
|
|
||||||
|
self.scope = 'user-library-read'
|
||||||
|
|
||||||
|
self.token = prompt_for_user_token(self.username, scope=self.scope)
|
||||||
|
|
||||||
|
self.spotify = Spotify(auth=self.token)
|
||||||
|
|
||||||
def test_artist_urn(self):
|
def test_artist_urn(self):
|
||||||
artist = self.spotify.artist(self.radiohead_urn)
|
artist = self.spotify.artist(self.radiohead_urn)
|
||||||
@ -74,7 +109,7 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
track = self.spotify.track(self.el_scorcho_bad_urn)
|
track = self.spotify.track(self.el_scorcho_bad_urn)
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
except spotipy.SpotifyException:
|
except SpotifyException:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_tracks(self):
|
def test_tracks(self):
|
||||||
@ -121,11 +156,11 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
self.assertTrue(found)
|
self.assertTrue(found)
|
||||||
|
|
||||||
def test_search_timeout(self):
|
def test_search_timeout(self):
|
||||||
sp = spotipy.Spotify(requests_timeout=.1)
|
sp = Spotify(auth=self.token, requests_timeout=.01)
|
||||||
try:
|
try:
|
||||||
results = sp.search(q='my*', type='track')
|
results = sp.search(q='my*', type='track')
|
||||||
self.assertTrue(False, 'unexpected search timeout')
|
self.assertTrue(False, 'unexpected search timeout')
|
||||||
except requests.ReadTimeout:
|
except requests.Timeout:
|
||||||
self.assertTrue(True, 'expected search timeout')
|
self.assertTrue(True, 'expected search timeout')
|
||||||
|
|
||||||
|
|
||||||
@ -149,14 +184,14 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
track = self.spotify.track(self.bad_id)
|
track = self.spotify.track(self.bad_id)
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
except spotipy.SpotifyException:
|
except SpotifyException:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_track_bad_id(self):
|
def test_track_bad_id(self):
|
||||||
try:
|
try:
|
||||||
track = self.spotify.track(self.bad_id)
|
track = self.spotify.track(self.bad_id)
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
except spotipy.SpotifyException:
|
except SpotifyException:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_unauthenticated_post_fails(self):
|
def test_unauthenticated_post_fails(self):
|
||||||
@ -166,20 +201,17 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
cm.exception.http_status == 403)
|
cm.exception.http_status == 403)
|
||||||
|
|
||||||
def test_custom_requests_session(self):
|
def test_custom_requests_session(self):
|
||||||
from requests import Session
|
sess = requests.Session()
|
||||||
sess = Session()
|
|
||||||
sess.headers["user-agent"] = "spotipy-test"
|
sess.headers["user-agent"] = "spotipy-test"
|
||||||
with_custom_session = spotipy.Spotify(requests_session=sess)
|
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):
|
def test_force_no_requests_session(self):
|
||||||
from requests import Session
|
with_no_session = Spotify(auth=self.token, requests_session=False)
|
||||||
with_no_session = spotipy.Spotify(requests_session=False)
|
self.assertFalse(isinstance(with_no_session._session, requests.Session))
|
||||||
self.assertFalse(isinstance(with_no_session._session, Session))
|
|
||||||
self.assertTrue(with_no_session.user(user="akx")["uri"] == "spotify:user:akx")
|
self.assertTrue(with_no_session.user(user="akx")["uri"] == "spotify:user:akx")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Need tests for:
|
Need tests for:
|
||||||
|
|
||||||
@ -188,4 +220,5 @@ class TestSpotipy(unittest.TestCase):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user