Skip to content

Commit

Permalink
spotipy lib update
Browse files Browse the repository at this point in the history
  • Loading branch information
guirem committed Jan 2, 2022
1 parent a7d9b6b commit af127eb
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 124 deletions.
2 changes: 1 addition & 1 deletion resources/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
setuptools
requests>=2.21.0
click
bs4
bs4>=4.8.1
six
tqdm
websocket-client
Expand Down
98 changes: 97 additions & 1 deletion resources/spotipy/cache_handler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
__all__ = ['CacheHandler', 'CacheFileHandler']
__all__ = [
'CacheHandler',
'CacheFileHandler',
'DjangoSessionCacheHandler',
'MemoryCacheHandler',
'RedisCacheHandler']

import errno
import json
import logging
import os
from spotipy.util import CLIENT_CREDS_ENV_VARS

from redis import RedisError

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -53,6 +62,7 @@ def __init__(self,
self.cache_path = cache_path
else:
cache_path = ".cache"
username = (username or os.getenv(CLIENT_CREDS_ENV_VARS["client_username"]))
if username:
cache_path += "-" + str(username)
self.cache_path = cache_path
Expand Down Expand Up @@ -82,3 +92,89 @@ def save_token_to_cache(self, token_info):
except IOError:
logger.warning('Couldn\'t write token to cache at: %s',
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


class DjangoSessionCacheHandler(CacheHandler):
"""
A cache handler that stores the token info in the session framework
provided by Django.
Read more at https://docs.djangoproject.com/en/3.2/topics/http/sessions/
"""

def __init__(self, request):
"""
Parameters:
* request: HttpRequest object provided by Django for every
incoming request
"""
self.request = request

def get_cached_token(self):
token_info = None
try:
token_info = self.request.session['token_info']
except KeyError:
logger.debug("Token not found in the session")

return token_info

def save_token_to_cache(self, token_info):
try:
self.request.session['token_info'] = token_info
except Exception as e:
logger.warning("Error saving token to cache: " + str(e))


class RedisCacheHandler(CacheHandler):
"""
A cache handler that stores the token info in the Redis.
"""

def __init__(self, redis, key=None):
"""
Parameters:
* redis: Redis object provided by redis-py library
(https://github.com/redis/redis-py)
* key: May be supplied, will otherwise be generated
(takes precedence over `token_info`)
"""
self.redis = redis
self.key = key if key else 'token_info'

def get_cached_token(self):
token_info = None
try:
if self.redis.exists(self.key):
token_info = json.loads(self.redis.get(self.key))
except RedisError as e:
logger.warning('Error getting token from cache: ' + str(e))

return token_info

def save_token_to_cache(self, token_info):
try:
self.redis.set(self.key, json.dumps(token_info))
except RedisError as e:
logger.warning('Error saving token to cache: ' + str(e))
32 changes: 19 additions & 13 deletions resources/spotipy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,22 @@ def _internal_call(self, method, url, payload, params):
except requests.exceptions.HTTPError as http_error:
response = http_error.response
try:
msg = response.json()["error"]["message"]
except (ValueError, KeyError):
msg = "error"
try:
reason = response.json()["error"]["reason"]
except (ValueError, KeyError):
json_response = response.json()
error = json_response.get("error", {})
msg = error.get("message")
reason = error.get("reason")
except ValueError:
# if the response cannnot be decoded into JSON (which raises a ValueError),
# then try to decode it into text

# if we receive an empty string (which is falsy), then replace it with `None`
msg = response.text or None
reason = None

logger.error('HTTP Error for %s to %s returned %s due to %s',
method, url, response.status_code, msg)
logger.error(
'HTTP Error for %s to %s with Params: %s returned %s due to %s',
method, url, args.get("params"), response.status_code, msg
)

raise SpotifyException(
response.status_code,
Expand Down Expand Up @@ -627,7 +633,7 @@ def playlist_tracks(
""" Get full details of the tracks of a playlist.
Parameters:
- playlist_id - the id of the playlist
- playlist_id - the playlist ID, URI or URL
- fields - which fields to return
- limit - the maximum number of tracks to return
- offset - the index of the first track to return
Expand Down Expand Up @@ -655,7 +661,7 @@ def playlist_items(
""" Get full details of the tracks and episodes of a playlist.
Parameters:
- playlist_id - the id of the playlist
- playlist_id - the playlist ID, URI or URL
- fields - which fields to return
- limit - the maximum number of tracks to return
- offset - the index of the first track to return
Expand All @@ -677,7 +683,7 @@ def playlist_cover_image(self, playlist_id):
""" Get cover of a playlist.
Parameters:
- playlist_id - the id of the playlist
- playlist_id - the playlist ID, URI or URL
"""
plid = self._get_id("playlist", playlist_id)
return self._get("playlists/%s/images" % (plid))
Expand Down Expand Up @@ -1176,7 +1182,7 @@ def current_user_saved_albums(self, limit=20, offset=0, market=None):
"Your Music" library
Parameters:
- limit - the number of albums to return
- limit - the number of albums to return (MAX_LIMIT=50)
- offset - the index of the first album to return
- market - an ISO 3166-1 alpha-2 country code.
Expand Down Expand Up @@ -1907,7 +1913,7 @@ def _get_id(self, type, id):
if type != fields[-2]:
logger.warning('Expected id of type %s but found type %s %s',
type, fields[-2], id)
return fields[-1]
return fields[-1].split("?")[0]
fields = id.split("/")
if len(fields) >= 3:
itype = fields[-2]
Expand Down
Loading

0 comments on commit af127eb

Please sign in to comment.