python-diskcache
python-diskcache copied to clipboard
Add Support for Flask Caching
Add support for Flask Caching. Details at https://flask-caching.readthedocs.io/en/latest/
Progress started in #154
Thank you for a great library !
I have been using Diskcache with Flask for some time, but not with all the possible Flask-Caching features.
I have just subclassed the Cache class:
import functools as ft
from diskcache.core import args_to_key, full_name
from diskcache import Cache
from pathlib import Path
from flask import Flask
class DiskCache(Cache):
def __init__(self, *args, **kwargs):
Cache.__init__(self, *args, **kwargs)
def init_app(self, app: Flask) -> None:
directory = app.config.get('CACHE_DIR')
if not directory:
raise ValueError(f"Missing CACHE_DIR setting")
else:
cpath = Path( directory )
if not cpath.is_dir():
raise ValueError(f"Invalid CACHE_DIR")
timeout = app.config.get('CACHE_DEFAULT_TIMEOUT', 3600)
self.__init__(directory, timeout=timeout, statistics=True, tag_index=True)
def set(self, key, value, expire=None, read=False, tag=None, retry=False, timeout=None):
if not expire and timeout:
expire = timeout
super().set(key, value, expire=expire, read=read, tag=tag, retry=retry)
def memoize(self, name=None, typed=False, expire=None, tag=None, ignore=(), timeout=None):
if not expire and timeout:
expire = timeout
def decorator(func):
base = (full_name(func),) if name is None else (name,)
@ft.wraps(func)
def wrapper(*args, **kwargs):
key = wrapper.__cache_key__(*args, **kwargs)
result = self.get(key, default='ENOVAL', retry=True)
if result == 'ENOVAL':
result = func(*args, **kwargs)
if expire is None or expire > 0:
self.set(key, result, expire, tag=tag, retry=True)
return result
def __cache_key__(*args, **kwargs):
return args_to_key(base, args, kwargs, typed, ignore)
wrapper.__cache_key__ = __cache_key__
return wrapper
return decorator
What I miss in your Cache class is support for the Flask app factory pattern - cache.init_app(app) - which can be hacked ie with adding the init_later param:
cache = DiskCache(init_later=True)
cache.init_app(app)
class Cache:
"""Disk and file backed cache."""
def __init__(self, directory=None, timeout=60, disk=Disk, **settings):
"""Initialize cache instance...
"""
try:
assert issubclass(disk, Disk)
except (TypeError, AssertionError):
raise ValueError('disk must subclass diskcache.Disk') from None
if settings.get('init_later'):
return
...