diff --git a/CHANGELOG.md b/CHANGELOG.md index de1c5e4..9bc8f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + + - Fixed broken examples in README, examples and doc + ### Changed - Allow session keepalive diff --git a/README.md b/README.md index 8a52a79..0075083 100644 --- a/README.md +++ b/README.md @@ -29,27 +29,34 @@ or easy_install spotipy ``` - ## Dependencies - [Requests](https://github.com/kennethreitz/requests) - spotipy requires the requests package to be installed ## Quick Start -To get started, simply install spotipy, create a Spotify object and call methods: + +A full set of examples can be found in the [online documentation](http://spotipy.readthedocs.org/) and in the [Spotipy examples directory](https://github.com/plamere/spotipy/tree/master/examples). Here are two basic examples. + +To get started, install spotipy and create an app on https://developers.spotify.com/. +Add your new ID and SECRET to your environment: + +> export SPOTIPY_CLIENT_ID='your-spotify-client-id' +> export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret' + +Then, create a Spotify object and call methods: ```python import spotipy -sp = spotipy.Spotify() +from spotipy.oauth2 import SpotifyClientCredentials + +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) results = sp.search(q='weezer', limit=20) for i, t in enumerate(results['tracks']['items']): print(' ', i, t['name']) ``` -A full set of examples can be found in the [online documentation](http://spotipy.readthedocs.org/) and in the [Spotipy examples directory](https://github.com/plamere/spotipy/tree/master/examples). - - ## 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. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index efb52cf..eb86981 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,7 +27,6 @@ released by the artist 'Birdy':: Here's another example showing how to get 30 second samples and cover art for the top 10 tracks for Led Zeppelin:: - from __future__ import print_function import spotipy lz_uri = 'spotify:artist:36QJpDe2go2KgaRleHCDTp' @@ -44,7 +43,6 @@ for the top 10 tracks for Led Zeppelin:: Finally, here's an example that will get the URL for an artist image given the artist's name:: - from __future__ import print_function import spotipy import sys @@ -71,9 +69,9 @@ API `_ documentation. Installation ============ -Install *Spotipy* with:: +Install or upgrade *Spotipy* with: - pip install spotipy + pip install spotipy --upgrade Or with:: @@ -84,38 +82,19 @@ Or you can get the source from github at https://github.com/plamere/spotipy Getting Started =============== -Non-Authorized requests -======================= -For methods that do not require authorization, simply create a Spotify object -and start making method calls like so:: - - from __future__ import print_function - import spotipy - spotify = spotipy.Spotify() - results = spotify.search(q='artist:' + name, type='artist') - print(results) - -Authorized requests -======================= -Many methods require user authentication. For these requests you will need to -generate an authorization token that indicates that the user has granted -permission for your application to perform the given task. You will need to +All methods require user authorization. You will need to register your app to get the credentials necessary to make authorized calls. Even if your script does not have an accessible URL you will need to specify one when registering your application which the Spotify authentication server will redirect to after successful login. The URL doesn't need to be publicly -accessible, so you can specify "http://localhost/", and after succesfully -authenticating your app, you can simply copy the -"http://localhost/?code=..." URL from your browser and paste it to the -console where your script is running. +accessible, so you can specify "http://localhost/". Register your app at `My Applications `_ and register the redirect URI mentioned in the above paragragh. - *spotipy* supports two authorization flows: - The **Authorization Code flow** This method is suitable for long-running applications @@ -123,11 +102,18 @@ redirect URI mentioned in the above paragragh. - The **Client Credentials flow** The method makes it possible to authenticate your requests to the Spotify Web API and to obtain - a higher rate limit than you would + a higher rate limit than you would with the Authorization Code flow. Authorization Code Flow ======================= + +This flow is suitable for long-running applications in which the user grants +permission only once. It provides an access token that can be refreshed. +Since the token exchange involves sending your secret key, perform this on a +secure location, like a backend service, and not from a client such as a +browser or from a mobile app. + To support the **Authorization Code Flow** *Spotipy* provides a 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:: @@ -144,14 +130,16 @@ you can set environment variables like so:: Call ``util.prompt_for_user_token`` method with the username and the desired scope (see `Using Scopes `_ for information -about scopes) and credentials. This will coordinate the user authorization via +about scopes) and credentials. After succesfully +authenticating your app, you can simply copy the +"http://localhost/?code=..." URL from your browser and paste it to the +console where your script is running. This will coordinate the user authorization via your web browser and callback to the SPOTIPY_REDIRECT_URI you were redirected to with the authorization token appended. The credentials are cached locally and are used to automatically re-authorized expired tokens. Here's an example of getting user authorization to read a user's saved tracks:: - from __future__ import print_function import sys import spotipy import spotipy.util as util @@ -177,8 +165,13 @@ Here's an example of getting user authorization to read a user's saved tracks:: Client Credentials Flow ======================= +The Client Credentials flow is used in server-to-server authentication. Only +endpoints that do not access user information can be accessed. The advantage here +in comparison with requests to the Web API made without an access token, +is that a higher rate limit is applied. + To support the **Client Credentials Flow** *Spotipy* provides a -class SpotifyClientCredentials that can be used to authenticate requests like so:: +class SpotifyClientCredentials that can be used to authenticate requests like so: import spotipy @@ -196,9 +189,6 @@ class SpotifyClientCredentials that can be used to authenticate requests like so else: playlists = None -Client credentials flow is appropriate for requests that do not require access to a -user's private data. Even if you are only making calls that do not require -authorization, using this flow yields the benefit of a higher rate limit IDs URIs and URLs ======================= @@ -223,8 +213,6 @@ Here are a few more examples of using *Spotipy*. Add tracks to a playlist:: - from __future__ import print_function - import pprint import sys import spotipy @@ -254,7 +242,6 @@ Shows the contents of every playlist owned by a user:: # shows a user's playlists (need to be authenticated via oauth) - from __future__ import print_function import sys import spotipy import spotipy.util as util diff --git a/examples/artist_albums.py b/examples/artist_albums.py index c147c3d..d426c9a 100644 --- a/examples/artist_albums.py +++ b/examples/artist_albums.py @@ -32,8 +32,7 @@ def show_artist_albums(artist): if __name__ == '__main__': - client_credentials_manager = SpotifyClientCredentials() - sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) + sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) if len(sys.argv) < 2: print(('Usage: {0} artist name'.format(sys.argv[0]))) diff --git a/examples/client_credentials_flow.py b/examples/client_credentials_flow.py index ab1f315..856bf5e 100644 --- a/examples/client_credentials_flow.py +++ b/examples/client_credentials_flow.py @@ -1,10 +1,10 @@ from spotipy.oauth2 import SpotifyClientCredentials import spotipy -import pprint +from pprint import pprint client_credentials_manager = SpotifyClientCredentials() sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) search_str = 'Muse' result = sp.search(search_str) -pprint.pprint(result) +pprint(result) diff --git a/examples/deadmau5.gv b/examples/deadmau5.gv deleted file mode 100644 index b5873ca..0000000 --- a/examples/deadmau5.gv +++ /dev/null @@ -1,31 +0,0 @@ -digraph G { - "deadmau5" -> "Billy Newton-Davis" [label="All U Ever Want"]; - "deadmau5" -> "Melleefresh" [label="Afterhours (The Remixes)"]; - "deadmau5" -> "Imogen Heap" [label="Telemiscommunications (Remixes)"]; - "deadmau5" -> "Kaskade" [label="DJ Hero EP"]; - "Billy Newton-Davis" -> "Spekrfreks" [label="Back It Up"]; - "Billy Newton-Davis" -> "Cajjmere Wray" [label="Fuk Chat"]; - "Billy Newton-Davis" -> "Nino Anthony" [label="Everything I Wanna Do Remixes"]; - "Melleefresh" -> "Wutam" [label="Do You Wannit Now"]; - "Melleefresh" -> "Stereo Scum" [label="How Dangerous"]; - "Melleefresh" -> "Tyler Michaud" [label="Kisses Remixes"]; - "Imogen Heap" -> "Ron van den Beuken" [label="Headlock"]; - "Spekrfreks" -> "SpekrFreks Feat. Michelle Ericsson" [label="Tears of Blood"]; - "Spekrfreks" -> "Michelle Ericsson" [label="Voyager EP"]; - "Nino Anthony" -> "Mr. Eyez" [label="Night Muzik"]; - "Tyler Michaud" -> "Interstate" [label="Junkie"]; - "Tyler Michaud" -> "Moonbeam" [label="Openhearted"]; - "Ron van den Beuken" -> "Simon Demillo" [label="Chaos"]; - "Ron van den Beuken" -> "Tatana" [label="United Music"]; - "Ron van den Beuken" -> "Fidde Stiggson" [label="Visions"]; - "Ron van den Beuken" -> "Tom Pulse" [label="Time"]; - "Michelle Ericsson" -> "Alex Torn" [label="Electro Avenue"]; - "Mr. Eyez" -> "John Joshua feat. Mr Eyez" [label="Way of Life"]; - "Mr. Eyez" -> "Doug Smuggler" [label="Sukka MC's"]; - "Mr. Eyez" -> "New Vegas" [label="Hard Funk"]; - "Interstate" -> "Hammer & Bennett" [label="Coldharbour Selections Part 8"]; - "Tom Pulse" -> "Tom Pulse feat. Fit4Funk" [label="Flying Through the Air"]; - "Hammer & Bennett" -> "Lens" [label="Coldharbour Selections Part 10"]; - "Lens" -> "Santiago Nino" [label="Coldharbour Selections Part 6"]; - "Santiago Nino" -> "Hammer" [label="Coldharbour Selections Part 19"]; -} diff --git a/examples/deadmau5.png b/examples/deadmau5.png deleted file mode 100644 index 7343e63..0000000 Binary files a/examples/deadmau5.png and /dev/null differ diff --git a/examples/long_track_test.dat b/examples/long_track_test.dat deleted file mode 100644 index fac3f95..0000000 --- a/examples/long_track_test.dat +++ /dev/null @@ -1,283 +0,0 @@ -spotify:track:0qMujfRhXLalSaDtN0PPMS -spotify:track:0S7Dd8FfW5ZomBAwY3rBg6 -spotify:track:5gCvgOuAxw8YpHCV9m1xue -spotify:track:0eZoEIFWMNTt3BVejJdUH7 -spotify:track:3P6OwCX7Ofiaaqtvujb6i5 -spotify:track:2q3PUwv7bnSFHFn73WyzIv -spotify:track:2sOwqF4Meye7XjSiO2oZk8 -spotify:track:5Hfa4TyZO402MFD10VbRCv -spotify:track:6SJFk7LilJXZwp8rvzGc1T -spotify:track:1dVy8va6CN9sWd8ISPWbmg -spotify:track:2UC9CbjVQSCMHykP0D39lj -spotify:track:02LhttutJp836x9MmTjUXQ -spotify:track:2j5siP7TDM8p8KJYz21f7i -spotify:track:1QzEIizaV0H420lOVRa4dW -spotify:track:7Emg43gSQ281JmC5FKBX5X -spotify:track:6Ly0owXzUn5aNeTNBIOzKH -spotify:track:22WpTfGxNHK5fdBTbFKjvV -spotify:track:4jqMLKRvugl6ya7o9G40NP -spotify:track:5o9L8CttqYj339wDetGdcG -spotify:track:3LNr24GL6u2OdLVH7GqMlm -spotify:track:7exER11O6jaBmUWhOvWRGh -spotify:track:1NqsDKWgqhVVjCvDyArfWn -spotify:track:7AxQN7tWw0aHlS8yYG1mi4 -spotify:track:3aEMkgM7iVXWNqTuP9phSM -spotify:track:37JwzWYOOYz2in4tXNNISx -spotify:track:2jLRbx1FdLauLTpjvKTgII -spotify:track:50BttjUL1U1L3Ngb0DRUWw -spotify:track:2GYyXvlQHvhcP9KEJo7pQs -spotify:track:2x0supcZhd6NEH1nem9DnR -spotify:track:45aBkgJ9UV2XVvWrLMOsyd -spotify:track:4xVEXwEALvLrmW4aef7esn -spotify:track:558w6Ru8SJCNzk0xdmISqX -spotify:track:0JnBXtqagQOFV9w9x7N0K6 -spotify:track:5aUnqiF9Y3W0OITq0UJscm -spotify:track:0jPr0tQreoKXHl460Jhp3P -spotify:track:6loFvY6N6URSVSnTz2RZ7L -spotify:track:3YYdwYqIlz3MKTVQLkXQ9m -spotify:track:77t1U17P4Q6ihd8JOq8ODr -spotify:track:5um9oqJyIRSOxYi1r4X04f -spotify:track:3bEzNqaPcOW6lQrXafl6F6 -spotify:track:5iHVKPDXHF40LaBCrxBsGH -spotify:track:6QybCOHAvZVEierFVIzY6E -spotify:track:7qXqrMSj9gr2GUAdZDjknQ -spotify:track:6I658qHs4LntNGSUUn1JHW -spotify:track:1ODvt9aF7ZuJeUtQ3HHNAF -spotify:track:7iU2b4II1E0saCk9vgsO9h -spotify:track:3h9m1K11aR6MUYPoHI6uQY -spotify:track:5kiHXz2911MbTjORtQ2thG -spotify:track:1qYShm8Jvs8zY9ivWKUhj1 -spotify:track:07HTDHDHxuHwtvS7xMpCsF -spotify:track:0dLeXCoYP3LTzQShO0DWds -spotify:track:7qLEaxMiR8WUsCG1uOBsuO -spotify:track:2veYJl7RAW2lkveifGHYKT -spotify:track:5efdzHjhTXm3P32utkjZsB -spotify:track:6xKDnd8rau33dOcr4eaLGp -spotify:track:67q3zVsJsPRks4k0eomEWy -spotify:track:1zD5Vk9Ay0V8OOI4YKuoAf -spotify:track:2v9IJFdS1O3Xszio2DOq4J -spotify:track:1392JJKNqrtn6ZKQ8bqB6g -spotify:track:3KQuCRQ6J9unCt6fB9OLFw -spotify:track:0M2YiDrjeH9kCTVitG7GIZ -spotify:track:4QIUa0bsk6cmtyl9TsHpyX -spotify:track:6q7zNqL13uQ8cYeLJPAnvM -spotify:track:3Un3OOg3VQnVgzqYFwtSA1 -spotify:track:0xbF056L1Rh3aorkYrnrcw -spotify:track:6LPff9WXf0mo93hWLQDfW4 -spotify:track:6MVim3XIOHTUUJt6ZZ4xiI -spotify:track:4oopnnqYQep1bRRHjWI5NZ -spotify:track:2SylgYRXnwmYe5dVUswwVC -spotify:track:64PbCTNpfIfsYNnbRjrarf -spotify:track:0zvOZPdyqHPEWjvhyURQ5X -spotify:track:0CQpJlD9j8gkpF6vYpPBvE -spotify:track:2xJC5rQTpX9Yv5EhbpETkk -spotify:track:4hpx4xuGn53AH1nWVGRh8v -spotify:track:4xP5U2WqMJK20BO9D918RI -spotify:track:0NZCRmTQbH2CcTXrA1tINk -spotify:track:7CXdkXxOJrOWAwKKrSPlWS -spotify:track:6NmldQ2cNdas2Rv4YwIrfn -spotify:track:0NZCRmTQbH2CcTXrA1tINk -spotify:track:3s6bstAaZbC6uBHPuel3W6 -spotify:track:2hJ7E250KxFXuE0TCCfoI3 -spotify:track:1Sv7P3pIY2Zjzpen78OORc -spotify:track:5VD27c9f7BuDaRVplcnebl -spotify:track:1uyDxNgwyXIJRy87tyewDt -spotify:track:7nV61Rd3q3LwRUt5qQ5rtR -spotify:track:5Lp4xptZSf2khojxC8iehH -spotify:track:0IcFhAtZQqCgdv4ugyjQZx -spotify:track:0vyJfb5merhL1NtmrucJaH -spotify:track:1x95pWB3KeK3evKa1VrW6e -spotify:track:3HM8glYP7qh2VQ2DilsEAi -spotify:track:60TdUFHyUfcBmRuf4AMldq -spotify:track:1uqZw35kbgxuvb5nJJ5y23 -spotify:track:74sz92IUs02Bh2fJzXyGSK -spotify:track:583YTL8Fl6pCWtZAi2GvVZ -spotify:track:1dl7TO9hPWPaUwURKqBGmP -spotify:track:0ph9DIJozeJOEvIev5qVQk -spotify:track:4mai1CggFbdIpK8MEohA0K -spotify:track:6h7Kh7pGFAwB1dyghm0mZZ -spotify:track:7DOZPeLfQqkcskfKUKoAUf -spotify:track:3FPobLmheSF7QWzq4pDLD9 -spotify:track:3PRVwEDVVK5ITqwu0Hy84V -spotify:track:50xlAtqoFecexXj3N4kynJ -spotify:track:5vwudDPhjnuA1KrNsFjAHK -spotify:track:6BhyyrUEbOI7szsjgbzAju -spotify:track:3XfylwQhFCIoDvC0BNjCWt -spotify:track:0iuTv9sYunbo4zW6cykFYk -spotify:track:5y95ucn3laegC0ObJhlufv -spotify:track:0MkD7ugsiBFbK83ZwAvobZ -spotify:track:1UczOJLWGL9VQJVAePRMcI -spotify:track:4Ks83rDIAwNokEG4PYnog4 -spotify:track:2CgAKuEdwtx34U5T2rLyw4 -spotify:track:2H3YWZ3Q1PNtUA8z0mPpGQ -spotify:track:33F1I9sAEUcB7Q05tHh9fp -spotify:track:5vKOOD6x7YMqcvgxaGnt64 -spotify:track:4vnfKsDUJGaHqEnpNKLOL8 -spotify:track:0JbiyOEt6YuDFTZj7Rep8s -spotify:track:4DQTlpLapighigY8paBEd9 -spotify:track:38bq59et0KNcjTMQJAWDJs -spotify:track:2AckvF8zhoMhmZ49jmIf8O -spotify:track:0g0RzAZH3nlKWkl41CLyNT -spotify:track:5Og1ngUAa8N6GRdLJp81Pg -spotify:track:03W5lEf82eVBF8rjDxhbW2 -spotify:track:4VtD7qiPoHYpKAuOmTLyc2 -spotify:track:1Xn6hGSkbjbnOFKQxvk5Qh -spotify:track:7aiL6F8q7D10xQtXchzu2W -spotify:track:6HhZrrj25eb6hAcqa1jmIa -spotify:track:7568pJYdTxmQiyV2Pt3TAK -spotify:track:7sXcHlfKfEwPSGDrLmDbfB -spotify:track:57vgSkXvr4KkaCIJMWSFB2 -spotify:track:2T848jgfBpBt0vhw2LSKhN -spotify:track:1A3HGfeudhMFNd8b6Mswp8 -spotify:track:4DqnhrbWAH3I92TAqtBrGY -spotify:track:6jLrlevctgoeGPXDLEdt6L -spotify:track:2Ntx16XsOz8pMz3ygHodpS -spotify:track:02lTCqFw0RasK7xAqu5fqE -spotify:track:3Jxi6P3Y4bYXEAHhcYho4a -spotify:track:6urjT2UUnX83D8CDOPfux3 -spotify:track:4oobntmhVjfkWkSNAo9ijn -spotify:track:1yCxOSKbSlYAUbjeeH0Yv3 -spotify:track:4AMsQnCRSXL4x0C0b0i7kk -spotify:track:0WKdB7PG53c1QlDbQzqn7s -spotify:track:15zhodeybsv2mz5Yw7hS48 -spotify:track:4CL8fkzCyhM0DDlotIDDpr -spotify:track:7Cb1KVyKSOUauQLTofWKEw -spotify:track:0SfG2rMDw7ZviADcXv1TI0 -spotify:track:2j3PFZXmenUxgjjBUIod7F -spotify:track:0dOg1ySSI7NkpAe89Zo0b9 -spotify:track:6Pgm5NvlnLVqPvPtIMj6Dh -spotify:track:33OzFYIVWZPn0E6RHctiC9 -spotify:track:7yPvz9Z57Vq3DnA1LqTwER -spotify:track:6sWj81TNza7VqfspjWjHDc -spotify:track:2nXSfOUS7BmPhLRV6ehiml -spotify:track:1MqGKtY9L5qjPi8s7gX645 -spotify:track:7a61OH8U2s1OhVPgCuNPMZ -spotify:track:3fzE5vxFTZ2DRiIdKI4l4B -spotify:track:6YxJ9uq7ex1rcFfx6boYDo -spotify:track:3qnf1FH4LHe9bHXEuMUZoG -spotify:track:6Jb4MjZlwDOsKyqXXCw7X6 -spotify:track:35YJCWAB360MTp0AxSZgNB -spotify:track:4f2FDf06hmv5YptohyLQV8 -spotify:track:0pkIyrSYE0BRpw4nNsBlmq -spotify:track:1ek5AmqUXMkx3eQPytV1BN -spotify:track:4jRtPv8a9wcpm8gJEKQSlR -spotify:track:1Fv48qm7W9AR1PwVc3wS9A -spotify:track:1mUpXELX93AvTswzLLY0UT -spotify:track:1qvFHNSBXGOsryKOr3p03m -spotify:track:5pvIVmZJZIc8SE3Gk3sEye -spotify:track:5ynfc3x7H5t8shUZRZpb6N -spotify:track:48Wl0w5LmiqhWwYVK9Win7 -spotify:track:45qDQvSBricT3zn3jzAxnk -spotify:track:0Gh1GsynRMY3cZZY7G0dlY -spotify:track:01nP5PpbvUBcAIMQW5i1vP -spotify:track:26Sm4ymfC0TVUK2RnHlciw -spotify:track:1myBSHHET1Re4UTSGmneeH -spotify:track:2dTRTQXRSCo4zgiXlyYaY3 -spotify:track:5qKmpbegJWROssoQgo0r7O -spotify:track:5IT43uHiMbw4AdI9VcCZxm -spotify:track:2ggBhNH6UexpYnziaW78SG -spotify:track:600wNkX9UT5rB0HRceHxX7 -spotify:track:30dT0S656DlaJrtimk8ItR -spotify:track:1PCftEVEn0PihLine6dIHQ -spotify:track:788Cp8dfA6GWwyEP8qHXTG -spotify:track:4DHKG1Hewrb9fTzVUXRl2D -spotify:track:0RQ3uttlfwETe72tZZQZFw -spotify:track:6kLfEKc7z5trZKWCv8hCYX -spotify:track:4RcRScJt7v5FhaZaCAWQ0T -spotify:track:4aJKkm3GYi8rCYPbhV8r0b -spotify:track:7IU6s1cVja1qWFmXkmR7iA -spotify:track:6vZLotWyNDlzDjoqY0Ec0D -spotify:track:5I6Y18eR8JelTClXNKdL2B -spotify:track:3ZKSCv9AfXOUuFO9j27EOb -spotify:track:0m4RZWh8jsqwIFZFxpNJZI -spotify:track:36NwlLTSsboo9SeQpTE3Mo -spotify:track:0M7mWKqwTIaVjYyxfZmtTa -spotify:track:0gnTF8QD5apHcK86nvCkrp -spotify:track:5MF1TOtDyYMQIyBXSDnzSu -spotify:track:12UzVR0M7asW2MHAZRJk0I -spotify:track:6uJpoNDk8sgJlQ13hKwGWH -spotify:track:50GWfznvmLBhUlHYKMq9G8 -spotify:track:7mIEvNbJxo1aEAGd7DkiC3 -spotify:track:1BY78IlCc8KiZjYLi9tk0l -spotify:track:4oYbwL03t1isZD4cFPtCxM -spotify:track:7lPzpmqhKwMaETmOBVTamL -spotify:track:5RqFC823JhgZjcX2p5pLC2 -spotify:track:6EHBJHPgbFv2uEdljLTYUo -spotify:track:0MCkLZZP1CJXOzBe2XGcdm -spotify:track:42I483ip9VozNoMKfbbnls -spotify:track:0BK3KDnit2B9lGptYsOyNG -spotify:track:0cVwLfU8BXN9zxZ2HKns9h -spotify:track:6mBsRxVAfZ7TdrooLmxexO -spotify:track:6QyJ8AQSoH1zJFyf86E6mx -spotify:track:5Vo4Lu0SF93q8pHFo68UOa -spotify:track:5EyYnQ3F8sPaylsWFTR4Qg -spotify:track:5lTEhTjBY2grPGjLKFSuks -spotify:track:0kcGX9Z9Q5i6EHX1QLNXDp -spotify:track:3t4hsTZCob6hwJU2f5Pz3u -spotify:track:2xHRb4OLnfhQMdJSyMW2dU -spotify:track:21l0IzdoW75sT5TewUT22V -spotify:track:5wllnBkcq1IMlTXnaW6Jv3 -spotify:track:4Uvbm8ijckGf4xDer9SF9s -spotify:track:1zKkQ6gyZQOMw68CUCf8GX -spotify:track:6pi7OwWvCYaOvEqAfBYiM4 -spotify:track:34yStWRRrbosgMs32yMlc1 -spotify:track:7gSbqXLD5glv5w7giXInvf -spotify:track:7EaYzSnP0akAQVfCu4RFBX -spotify:track:4Iduy3277LDiuCztPw9NAS -spotify:track:4UBTrrSotbB1DaRbapsR0R -spotify:track:54fskci17LPbSCmE2qGAD5 -spotify:track:1H84cRYr4wzEwgFM9PGOE5 -spotify:track:5nfQ7FgSfCG5FRK0Xoxy3M -spotify:track:7tSlB26fVA76eCVJQz1ueH -spotify:track:2hftOwcKNudZraI6Edvh8t -spotify:track:6CZEhTgAiPCa4fAD269PlI -spotify:track:2dPKh2wXy4Fc1S9UcmHRNu -spotify:track:4UDWJipAonm3DzOvRIo5N2 -spotify:track:3Goagh1ioAxjfKA5W6eqNN -spotify:track:6tT1EQyFcOZfmZQf1wSjtb -spotify:track:5KNltwC6xlNHIzUrigMISL -spotify:track:1HpTDohERdRdSw195oPKUv -spotify:track:5X5rx4uRMEWwxD1Lwl2NQU -spotify:track:43dgoxSKLWvfeUWZ9uEEWK -spotify:track:3KRGfygdhSiGG9r5JmWFZV -spotify:track:7u3L8sB8NdL5UeARrFN536 -spotify:track:0fZQfEfq9JxUEy1FjqOiCZ -spotify:track:58TxkZIEZWtqPMn1Y4Vd3t -spotify:track:3P4J0WzZSXGpl9z8Suz5jO -spotify:track:37Z1knZBcsUQfc1jM1zrOu -spotify:track:0yHBzIb97dsuxcOkRhKU0v -spotify:track:3emSZCViwDicSLBi6SMIRX -spotify:track:3bL9LUHgTTqPeU7s3bqyMd -spotify:track:6864dMeIjWotTlWlbhUsbr -spotify:track:78bpVL8pZBGhQa6CV9Bvlq -spotify:track:7F3WX3rfpm29WDy8UkfKmg -spotify:track:3uQDfCKlwfK9Yz10JFcsC7 -spotify:track:2ZyTdkTn5h4xPgX48hWGdI -spotify:track:4qb2AKvnaDdvJJnKmxo9ST -spotify:track:1Nruw7r9cwfQVLz7j9Qc1b -spotify:track:5bOG5FKR5eJOhNYCIO4E35 -spotify:track:5ZCjhZABvYc50lt5zRPdgZ -spotify:track:2kSpNkYlQCRCZX0a6tW02a -spotify:track:7HUFClGakCCS6DUHkdey5M -spotify:track:3CbPsxgJB53v51wWqcY6oD -spotify:track:5twEsir35519mNkxfH9Lnv -spotify:track:2HRYa6iG1M5DRefO8pK2I3 -spotify:track:2x0supcZhd6NEH1nem9DnR -spotify:track:5bZI4j4gZQUj0ZkE2wER9O -spotify:track:0yuKuvDJlOf4GjUtf3OPjf -spotify:track:28BFxsobryXuZghzAGBImi -spotify:track:50nv5PDK8zVmdIC7KdBSOz -spotify:track:3kJ6B8jf7G2KRPELgntYOL -spotify:track:3HJ8LpromeQLHrP5XPuBL3 -spotify:track:2KPflscGoyKv5Kc6PG7KNe -spotify:track:6ytJGSzgBunW0VePRAyhNn -spotify:track:1QninLAEEtyzoDTCsGNrQz -spotify:track:7oyKc3RgnMaSRgwNTLCDgE -spotify:track:0PA9HmVnyHknT43go3tFz3 -spotify:track:5cp7armpdpEOfdkD5WiX6q -spotify:track:1qmJbXpVLydNcN6VTR40GU -spotify:track:2bdapwYVEGpGWxlx3iooAB -spotify:track:21YbiQuw6j4k6DOBzE79z2 -spotify:track:31WCZ6zpqXOz3Rljc0Yor8 -spotify:track:3Ozp5uFYtC4Q6X4L4ivBDv - diff --git a/examples/search.py b/examples/search.py index adaf6c1..cf81208 100644 --- a/examples/search.py +++ b/examples/search.py @@ -10,7 +10,6 @@ if len(sys.argv) > 1: else: search_str = 'Radiohead' -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) result = sp.search(search_str) pprint.pprint(result) diff --git a/examples/show_album.py b/examples/show_album.py index bc18893..248e305 100644 --- a/examples/show_album.py +++ b/examples/show_album.py @@ -3,17 +3,14 @@ from spotipy.oauth2 import SpotifyClientCredentials import spotipy -from spotipy.oauth2 import SpotifyClientCredentials import sys -import pprint +from pprint import pprint if len(sys.argv) > 1: urn = sys.argv[1] else: urn = 'spotify:album:5yTx83u3qerZF7GRJu7eFk' - -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) album = sp.album(urn) -pprint.pprint(album) +pprint(album) diff --git a/examples/show_artist.py b/examples/show_artist.py index 6abe214..72f18cc 100644 --- a/examples/show_artist.py +++ b/examples/show_artist.py @@ -2,18 +2,15 @@ from spotipy.oauth2 import SpotifyClientCredentials import spotipy -from spotipy.oauth2 import SpotifyClientCredentials import sys -import pprint +from pprint import pprint if len(sys.argv) > 1: urn = sys.argv[1] else: urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) artist = sp.artist(urn) - -pprint.pprint(artist) +pprint(artist) diff --git a/examples/show_artist_top_tracks.py b/examples/show_artist_top_tracks.py index 5656aba..857bfb8 100644 --- a/examples/show_artist_top_tracks.py +++ b/examples/show_artist_top_tracks.py @@ -2,7 +2,6 @@ from spotipy.oauth2 import SpotifyClientCredentials import spotipy -from spotipy.oauth2 import SpotifyClientCredentials import sys if len(sys.argv) > 1: @@ -10,8 +9,7 @@ if len(sys.argv) > 1: else: urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) response = sp.artist_top_tracks(urn) for track in response['tracks']: diff --git a/examples/show_track_info.py b/examples/show_track_info.py index dcf5dcc..353172c 100644 --- a/examples/show_track_info.py +++ b/examples/show_track_info.py @@ -2,16 +2,15 @@ from spotipy.oauth2 import SpotifyClientCredentials import spotipy -from spotipy.oauth2 import SpotifyClientCredentials import sys -import pprint +from pprint import pprint if len(sys.argv) > 1: urn = sys.argv[1] else: urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ' -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) + track = sp.track(urn) -pprint.pprint(track) +pprint(track) diff --git a/examples/simple2.py b/examples/simple2.py index 3a0316b..1a207b2 100644 --- a/examples/simple2.py +++ b/examples/simple2.py @@ -13,4 +13,3 @@ for track in results['tracks'][:10]: print('track : ' + track['name']) print('audio : ' + track['preview_url']) print('cover art: ' + track['album']['images'][0]['url']) - print() diff --git a/examples/simple3.py b/examples/simple3.py index c3f6f60..ef3df9b 100644 --- a/examples/simple3.py +++ b/examples/simple3.py @@ -1,8 +1,9 @@ +import sys + from spotipy.oauth2 import SpotifyClientCredentials import spotipy -client_credentials_manager = SpotifyClientCredentials() -sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) +sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) if len(sys.argv) > 1: name = ' '.join(sys.argv[1:]) diff --git a/tests/test_auth.py b/tests/test_auth.py index 327898a..a0b8237 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -129,7 +129,7 @@ class AuthTestSpotipy(unittest.TestCase): def test_current_user_saved_albums(self): # List albums = self.spotify.current_user_saved_albums() - self.assertTrue(len(albums['items']) == 1) + self.assertTrue(len(albums['items']) > 1) # Add self.spotify.current_user_saved_albums_add(self.album_ids) @@ -143,7 +143,7 @@ class AuthTestSpotipy(unittest.TestCase): # Remove self.spotify.current_user_saved_albums_delete(self.album_ids) albums = self.spotify.current_user_saved_albums() - self.assertTrue(len(albums['items']) == 1) + self.assertTrue(len(albums['items']) > 1) def test_current_user_playlists(self): playlists = self.spotify.current_user_playlists(limit=10) diff --git a/tests/tests.py b/tests/tests.py index acac28b..abb5aa8 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,13 +1,17 @@ # -*- coding: utf-8 -*- -import os -import sys import unittest - +import os import requests -from spotipy.client import SpotifyException -from spotipy.oauth2 import SpotifyClientCredentials +import spotipy +from spotipy import ( + CLIENT_CREDS_ENV_VARS as CCEV, + prompt_for_user_token, + Spotify, + SpotifyException, + SpotifyClientCredentials +) class TestSpotipy(unittest.TestCase): @@ -36,10 +40,18 @@ class TestSpotipy(unittest.TestCase): bad_id = 'BAD_ID' - - def setUp(self): - client_credentials_manager = SpotifyClientCredentials() - self.spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager) + @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 ' + '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(client_credentials_manager=SpotifyClientCredentials()) def test_artist_urn(self): artist = self.spotify.artist(self.radiohead_urn) @@ -140,7 +152,9 @@ class TestSpotipy(unittest.TestCase): def test_search_timeout(self): client_credentials_manager = SpotifyClientCredentials() - sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager, requests_timeout=.1) + sp = spotipy.Spotify( + client_credentials_manager=client_credentials_manager, + requests_timeout=.01) try: sp.search(q='my*', type='track') @@ -182,16 +196,22 @@ class TestSpotipy(unittest.TestCase): def test_custom_requests_session(self): sess = requests.Session() sess.headers["user-agent"] = "spotipy-test" - client_credentials_manager = SpotifyClientCredentials() - with_custom_session = spotipy.Spotify(client_credentials_manager=client_credentials_manager, requests_session=sess) - self.assertTrue(with_custom_session.user(user="akx")["uri"] == "spotify:user:akx") + with_custom_session = spotipy.Spotify( + client_credentials_manager=SpotifyClientCredentials(), + requests_session=sess) + self.assertTrue( + with_custom_session.user( + user="akx")["uri"] == "spotify:user:akx") + sess.close() def test_force_no_requests_session(self): from requests import Session - client_credentials_manager = SpotifyClientCredentials() - with_no_session = spotipy.Spotify(client_credentials_manager=client_credentials_manager, requests_session=False) + with_no_session = spotipy.Spotify( + client_credentials_manager=SpotifyClientCredentials(), + requests_session=False) 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") '''