class NFLClientCredentials(requests.auth.AuthBase): """ A requests Auth object that maintains a token for the nfl.com api The token is cached using a file cache that may or may not work across multiple processes. The worst that can happen is that it is refreshed unnecessarily. """ def __init__(self, cache_name: str = 'nflapi'): self.cache = FileCache(cache_name, flag='cs') self.cache.clear() def __call__(self, r: requests.Request): r.headers['Authorization'] = self.__get_token( ua=r.headers.get('User-Agent', None)) return r def __get_token(self, ua): if self.cache.get('expire', EPOCH) < pendulum.now(): self.__update_token(ua) token = self.cache.get('token') logger.debug("Using token: %s" % token) return token def __update_token(self, ua): logger.debug('Updating auth token') data = {'grant_type': 'client_credentials'} response = self.__token_request(ENDPOINT_V1_REROUTE, data, ua) token = '{token_type} {access_token}'.format(**response) expire = pendulum.now().add(seconds=response['expires_in'] - 30) self.cache['token'] = token self.cache['expire'] = expire logger.debug('Updated token: %s - expires %s', token, expire) @staticmethod def __token_request(path, data, ua): headers = {'X-Domain-Id': '100', 'User-Agent': ua} logger.debug('Request: POST %s, data=<%s>', path, pformat(data)) url = API_HOST + path logger.debug('Request headers: %s', pformat(headers)) response = requests.request('POST', url, data=data, headers=headers) try: js = response.json() response.raise_for_status() logger.debug('Response: %s', pformat(js)) return js except HTTPError as e: raise Exception("Unsuccessful response: %r" % response.data) from e except ValueError as e: raise Exception("Response from API was not json: %s" % response.data) from e
class SZFileBackend(CacheBackend): def __init__(self, arguments): self._cache = FileCache(arguments.pop("appname", None), flag=arguments.pop("flag", "c"), serialize=arguments.pop("serialize", True), app_cache_dir=arguments.pop( "app_cache_dir", None)) def get(self, key): value = self._cache.get(key, NO_VALUE) return value def get_multi(self, keys): ret = [self._cache.get(key, NO_VALUE) for key in keys] return ret def set(self, key, value): self._cache[key] = value def set_multi(self, mapping): for key, value in mapping.items(): self._cache[key] = value def delete(self, key): self._cache.pop(key, None) def delete_multi(self, keys): for key in keys: self._cache.pop(key, None) @property def all_filenames(self): return self._cache._all_filenames() def sync(self, force=False): if (hasattr(self._cache, "_buffer") and self._cache._buffer) or force: self._cache.sync() def clear(self): self._cache.clear() if not hasattr(self._cache, "_buffer") or self._cache._sync: self._cache._sync = False self._cache._buffer = {}
class SZFileBackend(CacheBackend): def __init__(self, arguments): self._cache = FileCache(arguments.pop("appname", None), flag=arguments.pop("flag", "c"), serialize=arguments.pop("serialize", True), app_cache_dir=arguments.pop("app_cache_dir", None)) def get(self, key): value = self._cache.get(key, NO_VALUE) return value def get_multi(self, keys): ret = [ self._cache.get(key, NO_VALUE) for key in keys] return ret def set(self, key, value): self._cache[key] = value def set_multi(self, mapping): for key, value in mapping.items(): self._cache[key] = value def delete(self, key): self._cache.pop(key, None) def delete_multi(self, keys): for key in keys: self._cache.pop(key, None) @property def all_filenames(self): return self._cache._all_filenames() def sync(self, force=False): if (hasattr(self._cache, "_buffer") and self._cache._buffer) or force: self._cache.sync() def clear(self): self._cache.clear() if not hasattr(self._cache, "_buffer") or self._cache._sync: self._cache._sync = False self._cache._buffer = {}
def get_stopwords(extra_stopwords=[]): cache = FileCache('stopwords') stopwords = cache.get('stopwords', []) if stopwords: return set(stopwords + extra_stopwords) else: cache['stopwords'] = default_stopwords() cache.sync() return set(cache['stopwords'] + extra_stopwords)
def get_rabbit_host_from_vhost(self, vhost, caching=True): if caching: vhost_host_cache = FileCache('vhost-host', flag='cs') if vhost_host_cache.get(vhost): return vhost_host_cache[vhost] else: vhost_host_cache[vhost] = self.get_host_action(vhost) return vhost_host_cache[vhost] else: return self.get_host_action(vhost)
def get_stemmed_stopwords(extra_stopwords=[]): cache = FileCache('stopwords') stemmed_stopwords = cache.get('stemmed_stopwords', []) stemmed_extra = list(set([stemmize(w) for w in extra_stopwords])) if stemmed_stopwords: return set(stemmed_stopwords + stemmed_extra) else: stemmed = list(set(stemmize(w) for w in get_stopwords())) cache['stemmed_stopwords'] = stemmed cache.sync() return set(stemmed + stemmed_extra)
def detect_stuck_messages_queue(queue_body, ttl): past_queue = FileCache('message-queue', flag='cs') queue_name = queue_body['name'] current_messages = queue_body['messages'] current_consumers = queue_body['consumers'] current_time = datetime.now(timezone.utc) current_time = current_time.replace(tzinfo=None) if past_queue.get(queue_name): time_range_minutes = timedelta.total_seconds(current_time - past_queue[queue_name]['time_catch']) / 60 if past_queue[queue_name]['messages'] == current_messages: if time_range_minutes > ttl: return True if time_range_minutes < ttl: return False else: past_queue[queue_name] = {'messages': current_messages, 'time_catch': current_time, 'consumers': current_consumers} return False else: past_queue[queue_name] = {'messages': current_messages, 'time_catch': current_time, 'consumers': current_consumers} return False
class ConfigFinder: def __init__(self, config_file: str = "SpotiBot.json") -> None: """Instantiates instances of environment configuration from .ini file. Args: config_file: Name of .ini configuration file following the format of SpotiBot_SAMPLE.ini """ self.cache = FileCache(config_file.split(r".")[0], flag="cs") self.config_file = config_file self.path_to_config = self.cache.get(r"path_to_config") def clear_cache(self) -> object: """Clears cached path to configuration file.""" self.cache.clear() return self @property def cache_exists(self) -> bool: """Checks to see if a cached file path exists to a valid file.""" try: return os.path.isfile(self.path_to_config) except: return False @property def cache_is_valid(self) -> bool: """Checks to see if the valid file path contains the config file.""" try: return self.config_file == os.path.basename(self.path_to_config) except: return False def locate_config(self): """Traverse file system from bottom up to locate config file.""" for dirpath, dirnames, files in os.walk(os.path.expanduser("~"), topdown=False): if self.config_file in files: self.path_to_config = os.path.join(dirpath, self.config_file) break else: self.path_to_config = None return self.path_to_config def get_path(self) -> str: """Checks for cache existence and validates - traverses OS if not.""" print("Locating configuration...") print("\t<1 of 2> Checking for cached path...") if self.cache_exists and self.cache_is_valid: print(f"\t<2 of 2> Found cached path: {self.path_to_config}") else: print("\t<2 of 2> Cached path not found") print(f"\nLooking for {self.config_file} in local file system..") self.path_to_config = self.locate_config() if self.path_to_config: print(f"\t<1 of 1> '{self.config_file}' found at: " f"{self.path_to_config}") else: print(f"\t<1 of 1> Could not find config file" f" {self.config_file} please double check the name of " f"your configuration file or value passed in the" f"'config_file' argument") return self.path_to_config def read_file(self) -> object: """Locates creds file and caches location. Returns: Dictionary containing SpotiBot configuration params """ self.path_to_config = self.get_path() self.cache["path_to_config"] = self.path_to_config try: with open(self.path_to_config, "r") as r: self.cfg = json.load(r) except IOError as e: print(e) return self