| Index: mojo/public/third_party/jinja2/bccache.py
|
| diff --git a/mojo/public/third_party/jinja2/bccache.py b/mojo/public/third_party/jinja2/bccache.py
|
| deleted file mode 100644
|
| index f2f9db61b31c552e2ebac965004330ba9ff517b0..0000000000000000000000000000000000000000
|
| --- a/mojo/public/third_party/jinja2/bccache.py
|
| +++ /dev/null
|
| @@ -1,311 +0,0 @@
|
| -# -*- coding: utf-8 -*-
|
| -"""
|
| - jinja2.bccache
|
| - ~~~~~~~~~~~~~~
|
| -
|
| - This module implements the bytecode cache system Jinja is optionally
|
| - using. This is useful if you have very complex template situations and
|
| - the compiliation of all those templates slow down your application too
|
| - much.
|
| -
|
| - Situations where this is useful are often forking web applications that
|
| - are initialized on the first request.
|
| -
|
| - :copyright: (c) 2010 by the Jinja Team.
|
| - :license: BSD.
|
| -"""
|
| -from os import path, listdir
|
| -import sys
|
| -import marshal
|
| -import tempfile
|
| -import fnmatch
|
| -from hashlib import sha1
|
| -from jinja2.utils import open_if_exists
|
| -from jinja2._compat import BytesIO, pickle, PY2, text_type
|
| -
|
| -
|
| -# marshal works better on 3.x, one hack less required
|
| -if not PY2:
|
| - marshal_dump = marshal.dump
|
| - marshal_load = marshal.load
|
| -else:
|
| -
|
| - def marshal_dump(code, f):
|
| - if isinstance(f, file):
|
| - marshal.dump(code, f)
|
| - else:
|
| - f.write(marshal.dumps(code))
|
| -
|
| - def marshal_load(f):
|
| - if isinstance(f, file):
|
| - return marshal.load(f)
|
| - return marshal.loads(f.read())
|
| -
|
| -
|
| -bc_version = 2
|
| -
|
| -# magic version used to only change with new jinja versions. With 2.6
|
| -# we change this to also take Python version changes into account. The
|
| -# reason for this is that Python tends to segfault if fed earlier bytecode
|
| -# versions because someone thought it would be a good idea to reuse opcodes
|
| -# or make Python incompatible with earlier versions.
|
| -bc_magic = 'j2'.encode('ascii') + \
|
| - pickle.dumps(bc_version, 2) + \
|
| - pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1])
|
| -
|
| -
|
| -class Bucket(object):
|
| - """Buckets are used to store the bytecode for one template. It's created
|
| - and initialized by the bytecode cache and passed to the loading functions.
|
| -
|
| - The buckets get an internal checksum from the cache assigned and use this
|
| - to automatically reject outdated cache material. Individual bytecode
|
| - cache subclasses don't have to care about cache invalidation.
|
| - """
|
| -
|
| - def __init__(self, environment, key, checksum):
|
| - self.environment = environment
|
| - self.key = key
|
| - self.checksum = checksum
|
| - self.reset()
|
| -
|
| - def reset(self):
|
| - """Resets the bucket (unloads the bytecode)."""
|
| - self.code = None
|
| -
|
| - def load_bytecode(self, f):
|
| - """Loads bytecode from a file or file like object."""
|
| - # make sure the magic header is correct
|
| - magic = f.read(len(bc_magic))
|
| - if magic != bc_magic:
|
| - self.reset()
|
| - return
|
| - # the source code of the file changed, we need to reload
|
| - checksum = pickle.load(f)
|
| - if self.checksum != checksum:
|
| - self.reset()
|
| - return
|
| - self.code = marshal_load(f)
|
| -
|
| - def write_bytecode(self, f):
|
| - """Dump the bytecode into the file or file like object passed."""
|
| - if self.code is None:
|
| - raise TypeError('can\'t write empty bucket')
|
| - f.write(bc_magic)
|
| - pickle.dump(self.checksum, f, 2)
|
| - marshal_dump(self.code, f)
|
| -
|
| - def bytecode_from_string(self, string):
|
| - """Load bytecode from a string."""
|
| - self.load_bytecode(BytesIO(string))
|
| -
|
| - def bytecode_to_string(self):
|
| - """Return the bytecode as string."""
|
| - out = BytesIO()
|
| - self.write_bytecode(out)
|
| - return out.getvalue()
|
| -
|
| -
|
| -class BytecodeCache(object):
|
| - """To implement your own bytecode cache you have to subclass this class
|
| - and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
|
| - these methods are passed a :class:`~jinja2.bccache.Bucket`.
|
| -
|
| - A very basic bytecode cache that saves the bytecode on the file system::
|
| -
|
| - from os import path
|
| -
|
| - class MyCache(BytecodeCache):
|
| -
|
| - def __init__(self, directory):
|
| - self.directory = directory
|
| -
|
| - def load_bytecode(self, bucket):
|
| - filename = path.join(self.directory, bucket.key)
|
| - if path.exists(filename):
|
| - with open(filename, 'rb') as f:
|
| - bucket.load_bytecode(f)
|
| -
|
| - def dump_bytecode(self, bucket):
|
| - filename = path.join(self.directory, bucket.key)
|
| - with open(filename, 'wb') as f:
|
| - bucket.write_bytecode(f)
|
| -
|
| - A more advanced version of a filesystem based bytecode cache is part of
|
| - Jinja2.
|
| - """
|
| -
|
| - def load_bytecode(self, bucket):
|
| - """Subclasses have to override this method to load bytecode into a
|
| - bucket. If they are not able to find code in the cache for the
|
| - bucket, it must not do anything.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| - def dump_bytecode(self, bucket):
|
| - """Subclasses have to override this method to write the bytecode
|
| - from a bucket back to the cache. If it unable to do so it must not
|
| - fail silently but raise an exception.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| - def clear(self):
|
| - """Clears the cache. This method is not used by Jinja2 but should be
|
| - implemented to allow applications to clear the bytecode cache used
|
| - by a particular environment.
|
| - """
|
| -
|
| - def get_cache_key(self, name, filename=None):
|
| - """Returns the unique hash key for this template name."""
|
| - hash = sha1(name.encode('utf-8'))
|
| - if filename is not None:
|
| - filename = '|' + filename
|
| - if isinstance(filename, text_type):
|
| - filename = filename.encode('utf-8')
|
| - hash.update(filename)
|
| - return hash.hexdigest()
|
| -
|
| - def get_source_checksum(self, source):
|
| - """Returns a checksum for the source."""
|
| - return sha1(source.encode('utf-8')).hexdigest()
|
| -
|
| - def get_bucket(self, environment, name, filename, source):
|
| - """Return a cache bucket for the given template. All arguments are
|
| - mandatory but filename may be `None`.
|
| - """
|
| - key = self.get_cache_key(name, filename)
|
| - checksum = self.get_source_checksum(source)
|
| - bucket = Bucket(environment, key, checksum)
|
| - self.load_bytecode(bucket)
|
| - return bucket
|
| -
|
| - def set_bucket(self, bucket):
|
| - """Put the bucket into the cache."""
|
| - self.dump_bytecode(bucket)
|
| -
|
| -
|
| -class FileSystemBytecodeCache(BytecodeCache):
|
| - """A bytecode cache that stores bytecode on the filesystem. It accepts
|
| - two arguments: The directory where the cache items are stored and a
|
| - pattern string that is used to build the filename.
|
| -
|
| - If no directory is specified the system temporary items folder is used.
|
| -
|
| - The pattern can be used to have multiple separate caches operate on the
|
| - same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
|
| - is replaced with the cache key.
|
| -
|
| - >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
|
| -
|
| - This bytecode cache supports clearing of the cache using the clear method.
|
| - """
|
| -
|
| - def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
|
| - if directory is None:
|
| - directory = tempfile.gettempdir()
|
| - self.directory = directory
|
| - self.pattern = pattern
|
| -
|
| - def _get_cache_filename(self, bucket):
|
| - return path.join(self.directory, self.pattern % bucket.key)
|
| -
|
| - def load_bytecode(self, bucket):
|
| - f = open_if_exists(self._get_cache_filename(bucket), 'rb')
|
| - if f is not None:
|
| - try:
|
| - bucket.load_bytecode(f)
|
| - finally:
|
| - f.close()
|
| -
|
| - def dump_bytecode(self, bucket):
|
| - f = open(self._get_cache_filename(bucket), 'wb')
|
| - try:
|
| - bucket.write_bytecode(f)
|
| - finally:
|
| - f.close()
|
| -
|
| - def clear(self):
|
| - # imported lazily here because google app-engine doesn't support
|
| - # write access on the file system and the function does not exist
|
| - # normally.
|
| - from os import remove
|
| - files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
|
| - for filename in files:
|
| - try:
|
| - remove(path.join(self.directory, filename))
|
| - except OSError:
|
| - pass
|
| -
|
| -
|
| -class MemcachedBytecodeCache(BytecodeCache):
|
| - """This class implements a bytecode cache that uses a memcache cache for
|
| - storing the information. It does not enforce a specific memcache library
|
| - (tummy's memcache or cmemcache) but will accept any class that provides
|
| - the minimal interface required.
|
| -
|
| - Libraries compatible with this class:
|
| -
|
| - - `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
|
| - - `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
|
| - - `cmemcache <http://gijsbert.org/cmemcache/>`_
|
| -
|
| - (Unfortunately the django cache interface is not compatible because it
|
| - does not support storing binary data, only unicode. You can however pass
|
| - the underlying cache client to the bytecode cache which is available
|
| - as `django.core.cache.cache._client`.)
|
| -
|
| - The minimal interface for the client passed to the constructor is this:
|
| -
|
| - .. class:: MinimalClientInterface
|
| -
|
| - .. method:: set(key, value[, timeout])
|
| -
|
| - Stores the bytecode in the cache. `value` is a string and
|
| - `timeout` the timeout of the key. If timeout is not provided
|
| - a default timeout or no timeout should be assumed, if it's
|
| - provided it's an integer with the number of seconds the cache
|
| - item should exist.
|
| -
|
| - .. method:: get(key)
|
| -
|
| - Returns the value for the cache key. If the item does not
|
| - exist in the cache the return value must be `None`.
|
| -
|
| - The other arguments to the constructor are the prefix for all keys that
|
| - is added before the actual cache key and the timeout for the bytecode in
|
| - the cache system. We recommend a high (or no) timeout.
|
| -
|
| - This bytecode cache does not support clearing of used items in the cache.
|
| - The clear method is a no-operation function.
|
| -
|
| - .. versionadded:: 2.7
|
| - Added support for ignoring memcache errors through the
|
| - `ignore_memcache_errors` parameter.
|
| - """
|
| -
|
| - def __init__(self, client, prefix='jinja2/bytecode/', timeout=None,
|
| - ignore_memcache_errors=True):
|
| - self.client = client
|
| - self.prefix = prefix
|
| - self.timeout = timeout
|
| - self.ignore_memcache_errors = ignore_memcache_errors
|
| -
|
| - def load_bytecode(self, bucket):
|
| - try:
|
| - code = self.client.get(self.prefix + bucket.key)
|
| - 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.prefix + bucket.key, bucket.bytecode_to_string())
|
| - if self.timeout is not None:
|
| - args += (self.timeout,)
|
| - try:
|
| - self.client.set(*args)
|
| - except Exception:
|
| - if not self.ignore_memcache_errors:
|
| - raise
|
|
|