Skip to content

Instantly share code, notes, and snippets.

@agriffis
Created July 12, 2013 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agriffis/5985202 to your computer and use it in GitHub Desktop.
Save agriffis/5985202 to your computer and use it in GitHub Desktop.
from django.core.cache import get_cache
class KeyedCache(object):
"""
Proxied cache object to allow objects to implement their own keying,
for example a Django model can implement per-row caching with:
def cache_key(self, key):
return '{}.{}.{}'.format(self.__class__.__name__, self.pk, key)
@property
def cache(self):
return KeyedCache(lambda k: self.cache_key(k))
then access the cache as `self.cache` instead of the usual bare `cache`.
This was originally implemented as a Lieberman-style Proxy (see
util/__init__.py) but there were too many leaks because of state stored
in the underlying object which could cause the wrong make_key() to be
called. This new implementation is much simpler and exposes a limited
API which can be augmented as needed.
"""
def __init__(self, key_func, cache=None):
self._key_func = key_func
self._cache = cache or get_cache('default')
def get(self, key):
key = self._key_func(key)
return self._cache.get(key)
def get_many(self, keys):
keys = [self._key_func(k) for k in keys]
data = self._cache.get_many(keys)
prefix = self._key_func('') # assumes that key is appended
assert all(k.startswith(prefix) for k in data)
return {k[len(prefix):]:v for k, v in data.items()}
def set(self, key, value, timeout=None):
key = self._key_func(key)
return self._cache.set(key, value, timeout=timeout)
def set_many(self, data, timeout=None):
data = {self._key_func(k):v for k, v in data.items()}
return self._cache.set_many(data, timeout=timeout)
def add(self, key, value, timeout=None):
key = self._key_func(key)
return self._cache.add(key, value, timeout=timeout)
def delete(self, key):
key = self._key_func(key)
return self._cache.delete(key)
def delete_many(self, keys):
keys = [self._key_func(k) for k in keys]
return self._cache.delete_many(keys)
def clear(self):
keys = self.keys('*')
return self.delete_many(keys)
def has_key(self, key):
key = self._key_func(key)
return self._cache.has_key(key)
def keys(self, patt):
patt = self._key_func(patt)
keys = self._cache.keys(patt)
prefix = self._key_func('') # assumes that key is appended
assert all(k.startswith(prefix) for k in keys)
return [k[len(prefix):] for k in keys]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment