Skip to content

Instantly share code, notes, and snippets.

@tgs
Last active May 13, 2016 07:13
Show Gist options
  • Save tgs/6174451 to your computer and use it in GitHub Desktop.
Save tgs/6174451 to your computer and use it in GitHub Desktop.
A version of Jinja2's MemcachedBytecodeCache with two extra features: support for namespaces, as used in Google App Engine's memcache module; and the ability to clear the cache.
from jinja2.bccache import BytecodeCache
__author__ = "Thomas Grenfell Smith ([email protected])"
class ClearableMemcachedBytecodeCache(BytecodeCache):
"""Requires a fancy memcache client, like Google App Engine's,
that supports namespaces. Requires get, set, add, and incr.
When you call .clear(), the entries previously stored through
this object become inaccessible through it, although they
are not guaranteed to be evicted from the underlying memcached
immediately.
This is a modified version of
jinja2.bccache.MemcachedBytecodeCache.
"""
def __init__(self, client, namespace=None,
prefix='jinja2:bytecode:', timeout=None,
ignore_memcache_errors=True):
self.namespace = namespace
self.client = client
self.prefix = prefix
self.timeout = timeout
self.ignore_memcache_errors = ignore_memcache_errors
def _get_key(self, bucket):
generation_key = self.prefix + '__generation__'
generation = '1'
if not self.client.add(generation_key, generation, namespace=self.namespace):
generation = self.client.get(generation_key,
namespace=self.namespace)
return '%s:%s:%s' % (self.prefix, generation, bucket.key)
def clear(self):
generation_key = self.prefix + '__generation__'
if not self.client.incr(generation_key, 1, namespace=self.namespace):
self.client.set(generation_key, '1', namespace=self.namespace)
def load_bytecode(self, bucket):
try:
code = self.client.get(self._get_key(bucket),
namespace=self.namespace)
except Exception:
if not self.ignore_memcache_errors:
raise
code = None
if code is not None:
bucket.bytecode_from_string(code)
def dump_bytecode(self, bucket):
args = (self._get_key(bucket), bucket.bytecode_to_string())
if self.timeout is not None:
args += (self.timeout,)
try:
self.client.set(*args, namespace=self.namespace)
except Exception:
if not self.ignore_memcache_errors:
raise
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment