diff env/lib/python3.7/site-packages/jinja2/environment.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/jinja2/environment.py	Thu May 14 16:47:39 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1362 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Classes for managing templates and their runtime and compile time
-options.
-"""
-import os
-import sys
-import weakref
-from functools import partial
-from functools import reduce
-
-from markupsafe import Markup
-
-from . import nodes
-from ._compat import encode_filename
-from ._compat import implements_iterator
-from ._compat import implements_to_string
-from ._compat import iteritems
-from ._compat import PY2
-from ._compat import PYPY
-from ._compat import reraise
-from ._compat import string_types
-from ._compat import text_type
-from .compiler import CodeGenerator
-from .compiler import generate
-from .defaults import BLOCK_END_STRING
-from .defaults import BLOCK_START_STRING
-from .defaults import COMMENT_END_STRING
-from .defaults import COMMENT_START_STRING
-from .defaults import DEFAULT_FILTERS
-from .defaults import DEFAULT_NAMESPACE
-from .defaults import DEFAULT_POLICIES
-from .defaults import DEFAULT_TESTS
-from .defaults import KEEP_TRAILING_NEWLINE
-from .defaults import LINE_COMMENT_PREFIX
-from .defaults import LINE_STATEMENT_PREFIX
-from .defaults import LSTRIP_BLOCKS
-from .defaults import NEWLINE_SEQUENCE
-from .defaults import TRIM_BLOCKS
-from .defaults import VARIABLE_END_STRING
-from .defaults import VARIABLE_START_STRING
-from .exceptions import TemplateNotFound
-from .exceptions import TemplateRuntimeError
-from .exceptions import TemplatesNotFound
-from .exceptions import TemplateSyntaxError
-from .exceptions import UndefinedError
-from .lexer import get_lexer
-from .lexer import TokenStream
-from .nodes import EvalContext
-from .parser import Parser
-from .runtime import Context
-from .runtime import new_context
-from .runtime import Undefined
-from .utils import concat
-from .utils import consume
-from .utils import have_async_gen
-from .utils import import_string
-from .utils import internalcode
-from .utils import LRUCache
-from .utils import missing
-
-# for direct template usage we have up to ten living environments
-_spontaneous_environments = LRUCache(10)
-
-
-def get_spontaneous_environment(cls, *args):
-    """Return a new spontaneous environment. A spontaneous environment
-    is used for templates created directly rather than through an
-    existing environment.
-
-    :param cls: Environment class to create.
-    :param args: Positional arguments passed to environment.
-    """
-    key = (cls, args)
-
-    try:
-        return _spontaneous_environments[key]
-    except KeyError:
-        _spontaneous_environments[key] = env = cls(*args)
-        env.shared = True
-        return env
-
-
-def create_cache(size):
-    """Return the cache class for the given size."""
-    if size == 0:
-        return None
-    if size < 0:
-        return {}
-    return LRUCache(size)
-
-
-def copy_cache(cache):
-    """Create an empty copy of the given cache."""
-    if cache is None:
-        return None
-    elif type(cache) is dict:
-        return {}
-    return LRUCache(cache.capacity)
-
-
-def load_extensions(environment, extensions):
-    """Load the extensions from the list and bind it to the environment.
-    Returns a dict of instantiated environments.
-    """
-    result = {}
-    for extension in extensions:
-        if isinstance(extension, string_types):
-            extension = import_string(extension)
-        result[extension.identifier] = extension(environment)
-    return result
-
-
-def fail_for_missing_callable(string, name):
-    msg = string % name
-    if isinstance(name, Undefined):
-        try:
-            name._fail_with_undefined_error()
-        except Exception as e:
-            msg = "%s (%s; did you forget to quote the callable name?)" % (msg, e)
-    raise TemplateRuntimeError(msg)
-
-
-def _environment_sanity_check(environment):
-    """Perform a sanity check on the environment."""
-    assert issubclass(
-        environment.undefined, Undefined
-    ), "undefined must be a subclass of undefined because filters depend on it."
-    assert (
-        environment.block_start_string
-        != environment.variable_start_string
-        != environment.comment_start_string
-    ), "block, variable and comment start strings must be different"
-    assert environment.newline_sequence in (
-        "\r",
-        "\r\n",
-        "\n",
-    ), "newline_sequence set to unknown line ending string."
-    return environment
-
-
-class Environment(object):
-    r"""The core component of Jinja is the `Environment`.  It contains
-    important shared variables like configuration, filters, tests,
-    globals and others.  Instances of this class may be modified if
-    they are not shared and if no template was loaded so far.
-    Modifications on environments after the first template was loaded
-    will lead to surprising effects and undefined behavior.
-
-    Here are the possible initialization parameters:
-
-        `block_start_string`
-            The string marking the beginning of a block.  Defaults to ``'{%'``.
-
-        `block_end_string`
-            The string marking the end of a block.  Defaults to ``'%}'``.
-
-        `variable_start_string`
-            The string marking the beginning of a print statement.
-            Defaults to ``'{{'``.
-
-        `variable_end_string`
-            The string marking the end of a print statement.  Defaults to
-            ``'}}'``.
-
-        `comment_start_string`
-            The string marking the beginning of a comment.  Defaults to ``'{#'``.
-
-        `comment_end_string`
-            The string marking the end of a comment.  Defaults to ``'#}'``.
-
-        `line_statement_prefix`
-            If given and a string, this will be used as prefix for line based
-            statements.  See also :ref:`line-statements`.
-
-        `line_comment_prefix`
-            If given and a string, this will be used as prefix for line based
-            comments.  See also :ref:`line-statements`.
-
-            .. versionadded:: 2.2
-
-        `trim_blocks`
-            If this is set to ``True`` the first newline after a block is
-            removed (block, not variable tag!).  Defaults to `False`.
-
-        `lstrip_blocks`
-            If this is set to ``True`` leading spaces and tabs are stripped
-            from the start of a line to a block.  Defaults to `False`.
-
-        `newline_sequence`
-            The sequence that starts a newline.  Must be one of ``'\r'``,
-            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
-            useful default for Linux and OS X systems as well as web
-            applications.
-
-        `keep_trailing_newline`
-            Preserve the trailing newline when rendering templates.
-            The default is ``False``, which causes a single newline,
-            if present, to be stripped from the end of the template.
-
-            .. versionadded:: 2.7
-
-        `extensions`
-            List of Jinja extensions to use.  This can either be import paths
-            as strings or extension classes.  For more information have a
-            look at :ref:`the extensions documentation <jinja-extensions>`.
-
-        `optimized`
-            should the optimizer be enabled?  Default is ``True``.
-
-        `undefined`
-            :class:`Undefined` or a subclass of it that is used to represent
-            undefined values in the template.
-
-        `finalize`
-            A callable that can be used to process the result of a variable
-            expression before it is output.  For example one can convert
-            ``None`` implicitly into an empty string here.
-
-        `autoescape`
-            If set to ``True`` the XML/HTML autoescaping feature is enabled by
-            default.  For more details about autoescaping see
-            :class:`~markupsafe.Markup`.  As of Jinja 2.4 this can also
-            be a callable that is passed the template name and has to
-            return ``True`` or ``False`` depending on autoescape should be
-            enabled by default.
-
-            .. versionchanged:: 2.4
-               `autoescape` can now be a function
-
-        `loader`
-            The template loader for this environment.
-
-        `cache_size`
-            The size of the cache.  Per default this is ``400`` which means
-            that if more than 400 templates are loaded the loader will clean
-            out the least recently used template.  If the cache size is set to
-            ``0`` templates are recompiled all the time, if the cache size is
-            ``-1`` the cache will not be cleaned.
-
-            .. versionchanged:: 2.8
-               The cache size was increased to 400 from a low 50.
-
-        `auto_reload`
-            Some loaders load templates from locations where the template
-            sources may change (ie: file system or database).  If
-            ``auto_reload`` is set to ``True`` (default) every time a template is
-            requested the loader checks if the source changed and if yes, it
-            will reload the template.  For higher performance it's possible to
-            disable that.
-
-        `bytecode_cache`
-            If set to a bytecode cache object, this object will provide a
-            cache for the internal Jinja bytecode so that templates don't
-            have to be parsed if they were not changed.
-
-            See :ref:`bytecode-cache` for more information.
-
-        `enable_async`
-            If set to true this enables async template execution which allows
-            you to take advantage of newer Python features.  This requires
-            Python 3.6 or later.
-    """
-
-    #: if this environment is sandboxed.  Modifying this variable won't make
-    #: the environment sandboxed though.  For a real sandboxed environment
-    #: have a look at jinja2.sandbox.  This flag alone controls the code
-    #: generation by the compiler.
-    sandboxed = False
-
-    #: True if the environment is just an overlay
-    overlayed = False
-
-    #: the environment this environment is linked to if it is an overlay
-    linked_to = None
-
-    #: shared environments have this set to `True`.  A shared environment
-    #: must not be modified
-    shared = False
-
-    #: the class that is used for code generation.  See
-    #: :class:`~jinja2.compiler.CodeGenerator` for more information.
-    code_generator_class = CodeGenerator
-
-    #: the context class thatis used for templates.  See
-    #: :class:`~jinja2.runtime.Context` for more information.
-    context_class = Context
-
-    def __init__(
-        self,
-        block_start_string=BLOCK_START_STRING,
-        block_end_string=BLOCK_END_STRING,
-        variable_start_string=VARIABLE_START_STRING,
-        variable_end_string=VARIABLE_END_STRING,
-        comment_start_string=COMMENT_START_STRING,
-        comment_end_string=COMMENT_END_STRING,
-        line_statement_prefix=LINE_STATEMENT_PREFIX,
-        line_comment_prefix=LINE_COMMENT_PREFIX,
-        trim_blocks=TRIM_BLOCKS,
-        lstrip_blocks=LSTRIP_BLOCKS,
-        newline_sequence=NEWLINE_SEQUENCE,
-        keep_trailing_newline=KEEP_TRAILING_NEWLINE,
-        extensions=(),
-        optimized=True,
-        undefined=Undefined,
-        finalize=None,
-        autoescape=False,
-        loader=None,
-        cache_size=400,
-        auto_reload=True,
-        bytecode_cache=None,
-        enable_async=False,
-    ):
-        # !!Important notice!!
-        #   The constructor accepts quite a few arguments that should be
-        #   passed by keyword rather than position.  However it's important to
-        #   not change the order of arguments because it's used at least
-        #   internally in those cases:
-        #       -   spontaneous environments (i18n extension and Template)
-        #       -   unittests
-        #   If parameter changes are required only add parameters at the end
-        #   and don't change the arguments (or the defaults!) of the arguments
-        #   existing already.
-
-        # lexer / parser information
-        self.block_start_string = block_start_string
-        self.block_end_string = block_end_string
-        self.variable_start_string = variable_start_string
-        self.variable_end_string = variable_end_string
-        self.comment_start_string = comment_start_string
-        self.comment_end_string = comment_end_string
-        self.line_statement_prefix = line_statement_prefix
-        self.line_comment_prefix = line_comment_prefix
-        self.trim_blocks = trim_blocks
-        self.lstrip_blocks = lstrip_blocks
-        self.newline_sequence = newline_sequence
-        self.keep_trailing_newline = keep_trailing_newline
-
-        # runtime information
-        self.undefined = undefined
-        self.optimized = optimized
-        self.finalize = finalize
-        self.autoescape = autoescape
-
-        # defaults
-        self.filters = DEFAULT_FILTERS.copy()
-        self.tests = DEFAULT_TESTS.copy()
-        self.globals = DEFAULT_NAMESPACE.copy()
-
-        # set the loader provided
-        self.loader = loader
-        self.cache = create_cache(cache_size)
-        self.bytecode_cache = bytecode_cache
-        self.auto_reload = auto_reload
-
-        # configurable policies
-        self.policies = DEFAULT_POLICIES.copy()
-
-        # load extensions
-        self.extensions = load_extensions(self, extensions)
-
-        self.enable_async = enable_async
-        self.is_async = self.enable_async and have_async_gen
-        if self.is_async:
-            # runs patch_all() to enable async support
-            from . import asyncsupport  # noqa: F401
-
-        _environment_sanity_check(self)
-
-    def add_extension(self, extension):
-        """Adds an extension after the environment was created.
-
-        .. versionadded:: 2.5
-        """
-        self.extensions.update(load_extensions(self, [extension]))
-
-    def extend(self, **attributes):
-        """Add the items to the instance of the environment if they do not exist
-        yet.  This is used by :ref:`extensions <writing-extensions>` to register
-        callbacks and configuration values without breaking inheritance.
-        """
-        for key, value in iteritems(attributes):
-            if not hasattr(self, key):
-                setattr(self, key, value)
-
-    def overlay(
-        self,
-        block_start_string=missing,
-        block_end_string=missing,
-        variable_start_string=missing,
-        variable_end_string=missing,
-        comment_start_string=missing,
-        comment_end_string=missing,
-        line_statement_prefix=missing,
-        line_comment_prefix=missing,
-        trim_blocks=missing,
-        lstrip_blocks=missing,
-        extensions=missing,
-        optimized=missing,
-        undefined=missing,
-        finalize=missing,
-        autoescape=missing,
-        loader=missing,
-        cache_size=missing,
-        auto_reload=missing,
-        bytecode_cache=missing,
-    ):
-        """Create a new overlay environment that shares all the data with the
-        current environment except for cache and the overridden attributes.
-        Extensions cannot be removed for an overlayed environment.  An overlayed
-        environment automatically gets all the extensions of the environment it
-        is linked to plus optional extra extensions.
-
-        Creating overlays should happen after the initial environment was set
-        up completely.  Not all attributes are truly linked, some are just
-        copied over so modifications on the original environment may not shine
-        through.
-        """
-        args = dict(locals())
-        del args["self"], args["cache_size"], args["extensions"]
-
-        rv = object.__new__(self.__class__)
-        rv.__dict__.update(self.__dict__)
-        rv.overlayed = True
-        rv.linked_to = self
-
-        for key, value in iteritems(args):
-            if value is not missing:
-                setattr(rv, key, value)
-
-        if cache_size is not missing:
-            rv.cache = create_cache(cache_size)
-        else:
-            rv.cache = copy_cache(self.cache)
-
-        rv.extensions = {}
-        for key, value in iteritems(self.extensions):
-            rv.extensions[key] = value.bind(rv)
-        if extensions is not missing:
-            rv.extensions.update(load_extensions(rv, extensions))
-
-        return _environment_sanity_check(rv)
-
-    lexer = property(get_lexer, doc="The lexer for this environment.")
-
-    def iter_extensions(self):
-        """Iterates over the extensions by priority."""
-        return iter(sorted(self.extensions.values(), key=lambda x: x.priority))
-
-    def getitem(self, obj, argument):
-        """Get an item or attribute of an object but prefer the item."""
-        try:
-            return obj[argument]
-        except (AttributeError, TypeError, LookupError):
-            if isinstance(argument, string_types):
-                try:
-                    attr = str(argument)
-                except Exception:
-                    pass
-                else:
-                    try:
-                        return getattr(obj, attr)
-                    except AttributeError:
-                        pass
-            return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Get an item or attribute of an object but prefer the attribute.
-        Unlike :meth:`getitem` the attribute *must* be a bytestring.
-        """
-        try:
-            return getattr(obj, attribute)
-        except AttributeError:
-            pass
-        try:
-            return obj[attribute]
-        except (TypeError, LookupError, AttributeError):
-            return self.undefined(obj=obj, name=attribute)
-
-    def call_filter(
-        self, name, value, args=None, kwargs=None, context=None, eval_ctx=None
-    ):
-        """Invokes a filter on a value the same way the compiler does it.
-
-        Note that on Python 3 this might return a coroutine in case the
-        filter is running from an environment in async mode and the filter
-        supports async execution.  It's your responsibility to await this
-        if needed.
-
-        .. versionadded:: 2.7
-        """
-        func = self.filters.get(name)
-        if func is None:
-            fail_for_missing_callable("no filter named %r", name)
-        args = [value] + list(args or ())
-        if getattr(func, "contextfilter", False) is True:
-            if context is None:
-                raise TemplateRuntimeError(
-                    "Attempted to invoke context filter without context"
-                )
-            args.insert(0, context)
-        elif getattr(func, "evalcontextfilter", False) is True:
-            if eval_ctx is None:
-                if context is not None:
-                    eval_ctx = context.eval_ctx
-                else:
-                    eval_ctx = EvalContext(self)
-            args.insert(0, eval_ctx)
-        elif getattr(func, "environmentfilter", False) is True:
-            args.insert(0, self)
-        return func(*args, **(kwargs or {}))
-
-    def call_test(self, name, value, args=None, kwargs=None):
-        """Invokes a test on a value the same way the compiler does it.
-
-        .. versionadded:: 2.7
-        """
-        func = self.tests.get(name)
-        if func is None:
-            fail_for_missing_callable("no test named %r", name)
-        return func(value, *(args or ()), **(kwargs or {}))
-
-    @internalcode
-    def parse(self, source, name=None, filename=None):
-        """Parse the sourcecode and return the abstract syntax tree.  This
-        tree of nodes is used by the compiler to convert the template into
-        executable source- or bytecode.  This is useful for debugging or to
-        extract information from templates.
-
-        If you are :ref:`developing Jinja extensions <writing-extensions>`
-        this gives you a good overview of the node tree generated.
-        """
-        try:
-            return self._parse(source, name, filename)
-        except TemplateSyntaxError:
-            self.handle_exception(source=source)
-
-    def _parse(self, source, name, filename):
-        """Internal parsing function used by `parse` and `compile`."""
-        return Parser(self, source, name, encode_filename(filename)).parse()
-
-    def lex(self, source, name=None, filename=None):
-        """Lex the given sourcecode and return a generator that yields
-        tokens as tuples in the form ``(lineno, token_type, value)``.
-        This can be useful for :ref:`extension development <writing-extensions>`
-        and debugging templates.
-
-        This does not perform preprocessing.  If you want the preprocessing
-        of the extensions to be applied you have to filter source through
-        the :meth:`preprocess` method.
-        """
-        source = text_type(source)
-        try:
-            return self.lexer.tokeniter(source, name, filename)
-        except TemplateSyntaxError:
-            self.handle_exception(source=source)
-
-    def preprocess(self, source, name=None, filename=None):
-        """Preprocesses the source with all extensions.  This is automatically
-        called for all parsing and compiling methods but *not* for :meth:`lex`
-        because there you usually only want the actual source tokenized.
-        """
-        return reduce(
-            lambda s, e: e.preprocess(s, name, filename),
-            self.iter_extensions(),
-            text_type(source),
-        )
-
-    def _tokenize(self, source, name, filename=None, state=None):
-        """Called by the parser to do the preprocessing and filtering
-        for all the extensions.  Returns a :class:`~jinja2.lexer.TokenStream`.
-        """
-        source = self.preprocess(source, name, filename)
-        stream = self.lexer.tokenize(source, name, filename, state)
-        for ext in self.iter_extensions():
-            stream = ext.filter_stream(stream)
-            if not isinstance(stream, TokenStream):
-                stream = TokenStream(stream, name, filename)
-        return stream
-
-    def _generate(self, source, name, filename, defer_init=False):
-        """Internal hook that can be overridden to hook a different generate
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return generate(
-            source,
-            self,
-            name,
-            filename,
-            defer_init=defer_init,
-            optimized=self.optimized,
-        )
-
-    def _compile(self, source, filename):
-        """Internal hook that can be overridden to hook a different compile
-        method in.
-
-        .. versionadded:: 2.5
-        """
-        return compile(source, filename, "exec")
-
-    @internalcode
-    def compile(self, source, name=None, filename=None, raw=False, defer_init=False):
-        """Compile a node or template source code.  The `name` parameter is
-        the load name of the template after it was joined using
-        :meth:`join_path` if necessary, not the filename on the file system.
-        the `filename` parameter is the estimated filename of the template on
-        the file system.  If the template came from a database or memory this
-        can be omitted.
-
-        The return value of this method is a python code object.  If the `raw`
-        parameter is `True` the return value will be a string with python
-        code equivalent to the bytecode returned otherwise.  This method is
-        mainly used internally.
-
-        `defer_init` is use internally to aid the module code generator.  This
-        causes the generated code to be able to import without the global
-        environment variable to be set.
-
-        .. versionadded:: 2.4
-           `defer_init` parameter added.
-        """
-        source_hint = None
-        try:
-            if isinstance(source, string_types):
-                source_hint = source
-                source = self._parse(source, name, filename)
-            source = self._generate(source, name, filename, defer_init=defer_init)
-            if raw:
-                return source
-            if filename is None:
-                filename = "<template>"
-            else:
-                filename = encode_filename(filename)
-            return self._compile(source, filename)
-        except TemplateSyntaxError:
-            self.handle_exception(source=source_hint)
-
-    def compile_expression(self, source, undefined_to_none=True):
-        """A handy helper method that returns a callable that accepts keyword
-        arguments that appear as variables in the expression.  If called it
-        returns the result of the expression.
-
-        This is useful if applications want to use the same rules as Jinja
-        in template "configuration files" or similar situations.
-
-        Example usage:
-
-        >>> env = Environment()
-        >>> expr = env.compile_expression('foo == 42')
-        >>> expr(foo=23)
-        False
-        >>> expr(foo=42)
-        True
-
-        Per default the return value is converted to `None` if the
-        expression returns an undefined value.  This can be changed
-        by setting `undefined_to_none` to `False`.
-
-        >>> env.compile_expression('var')() is None
-        True
-        >>> env.compile_expression('var', undefined_to_none=False)()
-        Undefined
-
-        .. versionadded:: 2.1
-        """
-        parser = Parser(self, source, state="variable")
-        try:
-            expr = parser.parse_expression()
-            if not parser.stream.eos:
-                raise TemplateSyntaxError(
-                    "chunk after expression", parser.stream.current.lineno, None, None
-                )
-            expr.set_environment(self)
-        except TemplateSyntaxError:
-            if sys.exc_info() is not None:
-                self.handle_exception(source=source)
-
-        body = [nodes.Assign(nodes.Name("result", "store"), expr, lineno=1)]
-        template = self.from_string(nodes.Template(body, lineno=1))
-        return TemplateExpression(template, undefined_to_none)
-
-    def compile_templates(
-        self,
-        target,
-        extensions=None,
-        filter_func=None,
-        zip="deflated",
-        log_function=None,
-        ignore_errors=True,
-        py_compile=False,
-    ):
-        """Finds all the templates the loader can find, compiles them
-        and stores them in `target`.  If `zip` is `None`, instead of in a
-        zipfile, the templates will be stored in a directory.
-        By default a deflate zip algorithm is used. To switch to
-        the stored algorithm, `zip` can be set to ``'stored'``.
-
-        `extensions` and `filter_func` are passed to :meth:`list_templates`.
-        Each template returned will be compiled to the target folder or
-        zipfile.
-
-        By default template compilation errors are ignored.  In case a
-        log function is provided, errors are logged.  If you want template
-        syntax errors to abort the compilation you can set `ignore_errors`
-        to `False` and you will get an exception on syntax errors.
-
-        If `py_compile` is set to `True` .pyc files will be written to the
-        target instead of standard .py files.  This flag does not do anything
-        on pypy and Python 3 where pyc files are not picked up by itself and
-        don't give much benefit.
-
-        .. versionadded:: 2.4
-        """
-        from .loaders import ModuleLoader
-
-        if log_function is None:
-
-            def log_function(x):
-                pass
-
-        if py_compile:
-            if not PY2 or PYPY:
-                import warnings
-
-                warnings.warn(
-                    "'py_compile=True' has no effect on PyPy or Python"
-                    " 3 and will be removed in version 3.0",
-                    DeprecationWarning,
-                    stacklevel=2,
-                )
-                py_compile = False
-            else:
-                import imp
-                import marshal
-
-                py_header = imp.get_magic() + u"\xff\xff\xff\xff".encode("iso-8859-15")
-
-                # Python 3.3 added a source filesize to the header
-                if sys.version_info >= (3, 3):
-                    py_header += u"\x00\x00\x00\x00".encode("iso-8859-15")
-
-        def write_file(filename, data):
-            if zip:
-                info = ZipInfo(filename)
-                info.external_attr = 0o755 << 16
-                zip_file.writestr(info, data)
-            else:
-                if isinstance(data, text_type):
-                    data = data.encode("utf8")
-
-                with open(os.path.join(target, filename), "wb") as f:
-                    f.write(data)
-
-        if zip is not None:
-            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
-
-            zip_file = ZipFile(
-                target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip]
-            )
-            log_function('Compiling into Zip archive "%s"' % target)
-        else:
-            if not os.path.isdir(target):
-                os.makedirs(target)
-            log_function('Compiling into folder "%s"' % target)
-
-        try:
-            for name in self.list_templates(extensions, filter_func):
-                source, filename, _ = self.loader.get_source(self, name)
-                try:
-                    code = self.compile(source, name, filename, True, True)
-                except TemplateSyntaxError as e:
-                    if not ignore_errors:
-                        raise
-                    log_function('Could not compile "%s": %s' % (name, e))
-                    continue
-
-                filename = ModuleLoader.get_module_filename(name)
-
-                if py_compile:
-                    c = self._compile(code, encode_filename(filename))
-                    write_file(filename + "c", py_header + marshal.dumps(c))
-                    log_function('Byte-compiled "%s" as %s' % (name, filename + "c"))
-                else:
-                    write_file(filename, code)
-                    log_function('Compiled "%s" as %s' % (name, filename))
-        finally:
-            if zip:
-                zip_file.close()
-
-        log_function("Finished compiling templates")
-
-    def list_templates(self, extensions=None, filter_func=None):
-        """Returns a list of templates for this environment.  This requires
-        that the loader supports the loader's
-        :meth:`~BaseLoader.list_templates` method.
-
-        If there are other files in the template folder besides the
-        actual templates, the returned list can be filtered.  There are two
-        ways: either `extensions` is set to a list of file extensions for
-        templates, or a `filter_func` can be provided which is a callable that
-        is passed a template name and should return `True` if it should end up
-        in the result list.
-
-        If the loader does not support that, a :exc:`TypeError` is raised.
-
-        .. versionadded:: 2.4
-        """
-        names = self.loader.list_templates()
-
-        if extensions is not None:
-            if filter_func is not None:
-                raise TypeError(
-                    "either extensions or filter_func can be passed, but not both"
-                )
-
-            def filter_func(x):
-                return "." in x and x.rsplit(".", 1)[1] in extensions
-
-        if filter_func is not None:
-            names = [name for name in names if filter_func(name)]
-
-        return names
-
-    def handle_exception(self, source=None):
-        """Exception handling helper.  This is used internally to either raise
-        rewritten exceptions or return a rendered traceback for the template.
-        """
-        from .debug import rewrite_traceback_stack
-
-        reraise(*rewrite_traceback_stack(source=source))
-
-    def join_path(self, template, parent):
-        """Join a template with the parent.  By default all the lookups are
-        relative to the loader root so this method returns the `template`
-        parameter unchanged, but if the paths should be relative to the
-        parent template, this function can be used to calculate the real
-        template name.
-
-        Subclasses may override this method and implement template path
-        joining here.
-        """
-        return template
-
-    @internalcode
-    def _load_template(self, name, globals):
-        if self.loader is None:
-            raise TypeError("no loader for this environment specified")
-        cache_key = (weakref.ref(self.loader), name)
-        if self.cache is not None:
-            template = self.cache.get(cache_key)
-            if template is not None and (
-                not self.auto_reload or template.is_up_to_date
-            ):
-                return template
-        template = self.loader.load(self, name, globals)
-        if self.cache is not None:
-            self.cache[cache_key] = template
-        return template
-
-    @internalcode
-    def get_template(self, name, parent=None, globals=None):
-        """Load a template from the loader.  If a loader is configured this
-        method asks the loader for the template and returns a :class:`Template`.
-        If the `parent` parameter is not `None`, :meth:`join_path` is called
-        to get the real template name before loading.
-
-        The `globals` parameter can be used to provide template wide globals.
-        These variables are available in the context at render time.
-
-        If the template does not exist a :exc:`TemplateNotFound` exception is
-        raised.
-
-        .. versionchanged:: 2.4
-           If `name` is a :class:`Template` object it is returned from the
-           function unchanged.
-        """
-        if isinstance(name, Template):
-            return name
-        if parent is not None:
-            name = self.join_path(name, parent)
-        return self._load_template(name, self.make_globals(globals))
-
-    @internalcode
-    def select_template(self, names, parent=None, globals=None):
-        """Works like :meth:`get_template` but tries a number of templates
-        before it fails.  If it cannot find any of the templates, it will
-        raise a :exc:`TemplatesNotFound` exception.
-
-        .. versionchanged:: 2.11
-            If names is :class:`Undefined`, an :exc:`UndefinedError` is
-            raised instead. If no templates were found and names
-            contains :class:`Undefined`, the message is more helpful.
-
-        .. versionchanged:: 2.4
-           If `names` contains a :class:`Template` object it is returned
-           from the function unchanged.
-
-        .. versionadded:: 2.3
-        """
-        if isinstance(names, Undefined):
-            names._fail_with_undefined_error()
-
-        if not names:
-            raise TemplatesNotFound(
-                message=u"Tried to select from an empty list " u"of templates."
-            )
-        globals = self.make_globals(globals)
-        for name in names:
-            if isinstance(name, Template):
-                return name
-            if parent is not None:
-                name = self.join_path(name, parent)
-            try:
-                return self._load_template(name, globals)
-            except (TemplateNotFound, UndefinedError):
-                pass
-        raise TemplatesNotFound(names)
-
-    @internalcode
-    def get_or_select_template(self, template_name_or_list, parent=None, globals=None):
-        """Does a typecheck and dispatches to :meth:`select_template`
-        if an iterable of template names is given, otherwise to
-        :meth:`get_template`.
-
-        .. versionadded:: 2.3
-        """
-        if isinstance(template_name_or_list, (string_types, Undefined)):
-            return self.get_template(template_name_or_list, parent, globals)
-        elif isinstance(template_name_or_list, Template):
-            return template_name_or_list
-        return self.select_template(template_name_or_list, parent, globals)
-
-    def from_string(self, source, globals=None, template_class=None):
-        """Load a template from a string.  This parses the source given and
-        returns a :class:`Template` object.
-        """
-        globals = self.make_globals(globals)
-        cls = template_class or self.template_class
-        return cls.from_code(self, self.compile(source), globals, None)
-
-    def make_globals(self, d):
-        """Return a dict for the globals."""
-        if not d:
-            return self.globals
-        return dict(self.globals, **d)
-
-
-class Template(object):
-    """The central template object.  This class represents a compiled template
-    and is used to evaluate it.
-
-    Normally the template object is generated from an :class:`Environment` but
-    it also has a constructor that makes it possible to create a template
-    instance directly using the constructor.  It takes the same arguments as
-    the environment constructor but it's not possible to specify a loader.
-
-    Every template object has a few methods and members that are guaranteed
-    to exist.  However it's important that a template object should be
-    considered immutable.  Modifications on the object are not supported.
-
-    Template objects created from the constructor rather than an environment
-    do have an `environment` attribute that points to a temporary environment
-    that is probably shared with other templates created with the constructor
-    and compatible settings.
-
-    >>> template = Template('Hello {{ name }}!')
-    >>> template.render(name='John Doe') == u'Hello John Doe!'
-    True
-    >>> stream = template.stream(name='John Doe')
-    >>> next(stream) == u'Hello John Doe!'
-    True
-    >>> next(stream)
-    Traceback (most recent call last):
-        ...
-    StopIteration
-    """
-
-    #: Type of environment to create when creating a template directly
-    #: rather than through an existing environment.
-    environment_class = Environment
-
-    def __new__(
-        cls,
-        source,
-        block_start_string=BLOCK_START_STRING,
-        block_end_string=BLOCK_END_STRING,
-        variable_start_string=VARIABLE_START_STRING,
-        variable_end_string=VARIABLE_END_STRING,
-        comment_start_string=COMMENT_START_STRING,
-        comment_end_string=COMMENT_END_STRING,
-        line_statement_prefix=LINE_STATEMENT_PREFIX,
-        line_comment_prefix=LINE_COMMENT_PREFIX,
-        trim_blocks=TRIM_BLOCKS,
-        lstrip_blocks=LSTRIP_BLOCKS,
-        newline_sequence=NEWLINE_SEQUENCE,
-        keep_trailing_newline=KEEP_TRAILING_NEWLINE,
-        extensions=(),
-        optimized=True,
-        undefined=Undefined,
-        finalize=None,
-        autoescape=False,
-        enable_async=False,
-    ):
-        env = get_spontaneous_environment(
-            cls.environment_class,
-            block_start_string,
-            block_end_string,
-            variable_start_string,
-            variable_end_string,
-            comment_start_string,
-            comment_end_string,
-            line_statement_prefix,
-            line_comment_prefix,
-            trim_blocks,
-            lstrip_blocks,
-            newline_sequence,
-            keep_trailing_newline,
-            frozenset(extensions),
-            optimized,
-            undefined,
-            finalize,
-            autoescape,
-            None,
-            0,
-            False,
-            None,
-            enable_async,
-        )
-        return env.from_string(source, template_class=cls)
-
-    @classmethod
-    def from_code(cls, environment, code, globals, uptodate=None):
-        """Creates a template object from compiled code and the globals.  This
-        is used by the loaders and environment to create a template object.
-        """
-        namespace = {"environment": environment, "__file__": code.co_filename}
-        exec(code, namespace)
-        rv = cls._from_namespace(environment, namespace, globals)
-        rv._uptodate = uptodate
-        return rv
-
-    @classmethod
-    def from_module_dict(cls, environment, module_dict, globals):
-        """Creates a template object from a module.  This is used by the
-        module loader to create a template object.
-
-        .. versionadded:: 2.4
-        """
-        return cls._from_namespace(environment, module_dict, globals)
-
-    @classmethod
-    def _from_namespace(cls, environment, namespace, globals):
-        t = object.__new__(cls)
-        t.environment = environment
-        t.globals = globals
-        t.name = namespace["name"]
-        t.filename = namespace["__file__"]
-        t.blocks = namespace["blocks"]
-
-        # render function and module
-        t.root_render_func = namespace["root"]
-        t._module = None
-
-        # debug and loader helpers
-        t._debug_info = namespace["debug_info"]
-        t._uptodate = None
-
-        # store the reference
-        namespace["environment"] = environment
-        namespace["__jinja_template__"] = t
-
-        return t
-
-    def render(self, *args, **kwargs):
-        """This method accepts the same arguments as the `dict` constructor:
-        A dict, a dict subclass or some keyword arguments.  If no arguments
-        are given the context will be empty.  These two calls do the same::
-
-            template.render(knights='that say nih')
-            template.render({'knights': 'that say nih'})
-
-        This will return the rendered template as unicode string.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            return concat(self.root_render_func(self.new_context(vars)))
-        except Exception:
-            self.environment.handle_exception()
-
-    def render_async(self, *args, **kwargs):
-        """This works similar to :meth:`render` but returns a coroutine
-        that when awaited returns the entire rendered template string.  This
-        requires the async feature to be enabled.
-
-        Example usage::
-
-            await template.render_async(knights='that say nih; asynchronously')
-        """
-        # see asyncsupport for the actual implementation
-        raise NotImplementedError(
-            "This feature is not available for this version of Python"
-        )
-
-    def stream(self, *args, **kwargs):
-        """Works exactly like :meth:`generate` but returns a
-        :class:`TemplateStream`.
-        """
-        return TemplateStream(self.generate(*args, **kwargs))
-
-    def generate(self, *args, **kwargs):
-        """For very large templates it can be useful to not render the whole
-        template at once but evaluate each statement after another and yield
-        piece for piece.  This method basically does exactly that and returns
-        a generator that yields one item after another as unicode strings.
-
-        It accepts the same arguments as :meth:`render`.
-        """
-        vars = dict(*args, **kwargs)
-        try:
-            for event in self.root_render_func(self.new_context(vars)):
-                yield event
-        except Exception:
-            yield self.environment.handle_exception()
-
-    def generate_async(self, *args, **kwargs):
-        """An async version of :meth:`generate`.  Works very similarly but
-        returns an async iterator instead.
-        """
-        # see asyncsupport for the actual implementation
-        raise NotImplementedError(
-            "This feature is not available for this version of Python"
-        )
-
-    def new_context(self, vars=None, shared=False, locals=None):
-        """Create a new :class:`Context` for this template.  The vars
-        provided will be passed to the template.  Per default the globals
-        are added to the context.  If shared is set to `True` the data
-        is passed as is to the context without adding the globals.
-
-        `locals` can be a dict of local variables for internal usage.
-        """
-        return new_context(
-            self.environment, self.name, self.blocks, vars, shared, self.globals, locals
-        )
-
-    def make_module(self, vars=None, shared=False, locals=None):
-        """This method works like the :attr:`module` attribute when called
-        without arguments but it will evaluate the template on every call
-        rather than caching it.  It's also possible to provide
-        a dict which is then used as context.  The arguments are the same
-        as for the :meth:`new_context` method.
-        """
-        return TemplateModule(self, self.new_context(vars, shared, locals))
-
-    def make_module_async(self, vars=None, shared=False, locals=None):
-        """As template module creation can invoke template code for
-        asynchronous executions this method must be used instead of the
-        normal :meth:`make_module` one.  Likewise the module attribute
-        becomes unavailable in async mode.
-        """
-        # see asyncsupport for the actual implementation
-        raise NotImplementedError(
-            "This feature is not available for this version of Python"
-        )
-
-    @internalcode
-    def _get_default_module(self):
-        if self._module is not None:
-            return self._module
-        self._module = rv = self.make_module()
-        return rv
-
-    @property
-    def module(self):
-        """The template as module.  This is used for imports in the
-        template runtime but is also useful if one wants to access
-        exported template variables from the Python layer:
-
-        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
-        >>> str(t.module)
-        '23'
-        >>> t.module.foo() == u'42'
-        True
-
-        This attribute is not available if async mode is enabled.
-        """
-        return self._get_default_module()
-
-    def get_corresponding_lineno(self, lineno):
-        """Return the source line number of a line number in the
-        generated bytecode as they are not in sync.
-        """
-        for template_line, code_line in reversed(self.debug_info):
-            if code_line <= lineno:
-                return template_line
-        return 1
-
-    @property
-    def is_up_to_date(self):
-        """If this variable is `False` there is a newer version available."""
-        if self._uptodate is None:
-            return True
-        return self._uptodate()
-
-    @property
-    def debug_info(self):
-        """The debug info mapping."""
-        if self._debug_info:
-            return [tuple(map(int, x.split("="))) for x in self._debug_info.split("&")]
-        return []
-
-    def __repr__(self):
-        if self.name is None:
-            name = "memory:%x" % id(self)
-        else:
-            name = repr(self.name)
-        return "<%s %s>" % (self.__class__.__name__, name)
-
-
-@implements_to_string
-class TemplateModule(object):
-    """Represents an imported template.  All the exported names of the
-    template are available as attributes on this object.  Additionally
-    converting it into an unicode- or bytestrings renders the contents.
-    """
-
-    def __init__(self, template, context, body_stream=None):
-        if body_stream is None:
-            if context.environment.is_async:
-                raise RuntimeError(
-                    "Async mode requires a body stream "
-                    "to be passed to a template module.  Use "
-                    "the async methods of the API you are "
-                    "using."
-                )
-            body_stream = list(template.root_render_func(context))
-        self._body_stream = body_stream
-        self.__dict__.update(context.get_exported())
-        self.__name__ = template.name
-
-    def __html__(self):
-        return Markup(concat(self._body_stream))
-
-    def __str__(self):
-        return concat(self._body_stream)
-
-    def __repr__(self):
-        if self.__name__ is None:
-            name = "memory:%x" % id(self)
-        else:
-            name = repr(self.__name__)
-        return "<%s %s>" % (self.__class__.__name__, name)
-
-
-class TemplateExpression(object):
-    """The :meth:`jinja2.Environment.compile_expression` method returns an
-    instance of this object.  It encapsulates the expression-like access
-    to the template with an expression it wraps.
-    """
-
-    def __init__(self, template, undefined_to_none):
-        self._template = template
-        self._undefined_to_none = undefined_to_none
-
-    def __call__(self, *args, **kwargs):
-        context = self._template.new_context(dict(*args, **kwargs))
-        consume(self._template.root_render_func(context))
-        rv = context.vars["result"]
-        if self._undefined_to_none and isinstance(rv, Undefined):
-            rv = None
-        return rv
-
-
-@implements_iterator
-class TemplateStream(object):
-    """A template stream works pretty much like an ordinary python generator
-    but it can buffer multiple items to reduce the number of total iterations.
-    Per default the output is unbuffered which means that for every unbuffered
-    instruction in the template one unicode string is yielded.
-
-    If buffering is enabled with a buffer size of 5, five items are combined
-    into a new unicode string.  This is mainly useful if you are streaming
-    big templates to a client via WSGI which flushes after each iteration.
-    """
-
-    def __init__(self, gen):
-        self._gen = gen
-        self.disable_buffering()
-
-    def dump(self, fp, encoding=None, errors="strict"):
-        """Dump the complete stream into a file or file-like object.
-        Per default unicode strings are written, if you want to encode
-        before writing specify an `encoding`.
-
-        Example usage::
-
-            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
-        """
-        close = False
-        if isinstance(fp, string_types):
-            if encoding is None:
-                encoding = "utf-8"
-            fp = open(fp, "wb")
-            close = True
-        try:
-            if encoding is not None:
-                iterable = (x.encode(encoding, errors) for x in self)
-            else:
-                iterable = self
-            if hasattr(fp, "writelines"):
-                fp.writelines(iterable)
-            else:
-                for item in iterable:
-                    fp.write(item)
-        finally:
-            if close:
-                fp.close()
-
-    def disable_buffering(self):
-        """Disable the output buffering."""
-        self._next = partial(next, self._gen)
-        self.buffered = False
-
-    def _buffered_generator(self, size):
-        buf = []
-        c_size = 0
-        push = buf.append
-
-        while 1:
-            try:
-                while c_size < size:
-                    c = next(self._gen)
-                    push(c)
-                    if c:
-                        c_size += 1
-            except StopIteration:
-                if not c_size:
-                    return
-            yield concat(buf)
-            del buf[:]
-            c_size = 0
-
-    def enable_buffering(self, size=5):
-        """Enable buffering.  Buffer `size` items before yielding them."""
-        if size <= 1:
-            raise ValueError("buffer size too small")
-
-        self.buffered = True
-        self._next = partial(next, self._buffered_generator(size))
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        return self._next()
-
-
-# hook in default template class.  if anyone reads this comment: ignore that
-# it's possible to use custom templates ;-)
-Environment.template_class = Template