diff options
| author | floatdrop <[email protected]> | 2022-02-10 16:47:15 +0300 | 
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:47:15 +0300 | 
| commit | e63b84f1d39557d9e46ac380b1f388271894293c (patch) | |
| tree | 338cdaff3fb027e030b847db66df06019a0e3149 /contrib/python/Jinja2/py3/jinja2/bccache.py | |
| parent | f60febb7ea449535e7b073c386c7ff0539637fc0 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/Jinja2/py3/jinja2/bccache.py')
| -rw-r--r-- | contrib/python/Jinja2/py3/jinja2/bccache.py | 480 | 
1 files changed, 240 insertions, 240 deletions
diff --git a/contrib/python/Jinja2/py3/jinja2/bccache.py b/contrib/python/Jinja2/py3/jinja2/bccache.py index 3bb61b7c34c..f54cc4d3b63 100644 --- a/contrib/python/Jinja2/py3/jinja2/bccache.py +++ b/contrib/python/Jinja2/py3/jinja2/bccache.py @@ -1,27 +1,27 @@  """The optional bytecode cache system. This is useful if you have very  complex template situations and the compilation of all those templates  slows down your application too much. - +   Situations where this is useful are often forking web applications that  are initialized on the first request. -""" +"""   import errno  import fnmatch  import marshal -import os +import os   import pickle  import stat -import sys -import tempfile +import sys  +import tempfile   import typing as t -from hashlib import sha1 +from hashlib import sha1   from io import BytesIO  from types import CodeType - +   if t.TYPE_CHECKING:      import typing_extensions as te      from .environment import Environment - +       class _MemcachedClient(te.Protocol):          def get(self, key: str) -> bytes:              ... @@ -39,129 +39,129 @@ bc_magic = (      + pickle.dumps(bc_version, 2)      + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2)  ) - - +  +   class Bucket: -    """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. -    """ - +    """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: "Environment", key: str, checksum: str) -> None: -        self.environment = environment -        self.key = key -        self.checksum = checksum -        self.reset() - +        self.environment = environment  +        self.key = key  +        self.checksum = checksum  +        self.reset()  +       def reset(self) -> None: -        """Resets the bucket (unloads the bytecode).""" +        """Resets the bucket (unloads the bytecode)."""           self.code: t.Optional[CodeType] = None - +       def load_bytecode(self, f: t.BinaryIO) -> None: -        """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 -        # if marshal_load fails then we need to reload -        try: +        """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  +        # if marshal_load fails then we need to reload  +        try:               self.code = marshal.load(f) -        except (EOFError, ValueError, TypeError): -            self.reset() -            return - +        except (EOFError, ValueError, TypeError):  +            self.reset()  +            return  +       def write_bytecode(self, f: t.BinaryIO) -> None: -        """Dump the bytecode into the file or file like object passed.""" -        if self.code is None: +        """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) +        f.write(bc_magic)  +        pickle.dump(self.checksum, f, 2)           marshal.dump(self.code, f) - +       def bytecode_from_string(self, string: bytes) -> None:          """Load bytecode from bytes.""" -        self.load_bytecode(BytesIO(string)) - +        self.load_bytecode(BytesIO(string))  +       def bytecode_to_string(self) -> bytes:          """Return the bytecode as bytes.""" -        out = BytesIO() -        self.write_bytecode(out) -        return out.getvalue() - - +        out = BytesIO()  +        self.write_bytecode(out)  +        return out.getvalue()  +  +   class BytecodeCache: -    """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 +    """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       Jinja. -    """ - +    """  +       def load_bytecode(self, bucket: Bucket) -> None: -        """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() - +        """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: Bucket) -> None: -        """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() - +        """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) -> None:          """Clears the cache.  This method is not used by Jinja but should be -        implemented to allow applications to clear the bytecode cache used -        by a particular environment. -        """ - +        implemented to allow applications to clear the bytecode cache used  +        by a particular environment.  +        """  +       def get_cache_key(          self, name: str, filename: t.Optional[t.Union[str]] = None      ) -> str: -        """Returns the unique hash key for this template name.""" +        """Returns the unique hash key for this template name."""           hash = sha1(name.encode("utf-8")) -        if filename is not None: +        if filename is not None:               hash.update(f"|{filename}".encode()) -        return hash.hexdigest() - +        return hash.hexdigest()  +       def get_source_checksum(self, source: str) -> str: -        """Returns a checksum for the source.""" +        """Returns a checksum for the source."""           return sha1(source.encode("utf-8")).hexdigest() - +       def get_bucket(          self,          environment: "Environment", @@ -169,166 +169,166 @@ class BytecodeCache:          filename: t.Optional[str],          source: str,      ) -> Bucket: -        """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 - +        """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: Bucket) -> None: -        """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 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`` -    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. -    """ - +        """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 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``  +    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: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache"      ) -> None: -        if directory is None: -            directory = self._get_default_cache_dir() -        self.directory = directory -        self.pattern = pattern - +        if directory is None:  +            directory = self._get_default_cache_dir()  +        self.directory = directory  +        self.pattern = pattern  +       def _get_default_cache_dir(self) -> str:          def _unsafe_dir() -> "te.NoReturn":              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. +  +        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 +            return tmpdir           if not hasattr(os, "getuid"): -            _unsafe_dir() - +            _unsafe_dir()  +           dirname = f"_jinja2-cache-{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) +        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) +                _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 - +            _unsafe_dir()  +  +        return actual_dir  +       def _get_cache_filename(self, bucket: Bucket) -> str:          return os.path.join(self.directory, self.pattern % (bucket.key,)) - +       def load_bytecode(self, bucket: Bucket) -> None:          filename = self._get_cache_filename(bucket)          if os.path.exists(filename):              with open(filename, "rb") as f: -                bucket.load_bytecode(f) - +                bucket.load_bytecode(f)  +       def dump_bytecode(self, bucket: Bucket) -> None:          with open(self._get_cache_filename(bucket), "wb") as f: -            bucket.write_bytecode(f) - +            bucket.write_bytecode(f)  +       def clear(self) -> None: -        # 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 +        # 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(os.listdir(self.directory), self.pattern % ("*",)) -        for filename in files: -            try: +        for filename in files:  +            try:                   remove(os.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: - +            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:  +       -   `cachelib <https://github.com/pallets/cachelib>`_      -   `python-memcached <https://pypi.org/project/python-memcached/>`_ - -    (Unfortunately the django cache interface is not compatible because it +  +    (Unfortunately the django cache interface is not compatible because it       does not support storing binary data, only text. 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. -    """ - +    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: "_MemcachedClient", @@ -336,29 +336,29 @@ class MemcachedBytecodeCache(BytecodeCache):          timeout: t.Optional[int] = None,          ignore_memcache_errors: bool = True,      ): -        self.client = client -        self.prefix = prefix -        self.timeout = timeout -        self.ignore_memcache_errors = ignore_memcache_errors - +        self.client = client  +        self.prefix = prefix  +        self.timeout = timeout  +        self.ignore_memcache_errors = ignore_memcache_errors  +       def load_bytecode(self, bucket: Bucket) -> None: -        try: -            code = self.client.get(self.prefix + bucket.key) -        except Exception: -            if not self.ignore_memcache_errors: -                raise +        try:  +            code = self.client.get(self.prefix + bucket.key)  +        except Exception:  +            if not self.ignore_memcache_errors:  +                raise           else: -            bucket.bytecode_from_string(code) - +            bucket.bytecode_from_string(code)  +       def dump_bytecode(self, bucket: Bucket) -> None:          key = self.prefix + bucket.key          value = bucket.bytecode_to_string() -        try: +        try:               if self.timeout is not None:                  self.client.set(key, value, self.timeout)              else:                  self.client.set(key, value) -        except Exception: -            if not self.ignore_memcache_errors: -                raise +        except Exception:  +            if not self.ignore_memcache_errors:  +                raise   | 
