Merge pull request #1 from Peter-Schorn/master

merge master into v3.
This commit is contained in:
Peter Schorn 2021-04-14 12:17:57 -05:00 committed by GitHub
commit b6c3961d5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 39 deletions

View File

@ -7,8 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased [3.0.0-alpha] ## Unreleased [3.0.0-alpha]
While this is unreleased, please only add v3 features here. While this is unreleased, please only add v3 features here. Rebasing master onto v3 doesn't require a changelog update.
Rebasing master onto v3 doesn't require a changelog update.
### Added ### Added
@ -19,14 +18,24 @@ Rebasing master onto v3 doesn't require a changelog update.
* Made `CacheHandler` an abstract base class * Made `CacheHandler` an abstract base class
* Modified the return structure of the `audio_features` function (wrapping the [Get Audio Features for Several Tracks](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-several-audio-features) API) to conform to the return structure of the similar methods listed below. The functions wrapping these APIs do not unwrap the single key JSON response, and this is currently the only function that does this. * Modified the return structure of the `audio_features` function (wrapping the [Get Audio Features for Several Tracks](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-several-audio-features) API) to conform to the return structure of the similar methods listed below. The functions wrapping these APIs do not unwrap the single key JSON response, and this is currently the only function that does this.
* [Get Several Tracks](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-several-tracks) * [Get Several Tracks](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-several-tracks)
* [Get Multiple Artists](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-multiple-artists) * [Get Multiple Artists](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-multiple-artists)
* [Get Multiple Albums](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-multiple-albums) * [Get Multiple Albums](https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-multiple-albums)
## Unreleased [2.x.x] ## Unreleased [2.x.x]
### Added ### Added
* Added `MemoryCacheHandler`, a cache handler that simply stores the token info in memory as an instance attribute of this class.
### Fixed
* Fixed a bug in `CacheFileHandler.__init__`: The documentation says that the username will be retrieved from the environment, but it wasn't.
## [2.18.0] - 2021-04-13
### Added
- Enabled using both short and long IDs for playlist_change_details - Enabled using both short and long IDs for playlist_change_details
- Added a cache handler to `SpotifyClientCredentials` - Added a cache handler to `SpotifyClientCredentials`
- Added the following endpoints - Added the following endpoints
@ -43,13 +52,9 @@ Rebasing master onto v3 doesn't require a changelog update.
### Fixed ### Fixed
* Fixed the bugs in `SpotifyOAuth.refresh_access_token` and `SpotifyPKCE.refresh_access_token` which raised the incorrect exception upon receiving an error response from the server. This addresses #645. * Fixed the bugs in `SpotifyOAuth.refresh_access_token` and `SpotifyPKCE.refresh_access_token` which raised the incorrect exception upon receiving an error response from the server. This addresses #645.
* Fixed a bug in `RequestHandler.do_GET` in which the non-existent `state` attribute of `SpotifyOauthError` is accessed. This bug occurs when the user clicks "cancel" in the permissions dialog that opens in the browser. * Fixed a bug in `RequestHandler.do_GET` in which the non-existent `state` attribute of `SpotifyOauthError` is accessed. This bug occurs when the user clicks "cancel" in the permissions dialog that opens in the browser.
* Cleaned up the documentation for `SpotifyClientCredentials.__init__`, `SpotifyOAuth.__init__`, and `SpotifyPKCE.__init__`. * Cleaned up the documentation for `SpotifyClientCredentials.__init__`, `SpotifyOAuth.__init__`, and `SpotifyPKCE.__init__`.
## [2.17.1] - 2021-02-28 ## [2.17.1] - 2021-02-28
### Fixed ### Fixed
@ -104,7 +109,7 @@ Rebasing master onto v3 doesn't require a changelog update.
### Added ### Added
- `SpotifyPKCE.parse_auth_response_url`, mirroring that method in - `SpotifyPKCE.parse_auth_response_url`, mirroring that method in
`SpotifyOAuth` `SpotifyOAuth`
### Changed ### Changed
@ -113,7 +118,7 @@ Rebasing master onto v3 doesn't require a changelog update.
### Fixed ### Fixed
- Using `SpotifyPKCE.get_authorization_url` will now generate a code - Using `SpotifyPKCE.get_authorization_url` will now generate a code
challenge if needed challenge if needed
## [2.14.0] - 2020-08-29 ## [2.14.0] - 2020-08-29
@ -121,9 +126,9 @@ Rebasing master onto v3 doesn't require a changelog update.
- (experimental) Support to search multiple/all markets at once. - (experimental) Support to search multiple/all markets at once.
- Support to test whether the current user is following certain - Support to test whether the current user is following certain
users or artists users or artists
- Proper replacements for all deprecated playlist endpoints - Proper replacements for all deprecated playlist endpoints
(See https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/ and below) (See https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/ and below)
- Allow for OAuth 2.0 authorization by instructing the user to open the URL in a browser instead of opening the browser. - Allow for OAuth 2.0 authorization by instructing the user to open the URL in a browser instead of opening the browser.
- Reason for 403 error in SpotifyException - Reason for 403 error in SpotifyException
- Support for the PKCE Auth Flow - Support for the PKCE Auth Flow
@ -141,15 +146,16 @@ Rebasing master onto v3 doesn't require a changelog update.
- `user_playlist_replace_tracks` in favor of `playlist_replace_items` - `user_playlist_replace_tracks` in favor of `playlist_replace_items`
- `user_playlist_reorder_tracks` in favor of `playlist_reorder_items` - `user_playlist_reorder_tracks` in favor of `playlist_reorder_items`
- `user_playlist_remove_all_occurrences_of_tracks` in favor of - `user_playlist_remove_all_occurrences_of_tracks` in favor of
`playlist_remove_all_occurrences_of_items` `playlist_remove_all_occurrences_of_items`
- `user_playlist_remove_specific_occurrences_of_tracks` in favor of - `user_playlist_remove_specific_occurrences_of_tracks` in favor of
`playlist_remove_specific_occurrences_of_items` `playlist_remove_specific_occurrences_of_items`
- `user_playlist_follow_playlist` in favor of - `user_playlist_follow_playlist` in favor of
`current_user_follow_playlist` `current_user_follow_playlist`
- `user_playlist_is_following` in favor of `playlist_is_following` - `user_playlist_is_following` in favor of `playlist_is_following`
- `playlist_tracks` in favor of `playlist_items` - `playlist_tracks` in favor of `playlist_items`
### Fixed ### Fixed
- fixed issue where episode URIs were being converted to track URIs in playlist calls - fixed issue where episode URIs were being converted to track URIs in playlist calls
## [2.13.0] - 2020-06-25 ## [2.13.0] - 2020-06-25
@ -157,12 +163,12 @@ Rebasing master onto v3 doesn't require a changelog update.
### Added ### Added
- Added `SpotifyImplicitGrant` as an auth manager option. It provides - Added `SpotifyImplicitGrant` as an auth manager option. It provides
user authentication without a client secret but sacrifices the ability user authentication without a client secret but sacrifices the ability
to refresh the token without user input. (However, read the class to refresh the token without user input. (However, read the class
docstring for security advisory.) docstring for security advisory.)
- Added built-in verification of the `state` query parameter - Added built-in verification of the `state` query parameter
- Added two new attributes: error and error_description to `SpotifyOauthError` exception class to show - Added two new attributes: error and error_description to `SpotifyOauthError` exception class to show
authorization/authentication web api errors details. authorization/authentication web api errors details.
- Added `SpotifyStateError` subclass of `SpotifyOauthError` - Added `SpotifyStateError` subclass of `SpotifyOauthError`
- Allow extending `SpotifyClientCredentials` and `SpotifyOAuth` - Allow extending `SpotifyClientCredentials` and `SpotifyOAuth`
- Added the market paramter to `album_tracks` - Added the market paramter to `album_tracks`
@ -186,10 +192,10 @@ Rebasing master onto v3 doesn't require a changelog update.
### Changed ### Changed
- Updated the documentation to give more details on the authorization process and reflect - Updated the documentation to give more details on the authorization process and reflect
2020 Spotify Application jargon and practices. 2020 Spotify Application jargon and practices.
- The local webserver is only started for localhost redirect_uri which specify a port, - The local webserver is only started for localhost redirect_uri which specify a port,
i.e. it is started for `http://localhost:8080` or `http://127.0.0.1:8080`, not for `http://localhost`. i.e. it is started for `http://localhost:8080` or `http://127.0.0.1:8080`, not for `http://localhost`.
### Fixed ### Fixed
@ -258,6 +264,7 @@ Rebasing master onto v3 doesn't require a changelog update.
- Optional `show_dialog` parameter to be passed to `SpotifyOAuth` - Optional `show_dialog` parameter to be passed to `SpotifyOAuth`
### Changed ### Changed
- Both `SpotifyClientCredentials` and `SpotifyOAuth` inherit from a common `SpotifyAuthBase` which handles common parameters and logics. - Both `SpotifyClientCredentials` and `SpotifyOAuth` inherit from a common `SpotifyAuthBase` which handles common parameters and logics.
## [2.7.1] - 2020-01-20 ## [2.7.1] - 2020-01-20
@ -301,16 +308,19 @@ Rebasing master onto v3 doesn't require a changelog update.
## [2.6.1] - 2020-01-13 ## [2.6.1] - 2020-01-13
### Fixed ### Fixed
- Fixed inconsistent behaviour with some API methods when - Fixed inconsistent behaviour with some API methods when
a full HTTP URL is passed. a full HTTP URL is passed.
- Fixed invalid calls to logging warn method - Fixed invalid calls to logging warn method
### Removed ### Removed
- `mock` no longer needed for install. Only used in `tox`. - `mock` no longer needed for install. Only used in `tox`.
## [2.6.0] - 2020-01-12 ## [2.6.0] - 2020-01-12
### Added ### Added
- Support for `playlist` to get a playlist without specifying a user - Support for `playlist` to get a playlist without specifying a user
- Support for `current_user_saved_albums_delete` - Support for `current_user_saved_albums_delete`
- Support for `current_user_saved_albums_contains` - Support for `current_user_saved_albums_contains`
@ -319,95 +329,126 @@ Rebasing master onto v3 doesn't require a changelog update.
- Lint with flake8 using Github action - Lint with flake8 using Github action
### Changed ### Changed
- Fix typos in doc - Fix typos in doc
- Start following [SemVer](https://semver.org) properly - Start following [SemVer](https://semver.org) properly
## [2.5.0] - 2020-01-11 ## [2.5.0] - 2020-01-11
Added follow and player endpoints Added follow and player endpoints
## [2.4.4] - 2017-01-04 ## [2.4.4] - 2017-01-04
Python 3 fix Python 3 fix
## [2.4.3] - 2017-01-02 ## [2.4.3] - 2017-01-02
Fixed proxy issue in standard auth flow Fixed proxy issue in standard auth flow
## [2.4.2] - 2017-01-02 ## [2.4.2] - 2017-01-02
Support getting audio features for a single track Support getting audio features for a single track
## [2.4.1] - 2017-01-02 ## [2.4.1] - 2017-01-02
Incorporated proxy support Incorporated proxy support
## [2.4.0] - 2016-12-31 ## [2.4.0] - 2016-12-31
Incorporated a number of PRs Incorporated a number of PRs
## [2.3.8] - 2016-03-31 ## [2.3.8] - 2016-03-31
Added recs, audio features, user top lists Added recs, audio features, user top lists
## [2.3.7] - 2015-08-10 ## [2.3.7] - 2015-08-10
Added current_user_followed_artists Added current_user_followed_artists
## [2.3.6] - 2015-06-03 ## [2.3.6] - 2015-06-03
Support for offset/limit with album_tracks API Support for offset/limit with album_tracks API
## [2.3.5] - 2015-04-28 ## [2.3.5] - 2015-04-28
Fixed bug in auto retry logic Fixed bug in auto retry logic
## [2.3.3] - 2015-04-01 ## [2.3.3] - 2015-04-01
Aadded client credential flow Aadded client credential flow
## [2.3.2] - 2015-03-31 ## [2.3.2] - 2015-03-31
Added auto retry logic Added auto retry logic
## [2.3.0] - 2015-01-05 ## [2.3.0] - 2015-01-05
Added session support added by akx. Added session support added by akx.
## [2.2.0] - 2014-11-15 ## [2.2.0] - 2014-11-15
Added support for user_playlist_tracks Added support for user_playlist_tracks
## [2.1.0] - 2014-10-25 ## [2.1.0] - 2014-10-25
Added support for new_releases and featured_playlists Added support for new_releases and featured_playlists
## [2.0.2] - 2014-08-25 ## [2.0.2] - 2014-08-25
Moved to spotipy at pypi Moved to spotipy at pypi
## [1.2.0] - 2014-08-22 ## [1.2.0] - 2014-08-22
Upgraded APIs and docs to make it be a real library Upgraded APIs and docs to make it be a real library
## [1.310.0] - 2014-08-20 ## [1.310.0] - 2014-08-20
Added playlist replace and remove methods. Added auth tests. Improved API docs Added playlist replace and remove methods. Added auth tests. Improved API docs
## [1.301.0] - 2014-08-19 ## [1.301.0] - 2014-08-19
Upgraded version number to take precedence over previously botched release (sigh) Upgraded version number to take precedence over previously botched release (sigh)
## [1.50.0] - 2014-08-14 ## [1.50.0] - 2014-08-14
Refactored util out of examples and into the main package Refactored util out of examples and into the main package
## [1.49.0] - 2014-07-23 ## [1.49.0] - 2014-07-23
Support for "Your Music" tracks (add, delete, get), with examples Support for "Your Music" tracks (add, delete, get), with examples
## [1.45.0] - 2014-07-07 ## [1.45.0] - 2014-07-07
Support for related artists endpoint. Don't use cache auth codes when scope changes Support for related artists endpoint. Don't use cache auth codes when scope changes
## [1.44.0] - 2014-07-03 ## [1.44.0] - 2014-07-03
Added show tracks.py example Added show tracks.py example
## [1.43.0] - 2014-06-27 ## [1.43.0] - 2014-06-27
Fixed JSON handling issue Fixed JSON handling issue
## [1.42.0] - 2014-06-19 ## [1.42.0] - 2014-06-19
Removed dependency on simplejson Removed dependency on simplejson
## [1.40.0] - 2014-06-12 ## [1.40.0] - 2014-06-12
Initial public release. Initial public release.
## [1.4.2] - 2014-06-21 ## [1.4.2] - 2014-06-21
Added support for retrieving starred playlists Added support for retrieving starred playlists
## [1.1.0] - 2014-06-17 ## [1.1.0] - 2014-06-17
Updates to match released API Updates to match released API
## [1.1.0] - 2014-05-18 ## [1.1.0] - 2014-05-18
Repackaged for saner imports Repackaged for saner imports
## [1.0.0] - 2017-04-05 ## [1.0.0] - 2017-04-05
Initial release Initial release

View File

@ -1,10 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__all__ = ['CacheHandler', 'CacheFileHandler'] __all__ = ['CacheHandler', 'CacheFileHandler', 'MemoryCacheHandler']
import errno import errno
import json import json
import logging import logging
import os
from spotipy.util import CLIENT_CREDS_ENV_VARS
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -54,6 +56,7 @@ class CacheFileHandler(CacheHandler):
self.cache_path = cache_path self.cache_path = cache_path
else: else:
cache_path = ".cache" cache_path = ".cache"
username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"]))
if username: if username:
cache_path += "-" + str(username) cache_path += "-" + str(username)
self.cache_path = cache_path self.cache_path = cache_path
@ -83,3 +86,24 @@ class CacheFileHandler(CacheHandler):
except IOError: except IOError:
logger.warning('Couldn\'t write token to cache at: %s', logger.warning('Couldn\'t write token to cache at: %s',
self.cache_path) self.cache_path)
class MemoryCacheHandler(CacheHandler):
"""
A cache handler that simply stores the token info in memory as an
instance attribute of this class. The token info will be lost when this
instance is freed.
"""
def __init__(self, token_info=None):
"""
Parameters:
* token_info: The token info to store in memory. Can be None.
"""
self.token_info = token_info
def get_cached_token(self):
return self.token_info
def save_token_to_cache(self, token_info):
self.token_info = token_info

View File

@ -6,7 +6,7 @@ import unittest
import six.moves.urllib.parse as urllibparse import six.moves.urllib.parse as urllibparse
from spotipy import SpotifyOAuth, SpotifyImplicitGrant, SpotifyPKCE from spotipy import SpotifyOAuth, SpotifyImplicitGrant, SpotifyPKCE
from spotipy.cache_handler import CacheHandler from spotipy.cache_handler import MemoryCacheHandler
from spotipy.oauth2 import SpotifyClientCredentials, SpotifyOauthError from spotipy.oauth2 import SpotifyClientCredentials, SpotifyOauthError
from spotipy.oauth2 import SpotifyStateError from spotipy.oauth2 import SpotifyStateError
@ -51,18 +51,6 @@ def _make_pkceauth(*args, **kwargs):
return SpotifyPKCE("CLID", "REDIR", "STATE", *args, **kwargs) return SpotifyPKCE("CLID", "REDIR", "STATE", *args, **kwargs)
class MemoryCache(CacheHandler):
def __init__(self, token_info=None):
self.token_info = token_info
def get_cached_token(self):
return self.token_info
def save_token_to_cache(self, token_info):
self.token_info = token_info
return None
class OAuthCacheTest(unittest.TestCase): class OAuthCacheTest(unittest.TestCase):
@patch.multiple(SpotifyOAuth, @patch.multiple(SpotifyOAuth,
@ -161,7 +149,7 @@ class OAuthCacheTest(unittest.TestCase):
scope = "playlist-modify-private" scope = "playlist-modify-private"
tok = _make_fake_token(1, 1, scope) tok = _make_fake_token(1, 1, scope)
spot = _make_oauth(scope, cache_handler=MemoryCache()) spot = _make_oauth(scope, cache_handler=MemoryCacheHandler())
spot.cache_handler.save_token_to_cache(tok) spot.cache_handler.save_token_to_cache(tok)
cached_tok = spot.cache_handler.get_cached_token() cached_tok = spot.cache_handler.get_cached_token()