mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 09:13:53 +00:00
Allow open_browser to be set on creation of auth_manager (SpotifyOAuth/SpotifyPKCE) (#574)
* Fix plamere/spotipy#560
* Adhere to code style
* Update CHANGELOG.md for changes in 939f869bbc
* open_browser passed to get_auth_response should take precedence over the same argument in the constructor
* Update FAQ
* Add information about headless auth
* Add headless auth example
This commit is contained in:
parent
a42f2ccd0f
commit
87fe473672
@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
// Add your changes here and then delete this line
|
### Added
|
||||||
|
|
||||||
|
- `open_browser` can be passed to the constructors of `SpotifyOAuth` and `SpotifyPKCE` to make it easier to authorize in browserless environments
|
||||||
|
|
||||||
## [2.15.0] - 2020-09-08
|
## [2.15.0] - 2020-09-08
|
||||||
|
|
||||||
|
|||||||
9
FAQ.md
9
FAQ.md
@ -40,4 +40,11 @@ Problem: you can see a track on the Spotify app but searching for it using the A
|
|||||||
|
|
||||||
Solution: by default `search("abba")` works in the US market.
|
Solution: by default `search("abba")` works in the US market.
|
||||||
To search for in your current country, the [country indicator](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
|
To search for in your current country, the [country indicator](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
|
||||||
must be specified: `search("abba", market="DE")`.
|
must be specified: `search("abba", market="DE")`.
|
||||||
|
|
||||||
|
### How do I obtain authorization in a headless/browserless environment?
|
||||||
|
|
||||||
|
If you cannot open a browser, set `open_browser=False` when instantiating SpotifyOAuth or SpotifyPKCE. You will be
|
||||||
|
prompted to open the authorization URI manually.
|
||||||
|
|
||||||
|
See the [headless auth example](examples/headless.py).
|
||||||
8
examples/headless.py
Normal file
8
examples/headless.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import spotipy
|
||||||
|
|
||||||
|
from spotipy.oauth2 import SpotifyOAuth
|
||||||
|
|
||||||
|
# set open_browser=False to prevent Spotipy from attempting to open the default browser
|
||||||
|
spotify = spotipy.Spotify(auth_manager=SpotifyOAuth(open_browser=False))
|
||||||
|
|
||||||
|
print(spotify.me())
|
||||||
@ -234,18 +234,19 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
OAUTH_TOKEN_URL = "https://accounts.spotify.com/api/token"
|
OAUTH_TOKEN_URL = "https://accounts.spotify.com/api/token"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client_id=None,
|
client_id=None,
|
||||||
client_secret=None,
|
client_secret=None,
|
||||||
redirect_uri=None,
|
redirect_uri=None,
|
||||||
state=None,
|
state=None,
|
||||||
scope=None,
|
scope=None,
|
||||||
cache_path=None,
|
cache_path=None,
|
||||||
username=None,
|
username=None,
|
||||||
proxies=None,
|
proxies=None,
|
||||||
show_dialog=False,
|
show_dialog=False,
|
||||||
requests_session=True,
|
requests_session=True,
|
||||||
requests_timeout=None
|
requests_timeout=None,
|
||||||
|
open_browser=True
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Creates a SpotifyOAuth object
|
Creates a SpotifyOAuth object
|
||||||
@ -264,6 +265,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
* show_dialog: Interpreted as boolean
|
* show_dialog: Interpreted as boolean
|
||||||
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
||||||
of seconds
|
of seconds
|
||||||
|
* open_browser: 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)
|
||||||
@ -280,6 +282,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
self.proxies = proxies
|
self.proxies = proxies
|
||||||
self.requests_timeout = requests_timeout
|
self.requests_timeout = requests_timeout
|
||||||
self.show_dialog = show_dialog
|
self.show_dialog = show_dialog
|
||||||
|
self.open_browser = open_browser
|
||||||
|
|
||||||
def get_cached_token(self):
|
def get_cached_token(self):
|
||||||
""" Gets a cached auth token
|
""" Gets a cached auth token
|
||||||
@ -294,7 +297,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
|
|
||||||
# if scopes don't match, then bail
|
# if scopes don't match, then bail
|
||||||
if "scope" not in token_info or not self._is_scope_subset(
|
if "scope" not in token_info or not self._is_scope_subset(
|
||||||
self.scope, token_info["scope"]
|
self.scope, token_info["scope"]
|
||||||
):
|
):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -382,7 +385,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
except webbrowser.Error:
|
except webbrowser.Error:
|
||||||
logger.error("Please navigate here: %s", auth_url)
|
logger.error("Please navigate here: %s", auth_url)
|
||||||
|
|
||||||
def _get_auth_response_interactive(self, open_browser=True):
|
def _get_auth_response_interactive(self, open_browser=False):
|
||||||
if open_browser:
|
if open_browser:
|
||||||
self._open_auth_url()
|
self._open_auth_url()
|
||||||
prompt = "Enter the URL you were redirected to: "
|
prompt = "Enter the URL you were redirected to: "
|
||||||
@ -413,7 +416,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
else:
|
else:
|
||||||
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
||||||
|
|
||||||
def get_auth_response(self, open_browser=True):
|
def get_auth_response(self, open_browser=None):
|
||||||
logger.info('User authentication requires interaction with your '
|
logger.info('User authentication requires interaction with your '
|
||||||
'web browser. Once you enter your credentials and '
|
'web browser. Once you enter your credentials and '
|
||||||
'give authorization, you will be redirected to '
|
'give authorization, you will be redirected to '
|
||||||
@ -423,10 +426,13 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
redirect_info = urlparse(self.redirect_uri)
|
redirect_info = urlparse(self.redirect_uri)
|
||||||
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
||||||
|
|
||||||
|
if open_browser is None:
|
||||||
|
open_browser = self.open_browser
|
||||||
|
|
||||||
if (
|
if (
|
||||||
open_browser
|
(open_browser or self.open_browser)
|
||||||
and redirect_host in ("127.0.0.1", "localhost")
|
and redirect_host in ("127.0.0.1", "localhost")
|
||||||
and redirect_info.scheme == "http"
|
and redirect_info.scheme == "http"
|
||||||
):
|
):
|
||||||
# Only start a local http server if a port is specified
|
# Only start a local http server if a port is specified
|
||||||
if redirect_port:
|
if redirect_port:
|
||||||
@ -584,7 +590,8 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
username=None,
|
username=None,
|
||||||
proxies=None,
|
proxies=None,
|
||||||
requests_timeout=None,
|
requests_timeout=None,
|
||||||
requests_session=True,):
|
requests_session=True,
|
||||||
|
open_browser=True):
|
||||||
"""
|
"""
|
||||||
Creates Auth Manager with the PKCE Auth flow.
|
Creates Auth Manager with the PKCE Auth flow.
|
||||||
|
|
||||||
@ -602,6 +609,7 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
* proxies: Proxy for the requests library to route through
|
* proxies: Proxy for the requests library to route through
|
||||||
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
* requests_timeout: Tell Requests to stop waiting for a response after a given number
|
||||||
of seconds
|
of seconds
|
||||||
|
* open_browser: Whether or not the web browser should be opened to authorize a user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super(SpotifyPKCE, self).__init__(requests_session)
|
super(SpotifyPKCE, self).__init__(requests_session)
|
||||||
@ -620,6 +628,7 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
self.code_verifier = None
|
self.code_verifier = None
|
||||||
self.code_challenge = None
|
self.code_challenge = None
|
||||||
self.authorization_code = None
|
self.authorization_code = None
|
||||||
|
self.open_browser = open_browser
|
||||||
|
|
||||||
def _normalize_scope(self, scope):
|
def _normalize_scope(self, scope):
|
||||||
if scope:
|
if scope:
|
||||||
@ -642,7 +651,7 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
try:
|
try:
|
||||||
import secrets
|
import secrets
|
||||||
verifier = secrets.token_urlsafe(length)
|
verifier = secrets.token_urlsafe(length)
|
||||||
except ImportError: # For python 3.5 support
|
except ImportError: # For python 3.5 support
|
||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
rand_bytes = os.urandom(length)
|
rand_bytes = os.urandom(length)
|
||||||
@ -688,7 +697,7 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
except webbrowser.Error:
|
except webbrowser.Error:
|
||||||
logger.error("Please navigate here: %s", auth_url)
|
logger.error("Please navigate here: %s", auth_url)
|
||||||
|
|
||||||
def _get_auth_response(self, open_browser=True):
|
def _get_auth_response(self, open_browser=None):
|
||||||
logger.info('User authentication requires interaction with your '
|
logger.info('User authentication requires interaction with your '
|
||||||
'web browser. Once you enter your credentials and '
|
'web browser. Once you enter your credentials and '
|
||||||
'give authorization, you will be redirected to '
|
'give authorization, you will be redirected to '
|
||||||
@ -698,10 +707,13 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
redirect_info = urlparse(self.redirect_uri)
|
redirect_info = urlparse(self.redirect_uri)
|
||||||
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
||||||
|
|
||||||
|
if open_browser is None:
|
||||||
|
open_browser = self.open_browser
|
||||||
|
|
||||||
if (
|
if (
|
||||||
open_browser
|
open_browser
|
||||||
and redirect_host in ("127.0.0.1", "localhost")
|
and redirect_host in ("127.0.0.1", "localhost")
|
||||||
and redirect_info.scheme == "http"
|
and redirect_info.scheme == "http"
|
||||||
):
|
):
|
||||||
# Only start a local http server if a port is specified
|
# Only start a local http server if a port is specified
|
||||||
if redirect_port:
|
if redirect_port:
|
||||||
@ -730,8 +742,8 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
else:
|
else:
|
||||||
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
||||||
|
|
||||||
def _get_auth_response_interactive(self, open_browser=True):
|
def _get_auth_response_interactive(self, open_browser=False):
|
||||||
if open_browser:
|
if open_browser or self.open_browser:
|
||||||
self._open_auth_url()
|
self._open_auth_url()
|
||||||
prompt = "Enter the URL you were redirected to: "
|
prompt = "Enter the URL you were redirected to: "
|
||||||
else:
|
else:
|
||||||
@ -764,7 +776,7 @@ class SpotifyPKCE(SpotifyAuthBase):
|
|||||||
|
|
||||||
# if scopes don't match, then bail
|
# if scopes don't match, then bail
|
||||||
if "scope" not in token_info or not self._is_scope_subset(
|
if "scope" not in token_info or not self._is_scope_subset(
|
||||||
self.scope, token_info["scope"]
|
self.scope, token_info["scope"]
|
||||||
):
|
):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -1011,7 +1023,7 @@ class SpotifyImplicitGrant(SpotifyAuthBase):
|
|||||||
|
|
||||||
# if scopes don't match, then bail
|
# if scopes don't match, then bail
|
||||||
if "scope" not in token_info or not self._is_scope_subset(
|
if "scope" not in token_info or not self._is_scope_subset(
|
||||||
self.scope, token_info["scope"]
|
self.scope, token_info["scope"]
|
||||||
):
|
):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user