diff --git a/CHANGELOG.md b/CHANGELOG.md index ba4a44b..30e8930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added CONTRIBUTING.md + ### Changed + - Client retry logic has changed as it now uses urllib3's `Retry` in conjunction with requests `Session` - The session is customizable as it allows for: - status_forcelist - retries - status_retries - backoff_factor +- Spin up a local webserver to auto-fill authentication URL ## [2.10.0] - 2020-03-18 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b94f52..c40d756 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,9 @@ ## Contributing + If you would like to contribute to spotipy follow these steps: ### Export the needed environment variables + ```bash export SPOTIPY_CLIENT_ID=client_id_here export SPOTIPY_CLIENT_SECRET=client_secret_here @@ -9,10 +11,26 @@ export SPOTIPY_CLIENT_USERNAME=client_username_here # This is actually an id not export SPOTIPY_REDIRECT_URI=http://localhost/ # Make url is set in app you created to get your ID and SECRET ``` -### Create virtual enevironment, install dependencies, run tests: +### Create virtual environment, install dependencies, run tests: + ```bash $ virtualenv --python=python3.7 env (env) $ pip install requirements.txt (env) $ python -m unittest discover -v tests ``` +### Lint + +To automatically fix the code style: + + pip install autopep8 + autopep8 --in-place --aggressive --recursive . + +To verify the code style: + + pip install flake8 + flake8 . + +### README + +Don't forget to add a short description of your change in the [CHANGELOG](CHANGELOG.md) \ No newline at end of file diff --git a/spotipy/oauth2.py b/spotipy/oauth2.py index b8b2544..483271f 100644 --- a/spotipy/oauth2.py +++ b/spotipy/oauth2.py @@ -320,10 +320,9 @@ class SpotifyOAuth(SpotifyAuthBase): return self.parse_response_code(response) def _get_auth_response_local_server(self, redirect_port): - - with start_local_http_server(redirect_port) as server: - self._open_auth_url() - server.handle_request() + server = start_local_http_server(redirect_port) + self._open_auth_url() + server.handle_request() if server.auth_code is not None: return server.auth_code @@ -488,9 +487,12 @@ class RequestHandler(BaseHTTPRequestHandler): return self._write(""" +

Authentication status: {}

-Now you can close this window or tab. +This window can be closed. """.format(status)) diff --git a/tests/integration/test_non_user_endpoints.py b/tests/integration/test_non_user_endpoints.py index fdb5886..1c17d2c 100644 --- a/tests/integration/test_non_user_endpoints.py +++ b/tests/integration/test_non_user_endpoints.py @@ -192,8 +192,9 @@ class AuthTestSpotipy(unittest.TestCase): sp = spotipy.Spotify(requests_timeout=0.01, client_credentials_manager=client_credentials_manager) - with self.assertRaises(requests.exceptions.Timeout): - sp.search(q='my*', type='track') + # depending on the timing or bandwidth, this raises a timeout or connection error" + self.assertRaises((requests.exceptions.Timeout, requests.exceptions.ConnectionError), + lambda: sp.search(q='my*', type='track')) def test_album_search(self): results = self.spotify.search(q='weezer pinkerton', type='album') diff --git a/tests/integration/test_user_endpoints.py b/tests/integration/test_user_endpoints.py index 1705f6d..adf0d6d 100644 --- a/tests/integration/test_user_endpoints.py +++ b/tests/integration/test_user_endpoints.py @@ -59,7 +59,7 @@ class SpotipyPlaylistApiTest(unittest.TestCase): user = playlist['owner']['id'] pid = playlist['id'] results = self.spotify.user_playlist_tracks(user, pid) - self.assertEquals(len(results['items']), 0) + self.assertEqual(len(results['items']), 0) def test_current_user_playlists(self): playlists = self.spotify.current_user_playlists(limit=10) @@ -134,7 +134,7 @@ class SpotipyPlaylistApiTest(unittest.TestCase): self.spotify.playlist_upload_cover_image(self.new_playlist_uri, dog_base64) res = self.spotify.playlist_cover_image(self.new_playlist_uri) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) first_image = res[0] self.assertIn('width', first_image) self.assertIn('height', first_image) @@ -196,13 +196,13 @@ class SpotipyLibraryApiTests(unittest.TestCase): tracks = self.spotify.current_user_saved_tracks() new_total = tracks['total'] - self.assertEquals(new_total - total, len(self.four_tracks)) + self.assertEqual(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.assertEquals(new_total, total) + self.assertEqual(new_total, total) def test_current_user_saved_albums(self): # Add @@ -212,12 +212,12 @@ class SpotipyLibraryApiTests(unittest.TestCase): # Contains resp = self.spotify.current_user_saved_albums_contains(self.album_ids) - self.assertEquals(resp, [True, True]) + self.assertEqual(resp, [True, True]) # Remove self.spotify.current_user_saved_albums_delete(self.album_ids) resp = self.spotify.current_user_saved_albums_contains(self.album_ids) - self.assertEquals(resp, [False, False]) + self.assertEqual(resp, [False, False]) class SpotipyUserApiTests(unittest.TestCase): @@ -244,11 +244,11 @@ class SpotipyUserApiTests(unittest.TestCase): def test_basic_user_profile(self): user = self.spotify.user(self.username) - self.assertEquals(user['id'], self.username.lower()) + self.assertEqual(user['id'], self.username.lower()) def test_current_user(self): user = self.spotify.current_user() - self.assertEquals(user['id'], self.username.lower()) + self.assertEqual(user['id'], self.username.lower()) def test_me(self): user = self.spotify.me() @@ -373,7 +373,7 @@ class SpotipyPlayerApiTests(unittest.TestCase): def test_devices(self): # No devices playing by default res = self.spotify.devices() - self.assertEquals(len(res["devices"]), 0) + self.assertEqual(len(res["devices"]), 0) def test_current_user_recently_played(self): # No cursor