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 = {}
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
class Cache(object): _cache = {} _cachedir = None _cache_lock = None @property def cache_lock(self): return self._cache_lock def __init__(self, environment): """ Initializes the cache so that kraft does not have to constantly retrieve informational lists about unikraft, its available architectures, platforms, libraries and supported applications. """ self._cachedir = environment.get('UK_CACHEDIR') # Initiaize a cache instance self._cache = FileCache(app_cache_dir=self._cachedir, appname=__program__, flag='cs') self._cache_lock = threading.Lock() @property def cache(self): ret = None with self._cache_lock: ret = self._cache return ret def get(self, origin=None): ret = None if isinstance(origin, six.string_types) and origin in self._cache: logger.debug("Retrieving %s from cache..." % origin) with self._cache_lock: ret = self._cache[origin] return ret def find_item_by_name(self, type=None, name=None): for origin in self._cache: for item in self._cache[origin].items(): if ((type is not None and item[1].type.shortname == type) or type is None) and item[1].name == name: return item[1] return None def all(self): return self.cache def save(self, origin, manifest): if not isinstance(origin, six.string_types): raise TypeError("origin is not string") if not isinstance(manifest, Manifest): raise TypeError("Invalid manifest") with self._cache_lock: logger.debug("Saving %s into cache..." % manifest) self._cache[origin] = manifest def sync(self): logger.debug("Synchronizing cache with filesystem...") with self._cache_lock: self._cache.sync() def purge(self): logger.debug("Purging cache...") with self._cache_lock: self._cache.clear() def is_stale(self): """ Determine if the list of remote repositories is stale. Return a boolean value if at least one repository is marked as stale. """ logger.debug("Checking cache for staleness...") return True if len(self.all()) == 0 else False