| Index: third_party/jinja2/bccache.py
|
| diff --git a/third_party/jinja2/bccache.py b/third_party/jinja2/bccache.py
|
| index f2f9db61b31c552e2ebac965004330ba9ff517b0..f5bd3145f6b9ffc659d3fcfd7e46b2e27822c177 100644
|
| --- a/third_party/jinja2/bccache.py
|
| +++ b/third_party/jinja2/bccache.py
|
| @@ -15,7 +15,10 @@
|
| :license: BSD.
|
| """
|
| from os import path, listdir
|
| +import os
|
| import sys
|
| +import stat
|
| +import errno
|
| import marshal
|
| import tempfile
|
| import fnmatch
|
| @@ -85,7 +88,12 @@ class Bucket(object):
|
| if self.checksum != checksum:
|
| self.reset()
|
| return
|
| - self.code = marshal_load(f)
|
| + # if marshal_load fails then we need to reload
|
| + try:
|
| + self.code = marshal_load(f)
|
| + except (EOFError, ValueError, TypeError):
|
| + self.reset()
|
| + return
|
|
|
| def write_bytecode(self, f):
|
| """Dump the bytecode into the file or file like object passed."""
|
| @@ -189,7 +197,9 @@ class FileSystemBytecodeCache(BytecodeCache):
|
| 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.
|
| + If no directory is specified a default cache directory is selected. On
|
| + Windows the user's temp directory is used, on UNIX systems a directory
|
| + is created for the user in the system temp directory.
|
|
|
| The pattern can be used to have multiple separate caches operate on the
|
| same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
|
| @@ -202,10 +212,51 @@ class FileSystemBytecodeCache(BytecodeCache):
|
|
|
| def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
|
| if directory is None:
|
| - directory = tempfile.gettempdir()
|
| + directory = self._get_default_cache_dir()
|
| self.directory = directory
|
| self.pattern = pattern
|
|
|
| + def _get_default_cache_dir(self):
|
| + def _unsafe_dir():
|
| + raise RuntimeError('Cannot determine safe temp directory. You '
|
| + 'need to explicitly provide one.')
|
| +
|
| + tmpdir = tempfile.gettempdir()
|
| +
|
| + # On windows the temporary directory is used specific unless
|
| + # explicitly forced otherwise. We can just use that.
|
| + if os.name == 'nt':
|
| + return tmpdir
|
| + if not hasattr(os, 'getuid'):
|
| + _unsafe_dir()
|
| +
|
| + dirname = '_jinja2-cache-%d' % os.getuid()
|
| + actual_dir = os.path.join(tmpdir, dirname)
|
| +
|
| + try:
|
| + os.mkdir(actual_dir, stat.S_IRWXU)
|
| + except OSError as e:
|
| + if e.errno != errno.EEXIST:
|
| + raise
|
| + try:
|
| + os.chmod(actual_dir, stat.S_IRWXU)
|
| + actual_dir_stat = os.lstat(actual_dir)
|
| + if actual_dir_stat.st_uid != os.getuid() \
|
| + or not stat.S_ISDIR(actual_dir_stat.st_mode) \
|
| + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU:
|
| + _unsafe_dir()
|
| + except OSError as e:
|
| + if e.errno != errno.EEXIST:
|
| + raise
|
| +
|
| + actual_dir_stat = os.lstat(actual_dir)
|
| + if actual_dir_stat.st_uid != os.getuid() \
|
| + or not stat.S_ISDIR(actual_dir_stat.st_mode) \
|
| + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU:
|
| + _unsafe_dir()
|
| +
|
| + return actual_dir
|
| +
|
| def _get_cache_filename(self, bucket):
|
| return path.join(self.directory, self.pattern % bucket.key)
|
|
|
|
|