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) |