mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 09:13:53 +00:00
Allow the scope to be either a list or comma separated string (#650)
* Allow the scope to be either a list or comma separated string * Move normalize scope to util file and make it a base method Also adjust documentation to reflect the new scope parameter supporting a list * Add change to CHANGELOG.md
This commit is contained in:
parent
d001326cc3
commit
e07dd64925
@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- The query parameters of requests are now logged
|
- The query parameters of requests are now logged
|
||||||
- Deprecate specifing `cache_path` or `username` directly to `SpotifyOAuth`, `SpotifyPKCE`, and `SpotifyImplicitGrant` constructors, instead directing users to use the `CacheFileHandler` cache handler
|
- Deprecate specifing `cache_path` or `username` directly to `SpotifyOAuth`, `SpotifyPKCE`, and `SpotifyImplicitGrant` constructors, instead directing users to use the `CacheFileHandler` cache handler
|
||||||
- Removed requirement for examples/app.py to specify port multiple times (only SPOTIPY_REDIRECT_URI needs to contain the port)
|
- Removed requirement for examples/app.py to specify port multiple times (only SPOTIPY_REDIRECT_URI needs to contain the port)
|
||||||
|
- Add support for a list of scopes rather than just a comma separated string of scopes
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ from six.moves.urllib_parse import parse_qsl, urlparse
|
|||||||
|
|
||||||
from spotipy.cache_handler import CacheFileHandler, CacheHandler
|
from spotipy.cache_handler import CacheFileHandler, CacheHandler
|
||||||
from spotipy.exceptions import SpotifyException
|
from spotipy.exceptions import SpotifyException
|
||||||
from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port
|
from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port, normalize_scope
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -83,6 +83,9 @@ class SpotifyAuthBase(object):
|
|||||||
from requests import api
|
from requests import api
|
||||||
self._session = api
|
self._session = api
|
||||||
|
|
||||||
|
def _normalize_scope(self, scope):
|
||||||
|
return normalize_scope(scope)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client_id(self):
|
def client_id(self):
|
||||||
return self._client_id
|
return self._client_id
|
||||||
@ -254,21 +257,23 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
* client_id: Must be supplied or set as environment variable
|
* client_id: Must be supplied or set as environment variable
|
||||||
* client_secret: Must be supplied or set as environment variable
|
* client_secret: Must be supplied or set as environment variable
|
||||||
* redirect_uri: Must be supplied or set as environment variable
|
* redirect_uri: Must be supplied or set as environment variable
|
||||||
* state: May be supplied, no verification is performed
|
* state: Optional, no verification is performed
|
||||||
* scope: May be supplied, intuitively converted to proper format
|
* scope: Optional, either a list of scopes or comma separated string of scopes.
|
||||||
|
e.g, "playlist-read-private,playlist-read-collaborative"
|
||||||
* cache_handler: An instance of the `CacheHandler` class to handle
|
* cache_handler: An instance of the `CacheHandler` class to handle
|
||||||
getting and saving cached authorization tokens.
|
getting and saving cached authorization tokens.
|
||||||
May be supplied, will otherwise use `CacheFileHandler`.
|
Optional, will otherwise use `CacheFileHandler`.
|
||||||
(takes precedence over `cache_path` and `username`)
|
(takes precedence over `cache_path` and `username`)
|
||||||
* cache_path: (deprecated) May be supplied, will otherwise be generated
|
* cache_path: (deprecated) Optional, will otherwise be generated
|
||||||
(takes precedence over `username`)
|
(takes precedence over `username`)
|
||||||
* username: (deprecated) May be supplied or set as environment variable
|
* username: (deprecated) Optional or set as environment variable
|
||||||
(will set `cache_path` to `.cache-{username}`)
|
(will set `cache_path` to `.cache-{username}`)
|
||||||
* proxies: Proxy for the requests library to route through
|
* show_dialog: Optional, interpreted as boolean
|
||||||
* show_dialog: Interpreted as boolean
|
* proxies: Optional, proxy for the requests library to route through
|
||||||
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
* requests_timeout: Optional, tell Requests to stop waiting for a response after
|
||||||
of seconds
|
a given number of seconds
|
||||||
* open_browser: Whether or not the web browser should be opened to authorize a user
|
* open_browser: Optional, whether or not the web browser should be opened to
|
||||||
|
authorize a user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super(SpotifyOAuth, self).__init__(requests_session)
|
super(SpotifyOAuth, self).__init__(requests_session)
|
||||||
@ -513,13 +518,6 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
self.cache_handler.save_token_to_cache(token_info)
|
self.cache_handler.save_token_to_cache(token_info)
|
||||||
return token_info if as_dict else token_info["access_token"]
|
return token_info if as_dict else token_info["access_token"]
|
||||||
|
|
||||||
def _normalize_scope(self, scope):
|
|
||||||
if scope:
|
|
||||||
scopes = sorted(scope.split())
|
|
||||||
return " ".join(scopes)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def refresh_access_token(self, refresh_token):
|
def refresh_access_token(self, refresh_token):
|
||||||
payload = {
|
payload = {
|
||||||
"refresh_token": refresh_token,
|
"refresh_token": refresh_token,
|
||||||
@ -627,21 +625,23 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
* client_id: Must be supplied or set as environment variable
|
* client_id: Must be supplied or set as environment variable
|
||||||
* client_secret: Must be supplied or set as environment variable
|
* client_secret: Must be supplied or set as environment variable
|
||||||
* redirect_uri: Must be supplied or set as environment variable
|
* redirect_uri: Must be supplied or set as environment variable
|
||||||
* state: May be supplied, no verification is performed
|
* state: Optional, no verification is performed
|
||||||
* scope: May be supplied, intuitively converted to proper format
|
* scope: Optional, either a list of scopes or comma separated string of scopes.
|
||||||
|
e.g, "playlist-read-private,playlist-read-collaborative"
|
||||||
* cache_handler: An instance of the `CacheHandler` class to handle
|
* cache_handler: An instance of the `CacheHandler` class to handle
|
||||||
getting and saving cached authorization tokens.
|
getting and saving cached authorization tokens.
|
||||||
May be supplied, will otherwise use `CacheFileHandler`.
|
Optional, will otherwise use `CacheFileHandler`.
|
||||||
(takes precedence over `cache_path` and `username`)
|
(takes precedence over `cache_path` and `username`)
|
||||||
* cache_path: (deprecated) May be supplied, will otherwise be generated
|
* cache_path: (deprecated) Optional, will otherwise be generated
|
||||||
(takes precedence over `username`)
|
(takes precedence over `username`)
|
||||||
* username: (deprecated) May be supplied or set as environment variable
|
* username: (deprecated) Optional or set as environment variable
|
||||||
(will set `cache_path` to `.cache-{username}`)
|
(will set `cache_path` to `.cache-{username}`)
|
||||||
* show_dialog: Interpreted as boolean
|
* show_dialog: Optional, interpreted as boolean
|
||||||
* proxies: Proxy for the requests library to route through
|
* proxies: Optional, proxy for the requests library to route through
|
||||||
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
* requests_timeout: Optional, tell Requests to stop waiting for a response after
|
||||||
of seconds
|
a given number of seconds
|
||||||
* open_browser: Whether or not the web browser should be opened to authorize a user
|
* open_browser: Optional, thether or not the web browser should be opened to
|
||||||
|
authorize a user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super(SpotifyPKCE, self).__init__(requests_session)
|
super(SpotifyPKCE, self).__init__(requests_session)
|
||||||
@ -683,13 +683,6 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
self.authorization_code = None
|
self.authorization_code = None
|
||||||
self.open_browser = open_browser
|
self.open_browser = open_browser
|
||||||
|
|
||||||
def _normalize_scope(self, scope):
|
|
||||||
if scope:
|
|
||||||
scopes = sorted(scope.split())
|
|
||||||
return " ".join(scopes)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _get_code_verifier(self):
|
def _get_code_verifier(self):
|
||||||
""" Spotify PCKE code verifier - See step 1 of the reference guide below
|
""" Spotify PCKE code verifier - See step 1 of the reference guide below
|
||||||
Reference:
|
Reference:
|
||||||
@ -1040,7 +1033,8 @@ class SpotifyImplicitGrant(SpotifyAuthBase):
|
|||||||
* client_id: Must be supplied or set as environment variable
|
* client_id: Must be supplied or set as environment variable
|
||||||
* redirect_uri: Must be supplied or set as environment variable
|
* redirect_uri: Must be supplied or set as environment variable
|
||||||
* state: May be supplied, no verification is performed
|
* state: May be supplied, no verification is performed
|
||||||
* scope: May be supplied, intuitively converted to proper format
|
* scope: Optional, either a list of scopes or comma separated string of scopes.
|
||||||
|
e.g, "playlist-read-private,playlist-read-collaborative"
|
||||||
* cache_handler: An instance of the `CacheHandler` class to handle
|
* cache_handler: An instance of the `CacheHandler` class to handle
|
||||||
getting and saving cached authorization tokens.
|
getting and saving cached authorization tokens.
|
||||||
May be supplied, will otherwise use `CacheFileHandler`.
|
May be supplied, will otherwise use `CacheFileHandler`.
|
||||||
@ -1131,13 +1125,6 @@ class SpotifyImplicitGrant(SpotifyAuthBase):
|
|||||||
|
|
||||||
return token_info["access_token"]
|
return token_info["access_token"]
|
||||||
|
|
||||||
def _normalize_scope(self, scope):
|
|
||||||
if scope:
|
|
||||||
scopes = sorted(scope.split())
|
|
||||||
return " ".join(scopes)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_authorize_url(self, state=None):
|
def get_authorize_url(self, state=None):
|
||||||
""" Gets the URL to use to authorize this app """
|
""" Gets the URL to use to authorize this app """
|
||||||
payload = {
|
payload = {
|
||||||
|
|||||||
@ -117,3 +117,19 @@ def get_host_port(netloc):
|
|||||||
port = None
|
port = None
|
||||||
|
|
||||||
return host, port
|
return host, port
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_scope(scope):
|
||||||
|
if scope:
|
||||||
|
if isinstance(scope, str):
|
||||||
|
scopes = scope.split(',')
|
||||||
|
elif isinstance(scope, list) or isinstance(scope, tuple):
|
||||||
|
scopes = scope
|
||||||
|
else:
|
||||||
|
raise Exception(
|
||||||
|
"Unsupported scope value, please either provide a list of scopes, "
|
||||||
|
"or a string of scopes separated by commas"
|
||||||
|
)
|
||||||
|
return " ".join(sorted(scopes))
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user