aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Jinja2/py2/jinja2/runtime.py
diff options
context:
space:
mode:
authorfloatdrop <floatdrop@yandex-team.ru>2022-02-10 16:47:15 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:47:15 +0300
commite63b84f1d39557d9e46ac380b1f388271894293c (patch)
tree338cdaff3fb027e030b847db66df06019a0e3149 /contrib/python/Jinja2/py2/jinja2/runtime.py
parentf60febb7ea449535e7b073c386c7ff0539637fc0 (diff)
downloadydb-e63b84f1d39557d9e46ac380b1f388271894293c.tar.gz
Restoring authorship annotation for <floatdrop@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/Jinja2/py2/jinja2/runtime.py')
-rw-r--r--contrib/python/Jinja2/py2/jinja2/runtime.py1142
1 files changed, 571 insertions, 571 deletions
diff --git a/contrib/python/Jinja2/py2/jinja2/runtime.py b/contrib/python/Jinja2/py2/jinja2/runtime.py
index 3ad7968624..850f82da1c 100644
--- a/contrib/python/Jinja2/py2/jinja2/runtime.py
+++ b/contrib/python/Jinja2/py2/jinja2/runtime.py
@@ -1,13 +1,13 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""The runtime functions and state used by compiled templates."""
-import sys
-from itertools import chain
-from types import MethodType
-
+import sys
+from itertools import chain
+from types import MethodType
+
from markupsafe import escape # noqa: F401
from markupsafe import Markup
from markupsafe import soft_unicode
-
+
from ._compat import abc
from ._compat import imap
from ._compat import implements_iterator
@@ -27,8 +27,8 @@ from .utils import internalcode
from .utils import missing
from .utils import Namespace # noqa: F401
from .utils import object_type_repr
-
-# these variables are exported to the template runtime
+
+# these variables are exported to the template runtime
exported = [
"LoopContext",
"TemplateReference",
@@ -46,35 +46,35 @@ exported = [
"Namespace",
"Undefined",
]
-
-#: the name of the function that is used to convert something into
-#: a string. We can just use the text type here.
-to_string = text_type
-
-
+
+#: the name of the function that is used to convert something into
+#: a string. We can just use the text type here.
+to_string = text_type
+
+
def identity(x):
"""Returns its argument. Useful for certain things in the
environment.
"""
return x
-
-
-def markup_join(seq):
- """Concatenation that escapes if necessary and converts to unicode."""
- buf = []
- iterator = imap(soft_unicode, seq)
- for arg in iterator:
- buf.append(arg)
+
+
+def markup_join(seq):
+ """Concatenation that escapes if necessary and converts to unicode."""
+ buf = []
+ iterator = imap(soft_unicode, seq)
+ for arg in iterator:
+ buf.append(arg)
if hasattr(arg, "__html__"):
return Markup(u"").join(chain(buf, iterator))
- return concat(buf)
-
-
-def unicode_join(seq):
- """Simple args to unicode conversion and concatenation."""
- return concat(imap(text_type, seq))
-
-
+ return concat(buf)
+
+
+def unicode_join(seq):
+ """Simple args to unicode conversion and concatenation."""
+ return concat(imap(text_type, seq))
+
+
def new_context(
environment,
template_name,
@@ -85,311 +85,311 @@ def new_context(
locals=None,
):
"""Internal helper for context creation."""
- if vars is None:
- vars = {}
- if shared:
- parent = vars
- else:
- parent = dict(globals or (), **vars)
- if locals:
- # if the parent is shared a copy should be created because
- # we don't want to modify the dict passed
- if shared:
- parent = dict(parent)
- for key, value in iteritems(locals):
- if value is not missing:
- parent[key] = value
+ if vars is None:
+ vars = {}
+ if shared:
+ parent = vars
+ else:
+ parent = dict(globals or (), **vars)
+ if locals:
+ # if the parent is shared a copy should be created because
+ # we don't want to modify the dict passed
+ if shared:
+ parent = dict(parent)
+ for key, value in iteritems(locals):
+ if value is not missing:
+ parent[key] = value
return environment.context_class(environment, parent, template_name, blocks)
-
-
-class TemplateReference(object):
- """The `self` in templates."""
-
- def __init__(self, context):
- self.__context = context
-
- def __getitem__(self, name):
- blocks = self.__context.blocks[name]
- return BlockReference(name, self.__context, blocks, 0)
-
- def __repr__(self):
+
+
+class TemplateReference(object):
+ """The `self` in templates."""
+
+ def __init__(self, context):
+ self.__context = context
+
+ def __getitem__(self, name):
+ blocks = self.__context.blocks[name]
+ return BlockReference(name, self.__context, blocks, 0)
+
+ def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.__context.name)
-
-
-def _get_func(x):
+
+
+def _get_func(x):
return getattr(x, "__func__", x)
-
-
-class ContextMeta(type):
+
+
+class ContextMeta(type):
def __new__(mcs, name, bases, d):
rv = type.__new__(mcs, name, bases, d)
- if bases == ():
- return rv
-
- resolve = _get_func(rv.resolve)
- default_resolve = _get_func(Context.resolve)
- resolve_or_missing = _get_func(rv.resolve_or_missing)
- default_resolve_or_missing = _get_func(Context.resolve_or_missing)
-
- # If we have a changed resolve but no changed default or missing
- # resolve we invert the call logic.
+ if bases == ():
+ return rv
+
+ resolve = _get_func(rv.resolve)
+ default_resolve = _get_func(Context.resolve)
+ resolve_or_missing = _get_func(rv.resolve_or_missing)
+ default_resolve_or_missing = _get_func(Context.resolve_or_missing)
+
+ # If we have a changed resolve but no changed default or missing
+ # resolve we invert the call logic.
if (
resolve is not default_resolve
and resolve_or_missing is default_resolve_or_missing
):
- rv._legacy_resolve_mode = True
+ rv._legacy_resolve_mode = True
elif (
resolve is default_resolve
and resolve_or_missing is default_resolve_or_missing
):
- rv._fast_resolve_mode = True
-
- return rv
-
-
-def resolve_or_missing(context, key, missing=missing):
- if key in context.vars:
- return context.vars[key]
- if key in context.parent:
- return context.parent[key]
- return missing
-
-
-class Context(with_metaclass(ContextMeta)):
- """The template context holds the variables of a template. It stores the
- values passed to the template and also the names the template exports.
- Creating instances is neither supported nor useful as it's created
- automatically at various stages of the template evaluation and should not
- be created by hand.
-
- The context is immutable. Modifications on :attr:`parent` **must not**
- happen and modifications on :attr:`vars` are allowed from generated
- template code only. Template filters and global functions marked as
- :func:`contextfunction`\\s get the active context passed as first argument
- and are allowed to access the context read-only.
-
- The template context supports read only dict operations (`get`,
- `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
- `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
- method that doesn't fail with a `KeyError` but returns an
- :class:`Undefined` object for missing variables.
- """
-
- # XXX: we want to eventually make this be a deprecation warning and
- # remove it.
- _legacy_resolve_mode = False
- _fast_resolve_mode = False
-
- def __init__(self, environment, parent, name, blocks):
- self.parent = parent
- self.vars = {}
- self.environment = environment
- self.eval_ctx = EvalContext(self.environment, name)
- self.exported_vars = set()
- self.name = name
-
- # create the initial mapping of blocks. Whenever template inheritance
- # takes place the runtime will update this mapping with the new blocks
- # from the template.
- self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
-
- # In case we detect the fast resolve mode we can set up an alias
- # here that bypasses the legacy code logic.
- if self._fast_resolve_mode:
- self.resolve_or_missing = MethodType(resolve_or_missing, self)
-
- def super(self, name, current):
- """Render a parent block."""
- try:
- blocks = self.blocks[name]
- index = blocks.index(current) + 1
- blocks[index]
- except LookupError:
+ rv._fast_resolve_mode = True
+
+ return rv
+
+
+def resolve_or_missing(context, key, missing=missing):
+ if key in context.vars:
+ return context.vars[key]
+ if key in context.parent:
+ return context.parent[key]
+ return missing
+
+
+class Context(with_metaclass(ContextMeta)):
+ """The template context holds the variables of a template. It stores the
+ values passed to the template and also the names the template exports.
+ Creating instances is neither supported nor useful as it's created
+ automatically at various stages of the template evaluation and should not
+ be created by hand.
+
+ The context is immutable. Modifications on :attr:`parent` **must not**
+ happen and modifications on :attr:`vars` are allowed from generated
+ template code only. Template filters and global functions marked as
+ :func:`contextfunction`\\s get the active context passed as first argument
+ and are allowed to access the context read-only.
+
+ The template context supports read only dict operations (`get`,
+ `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
+ `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
+ method that doesn't fail with a `KeyError` but returns an
+ :class:`Undefined` object for missing variables.
+ """
+
+ # XXX: we want to eventually make this be a deprecation warning and
+ # remove it.
+ _legacy_resolve_mode = False
+ _fast_resolve_mode = False
+
+ def __init__(self, environment, parent, name, blocks):
+ self.parent = parent
+ self.vars = {}
+ self.environment = environment
+ self.eval_ctx = EvalContext(self.environment, name)
+ self.exported_vars = set()
+ self.name = name
+
+ # create the initial mapping of blocks. Whenever template inheritance
+ # takes place the runtime will update this mapping with the new blocks
+ # from the template.
+ self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
+
+ # In case we detect the fast resolve mode we can set up an alias
+ # here that bypasses the legacy code logic.
+ if self._fast_resolve_mode:
+ self.resolve_or_missing = MethodType(resolve_or_missing, self)
+
+ def super(self, name, current):
+ """Render a parent block."""
+ try:
+ blocks = self.blocks[name]
+ index = blocks.index(current) + 1
+ blocks[index]
+ except LookupError:
return self.environment.undefined(
"there is no parent block called %r." % name, name="super"
)
- return BlockReference(name, self, blocks, index)
-
- def get(self, key, default=None):
- """Returns an item from the template context, if it doesn't exist
- `default` is returned.
- """
- try:
- return self[key]
- except KeyError:
- return default
-
- def resolve(self, key):
- """Looks up a variable like `__getitem__` or `get` but returns an
- :class:`Undefined` object with the name of the name looked up.
- """
- if self._legacy_resolve_mode:
- rv = resolve_or_missing(self, key)
- else:
- rv = self.resolve_or_missing(key)
- if rv is missing:
- return self.environment.undefined(name=key)
- return rv
-
- def resolve_or_missing(self, key):
- """Resolves a variable like :meth:`resolve` but returns the
- special `missing` value if it cannot be found.
- """
- if self._legacy_resolve_mode:
- rv = self.resolve(key)
- if isinstance(rv, Undefined):
- rv = missing
- return rv
- return resolve_or_missing(self, key)
-
- def get_exported(self):
- """Get a new dict with the exported variables."""
- return dict((k, self.vars[k]) for k in self.exported_vars)
-
- def get_all(self):
- """Return the complete context as dict including the exported
- variables. For optimizations reasons this might not return an
- actual copy so be careful with using it.
- """
- if not self.vars:
- return self.parent
- if not self.parent:
- return self.vars
- return dict(self.parent, **self.vars)
-
- @internalcode
+ return BlockReference(name, self, blocks, index)
+
+ def get(self, key, default=None):
+ """Returns an item from the template context, if it doesn't exist
+ `default` is returned.
+ """
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def resolve(self, key):
+ """Looks up a variable like `__getitem__` or `get` but returns an
+ :class:`Undefined` object with the name of the name looked up.
+ """
+ if self._legacy_resolve_mode:
+ rv = resolve_or_missing(self, key)
+ else:
+ rv = self.resolve_or_missing(key)
+ if rv is missing:
+ return self.environment.undefined(name=key)
+ return rv
+
+ def resolve_or_missing(self, key):
+ """Resolves a variable like :meth:`resolve` but returns the
+ special `missing` value if it cannot be found.
+ """
+ if self._legacy_resolve_mode:
+ rv = self.resolve(key)
+ if isinstance(rv, Undefined):
+ rv = missing
+ return rv
+ return resolve_or_missing(self, key)
+
+ def get_exported(self):
+ """Get a new dict with the exported variables."""
+ return dict((k, self.vars[k]) for k in self.exported_vars)
+
+ def get_all(self):
+ """Return the complete context as dict including the exported
+ variables. For optimizations reasons this might not return an
+ actual copy so be careful with using it.
+ """
+ if not self.vars:
+ return self.parent
+ if not self.parent:
+ return self.vars
+ return dict(self.parent, **self.vars)
+
+ @internalcode
def call(__self, __obj, *args, **kwargs): # noqa: B902
- """Call the callable with the arguments and keyword arguments
- provided but inject the active context or environment as first
- argument if the callable is a :func:`contextfunction` or
- :func:`environmentfunction`.
- """
- if __debug__:
- __traceback_hide__ = True # noqa
-
- # Allow callable classes to take a context
+ """Call the callable with the arguments and keyword arguments
+ provided but inject the active context or environment as first
+ argument if the callable is a :func:`contextfunction` or
+ :func:`environmentfunction`.
+ """
+ if __debug__:
+ __traceback_hide__ = True # noqa
+
+ # Allow callable classes to take a context
if hasattr(__obj, "__call__"): # noqa: B004
- fn = __obj.__call__
+ fn = __obj.__call__
for fn_type in (
"contextfunction",
"evalcontextfunction",
"environmentfunction",
):
- if hasattr(fn, fn_type):
- __obj = fn
- break
-
+ if hasattr(fn, fn_type):
+ __obj = fn
+ break
+
if callable(__obj):
if getattr(__obj, "contextfunction", False) is True:
- args = (__self,) + args
+ args = (__self,) + args
elif getattr(__obj, "evalcontextfunction", False) is True:
- args = (__self.eval_ctx,) + args
+ args = (__self.eval_ctx,) + args
elif getattr(__obj, "environmentfunction", False) is True:
- args = (__self.environment,) + args
- try:
- return __obj(*args, **kwargs)
- except StopIteration:
+ args = (__self.environment,) + args
+ try:
+ return __obj(*args, **kwargs)
+ except StopIteration:
return __self.environment.undefined(
"value was undefined because "
"a callable raised a "
"StopIteration exception"
)
-
- def derived(self, locals=None):
- """Internal helper function to create a derived context. This is
- used in situations where the system needs a new context in the same
- template that is independent.
- """
+
+ def derived(self, locals=None):
+ """Internal helper function to create a derived context. This is
+ used in situations where the system needs a new context in the same
+ template that is independent.
+ """
context = new_context(
self.environment, self.name, {}, self.get_all(), True, None, locals
)
- context.eval_ctx = self.eval_ctx
- context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
- return context
-
+ context.eval_ctx = self.eval_ctx
+ context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
+ return context
+
def _all(meth): # noqa: B902
def proxy(self):
return getattr(self.get_all(), meth)()
- proxy.__doc__ = getattr(dict, meth).__doc__
- proxy.__name__ = meth
- return proxy
-
+ proxy.__doc__ = getattr(dict, meth).__doc__
+ proxy.__name__ = meth
+ return proxy
+
keys = _all("keys")
values = _all("values")
items = _all("items")
-
- # not available on python 3
- if PY2:
+
+ # not available on python 3
+ if PY2:
iterkeys = _all("iterkeys")
itervalues = _all("itervalues")
iteritems = _all("iteritems")
- del _all
-
- def __contains__(self, name):
- return name in self.vars or name in self.parent
-
- def __getitem__(self, key):
- """Lookup a variable or raise `KeyError` if the variable is
- undefined.
- """
- item = self.resolve_or_missing(key)
- if item is missing:
- raise KeyError(key)
- return item
-
- def __repr__(self):
+ del _all
+
+ def __contains__(self, name):
+ return name in self.vars or name in self.parent
+
+ def __getitem__(self, key):
+ """Lookup a variable or raise `KeyError` if the variable is
+ undefined.
+ """
+ item = self.resolve_or_missing(key)
+ if item is missing:
+ raise KeyError(key)
+ return item
+
+ def __repr__(self):
return "<%s %s of %r>" % (
- self.__class__.__name__,
- repr(self.get_all()),
+ self.__class__.__name__,
+ repr(self.get_all()),
self.name,
- )
-
-
+ )
+
+
abc.Mapping.register(Context)
-
-
-class BlockReference(object):
- """One block on a template reference."""
-
- def __init__(self, name, context, stack, depth):
- self.name = name
- self._context = context
- self._stack = stack
- self._depth = depth
-
- @property
- def super(self):
- """Super the block."""
- if self._depth + 1 >= len(self._stack):
+
+
+class BlockReference(object):
+ """One block on a template reference."""
+
+ def __init__(self, name, context, stack, depth):
+ self.name = name
+ self._context = context
+ self._stack = stack
+ self._depth = depth
+
+ @property
+ def super(self):
+ """Super the block."""
+ if self._depth + 1 >= len(self._stack):
return self._context.environment.undefined(
"there is no parent block called %r." % self.name, name="super"
)
return BlockReference(self.name, self._context, self._stack, self._depth + 1)
-
- @internalcode
- def __call__(self):
- rv = concat(self._stack[self._depth](self._context))
- if self._context.eval_ctx.autoescape:
- rv = Markup(rv)
- return rv
-
-
+
+ @internalcode
+ def __call__(self):
+ rv = concat(self._stack[self._depth](self._context))
+ if self._context.eval_ctx.autoescape:
+ rv = Markup(rv)
+ return rv
+
+
@implements_iterator
class LoopContext:
"""A wrapper iterable for dynamic ``for`` loops, with information
about the loop and iteration.
"""
-
+
#: Current iteration of the loop, starting at 0.
index0 = -1
- _length = None
+ _length = None
_after = missing
_current = missing
_before = missing
_last_changed_value = missing
-
+
def __init__(self, iterable, undefined, recurse=None, depth0=0):
"""
:param iterable: Iterable to wrap.
@@ -401,68 +401,68 @@ class LoopContext:
"""
self._iterable = iterable
self._iterator = self._to_iterator(iterable)
- self._undefined = undefined
- self._recurse = recurse
+ self._undefined = undefined
+ self._recurse = recurse
#: How many levels deep a recursive loop currently is, starting at 0.
- self.depth0 = depth0
-
+ self.depth0 = depth0
+
@staticmethod
def _to_iterator(iterable):
return iter(iterable)
-
+
@property
def length(self):
"""Length of the iterable.
-
+
If the iterable is a generator or otherwise does not have a
size, it is eagerly evaluated to get a size.
"""
if self._length is not None:
return self._length
-
+
try:
self._length = len(self._iterable)
except TypeError:
iterable = list(self._iterator)
self._iterator = self._to_iterator(iterable)
self._length = len(iterable) + self.index + (self._after is not missing)
-
+
return self._length
-
- def __len__(self):
- return self.length
-
+
+ def __len__(self):
+ return self.length
+
@property
def depth(self):
"""How many levels deep a recursive loop currently is, starting at 1."""
return self.depth0 + 1
-
+
@property
def index(self):
"""Current iteration of the loop, starting at 1."""
return self.index0 + 1
-
+
@property
def revindex0(self):
"""Number of iterations from the end of the loop, ending at 0.
-
+
Requires calculating :attr:`length`.
"""
return self.length - self.index
-
+
@property
def revindex(self):
"""Number of iterations from the end of the loop, ending at 1.
-
+
Requires calculating :attr:`length`.
"""
return self.length - self.index0
-
+
@property
def first(self):
"""Whether this is the first iteration of the loop."""
return self.index0 == 0
-
+
def _peek_next(self):
"""Return the next element in the iterable, or :data:`missing`
if the iterable is exhausted. Only peeks one item ahead, caching
@@ -475,16 +475,16 @@ class LoopContext:
self._after = next(self._iterator, missing)
return self._after
- @property
+ @property
def last(self):
"""Whether this is the last iteration of the loop.
-
+
Causes the iterable to advance early. See
:func:`itertools.groupby` for issues this can cause.
The :func:`groupby` filter avoids that issue.
"""
return self._peek_next() is missing
-
+
@property
def previtem(self):
"""The item in the previous iteration. Undefined during the
@@ -492,20 +492,20 @@ class LoopContext:
"""
if self.first:
return self._undefined("there is no previous item")
-
+
return self._before
-
+
@property
def nextitem(self):
"""The item in the next iteration. Undefined during the last
iteration.
-
+
Causes the iterable to advance early. See
:func:`itertools.groupby` for issues this can cause.
The :func:`groupby` filter avoids that issue.
"""
rv = self._peek_next()
-
+
if rv is missing:
return self._undefined("there is no next item")
@@ -534,21 +534,21 @@ class LoopContext:
return False
- def __iter__(self):
- return self
-
- def __next__(self):
+ def __iter__(self):
+ return self
+
+ def __next__(self):
if self._after is not missing:
rv = self._after
self._after = missing
else:
rv = next(self._iterator)
-
+
self.index0 += 1
self._before = self._current
self._current = rv
return rv, self
-
+
@internalcode
def __call__(self, iterable):
"""When iterating over nested data, render the body of the loop
@@ -567,9 +567,9 @@ class LoopContext:
return "<%s %d/%d>" % (self.__class__.__name__, self.index, self.length)
-class Macro(object):
- """Wraps a macro function."""
-
+class Macro(object):
+ """Wraps a macro function."""
+
def __init__(
self,
environment,
@@ -581,79 +581,79 @@ class Macro(object):
caller,
default_autoescape=None,
):
- self._environment = environment
- self._func = func
- self._argument_count = len(arguments)
- self.name = name
- self.arguments = arguments
- self.catch_kwargs = catch_kwargs
- self.catch_varargs = catch_varargs
- self.caller = caller
+ self._environment = environment
+ self._func = func
+ self._argument_count = len(arguments)
+ self.name = name
+ self.arguments = arguments
+ self.catch_kwargs = catch_kwargs
+ self.catch_varargs = catch_varargs
+ self.caller = caller
self.explicit_caller = "caller" in arguments
- if default_autoescape is None:
- default_autoescape = environment.autoescape
- self._default_autoescape = default_autoescape
-
- @internalcode
- @evalcontextfunction
- def __call__(self, *args, **kwargs):
- # This requires a bit of explanation, In the past we used to
- # decide largely based on compile-time information if a macro is
- # safe or unsafe. While there was a volatile mode it was largely
- # unused for deciding on escaping. This turns out to be
+ if default_autoescape is None:
+ default_autoescape = environment.autoescape
+ self._default_autoescape = default_autoescape
+
+ @internalcode
+ @evalcontextfunction
+ def __call__(self, *args, **kwargs):
+ # This requires a bit of explanation, In the past we used to
+ # decide largely based on compile-time information if a macro is
+ # safe or unsafe. While there was a volatile mode it was largely
+ # unused for deciding on escaping. This turns out to be
# problematic for macros because whether a macro is safe depends not
# on the escape mode when it was defined, but rather when it was used.
- #
- # Because however we export macros from the module system and
- # there are historic callers that do not pass an eval context (and
- # will continue to not pass one), we need to perform an instance
- # check here.
- #
- # This is considered safe because an eval context is not a valid
+ #
+ # Because however we export macros from the module system and
+ # there are historic callers that do not pass an eval context (and
+ # will continue to not pass one), we need to perform an instance
+ # check here.
+ #
+ # This is considered safe because an eval context is not a valid
# argument to callables otherwise anyway. Worst case here is
- # that if no eval context is passed we fall back to the compile
- # time autoescape flag.
- if args and isinstance(args[0], EvalContext):
- autoescape = args[0].autoescape
- args = args[1:]
- else:
- autoescape = self._default_autoescape
-
- # try to consume the positional arguments
+ # that if no eval context is passed we fall back to the compile
+ # time autoescape flag.
+ if args and isinstance(args[0], EvalContext):
+ autoescape = args[0].autoescape
+ args = args[1:]
+ else:
+ autoescape = self._default_autoescape
+
+ # try to consume the positional arguments
arguments = list(args[: self._argument_count])
- off = len(arguments)
-
- # For information why this is necessary refer to the handling
- # of caller in the `macro_body` handler in the compiler.
- found_caller = False
-
- # if the number of arguments consumed is not the number of
- # arguments expected we start filling in keyword arguments
- # and defaults.
- if off != self._argument_count:
+ off = len(arguments)
+
+ # For information why this is necessary refer to the handling
+ # of caller in the `macro_body` handler in the compiler.
+ found_caller = False
+
+ # if the number of arguments consumed is not the number of
+ # arguments expected we start filling in keyword arguments
+ # and defaults.
+ if off != self._argument_count:
for name in self.arguments[len(arguments) :]:
- try:
- value = kwargs.pop(name)
- except KeyError:
- value = missing
+ try:
+ value = kwargs.pop(name)
+ except KeyError:
+ value = missing
if name == "caller":
- found_caller = True
- arguments.append(value)
- else:
- found_caller = self.explicit_caller
-
- # it's important that the order of these arguments does not change
- # if not also changed in the compiler's `function_scoping` method.
- # the order is caller, keyword arguments, positional arguments!
- if self.caller and not found_caller:
+ found_caller = True
+ arguments.append(value)
+ else:
+ found_caller = self.explicit_caller
+
+ # it's important that the order of these arguments does not change
+ # if not also changed in the compiler's `function_scoping` method.
+ # the order is caller, keyword arguments, positional arguments!
+ if self.caller and not found_caller:
caller = kwargs.pop("caller", None)
- if caller is None:
+ if caller is None:
caller = self._environment.undefined("No caller defined", name="caller")
- arguments.append(caller)
-
- if self.catch_kwargs:
- arguments.append(kwargs)
- elif kwargs:
+ arguments.append(caller)
+
+ if self.catch_kwargs:
+ arguments.append(kwargs)
+ elif kwargs:
if "caller" in kwargs:
raise TypeError(
"macro %r was invoked with two values for "
@@ -664,46 +664,46 @@ class Macro(object):
"macro %r takes no keyword argument %r"
% (self.name, next(iter(kwargs)))
)
- if self.catch_varargs:
+ if self.catch_varargs:
arguments.append(args[self._argument_count :])
- elif len(args) > self._argument_count:
+ elif len(args) > self._argument_count:
raise TypeError(
"macro %r takes not more than %d argument(s)"
% (self.name, len(self.arguments))
)
-
- return self._invoke(arguments, autoescape)
-
- def _invoke(self, arguments, autoescape):
- """This method is being swapped out by the async implementation."""
- rv = self._func(*arguments)
- if autoescape:
- rv = Markup(rv)
- return rv
-
- def __repr__(self):
+
+ return self._invoke(arguments, autoescape)
+
+ def _invoke(self, arguments, autoescape):
+ """This method is being swapped out by the async implementation."""
+ rv = self._func(*arguments)
+ if autoescape:
+ rv = Markup(rv)
+ return rv
+
+ def __repr__(self):
return "<%s %s>" % (
- self.__class__.__name__,
+ self.__class__.__name__,
self.name is None and "anonymous" or repr(self.name),
- )
-
-
-@implements_to_string
-class Undefined(object):
- """The default undefined type. This undefined type can be printed and
+ )
+
+
+@implements_to_string
+class Undefined(object):
+ """The default undefined type. This undefined type can be printed and
iterated over, but every other access will raise an :exc:`UndefinedError`:
-
- >>> foo = Undefined(name='foo')
- >>> str(foo)
- ''
- >>> not foo
- True
- >>> foo + 42
- Traceback (most recent call last):
- ...
- jinja2.exceptions.UndefinedError: 'foo' is undefined
- """
-
+
+ >>> foo = Undefined(name='foo')
+ >>> str(foo)
+ ''
+ >>> not foo
+ True
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+
__slots__ = (
"_undefined_hint",
"_undefined_obj",
@@ -711,12 +711,12 @@ class Undefined(object):
"_undefined_exception",
)
- def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
- self._undefined_hint = hint
- self._undefined_obj = obj
- self._undefined_name = name
- self._undefined_exception = exc
-
+ def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
+ self._undefined_hint = hint
+ self._undefined_obj = obj
+ self._undefined_name = name
+ self._undefined_exception = exc
+
@property
def _undefined_message(self):
"""Build a message about the undefined value based on how it was
@@ -739,19 +739,19 @@ class Undefined(object):
self._undefined_name,
)
- @internalcode
- def _fail_with_undefined_error(self, *args, **kwargs):
+ @internalcode
+ def _fail_with_undefined_error(self, *args, **kwargs):
"""Raise an :exc:`UndefinedError` when operations are performed
on the undefined value.
- """
+ """
raise self._undefined_exception(self._undefined_message)
-
- @internalcode
- def __getattr__(self, name):
+
+ @internalcode
+ def __getattr__(self, name):
if name[:2] == "__":
- raise AttributeError(name)
- return self._fail_with_undefined_error()
-
+ raise AttributeError(name)
+ return self._fail_with_undefined_error()
+
__add__ = (
__radd__
) = (
@@ -797,121 +797,121 @@ class Undefined(object):
) = (
__complex__
) = __pow__ = __rpow__ = __sub__ = __rsub__ = _fail_with_undefined_error
-
- def __eq__(self, other):
- return type(self) is type(other)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __hash__(self):
- return id(type(self))
-
- def __str__(self):
+
+ def __eq__(self, other):
+ return type(self) is type(other)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return id(type(self))
+
+ def __str__(self):
return u""
-
- def __len__(self):
- return 0
-
- def __iter__(self):
- if 0:
- yield None
-
- def __nonzero__(self):
- return False
-
- __bool__ = __nonzero__
-
- def __repr__(self):
+
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ if 0:
+ yield None
+
+ def __nonzero__(self):
+ return False
+
+ __bool__ = __nonzero__
+
+ def __repr__(self):
return "Undefined"
-
-
-def make_logging_undefined(logger=None, base=None):
- """Given a logger object this returns a new undefined class that will
- log certain failures. It will log iterations and printing. If no
- logger is given a default logger is created.
-
- Example::
-
- logger = logging.getLogger(__name__)
- LoggingUndefined = make_logging_undefined(
- logger=logger,
- base=Undefined
- )
-
- .. versionadded:: 2.8
-
- :param logger: the logger to use. If not provided, a default logger
- is created.
- :param base: the base class to add logging functionality to. This
- defaults to :class:`Undefined`.
- """
- if logger is None:
- import logging
-
- logger = logging.getLogger(__name__)
- logger.addHandler(logging.StreamHandler(sys.stderr))
- if base is None:
- base = Undefined
-
- def _log_message(undef):
- if undef._undefined_hint is None:
- if undef._undefined_obj is missing:
+
+
+def make_logging_undefined(logger=None, base=None):
+ """Given a logger object this returns a new undefined class that will
+ log certain failures. It will log iterations and printing. If no
+ logger is given a default logger is created.
+
+ Example::
+
+ logger = logging.getLogger(__name__)
+ LoggingUndefined = make_logging_undefined(
+ logger=logger,
+ base=Undefined
+ )
+
+ .. versionadded:: 2.8
+
+ :param logger: the logger to use. If not provided, a default logger
+ is created.
+ :param base: the base class to add logging functionality to. This
+ defaults to :class:`Undefined`.
+ """
+ if logger is None:
+ import logging
+
+ logger = logging.getLogger(__name__)
+ logger.addHandler(logging.StreamHandler(sys.stderr))
+ if base is None:
+ base = Undefined
+
+ def _log_message(undef):
+ if undef._undefined_hint is None:
+ if undef._undefined_obj is missing:
hint = "%s is undefined" % undef._undefined_name
- elif not isinstance(undef._undefined_name, string_types):
+ elif not isinstance(undef._undefined_name, string_types):
hint = "%s has no element %s" % (
- object_type_repr(undef._undefined_obj),
+ object_type_repr(undef._undefined_obj),
undef._undefined_name,
)
- else:
+ else:
hint = "%s has no attribute %s" % (
- object_type_repr(undef._undefined_obj),
+ object_type_repr(undef._undefined_obj),
undef._undefined_name,
)
- else:
- hint = undef._undefined_hint
+ else:
+ hint = undef._undefined_hint
logger.warning("Template variable warning: %s", hint)
-
- class LoggingUndefined(base):
- def _fail_with_undefined_error(self, *args, **kwargs):
- try:
- return base._fail_with_undefined_error(self, *args, **kwargs)
- except self._undefined_exception as e:
+
+ class LoggingUndefined(base):
+ def _fail_with_undefined_error(self, *args, **kwargs):
+ try:
+ return base._fail_with_undefined_error(self, *args, **kwargs)
+ except self._undefined_exception as e:
logger.error("Template variable error: %s", str(e))
- raise e
-
- def __str__(self):
- rv = base.__str__(self)
- _log_message(self)
- return rv
-
- def __iter__(self):
- rv = base.__iter__(self)
- _log_message(self)
- return rv
-
- if PY2:
-
- def __nonzero__(self):
- rv = base.__nonzero__(self)
- _log_message(self)
- return rv
-
- def __unicode__(self):
- rv = base.__unicode__(self)
- _log_message(self)
- return rv
-
- else:
-
- def __bool__(self):
- rv = base.__bool__(self)
- _log_message(self)
- return rv
-
- return LoggingUndefined
-
-
+ raise e
+
+ def __str__(self):
+ rv = base.__str__(self)
+ _log_message(self)
+ return rv
+
+ def __iter__(self):
+ rv = base.__iter__(self)
+ _log_message(self)
+ return rv
+
+ if PY2:
+
+ def __nonzero__(self):
+ rv = base.__nonzero__(self)
+ _log_message(self)
+ return rv
+
+ def __unicode__(self):
+ rv = base.__unicode__(self)
+ _log_message(self)
+ return rv
+
+ else:
+
+ def __bool__(self):
+ rv = base.__bool__(self)
+ _log_message(self)
+ return rv
+
+ return LoggingUndefined
+
+
# No @implements_to_string decorator here because __str__
# is not overwritten from Undefined in this class.
# This would cause a recursion error in Python 2.
@@ -942,56 +942,56 @@ class ChainableUndefined(Undefined):
__getitem__ = __getattr__
-@implements_to_string
-class DebugUndefined(Undefined):
- """An undefined that returns the debug info when printed.
-
- >>> foo = DebugUndefined(name='foo')
- >>> str(foo)
- '{{ foo }}'
- >>> not foo
- True
- >>> foo + 42
- Traceback (most recent call last):
- ...
- jinja2.exceptions.UndefinedError: 'foo' is undefined
- """
-
- __slots__ = ()
-
- def __str__(self):
- if self._undefined_hint is None:
- if self._undefined_obj is missing:
+@implements_to_string
+class DebugUndefined(Undefined):
+ """An undefined that returns the debug info when printed.
+
+ >>> foo = DebugUndefined(name='foo')
+ >>> str(foo)
+ '{{ foo }}'
+ >>> not foo
+ True
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+
+ __slots__ = ()
+
+ def __str__(self):
+ if self._undefined_hint is None:
+ if self._undefined_obj is missing:
return u"{{ %s }}" % self._undefined_name
return "{{ no such element: %s[%r] }}" % (
- object_type_repr(self._undefined_obj),
+ object_type_repr(self._undefined_obj),
self._undefined_name,
- )
+ )
return u"{{ undefined value printed: %s }}" % self._undefined_hint
-
-
-@implements_to_string
-class StrictUndefined(Undefined):
- """An undefined that barks on print and iteration as well as boolean
- tests and all kinds of comparisons. In other words: you can do nothing
- with it except checking if it's defined using the `defined` test.
-
- >>> foo = StrictUndefined(name='foo')
- >>> str(foo)
- Traceback (most recent call last):
- ...
- jinja2.exceptions.UndefinedError: 'foo' is undefined
- >>> not foo
- Traceback (most recent call last):
- ...
- jinja2.exceptions.UndefinedError: 'foo' is undefined
- >>> foo + 42
- Traceback (most recent call last):
- ...
- jinja2.exceptions.UndefinedError: 'foo' is undefined
- """
-
- __slots__ = ()
+
+
+@implements_to_string
+class StrictUndefined(Undefined):
+ """An undefined that barks on print and iteration as well as boolean
+ tests and all kinds of comparisons. In other words: you can do nothing
+ with it except checking if it's defined using the `defined` test.
+
+ >>> foo = StrictUndefined(name='foo')
+ >>> str(foo)
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ >>> not foo
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ >>> foo + 42
+ Traceback (most recent call last):
+ ...
+ jinja2.exceptions.UndefinedError: 'foo' is undefined
+ """
+
+ __slots__ = ()
__iter__ = (
__str__
) = (
@@ -999,10 +999,10 @@ class StrictUndefined(Undefined):
) = (
__nonzero__
) = __eq__ = __ne__ = __bool__ = __hash__ = Undefined._fail_with_undefined_error
-
-
-# remove remaining slots attributes, after the metaclass did the magic they
-# are unneeded and irritating as they contain wrong data for the subclasses.
+
+
+# remove remaining slots attributes, after the metaclass did the magic they
+# are unneeded and irritating as they contain wrong data for the subclasses.
del (
Undefined.__slots__,
ChainableUndefined.__slots__,