Make is_token_expired public

Make is_token_expired_public on SpotifyClientCredentials and SpotifyOAuth.
This method is useful for checking whether tokens that have been stored in cookies etc have timed out. So it's useful for library users to have access to it.

Refactor common implementation of is_token_expired
This commit is contained in:
Michael Birtwell 2017-01-07 13:17:57 +00:00
parent f638b0c59b
commit d092683be3
2 changed files with 20 additions and 17 deletions

View File

@ -21,6 +21,11 @@ def _make_authorization_headers(client_id, client_secret):
return {'Authorization': 'Basic %s' % auth_header.decode('ascii')} return {'Authorization': 'Basic %s' % auth_header.decode('ascii')}
def is_token_expired(token_info):
now = int(time.time())
return token_info['expires_at'] - now < 60
class SpotifyClientCredentials(object): class SpotifyClientCredentials(object):
OAUTH_TOKEN_URL = 'https://accounts.spotify.com/api/token' OAUTH_TOKEN_URL = 'https://accounts.spotify.com/api/token'
@ -52,7 +57,7 @@ class SpotifyClientCredentials(object):
If a valid access token is in memory, returns it If a valid access token is in memory, returns it
Else feches a new token and returns it Else feches a new token and returns it
""" """
if self.token_info and not self._is_token_expired(self.token_info): if self.token_info and not self.is_token_expired(self.token_info):
return self.token_info['access_token'] return self.token_info['access_token']
token_info = self._request_access_token() token_info = self._request_access_token()
@ -73,9 +78,8 @@ class SpotifyClientCredentials(object):
token_info = response.json() token_info = response.json()
return token_info return token_info
def _is_token_expired(self, token_info): def is_token_expired(self, token_info):
now = int(time.time()) return is_token_expired(token_info)
return token_info['expires_at'] - now < 60
def _add_custom_values_to_token_info(self, token_info): def _add_custom_values_to_token_info(self, token_info):
""" """
@ -131,7 +135,7 @@ class SpotifyOAuth(object):
if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']): if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
return None return None
if self._is_token_expired(token_info): if self.is_token_expired(token_info):
token_info = self.refresh_access_token(token_info['refresh_token']) token_info = self.refresh_access_token(token_info['refresh_token'])
except IOError: except IOError:
@ -154,9 +158,8 @@ class SpotifyOAuth(object):
return needle_scope <= haystack_scope return needle_scope <= haystack_scope
def _is_token_expired(self, token_info): def is_token_expired(self, token_info):
now = int(time.time()) return is_token_expired(token_info)
return token_info['expires_at'] < now
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

View File

@ -39,16 +39,16 @@ def _make_oauth(*args, **kwargs):
class OAuthCacheTest(unittest.TestCase): class OAuthCacheTest(unittest.TestCase):
@patch.multiple(SpotifyOAuth, @patch.multiple(SpotifyOAuth,
_is_token_expired=DEFAULT, refresh_access_token=DEFAULT) is_token_expired=DEFAULT, refresh_access_token=DEFAULT)
@patch('spotipy.oauth2.open', create=True) @patch('spotipy.oauth2.open', create=True)
def test_gets_from_cache_path(self, opener, def test_gets_from_cache_path(self, opener,
_is_token_expired, refresh_access_token): is_token_expired, refresh_access_token):
scope = "playlist-modify-private" scope = "playlist-modify-private"
path = ".cache-username" path = ".cache-username"
tok = _make_fake_token(1, 1, scope) tok = _make_fake_token(1, 1, scope)
opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False)) opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False))
_is_token_expired.return_value = False is_token_expired.return_value = False
spot = _make_oauth(scope, path) spot = _make_oauth(scope, path)
cached_tok = spot.get_cached_token() cached_tok = spot.get_cached_token()
@ -58,10 +58,10 @@ class OAuthCacheTest(unittest.TestCase):
self.assertEqual(refresh_access_token.call_count, 0) self.assertEqual(refresh_access_token.call_count, 0)
@patch.multiple(SpotifyOAuth, @patch.multiple(SpotifyOAuth,
_is_token_expired=DEFAULT, refresh_access_token=DEFAULT) is_token_expired=DEFAULT, refresh_access_token=DEFAULT)
@patch('spotipy.oauth2.open', create=True) @patch('spotipy.oauth2.open', create=True)
def test_expired_token_refreshes(self, opener, def test_expired_token_refreshes(self, opener,
_is_token_expired, refresh_access_token): is_token_expired, refresh_access_token):
scope = "playlist-modify-private" scope = "playlist-modify-private"
path = ".cache-username" path = ".cache-username"
expired_tok = _make_fake_token(0, None, scope) expired_tok = _make_fake_token(0, None, scope)
@ -74,22 +74,22 @@ class OAuthCacheTest(unittest.TestCase):
spot = _make_oauth(scope, path) spot = _make_oauth(scope, path)
spot.get_cached_token() spot.get_cached_token()
_is_token_expired.assert_called_with(expired_tok) is_token_expired.assert_called_with(expired_tok)
refresh_access_token.assert_called_with(expired_tok['refresh_token']) refresh_access_token.assert_called_with(expired_tok['refresh_token'])
opener.assert_any_call(path) opener.assert_any_call(path)
@patch.multiple(SpotifyOAuth, @patch.multiple(SpotifyOAuth,
_is_token_expired=DEFAULT, refresh_access_token=DEFAULT) is_token_expired=DEFAULT, refresh_access_token=DEFAULT)
@patch('spotipy.oauth2.open', create=True) @patch('spotipy.oauth2.open', create=True)
def test_badly_scoped_token_bails(self, opener, def test_badly_scoped_token_bails(self, opener,
_is_token_expired, refresh_access_token): is_token_expired, refresh_access_token):
token_scope = "playlist-modify-public" token_scope = "playlist-modify-public"
requested_scope = "playlist-modify-private" requested_scope = "playlist-modify-private"
path = ".cache-username" path = ".cache-username"
tok = _make_fake_token(1, 1, token_scope) tok = _make_fake_token(1, 1, token_scope)
opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False)) opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False))
_is_token_expired.return_value = False is_token_expired.return_value = False
spot = _make_oauth(requested_scope, path) spot = _make_oauth(requested_scope, path)
cached_tok = spot.get_cached_token() cached_tok = spot.get_cached_token()