| Index: mojo/public/third_party/jinja2/environment.py
|
| diff --git a/mojo/public/third_party/jinja2/environment.py b/mojo/public/third_party/jinja2/environment.py
|
| deleted file mode 100644
|
| index 45fabada2eb238504e1c0ccda6e42fd9cf2e707e..0000000000000000000000000000000000000000
|
| --- a/mojo/public/third_party/jinja2/environment.py
|
| +++ /dev/null
|
| @@ -1,1191 +0,0 @@
|
| -# -*- coding: utf-8 -*-
|
| -"""
|
| - jinja2.environment
|
| - ~~~~~~~~~~~~~~~~~~
|
| -
|
| - Provides a class that holds runtime and parsing time options.
|
| -
|
| - :copyright: (c) 2010 by the Jinja Team.
|
| - :license: BSD, see LICENSE for more details.
|
| -"""
|
| -import os
|
| -import sys
|
| -from jinja2 import nodes
|
| -from jinja2.defaults import 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, NEWLINE_SEQUENCE, \
|
| - DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \
|
| - KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
|
| -from jinja2.lexer import get_lexer, TokenStream
|
| -from jinja2.parser import Parser
|
| -from jinja2.nodes import EvalContext
|
| -from jinja2.optimizer import optimize
|
| -from jinja2.compiler import generate
|
| -from jinja2.runtime import Undefined, new_context
|
| -from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
|
| - TemplatesNotFound, TemplateRuntimeError
|
| -from jinja2.utils import import_string, LRUCache, Markup, missing, \
|
| - concat, consume, internalcode
|
| -from jinja2._compat import imap, ifilter, string_types, iteritems, \
|
| - text_type, reraise, implements_iterator, implements_to_string, \
|
| - get_next, encode_filename, PY2, PYPY
|
| -from functools import reduce
|
| -
|
| -
|
| -# for direct template usage we have up to ten living environments
|
| -_spontaneous_environments = LRUCache(10)
|
| -
|
| -# the function to create jinja traceback objects. This is dynamically
|
| -# imported on the first exception in the exception handler.
|
| -_make_traceback = None
|
| -
|
| -
|
| -def get_spontaneous_environment(*args):
|
| - """Return a new spontaneous environment. A spontaneous environment is an
|
| - unnamed and unaccessible (in theory) environment that is used for
|
| - templates generated from a string and not from the file system.
|
| - """
|
| - try:
|
| - env = _spontaneous_environments.get(args)
|
| - except TypeError:
|
| - return Environment(*args)
|
| - if env is not None:
|
| - return env
|
| - _spontaneous_environments[args] = env = Environment(*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 _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 the possible initialization parameters:
|
| -
|
| - `block_start_string`
|
| - The string marking the begin 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 begin 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 begin 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
|
| - 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 auto escaping see
|
| - :class:`~jinja2.utils.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 ``50`` which means
|
| - that if more than 50 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.
|
| -
|
| - `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.
|
| - """
|
| -
|
| - #: 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
|
| -
|
| - #: these are currently EXPERIMENTAL undocumented features.
|
| - exception_handler = None
|
| - exception_formatter = None
|
| -
|
| - 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=50,
|
| - auto_reload=True,
|
| - bytecode_cache=None):
|
| - # !!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
|
| -
|
| - # load extensions
|
| - self.extensions = load_extensions(self, extensions)
|
| -
|
| - _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 of 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 (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.
|
| -
|
| - .. versionadded:: 2.7
|
| - """
|
| - func = self.filters.get(name)
|
| - if func is None:
|
| - raise TemplateRuntimeError('no filter named %r' % name)
|
| - args = [value] + list(args or ())
|
| - if getattr(func, 'contextfilter', False):
|
| - if context is None:
|
| - raise TemplateRuntimeError('Attempted to invoke context '
|
| - 'filter without context')
|
| - args.insert(0, context)
|
| - elif getattr(func, 'evalcontextfilter', False):
|
| - 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):
|
| - 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:
|
| - raise TemplateRuntimeError('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 Jinja2 extensions <writing-extensions>`
|
| - this gives you a good overview of the node tree generated.
|
| - """
|
| - try:
|
| - return self._parse(source, name, filename)
|
| - except TemplateSyntaxError:
|
| - exc_info = sys.exc_info()
|
| - self.handle_exception(exc_info, source_hint=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:
|
| - exc_info = sys.exc_info()
|
| - self.handle_exception(exc_info, source_hint=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)
|
| -
|
| - 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)
|
| - if self.optimized:
|
| - source = optimize(source, self)
|
| - 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:
|
| - exc_info = sys.exc_info()
|
| - self.handle_exception(exc_info, source_hint=source)
|
| -
|
| - 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')
|
| - exc_info = None
|
| - 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:
|
| - exc_info = sys.exc_info()
|
| - if exc_info is not None:
|
| - self.handle_exception(exc_info, source_hint=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 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 jinja2.loaders import ModuleLoader
|
| -
|
| - if log_function is None:
|
| - log_function = lambda x: None
|
| -
|
| - if py_compile:
|
| - if not PY2 or PYPY:
|
| - from warnings import warn
|
| - warn(Warning('py_compile has no effect on pypy or Python 3'))
|
| - py_compile = False
|
| - else:
|
| - import imp, 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, mode):
|
| - if zip:
|
| - info = ZipInfo(filename)
|
| - info.external_attr = 0o755 << 16
|
| - zip_file.writestr(info, data)
|
| - else:
|
| - f = open(os.path.join(target, filename), mode)
|
| - try:
|
| - f.write(data)
|
| - finally:
|
| - f.close()
|
| -
|
| - 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), 'wb')
|
| - log_function('Byte-compiled "%s" as %s' %
|
| - (name, filename + 'c'))
|
| - else:
|
| - write_file(filename, code, 'w')
|
| - 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
|
| - """
|
| - x = 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')
|
| - filter_func = lambda x: '.' in x and \
|
| - x.rsplit('.', 1)[1] in extensions
|
| - if filter_func is not None:
|
| - x = ifilter(filter_func, x)
|
| - return x
|
| -
|
| - def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
|
| - """Exception handling helper. This is used internally to either raise
|
| - rewritten exceptions or return a rendered traceback for the template.
|
| - """
|
| - global _make_traceback
|
| - if exc_info is None:
|
| - exc_info = sys.exc_info()
|
| -
|
| - # the debugging module is imported when it's used for the first time.
|
| - # we're doing a lot of stuff there and for applications that do not
|
| - # get any exceptions in template rendering there is no need to load
|
| - # all of that.
|
| - if _make_traceback is None:
|
| - from jinja2.debug import make_traceback as _make_traceback
|
| - traceback = _make_traceback(exc_info, source_hint)
|
| - if rendered and self.exception_formatter is not None:
|
| - return self.exception_formatter(traceback)
|
| - if self.exception_handler is not None:
|
| - self.exception_handler(traceback)
|
| - exc_type, exc_value, tb = traceback.standard_exc_info
|
| - reraise(exc_type, exc_value, tb)
|
| -
|
| - 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')
|
| - if self.cache is not None:
|
| - template = self.cache.get(name)
|
| - 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[name] = 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 ask 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.
|
| -
|
| - .. versionadded:: 2.3
|
| -
|
| - .. versionchanged:: 2.4
|
| - If `names` contains a :class:`Template` object it is returned
|
| - from the function unchanged.
|
| - """
|
| - 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:
|
| - 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):
|
| - 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!'
|
| -
|
| - >>> stream = template.stream(name='John Doe')
|
| - >>> stream.next()
|
| - u'Hello John Doe!'
|
| - >>> stream.next()
|
| - Traceback (most recent call last):
|
| - ...
|
| - StopIteration
|
| - """
|
| -
|
| - 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):
|
| - env = get_spontaneous_environment(
|
| - 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)
|
| - 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:
|
| - exc_info = sys.exc_info()
|
| - return self.environment.handle_exception(exc_info, True)
|
| -
|
| - 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:
|
| - exc_info = sys.exc_info()
|
| - else:
|
| - return
|
| - yield self.environment.handle_exception(exc_info, True)
|
| -
|
| - 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 it 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))
|
| -
|
| - @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')
|
| - >>> unicode(t.module)
|
| - u'23'
|
| - >>> t.module.foo()
|
| - u'42'
|
| - """
|
| - if self._module is not None:
|
| - return self._module
|
| - self._module = rv = self.make_module()
|
| - return rv
|
| -
|
| - 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."""
|
| - return [tuple(imap(int, x.split('='))) for x in
|
| - self._debug_info.split('&')]
|
| -
|
| - 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):
|
| - self._body_stream = list(template.root_render_func(context))
|
| - 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):
|
| - fp = open(fp, encoding is None and 'w' or '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 = get_next(self._gen)
|
| - self.buffered = False
|
| -
|
| - def enable_buffering(self, size=5):
|
| - """Enable buffering. Buffer `size` items before yielding them."""
|
| - if size <= 1:
|
| - raise ValueError('buffer size too small')
|
| -
|
| - def generator(next):
|
| - buf = []
|
| - c_size = 0
|
| - push = buf.append
|
| -
|
| - while 1:
|
| - try:
|
| - while c_size < size:
|
| - c = next()
|
| - push(c)
|
| - if c:
|
| - c_size += 1
|
| - except StopIteration:
|
| - if not c_size:
|
| - return
|
| - yield concat(buf)
|
| - del buf[:]
|
| - c_size = 0
|
| -
|
| - self.buffered = True
|
| - self._next = get_next(generator(get_next(self._gen)))
|
| -
|
| - 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
|
|
|