code time

This commit is contained in:
cere 2024-02-21 00:35:31 -05:00
parent 789a5e0b02
commit ae28da8d60
153 changed files with 56768 additions and 1 deletions

View file

@ -0,0 +1,5 @@
from .cache_handler import * # noqa
from .client import * # noqa
from .exceptions import * # noqa
from .oauth2 import * # noqa
from .util import * # noqa

View file

@ -0,0 +1,173 @@
__all__ = [
'CacheHandler',
'CacheFileHandler',
'DjangoSessionCacheHandler',
'FlaskSessionCacheHandler',
'MemoryCacheHandler']
import errno
import json
import logging
import os
from spotipy.util import CLIENT_CREDS_ENV_VARS
logger = logging.getLogger(__name__)
class CacheHandler():
"""
An abstraction layer for handling the caching and retrieval of
authorization tokens.
Custom extensions of this class must implement get_cached_token
and save_token_to_cache methods with the same input and output
structure as the CacheHandler class.
"""
def get_cached_token(self):
"""
Get and return a token_info dictionary object.
"""
# return token_info
raise NotImplementedError()
def save_token_to_cache(self, token_info):
"""
Save a token_info dictionary object to the cache and return None.
"""
raise NotImplementedError()
return None
class CacheFileHandler(CacheHandler):
"""
Handles reading and writing cached Spotify authorization tokens
as json files on disk.
"""
def __init__(self,
cache_path=None,
username=None,
encoder_cls=None):
"""
Parameters:
* cache_path: May be supplied, will otherwise be generated
(takes precedence over `username`)
* username: May be supplied or set as environment variable
(will set `cache_path` to `.cache-{username}`)
* encoder_cls: May be supplied as a means of overwriting the
default serializer used for writing tokens to disk
"""
self.encoder_cls = encoder_cls
if cache_path:
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
def get_cached_token(self):
token_info = None
try:
f = open(self.cache_path)
token_info_string = f.read()
f.close()
token_info = json.loads(token_info_string)
except IOError as error:
if error.errno == errno.ENOENT:
logger.debug("cache does not exist at: %s", self.cache_path)
else:
logger.warning("Couldn't read cache at: %s", self.cache_path)
return token_info
def save_token_to_cache(self, token_info):
try:
f = open(self.cache_path, "w")
f.write(json.dumps(token_info, cls=self.encoder_cls))
f.close()
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 FlaskSessionCacheHandler(CacheHandler):
"""
A cache handler that stores the token info in the session framework
provided by flask.
"""
def __init__(self, session):
self.session = session
def get_cached_token(self):
token_info = None
try:
token_info = self.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.session["token_info"] = token_info
except Exception as e:
logger.warning("Error saving token to cache: " + str(e))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
class SpotifyException(Exception):
def __init__(self, http_status, code, msg, reason=None, headers=None):
self.http_status = http_status
self.code = code
self.msg = msg
self.reason = reason
# `headers` is used to support `Retry-After` in the event of a
# 429 status code.
if headers is None:
headers = {}
self.headers = headers
def __str__(self):
return 'http status: {0}, code:{1} - {2}, reason: {3}'.format(
self.http_status, self.code, self.msg, self.reason)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
""" Shows a user's playlists (need to be authenticated via oauth) """
__all__ = ["CLIENT_CREDS_ENV_VARS", "prompt_for_user_token"]
import logging
import os
import warnings
import spotipy
LOGGER = logging.getLogger(__name__)
CLIENT_CREDS_ENV_VARS = {
"client_id": "SPOTIPY_CLIENT_ID",
"client_secret": "SPOTIPY_CLIENT_SECRET",
"client_username": "SPOTIPY_CLIENT_USERNAME",
"redirect_uri": "SPOTIPY_REDIRECT_URI",
}
def prompt_for_user_token(
username=None,
scope=None,
client_id=None,
client_secret=None,
redirect_uri=None,
cache_path=None,
oauth_manager=None,
show_dialog=False
):
warnings.warn(
"'prompt_for_user_token' is deprecated."
"Use the following instead: "
" auth_manager=SpotifyOAuth(scope=scope)"
" spotipy.Spotify(auth_manager=auth_manager)",
DeprecationWarning
)
""" prompts the user to login if necessary and returns
the user token suitable for use with the spotipy.Spotify
constructor
Parameters:
- username - the Spotify username (optional)
- scope - the desired scope of the request (optional)
- client_id - the client id of your app (required)
- client_secret - the client secret of your app (required)
- redirect_uri - the redirect URI of your app (required)
- cache_path - path to location to save tokens (optional)
- oauth_manager - Oauth manager object (optional)
- show_dialog - If true, a login prompt always shows (optional, defaults to False)
"""
if not oauth_manager:
if not client_id:
client_id = os.getenv("SPOTIPY_CLIENT_ID")
if not client_secret:
client_secret = os.getenv("SPOTIPY_CLIENT_SECRET")
if not redirect_uri:
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
if not client_id:
LOGGER.warning(
"""
You need to set your Spotify API credentials.
You can do this by setting environment variables like so:
export SPOTIPY_CLIENT_ID='your-spotify-client-id'
export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret'
export SPOTIPY_REDIRECT_URI='your-app-redirect-url'
Get your credentials at
https://developer.spotify.com/my-applications
"""
)
raise spotipy.SpotifyException(550, -1, "no credentials set")
sp_oauth = oauth_manager or spotipy.SpotifyOAuth(
client_id,
client_secret,
redirect_uri,
scope=scope,
cache_path=cache_path,
username=username,
show_dialog=show_dialog
)
# try to get a valid token for this user, from the cache,
# if not in the cache, then create a new (this will send
# the user to a web page where they can authorize this app)
token_info = sp_oauth.validate_token(sp_oauth.cache_handler.get_cached_token())
if not token_info:
code = sp_oauth.get_auth_response()
token = sp_oauth.get_access_token(code, as_dict=False)
else:
return token_info["access_token"]
# Auth'ed API request
if token:
return token
else:
return None
def get_host_port(netloc):
if ":" in netloc:
host, port = netloc.split(":", 1)
port = int(port)
else:
host = netloc
port = None
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