class WechatCache(WechatSogouBase): """基于文件的缓存 """ def __init__(self, cache_dir='cache', default_timeout=300): """初始化 cache_dir是缓存目录 """ self.cache = FileSystemCache(cache_dir, default_timeout=default_timeout) def clear(self): """清空缓存 """ return self.cache.clear() def get(self, key): """获取缓存 获取键值key的缓存值 如果没有对应缓存,返回None """ return self.cache.get(key) def add(self, key, value, timeout=None): """增加缓存 如果键值key对应的缓存不存在,那么增加值value到键值key,过期时间timeout,默认300秒 否则返回False(即不能覆盖设置缓存) """ return self.cache.add(key, value, timeout) def set(self, key, value, timeout=None): """设置缓存 设置键值key的缓存为value,过期时间300秒 """ return self.cache.set(key, value, timeout) def delete(self, key): """删除缓存 删除键值key存储的缓存 """ return self.cache.delete(key)
class WechatCache(object): """基于文件的缓存 """ def __init__(self, cache_dir='cache', default_timeout=300): """初始化 cache_dir是缓存目录 """ self.cache = FileSystemCache(cache_dir, default_timeout=default_timeout) def clear(self): """清空缓存 """ return self.cache.clear() def get(self, key): """获取缓存 获取键值key的缓存值 如果没有对应缓存,返回None """ return self.cache.get(key) def add(self, key, value, timeout=None): """增加缓存 如果键值key对应的缓存不存在,那么增加值value到键值key,过期时间timeout,默认300秒 否则返回False(即不能覆盖设置缓存) """ return self.cache.add(key, value, timeout) def set(self, key, value, timeout=None): """设置缓存 设置键值key的缓存为value,过期时间300秒 """ return self.cache.set(key, value, timeout) def delete(self, key): """删除缓存 删除键值key存储的缓存 """ return self.cache.delete(key)
class WechatCache: def __init__(self, cache_dir='cache', default_timeout=300): self.cache = FileSystemCache(cache_dir=cache_dir, default_timeout=default_timeout) def clear(self): return self.cache.clear() def get(self, key): return self.cache.get(key) def add(self, key, value, timeout=None): return self.cache.add(key, value, timeout) def set(self, key, value, timeout=None): return self.cache.set(key, value, timeout) def delete(self, key): return self.cache.delete(key)
class Cache(object): """Cache module based on werkzeug.contrib.cache. This is a mixed version of NullCache, SimpleCache, FileSystemCache, MemcachedCache, and RedisCache. :param app: Flask app instance. :param config_prefix: Define a prefix for Flask app config. :param kwargs: Extra parameters. You need to configure a type of the cache, and its related configurations. The default ``config_prefix`` is ``AUTHLIB``, so it requires a config of:: AUTHLIB_CACHE_TYPE = 'simple' If ``config_prefix`` is something else, like ``EXAMPLE``, it would be:: EXAMPLE_CACHE_TYPE = 'simple' The available cache types are: * null: It will not cache anything. No configuration. * simple: It caches things in memory. The only configuration is ``threshold``:: AUTHLIB_CACHE_THRESHOLD = 500 * memcache: It caches things in Memcache. Available configurations:: AUTHLIB_CACHE_MEMCACHED_SERVERS = [] AUTHLIB_CACHE_KEY_PREFIX = None * redis: It caches things in Redis. Available configurations:: AUTHLIB_CACHE_REDIS_HOST = 'localhost' AUTHLIB_CACHE_REDIS_PORT = 6379 AUTHLIB_CACHE_REDIS_PASSWORD = None AUTHLIB_CACHE_REDIS_DB = 0 AUTHLIB_CACHE_KEY_PREFIX = None * filesystem: It caches things in local filesystem. Available configurations:: AUTHLIB_CACHE_DIR = '' # required AUTHLIB_CACHE_THRESHOLD = 500 """ def __init__(self, app, config_prefix='AUTHLIB', **kwargs): deprecate(DEPRECATE_MESSAGE, 0.7) self.config_prefix = config_prefix self.config = app.config cache_type = self._config('type') kwargs.update( dict(default_timeout=self._config('DEFAULT_TIMEOUT', 100))) if cache_type == 'null': self.cache = NullCache() elif cache_type == 'simple': kwargs.update(dict(threshold=self._config('threshold', 500))) self.cache = SimpleCache(**kwargs) elif cache_type == 'memcache': kwargs.update( dict( servers=self._config('MEMCACHED_SERVERS'), key_prefix=self._config('KEY_PREFIX', None), )) self.cache = MemcachedCache(**kwargs) elif cache_type == 'redis': kwargs.update( dict( host=self._config('REDIS_HOST', 'localhost'), port=self._config('REDIS_PORT', 6379), password=self._config('REDIS_PASSWORD', None), db=self._config('REDIS_DB', 0), key_prefix=self._config('KEY_PREFIX', None), )) self.cache = RedisCache(**kwargs) elif cache_type == 'filesystem': kwargs.update(dict(threshold=self._config('threshold', 500), )) self.cache = FileSystemCache(self._config('DIR'), **kwargs) else: raise RuntimeError('`%s` is not a valid cache type!' % cache_type) app.extensions[config_prefix.lower() + '_cache'] = self.cache def _config(self, key, default=_missing): key = key.upper() prior = '%s_CACHE_%s' % (self.config_prefix, key) if prior in self.config: return self.config[prior] fallback = 'CACHE_%s' % key if fallback in self.config: return self.config[fallback] if default is _missing: raise RuntimeError('%s is missing.' % prior) return default def get(self, key): """Look up key in the cache and return the value for it. :param key: the key to be looked up. :returns: The value if it exists and is readable, else ``None``. """ return self.cache.get(key) def delete(self, key): """Delete `key` from the cache. :param key: the key to delete. :returns: Whether the key existed and has been deleted. """ return self.cache.delete(key) def get_many(self, *keys): """Returns a list of values for the given keys. For each key a item in the list is created:: foo, bar = cache.get_many("foo", "bar") Has the same error handling as :meth:`get`. :param keys: The function accepts multiple keys as positional arguments. """ return [self.cache.get(k) for k in keys] def get_dict(self, *keys): """Like :meth:`get_many` but return a dict:: d = cache.get_dict("foo", "bar") foo = d["foo"] bar = d["bar"] :param keys: The function accepts multiple keys as positional arguments. """ return self.cache.get_dict(*keys) def set(self, key, value, timeout=None): """Add a new key/value to the cache (overwrites value, if key already exists in the cache). :param key: the key to set :param value: the value for the key :param timeout: the cache timeout for the key in seconds (if not specified, it uses the default timeout). A timeout of 0 idicates that the cache never expires. :returns: ``True`` if key has been updated, ``False`` for backend errors. Pickling errors, however, will raise a subclass of ``pickle.PickleError``. """ return self.cache.set(key, value, timeout) def add(self, key, value, timeout=None): """Works like :meth:`set` but does not overwrite the values of already existing keys. :param key: the key to set :param value: the value for the key :param timeout: the cache timeout for the key in seconds (if not specified, it uses the default timeout). A timeout of 0 idicates that the cache never expires. :returns: Same as :meth:`set`, but also ``False`` for already existing keys. """ return self.cache.add(key, value, timeout) def set_many(self, mapping, timeout=None): """Sets multiple keys and values from a mapping. :param mapping: a mapping with the keys/values to set. :param timeout: the cache timeout for the key in seconds (if not specified, it uses the default timeout). A timeout of 0 idicates that the cache never expires. :returns: Whether all given keys have been set. """ return self.cache.set_many(mapping, timeout) def delete_many(self, *keys): """Deletes multiple keys at once. :param keys: The function accepts multiple keys as positional arguments. :returns: Whether all given keys have been deleted. :rtype: boolean """ return self.cache.delete_many(*keys) def has(self, key): """Checks if a key exists in the cache without returning it. This is a cheap operation that bypasses loading the actual data on the backend. This method is optional and may not be implemented on all caches. :param key: the key to check """ return self.cache.has(key) def clear(self): """Clears the cache. Keep in mind that not all caches support completely clearing the cache. :returns: Whether the cache has been cleared. """ return self.cache.clear() def inc(self, key, delta=1): """Increments the value of a key by `delta`. If the key does not yet exist it is initialized with `delta`. For supporting caches this is an atomic operation. :param key: the key to increment. :param delta: the delta to add. :returns: The new value or ``None`` for backend errors. """ return self.cache.inc(key, delta=delta) def dec(self, key, delta=1): """Decrements the value of a key by `delta`. If the key does not yet exist it is initialized with `-delta`. For supporting caches this is an atomic operation. :param key: the key to increment. :param delta: the delta to subtract. :returns: The new value or `None` for backend errors. """ return self.cache.dec(key, delta=delta)
class Cache(object): """ This class is used to control the cache objects. If TESTING is True it will use NullCache. """ def __init__(self, app=None): self.cache = None if app is not None: self.init_app(app) else: self.app = None def init_app(self, app): "This is used to initialize cache with your app object" app.config.setdefault('CACHE_DEFAULT_TIMEOUT', 300) app.config.setdefault('CACHE_THRESHOLD', 500) app.config.setdefault('CACHE_KEY_PREFIX', None) app.config.setdefault('CACHE_MEMCACHED_SERVERS', None) app.config.setdefault('CACHE_DIR', None) app.config.setdefault('CACHE_TYPE', 'NullCache') self.app = app self._set_cache() def _set_cache(self): if self.app.config['TESTING']: self.cache = NullCache() else: if self.app.config['CACHE_TYPE'] == 'Null': self.cache = NullCache() elif self.app.config['CACHE_TYPE'] == 'Simple': self.cache = SimpleCache( threshold=self.app.config['CACHE_THRESHOLD'], default_timeout=self.app.config['CACHE_DEFAULT_TIMEOUT']) elif self.app.config['CACHE_TYPE'] == 'Memcached': self.cache = MemcachedCache( self.app.config['CACHE_MEMCACHED_SERVERS'], default_timeout=self.app.config['CACHE_DEFAULT_TIMEOUT'], key_prefix=self.app.config['CACHE_KEY_PREFIX']) elif self.app.config['CACHE_TYPE'] == 'GAE': self.cache = GAEMemcachedCache( default_timeout=self.app.config['CACHE_DEFAULT_TIMEOUT'], key_prefix=self.app.config['CACHE_KEY_PREFIX']) elif self.app.config['CACHE_TYPE'] == 'FileSystem': self.cache = FileSystemCache( self.app.config['CACHE_DIR'], threshold=self.app.config['CACHE_THRESHOLD'], default_timeout=self.app.config['CACHE_DEFAULT_TIMEOUT']) def get(self, *args, **kwargs): "Proxy function for internal cache object." return self.cache.get(*args, **kwargs) def set(self, *args, **kwargs): "Proxy function for internal cache object." self.cache.set(*args, **kwargs) def add(self, *args, **kwargs): "Proxy function for internal cache object." self.cache.add(*args, **kwargs) def delete(self, *args, **kwargs): "Proxy function for internal cache object." self.cache.delete(*args, **kwargs) def cached(self, timeout=None, key_prefix='view/%s', unless=None): """ Decorator. Use this to cache a function. By default the cache key is `view/request.path`. You are able to use this decorator with any function by changing the `key_prefix`. If the token `%s` is located within the `key_prefix` then it will replace that with `request.path` Example:: # An example view function @cache.cached(timeout=50) def big_foo(): return big_bar_calc() # An example misc function to cache. @cache.cached(key_prefix='MyCachedList') def get_list(): return [random.randrange(0, 1) for i in range(50000)] .. code-block:: pycon >>> my_list = get_list() :param timeout: Default None. If set to an integer, will cache for that amount of time. :param key_prefix: Default 'view/%(request.path)s'. Beginning key to . use for the cache key. :param unless: Default None. Cache will *always* execute the caching facilities unless this callable is true. This will bypass the caching entirely. """ def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): #: Bypass the cache entirely. if callable(unless) and unless() is True: return f(*args, **kwargs) if '%s' in key_prefix: cache_key = key_prefix % request.path else: cache_key = key_prefix rv = self.cache.get(cache_key) if not rv or current_app.debug: rv = f(*args, **kwargs) self.cache.set(cache_key, rv, timeout=timeout) return rv return decorated_function return decorator def memoize(self, timeout=None): """ Use this to cache the result of a function, taking its arguments into account in the cache key. Information on `Memoization <http://en.wikipedia.org/wiki/Memoization>`_. Example:: @cache.memoize(timeout=50) def big_foo(a, b): return a + b + random.randrange(0, 1000) .. code-block:: pycon >>> big_foo(5, 2) 753 >>> big_foo(5, 3) 234 >>> big_foo(5, 2) 753 :param timeout: Default None. If set to an integer, will cache for that amount of time. """ def memoize(f): @wraps(f) def decorated_function(*args, **kwargs): cache_key = (f.__name__, id(f), args, str(kwargs)) rv = self.cache.get(cache_key) if rv is None: rv = f(*args, **kwargs) self.cache.set(cache_key, rv) return rv return decorated_function return memoize