From 6ab96c3c91b28f60d2822e4fe3bc70cc353352a1 Mon Sep 17 00:00:00 2001 From: Stephane Bruckert Date: Sat, 11 Jan 2020 23:30:57 +0000 Subject: [PATCH] Clean up + missing tests --- .gitignore | 4 +- CHANGELOG.md | 30 ++++++++++ CHANGES.txt | 25 -------- README.md | 35 +----------- deploy | 3 +- examples/replace_tracks_in_playlist.py | 1 - spotipy/client.py | 61 +++++++------------- tests/test_auth.py | 79 ++++++++++++++++++++------ 8 files changed, 116 insertions(+), 122 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 CHANGES.txt diff --git a/.gitignore b/.gitignore index d88e85e..137335b 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,5 @@ coverage.xml # Sphinx documentation docs/_build/ - .* -archive -*.sh +archive \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2a4e430 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +- 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 diff --git a/CHANGES.txt b/CHANGES.txt deleted file mode 100644 index 7e644d0..0000000 --- a/CHANGES.txt +++ /dev/null @@ -1,25 +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 -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.4.5, August 12, 2019 -- Incorporated a number of PRs \ No newline at end of file diff --git a/README.md b/README.md index 2add256..9c3151f 100644 --- a/README.md +++ b/README.md @@ -51,37 +51,4 @@ A full set of examples can be found in the [online documentation](http://spotipy ## 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. - -## 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 +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. \ No newline at end of file diff --git a/deploy b/deploy index ea1b5aa..36d5c3f 100755 --- a/deploy +++ b/deploy @@ -15,5 +15,4 @@ # docs should automatically be updated. verify them at # http://spotipy.readthedocs.org/en/latest/ -sudo python setup.py sdist upload - +sudo python setup.py sdist upload \ No newline at end of file diff --git a/examples/replace_tracks_in_playlist.py b/examples/replace_tracks_in_playlist.py index 452d328..d7236cc 100644 --- a/examples/replace_tracks_in_playlist.py +++ b/examples/replace_tracks_in_playlist.py @@ -1,4 +1,3 @@ - # Replaces all tracks in a playlist import pprint diff --git a/spotipy/client.py b/spotipy/client.py index 3c556d3..273563c 100644 --- a/spotipy/client.py +++ b/spotipy/client.py @@ -40,7 +40,7 @@ class Spotify(object): import spotipy - urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' + urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' sp = spotipy.Spotify() sp.trace = True # turn on tracing @@ -395,9 +395,7 @@ class Spotify(object): - 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) @@ -608,29 +606,6 @@ class Spotify(object): ''' 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_albums_delete(self, albums=None): - """ Remove one or more albums from the current user's - "Your Music" library. - - Parameters: - - albums - a list of album URIs, URLs or IDs - """ - alist = [] - if albums is not None: - alist = [self._get_id('album', a) for a in albums] - return self._delete('me/albums/?ids=' + ','.join(alist)) - def current_user_saved_tracks(self, limit=20, offset=0): """ Gets a list of the tracks saved in the current authorized user's "Your Music" library @@ -646,8 +621,8 @@ class Spotify(object): """ Gets a list of the artists followed by the current authorized user Parameters: - - limit - the number of tracks to return - - after - ghe last artist ID retrieved from the previous request + - limit - the number of artists to return + - after - the last artist ID retrieved from the previous request """ return self._get('me/following', type='artist', limit=limit, @@ -723,16 +698,16 @@ class Spotify(object): ''' return self._get('me/player/recently-played', limit=limit) - def current_user_saved_albums_delete(self, albums=[]): - """ Remove one or more albums from the current user's - "Your Music" library. + 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: - - albums - a list of album URIs, URLs or IDs + - limit - the number of albums to return + - offset - the index of the first album to return + """ - alist = [self._get_id('album', a) for a in albums] - r = self._delete('me/albums/?ids=' + ','.join(alist)) - return r + 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 @@ -742,8 +717,7 @@ class Spotify(object): - albums - a list of album URIs, URLs or IDs """ alist = [self._get_id('album', a) for a in albums] - r = self._get('me/albums/contains?ids=' + ','.join(alist)) - return r + return self._get('me/albums/contains?ids=' + ','.join(alist)) def current_user_saved_albums_add(self, albums=[]): """ Add one or more albums to the current user's @@ -752,8 +726,17 @@ class Spotify(object): - albums - a list of album URIs, URLs or IDs """ alist = [self._get_id('album', a) for a in albums] - r = self._put('me/albums?ids=' + ','.join(alist)) - return r + return self._put('me/albums?ids=' + ','.join(alist)) + + 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=[]): ''' Follow one or more artists diff --git a/tests/test_auth.py b/tests/test_auth.py index f295e34..66e2ab4 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -15,7 +15,7 @@ following environment variables from __future__ import print_function import os -import pprint +from pprint import pprint import sys import unittest @@ -45,6 +45,7 @@ class AuthTestSpotipy(unittest.TestCase): """ playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx" + playlist_new_id = "spotify:playlist:7GlxpQjjxRjmbb3RP2rDqI" four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp", "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC", @@ -57,8 +58,12 @@ class AuthTestSpotipy(unittest.TestCase): "spotify:track:29xKs5BAHlmlX1u4gzQAbJ", "spotify:track:1PB7gRWcvefzu7t3LJLUlf"] + album_ids = ["spotify:album:6kL09DaURb7rAoqqaA51KU", + "spotify:album:6RTzC0rDbvagTSJLlY7AKl"] + bad_id = 'BAD_ID' + @classmethod def setUpClass(self): @@ -75,7 +80,8 @@ class AuthTestSpotipy(unittest.TestCase): 'user-follow-read ' 'user-library-modify ' 'user-read-private ' - 'user-top-read' + 'user-top-read ' + 'user-follow-modify' ) self.token = prompt_for_user_token(self.username, scope=self.scope) @@ -84,7 +90,7 @@ class AuthTestSpotipy(unittest.TestCase): def test_track_bad_id(self): try: - track = self.spotify.track(self.bad_id) + self.spotify.track(self.bad_id) self.assertTrue(False) except SpotifyException: self.assertTrue(True) @@ -120,17 +126,25 @@ class AuthTestSpotipy(unittest.TestCase): # known API issue currently causes this test to fail # the issue is that the API doesn't currently respect the - # limit paramter + # limit parameter self.assertTrue(len(playlists['items']) == 5) - def test_current_user_saved_tracks(self): - tracks = self.spotify.current_user_saved_tracks() - self.assertTrue(len(tracks['items']) > 0) - def test_current_user_saved_albums(self): + # List albums = self.spotify.current_user_saved_albums() - self.assertTrue(len(albums['items']) > 0) + 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) @@ -149,11 +163,13 @@ class AuthTestSpotipy(unittest.TestCase): 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() @@ -165,7 +181,6 @@ class AuthTestSpotipy(unittest.TestCase): new_total = tracks['total'] self.assertTrue(new_total == total) - def test_categories(self): response = self.spotify.categories() self.assertTrue(len(response['categories']) > 0) @@ -218,25 +233,20 @@ class AuthTestSpotipy(unittest.TestCase): 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) @@ -244,11 +254,44 @@ class AuthTestSpotipy(unittest.TestCase): # 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) -if __name__ == '__main__': + 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()