xref: /aosp_15_r20/external/libchrome/third_party/jinja2/runtime.py (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker# -*- coding: utf-8 -*-
2*635a8641SAndroid Build Coastguard Worker"""
3*635a8641SAndroid Build Coastguard Worker    jinja2.runtime
4*635a8641SAndroid Build Coastguard Worker    ~~~~~~~~~~~~~~
5*635a8641SAndroid Build Coastguard Worker
6*635a8641SAndroid Build Coastguard Worker    Runtime helpers.
7*635a8641SAndroid Build Coastguard Worker
8*635a8641SAndroid Build Coastguard Worker    :copyright: (c) 2017 by the Jinja Team.
9*635a8641SAndroid Build Coastguard Worker    :license: BSD.
10*635a8641SAndroid Build Coastguard Worker"""
11*635a8641SAndroid Build Coastguard Workerimport sys
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard Workerfrom itertools import chain
14*635a8641SAndroid Build Coastguard Workerfrom types import MethodType
15*635a8641SAndroid Build Coastguard Worker
16*635a8641SAndroid Build Coastguard Workerfrom jinja2.nodes import EvalContext, _context_function_types
17*635a8641SAndroid Build Coastguard Workerfrom jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
18*635a8641SAndroid Build Coastguard Worker     internalcode, object_type_repr, evalcontextfunction, Namespace
19*635a8641SAndroid Build Coastguard Workerfrom jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
20*635a8641SAndroid Build Coastguard Worker     TemplateNotFound
21*635a8641SAndroid Build Coastguard Workerfrom jinja2._compat import imap, text_type, iteritems, \
22*635a8641SAndroid Build Coastguard Worker     implements_iterator, implements_to_string, string_types, PY2, \
23*635a8641SAndroid Build Coastguard Worker     with_metaclass
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker# these variables are exported to the template runtime
27*635a8641SAndroid Build Coastguard Worker__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
28*635a8641SAndroid Build Coastguard Worker           'TemplateRuntimeError', 'missing', 'concat', 'escape',
29*635a8641SAndroid Build Coastguard Worker           'markup_join', 'unicode_join', 'to_string', 'identity',
30*635a8641SAndroid Build Coastguard Worker           'TemplateNotFound', 'Namespace']
31*635a8641SAndroid Build Coastguard Worker
32*635a8641SAndroid Build Coastguard Worker#: the name of the function that is used to convert something into
33*635a8641SAndroid Build Coastguard Worker#: a string.  We can just use the text type here.
34*635a8641SAndroid Build Coastguard Workerto_string = text_type
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker#: the identity function.  Useful for certain things in the environment
37*635a8641SAndroid Build Coastguard Workeridentity = lambda x: x
38*635a8641SAndroid Build Coastguard Worker
39*635a8641SAndroid Build Coastguard Worker_first_iteration = object()
40*635a8641SAndroid Build Coastguard Worker_last_iteration = object()
41*635a8641SAndroid Build Coastguard Worker
42*635a8641SAndroid Build Coastguard Worker
43*635a8641SAndroid Build Coastguard Workerdef markup_join(seq):
44*635a8641SAndroid Build Coastguard Worker    """Concatenation that escapes if necessary and converts to unicode."""
45*635a8641SAndroid Build Coastguard Worker    buf = []
46*635a8641SAndroid Build Coastguard Worker    iterator = imap(soft_unicode, seq)
47*635a8641SAndroid Build Coastguard Worker    for arg in iterator:
48*635a8641SAndroid Build Coastguard Worker        buf.append(arg)
49*635a8641SAndroid Build Coastguard Worker        if hasattr(arg, '__html__'):
50*635a8641SAndroid Build Coastguard Worker            return Markup(u'').join(chain(buf, iterator))
51*635a8641SAndroid Build Coastguard Worker    return concat(buf)
52*635a8641SAndroid Build Coastguard Worker
53*635a8641SAndroid Build Coastguard Worker
54*635a8641SAndroid Build Coastguard Workerdef unicode_join(seq):
55*635a8641SAndroid Build Coastguard Worker    """Simple args to unicode conversion and concatenation."""
56*635a8641SAndroid Build Coastguard Worker    return concat(imap(text_type, seq))
57*635a8641SAndroid Build Coastguard Worker
58*635a8641SAndroid Build Coastguard Worker
59*635a8641SAndroid Build Coastguard Workerdef new_context(environment, template_name, blocks, vars=None,
60*635a8641SAndroid Build Coastguard Worker                shared=None, globals=None, locals=None):
61*635a8641SAndroid Build Coastguard Worker    """Internal helper to for context creation."""
62*635a8641SAndroid Build Coastguard Worker    if vars is None:
63*635a8641SAndroid Build Coastguard Worker        vars = {}
64*635a8641SAndroid Build Coastguard Worker    if shared:
65*635a8641SAndroid Build Coastguard Worker        parent = vars
66*635a8641SAndroid Build Coastguard Worker    else:
67*635a8641SAndroid Build Coastguard Worker        parent = dict(globals or (), **vars)
68*635a8641SAndroid Build Coastguard Worker    if locals:
69*635a8641SAndroid Build Coastguard Worker        # if the parent is shared a copy should be created because
70*635a8641SAndroid Build Coastguard Worker        # we don't want to modify the dict passed
71*635a8641SAndroid Build Coastguard Worker        if shared:
72*635a8641SAndroid Build Coastguard Worker            parent = dict(parent)
73*635a8641SAndroid Build Coastguard Worker        for key, value in iteritems(locals):
74*635a8641SAndroid Build Coastguard Worker            if value is not missing:
75*635a8641SAndroid Build Coastguard Worker                parent[key] = value
76*635a8641SAndroid Build Coastguard Worker    return environment.context_class(environment, parent, template_name,
77*635a8641SAndroid Build Coastguard Worker                                     blocks)
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker
80*635a8641SAndroid Build Coastguard Workerclass TemplateReference(object):
81*635a8641SAndroid Build Coastguard Worker    """The `self` in templates."""
82*635a8641SAndroid Build Coastguard Worker
83*635a8641SAndroid Build Coastguard Worker    def __init__(self, context):
84*635a8641SAndroid Build Coastguard Worker        self.__context = context
85*635a8641SAndroid Build Coastguard Worker
86*635a8641SAndroid Build Coastguard Worker    def __getitem__(self, name):
87*635a8641SAndroid Build Coastguard Worker        blocks = self.__context.blocks[name]
88*635a8641SAndroid Build Coastguard Worker        return BlockReference(name, self.__context, blocks, 0)
89*635a8641SAndroid Build Coastguard Worker
90*635a8641SAndroid Build Coastguard Worker    def __repr__(self):
91*635a8641SAndroid Build Coastguard Worker        return '<%s %r>' % (
92*635a8641SAndroid Build Coastguard Worker            self.__class__.__name__,
93*635a8641SAndroid Build Coastguard Worker            self.__context.name
94*635a8641SAndroid Build Coastguard Worker        )
95*635a8641SAndroid Build Coastguard Worker
96*635a8641SAndroid Build Coastguard Worker
97*635a8641SAndroid Build Coastguard Workerdef _get_func(x):
98*635a8641SAndroid Build Coastguard Worker    return getattr(x, '__func__', x)
99*635a8641SAndroid Build Coastguard Worker
100*635a8641SAndroid Build Coastguard Worker
101*635a8641SAndroid Build Coastguard Workerclass ContextMeta(type):
102*635a8641SAndroid Build Coastguard Worker
103*635a8641SAndroid Build Coastguard Worker    def __new__(cls, name, bases, d):
104*635a8641SAndroid Build Coastguard Worker        rv = type.__new__(cls, name, bases, d)
105*635a8641SAndroid Build Coastguard Worker        if bases == ():
106*635a8641SAndroid Build Coastguard Worker            return rv
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker        resolve = _get_func(rv.resolve)
109*635a8641SAndroid Build Coastguard Worker        default_resolve = _get_func(Context.resolve)
110*635a8641SAndroid Build Coastguard Worker        resolve_or_missing = _get_func(rv.resolve_or_missing)
111*635a8641SAndroid Build Coastguard Worker        default_resolve_or_missing = _get_func(Context.resolve_or_missing)
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker        # If we have a changed resolve but no changed default or missing
114*635a8641SAndroid Build Coastguard Worker        # resolve we invert the call logic.
115*635a8641SAndroid Build Coastguard Worker        if resolve is not default_resolve and \
116*635a8641SAndroid Build Coastguard Worker           resolve_or_missing is default_resolve_or_missing:
117*635a8641SAndroid Build Coastguard Worker            rv._legacy_resolve_mode = True
118*635a8641SAndroid Build Coastguard Worker        elif resolve is default_resolve and \
119*635a8641SAndroid Build Coastguard Worker             resolve_or_missing is default_resolve_or_missing:
120*635a8641SAndroid Build Coastguard Worker            rv._fast_resolve_mode = True
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard Worker        return rv
123*635a8641SAndroid Build Coastguard Worker
124*635a8641SAndroid Build Coastguard Worker
125*635a8641SAndroid Build Coastguard Workerdef resolve_or_missing(context, key, missing=missing):
126*635a8641SAndroid Build Coastguard Worker    if key in context.vars:
127*635a8641SAndroid Build Coastguard Worker        return context.vars[key]
128*635a8641SAndroid Build Coastguard Worker    if key in context.parent:
129*635a8641SAndroid Build Coastguard Worker        return context.parent[key]
130*635a8641SAndroid Build Coastguard Worker    return missing
131*635a8641SAndroid Build Coastguard Worker
132*635a8641SAndroid Build Coastguard Worker
133*635a8641SAndroid Build Coastguard Workerclass Context(with_metaclass(ContextMeta)):
134*635a8641SAndroid Build Coastguard Worker    """The template context holds the variables of a template.  It stores the
135*635a8641SAndroid Build Coastguard Worker    values passed to the template and also the names the template exports.
136*635a8641SAndroid Build Coastguard Worker    Creating instances is neither supported nor useful as it's created
137*635a8641SAndroid Build Coastguard Worker    automatically at various stages of the template evaluation and should not
138*635a8641SAndroid Build Coastguard Worker    be created by hand.
139*635a8641SAndroid Build Coastguard Worker
140*635a8641SAndroid Build Coastguard Worker    The context is immutable.  Modifications on :attr:`parent` **must not**
141*635a8641SAndroid Build Coastguard Worker    happen and modifications on :attr:`vars` are allowed from generated
142*635a8641SAndroid Build Coastguard Worker    template code only.  Template filters and global functions marked as
143*635a8641SAndroid Build Coastguard Worker    :func:`contextfunction`\\s get the active context passed as first argument
144*635a8641SAndroid Build Coastguard Worker    and are allowed to access the context read-only.
145*635a8641SAndroid Build Coastguard Worker
146*635a8641SAndroid Build Coastguard Worker    The template context supports read only dict operations (`get`,
147*635a8641SAndroid Build Coastguard Worker    `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
148*635a8641SAndroid Build Coastguard Worker    `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
149*635a8641SAndroid Build Coastguard Worker    method that doesn't fail with a `KeyError` but returns an
150*635a8641SAndroid Build Coastguard Worker    :class:`Undefined` object for missing variables.
151*635a8641SAndroid Build Coastguard Worker    """
152*635a8641SAndroid Build Coastguard Worker    # XXX: we want to eventually make this be a deprecation warning and
153*635a8641SAndroid Build Coastguard Worker    # remove it.
154*635a8641SAndroid Build Coastguard Worker    _legacy_resolve_mode = False
155*635a8641SAndroid Build Coastguard Worker    _fast_resolve_mode = False
156*635a8641SAndroid Build Coastguard Worker
157*635a8641SAndroid Build Coastguard Worker    def __init__(self, environment, parent, name, blocks):
158*635a8641SAndroid Build Coastguard Worker        self.parent = parent
159*635a8641SAndroid Build Coastguard Worker        self.vars = {}
160*635a8641SAndroid Build Coastguard Worker        self.environment = environment
161*635a8641SAndroid Build Coastguard Worker        self.eval_ctx = EvalContext(self.environment, name)
162*635a8641SAndroid Build Coastguard Worker        self.exported_vars = set()
163*635a8641SAndroid Build Coastguard Worker        self.name = name
164*635a8641SAndroid Build Coastguard Worker
165*635a8641SAndroid Build Coastguard Worker        # create the initial mapping of blocks.  Whenever template inheritance
166*635a8641SAndroid Build Coastguard Worker        # takes place the runtime will update this mapping with the new blocks
167*635a8641SAndroid Build Coastguard Worker        # from the template.
168*635a8641SAndroid Build Coastguard Worker        self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
169*635a8641SAndroid Build Coastguard Worker
170*635a8641SAndroid Build Coastguard Worker        # In case we detect the fast resolve mode we can set up an alias
171*635a8641SAndroid Build Coastguard Worker        # here that bypasses the legacy code logic.
172*635a8641SAndroid Build Coastguard Worker        if self._fast_resolve_mode:
173*635a8641SAndroid Build Coastguard Worker            self.resolve_or_missing = MethodType(resolve_or_missing, self)
174*635a8641SAndroid Build Coastguard Worker
175*635a8641SAndroid Build Coastguard Worker    def super(self, name, current):
176*635a8641SAndroid Build Coastguard Worker        """Render a parent block."""
177*635a8641SAndroid Build Coastguard Worker        try:
178*635a8641SAndroid Build Coastguard Worker            blocks = self.blocks[name]
179*635a8641SAndroid Build Coastguard Worker            index = blocks.index(current) + 1
180*635a8641SAndroid Build Coastguard Worker            blocks[index]
181*635a8641SAndroid Build Coastguard Worker        except LookupError:
182*635a8641SAndroid Build Coastguard Worker            return self.environment.undefined('there is no parent block '
183*635a8641SAndroid Build Coastguard Worker                                              'called %r.' % name,
184*635a8641SAndroid Build Coastguard Worker                                              name='super')
185*635a8641SAndroid Build Coastguard Worker        return BlockReference(name, self, blocks, index)
186*635a8641SAndroid Build Coastguard Worker
187*635a8641SAndroid Build Coastguard Worker    def get(self, key, default=None):
188*635a8641SAndroid Build Coastguard Worker        """Returns an item from the template context, if it doesn't exist
189*635a8641SAndroid Build Coastguard Worker        `default` is returned.
190*635a8641SAndroid Build Coastguard Worker        """
191*635a8641SAndroid Build Coastguard Worker        try:
192*635a8641SAndroid Build Coastguard Worker            return self[key]
193*635a8641SAndroid Build Coastguard Worker        except KeyError:
194*635a8641SAndroid Build Coastguard Worker            return default
195*635a8641SAndroid Build Coastguard Worker
196*635a8641SAndroid Build Coastguard Worker    def resolve(self, key):
197*635a8641SAndroid Build Coastguard Worker        """Looks up a variable like `__getitem__` or `get` but returns an
198*635a8641SAndroid Build Coastguard Worker        :class:`Undefined` object with the name of the name looked up.
199*635a8641SAndroid Build Coastguard Worker        """
200*635a8641SAndroid Build Coastguard Worker        if self._legacy_resolve_mode:
201*635a8641SAndroid Build Coastguard Worker            rv = resolve_or_missing(self, key)
202*635a8641SAndroid Build Coastguard Worker        else:
203*635a8641SAndroid Build Coastguard Worker            rv = self.resolve_or_missing(key)
204*635a8641SAndroid Build Coastguard Worker        if rv is missing:
205*635a8641SAndroid Build Coastguard Worker            return self.environment.undefined(name=key)
206*635a8641SAndroid Build Coastguard Worker        return rv
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard Worker    def resolve_or_missing(self, key):
209*635a8641SAndroid Build Coastguard Worker        """Resolves a variable like :meth:`resolve` but returns the
210*635a8641SAndroid Build Coastguard Worker        special `missing` value if it cannot be found.
211*635a8641SAndroid Build Coastguard Worker        """
212*635a8641SAndroid Build Coastguard Worker        if self._legacy_resolve_mode:
213*635a8641SAndroid Build Coastguard Worker            rv = self.resolve(key)
214*635a8641SAndroid Build Coastguard Worker            if isinstance(rv, Undefined):
215*635a8641SAndroid Build Coastguard Worker                rv = missing
216*635a8641SAndroid Build Coastguard Worker            return rv
217*635a8641SAndroid Build Coastguard Worker        return resolve_or_missing(self, key)
218*635a8641SAndroid Build Coastguard Worker
219*635a8641SAndroid Build Coastguard Worker    def get_exported(self):
220*635a8641SAndroid Build Coastguard Worker        """Get a new dict with the exported variables."""
221*635a8641SAndroid Build Coastguard Worker        return dict((k, self.vars[k]) for k in self.exported_vars)
222*635a8641SAndroid Build Coastguard Worker
223*635a8641SAndroid Build Coastguard Worker    def get_all(self):
224*635a8641SAndroid Build Coastguard Worker        """Return the complete context as dict including the exported
225*635a8641SAndroid Build Coastguard Worker        variables.  For optimizations reasons this might not return an
226*635a8641SAndroid Build Coastguard Worker        actual copy so be careful with using it.
227*635a8641SAndroid Build Coastguard Worker        """
228*635a8641SAndroid Build Coastguard Worker        if not self.vars:
229*635a8641SAndroid Build Coastguard Worker            return self.parent
230*635a8641SAndroid Build Coastguard Worker        if not self.parent:
231*635a8641SAndroid Build Coastguard Worker            return self.vars
232*635a8641SAndroid Build Coastguard Worker        return dict(self.parent, **self.vars)
233*635a8641SAndroid Build Coastguard Worker
234*635a8641SAndroid Build Coastguard Worker    @internalcode
235*635a8641SAndroid Build Coastguard Worker    def call(__self, __obj, *args, **kwargs):
236*635a8641SAndroid Build Coastguard Worker        """Call the callable with the arguments and keyword arguments
237*635a8641SAndroid Build Coastguard Worker        provided but inject the active context or environment as first
238*635a8641SAndroid Build Coastguard Worker        argument if the callable is a :func:`contextfunction` or
239*635a8641SAndroid Build Coastguard Worker        :func:`environmentfunction`.
240*635a8641SAndroid Build Coastguard Worker        """
241*635a8641SAndroid Build Coastguard Worker        if __debug__:
242*635a8641SAndroid Build Coastguard Worker            __traceback_hide__ = True  # noqa
243*635a8641SAndroid Build Coastguard Worker
244*635a8641SAndroid Build Coastguard Worker        # Allow callable classes to take a context
245*635a8641SAndroid Build Coastguard Worker        if hasattr(__obj, '__call__'):
246*635a8641SAndroid Build Coastguard Worker            fn = __obj.__call__
247*635a8641SAndroid Build Coastguard Worker            for fn_type in ('contextfunction',
248*635a8641SAndroid Build Coastguard Worker                            'evalcontextfunction',
249*635a8641SAndroid Build Coastguard Worker                            'environmentfunction'):
250*635a8641SAndroid Build Coastguard Worker                if hasattr(fn, fn_type):
251*635a8641SAndroid Build Coastguard Worker                    __obj = fn
252*635a8641SAndroid Build Coastguard Worker                    break
253*635a8641SAndroid Build Coastguard Worker
254*635a8641SAndroid Build Coastguard Worker        if isinstance(__obj, _context_function_types):
255*635a8641SAndroid Build Coastguard Worker            if getattr(__obj, 'contextfunction', 0):
256*635a8641SAndroid Build Coastguard Worker                args = (__self,) + args
257*635a8641SAndroid Build Coastguard Worker            elif getattr(__obj, 'evalcontextfunction', 0):
258*635a8641SAndroid Build Coastguard Worker                args = (__self.eval_ctx,) + args
259*635a8641SAndroid Build Coastguard Worker            elif getattr(__obj, 'environmentfunction', 0):
260*635a8641SAndroid Build Coastguard Worker                args = (__self.environment,) + args
261*635a8641SAndroid Build Coastguard Worker        try:
262*635a8641SAndroid Build Coastguard Worker            return __obj(*args, **kwargs)
263*635a8641SAndroid Build Coastguard Worker        except StopIteration:
264*635a8641SAndroid Build Coastguard Worker            return __self.environment.undefined('value was undefined because '
265*635a8641SAndroid Build Coastguard Worker                                                'a callable raised a '
266*635a8641SAndroid Build Coastguard Worker                                                'StopIteration exception')
267*635a8641SAndroid Build Coastguard Worker
268*635a8641SAndroid Build Coastguard Worker    def derived(self, locals=None):
269*635a8641SAndroid Build Coastguard Worker        """Internal helper function to create a derived context.  This is
270*635a8641SAndroid Build Coastguard Worker        used in situations where the system needs a new context in the same
271*635a8641SAndroid Build Coastguard Worker        template that is independent.
272*635a8641SAndroid Build Coastguard Worker        """
273*635a8641SAndroid Build Coastguard Worker        context = new_context(self.environment, self.name, {},
274*635a8641SAndroid Build Coastguard Worker                              self.get_all(), True, None, locals)
275*635a8641SAndroid Build Coastguard Worker        context.eval_ctx = self.eval_ctx
276*635a8641SAndroid Build Coastguard Worker        context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
277*635a8641SAndroid Build Coastguard Worker        return context
278*635a8641SAndroid Build Coastguard Worker
279*635a8641SAndroid Build Coastguard Worker    def _all(meth):
280*635a8641SAndroid Build Coastguard Worker        proxy = lambda self: getattr(self.get_all(), meth)()
281*635a8641SAndroid Build Coastguard Worker        proxy.__doc__ = getattr(dict, meth).__doc__
282*635a8641SAndroid Build Coastguard Worker        proxy.__name__ = meth
283*635a8641SAndroid Build Coastguard Worker        return proxy
284*635a8641SAndroid Build Coastguard Worker
285*635a8641SAndroid Build Coastguard Worker    keys = _all('keys')
286*635a8641SAndroid Build Coastguard Worker    values = _all('values')
287*635a8641SAndroid Build Coastguard Worker    items = _all('items')
288*635a8641SAndroid Build Coastguard Worker
289*635a8641SAndroid Build Coastguard Worker    # not available on python 3
290*635a8641SAndroid Build Coastguard Worker    if PY2:
291*635a8641SAndroid Build Coastguard Worker        iterkeys = _all('iterkeys')
292*635a8641SAndroid Build Coastguard Worker        itervalues = _all('itervalues')
293*635a8641SAndroid Build Coastguard Worker        iteritems = _all('iteritems')
294*635a8641SAndroid Build Coastguard Worker    del _all
295*635a8641SAndroid Build Coastguard Worker
296*635a8641SAndroid Build Coastguard Worker    def __contains__(self, name):
297*635a8641SAndroid Build Coastguard Worker        return name in self.vars or name in self.parent
298*635a8641SAndroid Build Coastguard Worker
299*635a8641SAndroid Build Coastguard Worker    def __getitem__(self, key):
300*635a8641SAndroid Build Coastguard Worker        """Lookup a variable or raise `KeyError` if the variable is
301*635a8641SAndroid Build Coastguard Worker        undefined.
302*635a8641SAndroid Build Coastguard Worker        """
303*635a8641SAndroid Build Coastguard Worker        item = self.resolve_or_missing(key)
304*635a8641SAndroid Build Coastguard Worker        if item is missing:
305*635a8641SAndroid Build Coastguard Worker            raise KeyError(key)
306*635a8641SAndroid Build Coastguard Worker        return item
307*635a8641SAndroid Build Coastguard Worker
308*635a8641SAndroid Build Coastguard Worker    def __repr__(self):
309*635a8641SAndroid Build Coastguard Worker        return '<%s %s of %r>' % (
310*635a8641SAndroid Build Coastguard Worker            self.__class__.__name__,
311*635a8641SAndroid Build Coastguard Worker            repr(self.get_all()),
312*635a8641SAndroid Build Coastguard Worker            self.name
313*635a8641SAndroid Build Coastguard Worker        )
314*635a8641SAndroid Build Coastguard Worker
315*635a8641SAndroid Build Coastguard Worker
316*635a8641SAndroid Build Coastguard Worker# register the context as mapping if possible
317*635a8641SAndroid Build Coastguard Workertry:
318*635a8641SAndroid Build Coastguard Worker    from collections import Mapping
319*635a8641SAndroid Build Coastguard Worker    Mapping.register(Context)
320*635a8641SAndroid Build Coastguard Workerexcept ImportError:
321*635a8641SAndroid Build Coastguard Worker    pass
322*635a8641SAndroid Build Coastguard Worker
323*635a8641SAndroid Build Coastguard Worker
324*635a8641SAndroid Build Coastguard Workerclass BlockReference(object):
325*635a8641SAndroid Build Coastguard Worker    """One block on a template reference."""
326*635a8641SAndroid Build Coastguard Worker
327*635a8641SAndroid Build Coastguard Worker    def __init__(self, name, context, stack, depth):
328*635a8641SAndroid Build Coastguard Worker        self.name = name
329*635a8641SAndroid Build Coastguard Worker        self._context = context
330*635a8641SAndroid Build Coastguard Worker        self._stack = stack
331*635a8641SAndroid Build Coastguard Worker        self._depth = depth
332*635a8641SAndroid Build Coastguard Worker
333*635a8641SAndroid Build Coastguard Worker    @property
334*635a8641SAndroid Build Coastguard Worker    def super(self):
335*635a8641SAndroid Build Coastguard Worker        """Super the block."""
336*635a8641SAndroid Build Coastguard Worker        if self._depth + 1 >= len(self._stack):
337*635a8641SAndroid Build Coastguard Worker            return self._context.environment. \
338*635a8641SAndroid Build Coastguard Worker                undefined('there is no parent block called %r.' %
339*635a8641SAndroid Build Coastguard Worker                          self.name, name='super')
340*635a8641SAndroid Build Coastguard Worker        return BlockReference(self.name, self._context, self._stack,
341*635a8641SAndroid Build Coastguard Worker                              self._depth + 1)
342*635a8641SAndroid Build Coastguard Worker
343*635a8641SAndroid Build Coastguard Worker    @internalcode
344*635a8641SAndroid Build Coastguard Worker    def __call__(self):
345*635a8641SAndroid Build Coastguard Worker        rv = concat(self._stack[self._depth](self._context))
346*635a8641SAndroid Build Coastguard Worker        if self._context.eval_ctx.autoescape:
347*635a8641SAndroid Build Coastguard Worker            rv = Markup(rv)
348*635a8641SAndroid Build Coastguard Worker        return rv
349*635a8641SAndroid Build Coastguard Worker
350*635a8641SAndroid Build Coastguard Worker
351*635a8641SAndroid Build Coastguard Workerclass LoopContextBase(object):
352*635a8641SAndroid Build Coastguard Worker    """A loop context for dynamic iteration."""
353*635a8641SAndroid Build Coastguard Worker
354*635a8641SAndroid Build Coastguard Worker    _before = _first_iteration
355*635a8641SAndroid Build Coastguard Worker    _current = _first_iteration
356*635a8641SAndroid Build Coastguard Worker    _after = _last_iteration
357*635a8641SAndroid Build Coastguard Worker    _length = None
358*635a8641SAndroid Build Coastguard Worker
359*635a8641SAndroid Build Coastguard Worker    def __init__(self, undefined, recurse=None, depth0=0):
360*635a8641SAndroid Build Coastguard Worker        self._undefined = undefined
361*635a8641SAndroid Build Coastguard Worker        self._recurse = recurse
362*635a8641SAndroid Build Coastguard Worker        self.index0 = -1
363*635a8641SAndroid Build Coastguard Worker        self.depth0 = depth0
364*635a8641SAndroid Build Coastguard Worker        self._last_checked_value = missing
365*635a8641SAndroid Build Coastguard Worker
366*635a8641SAndroid Build Coastguard Worker    def cycle(self, *args):
367*635a8641SAndroid Build Coastguard Worker        """Cycles among the arguments with the current loop index."""
368*635a8641SAndroid Build Coastguard Worker        if not args:
369*635a8641SAndroid Build Coastguard Worker            raise TypeError('no items for cycling given')
370*635a8641SAndroid Build Coastguard Worker        return args[self.index0 % len(args)]
371*635a8641SAndroid Build Coastguard Worker
372*635a8641SAndroid Build Coastguard Worker    def changed(self, *value):
373*635a8641SAndroid Build Coastguard Worker        """Checks whether the value has changed since the last call."""
374*635a8641SAndroid Build Coastguard Worker        if self._last_checked_value != value:
375*635a8641SAndroid Build Coastguard Worker            self._last_checked_value = value
376*635a8641SAndroid Build Coastguard Worker            return True
377*635a8641SAndroid Build Coastguard Worker        return False
378*635a8641SAndroid Build Coastguard Worker
379*635a8641SAndroid Build Coastguard Worker    first = property(lambda x: x.index0 == 0)
380*635a8641SAndroid Build Coastguard Worker    last = property(lambda x: x._after is _last_iteration)
381*635a8641SAndroid Build Coastguard Worker    index = property(lambda x: x.index0 + 1)
382*635a8641SAndroid Build Coastguard Worker    revindex = property(lambda x: x.length - x.index0)
383*635a8641SAndroid Build Coastguard Worker    revindex0 = property(lambda x: x.length - x.index)
384*635a8641SAndroid Build Coastguard Worker    depth = property(lambda x: x.depth0 + 1)
385*635a8641SAndroid Build Coastguard Worker
386*635a8641SAndroid Build Coastguard Worker    @property
387*635a8641SAndroid Build Coastguard Worker    def previtem(self):
388*635a8641SAndroid Build Coastguard Worker        if self._before is _first_iteration:
389*635a8641SAndroid Build Coastguard Worker            return self._undefined('there is no previous item')
390*635a8641SAndroid Build Coastguard Worker        return self._before
391*635a8641SAndroid Build Coastguard Worker
392*635a8641SAndroid Build Coastguard Worker    @property
393*635a8641SAndroid Build Coastguard Worker    def nextitem(self):
394*635a8641SAndroid Build Coastguard Worker        if self._after is _last_iteration:
395*635a8641SAndroid Build Coastguard Worker            return self._undefined('there is no next item')
396*635a8641SAndroid Build Coastguard Worker        return self._after
397*635a8641SAndroid Build Coastguard Worker
398*635a8641SAndroid Build Coastguard Worker    def __len__(self):
399*635a8641SAndroid Build Coastguard Worker        return self.length
400*635a8641SAndroid Build Coastguard Worker
401*635a8641SAndroid Build Coastguard Worker    @internalcode
402*635a8641SAndroid Build Coastguard Worker    def loop(self, iterable):
403*635a8641SAndroid Build Coastguard Worker        if self._recurse is None:
404*635a8641SAndroid Build Coastguard Worker            raise TypeError('Tried to call non recursive loop.  Maybe you '
405*635a8641SAndroid Build Coastguard Worker                            "forgot the 'recursive' modifier.")
406*635a8641SAndroid Build Coastguard Worker        return self._recurse(iterable, self._recurse, self.depth0 + 1)
407*635a8641SAndroid Build Coastguard Worker
408*635a8641SAndroid Build Coastguard Worker    # a nifty trick to enhance the error message if someone tried to call
409*635a8641SAndroid Build Coastguard Worker    # the the loop without or with too many arguments.
410*635a8641SAndroid Build Coastguard Worker    __call__ = loop
411*635a8641SAndroid Build Coastguard Worker    del loop
412*635a8641SAndroid Build Coastguard Worker
413*635a8641SAndroid Build Coastguard Worker    def __repr__(self):
414*635a8641SAndroid Build Coastguard Worker        return '<%s %r/%r>' % (
415*635a8641SAndroid Build Coastguard Worker            self.__class__.__name__,
416*635a8641SAndroid Build Coastguard Worker            self.index,
417*635a8641SAndroid Build Coastguard Worker            self.length
418*635a8641SAndroid Build Coastguard Worker        )
419*635a8641SAndroid Build Coastguard Worker
420*635a8641SAndroid Build Coastguard Worker
421*635a8641SAndroid Build Coastguard Workerclass LoopContext(LoopContextBase):
422*635a8641SAndroid Build Coastguard Worker
423*635a8641SAndroid Build Coastguard Worker    def __init__(self, iterable, undefined, recurse=None, depth0=0):
424*635a8641SAndroid Build Coastguard Worker        LoopContextBase.__init__(self, undefined, recurse, depth0)
425*635a8641SAndroid Build Coastguard Worker        self._iterator = iter(iterable)
426*635a8641SAndroid Build Coastguard Worker
427*635a8641SAndroid Build Coastguard Worker        # try to get the length of the iterable early.  This must be done
428*635a8641SAndroid Build Coastguard Worker        # here because there are some broken iterators around where there
429*635a8641SAndroid Build Coastguard Worker        # __len__ is the number of iterations left (i'm looking at your
430*635a8641SAndroid Build Coastguard Worker        # listreverseiterator!).
431*635a8641SAndroid Build Coastguard Worker        try:
432*635a8641SAndroid Build Coastguard Worker            self._length = len(iterable)
433*635a8641SAndroid Build Coastguard Worker        except (TypeError, AttributeError):
434*635a8641SAndroid Build Coastguard Worker            self._length = None
435*635a8641SAndroid Build Coastguard Worker        self._after = self._safe_next()
436*635a8641SAndroid Build Coastguard Worker
437*635a8641SAndroid Build Coastguard Worker    @property
438*635a8641SAndroid Build Coastguard Worker    def length(self):
439*635a8641SAndroid Build Coastguard Worker        if self._length is None:
440*635a8641SAndroid Build Coastguard Worker            # if was not possible to get the length of the iterator when
441*635a8641SAndroid Build Coastguard Worker            # the loop context was created (ie: iterating over a generator)
442*635a8641SAndroid Build Coastguard Worker            # we have to convert the iterable into a sequence and use the
443*635a8641SAndroid Build Coastguard Worker            # length of that + the number of iterations so far.
444*635a8641SAndroid Build Coastguard Worker            iterable = tuple(self._iterator)
445*635a8641SAndroid Build Coastguard Worker            self._iterator = iter(iterable)
446*635a8641SAndroid Build Coastguard Worker            iterations_done = self.index0 + 2
447*635a8641SAndroid Build Coastguard Worker            self._length = len(iterable) + iterations_done
448*635a8641SAndroid Build Coastguard Worker        return self._length
449*635a8641SAndroid Build Coastguard Worker
450*635a8641SAndroid Build Coastguard Worker    def __iter__(self):
451*635a8641SAndroid Build Coastguard Worker        return LoopContextIterator(self)
452*635a8641SAndroid Build Coastguard Worker
453*635a8641SAndroid Build Coastguard Worker    def _safe_next(self):
454*635a8641SAndroid Build Coastguard Worker        try:
455*635a8641SAndroid Build Coastguard Worker            return next(self._iterator)
456*635a8641SAndroid Build Coastguard Worker        except StopIteration:
457*635a8641SAndroid Build Coastguard Worker            return _last_iteration
458*635a8641SAndroid Build Coastguard Worker
459*635a8641SAndroid Build Coastguard Worker
460*635a8641SAndroid Build Coastguard Worker@implements_iterator
461*635a8641SAndroid Build Coastguard Workerclass LoopContextIterator(object):
462*635a8641SAndroid Build Coastguard Worker    """The iterator for a loop context."""
463*635a8641SAndroid Build Coastguard Worker    __slots__ = ('context',)
464*635a8641SAndroid Build Coastguard Worker
465*635a8641SAndroid Build Coastguard Worker    def __init__(self, context):
466*635a8641SAndroid Build Coastguard Worker        self.context = context
467*635a8641SAndroid Build Coastguard Worker
468*635a8641SAndroid Build Coastguard Worker    def __iter__(self):
469*635a8641SAndroid Build Coastguard Worker        return self
470*635a8641SAndroid Build Coastguard Worker
471*635a8641SAndroid Build Coastguard Worker    def __next__(self):
472*635a8641SAndroid Build Coastguard Worker        ctx = self.context
473*635a8641SAndroid Build Coastguard Worker        ctx.index0 += 1
474*635a8641SAndroid Build Coastguard Worker        if ctx._after is _last_iteration:
475*635a8641SAndroid Build Coastguard Worker            raise StopIteration()
476*635a8641SAndroid Build Coastguard Worker        ctx._before = ctx._current
477*635a8641SAndroid Build Coastguard Worker        ctx._current = ctx._after
478*635a8641SAndroid Build Coastguard Worker        ctx._after = ctx._safe_next()
479*635a8641SAndroid Build Coastguard Worker        return ctx._current, ctx
480*635a8641SAndroid Build Coastguard Worker
481*635a8641SAndroid Build Coastguard Worker
482*635a8641SAndroid Build Coastguard Workerclass Macro(object):
483*635a8641SAndroid Build Coastguard Worker    """Wraps a macro function."""
484*635a8641SAndroid Build Coastguard Worker
485*635a8641SAndroid Build Coastguard Worker    def __init__(self, environment, func, name, arguments,
486*635a8641SAndroid Build Coastguard Worker                 catch_kwargs, catch_varargs, caller,
487*635a8641SAndroid Build Coastguard Worker                 default_autoescape=None):
488*635a8641SAndroid Build Coastguard Worker        self._environment = environment
489*635a8641SAndroid Build Coastguard Worker        self._func = func
490*635a8641SAndroid Build Coastguard Worker        self._argument_count = len(arguments)
491*635a8641SAndroid Build Coastguard Worker        self.name = name
492*635a8641SAndroid Build Coastguard Worker        self.arguments = arguments
493*635a8641SAndroid Build Coastguard Worker        self.catch_kwargs = catch_kwargs
494*635a8641SAndroid Build Coastguard Worker        self.catch_varargs = catch_varargs
495*635a8641SAndroid Build Coastguard Worker        self.caller = caller
496*635a8641SAndroid Build Coastguard Worker        self.explicit_caller = 'caller' in arguments
497*635a8641SAndroid Build Coastguard Worker        if default_autoescape is None:
498*635a8641SAndroid Build Coastguard Worker            default_autoescape = environment.autoescape
499*635a8641SAndroid Build Coastguard Worker        self._default_autoescape = default_autoescape
500*635a8641SAndroid Build Coastguard Worker
501*635a8641SAndroid Build Coastguard Worker    @internalcode
502*635a8641SAndroid Build Coastguard Worker    @evalcontextfunction
503*635a8641SAndroid Build Coastguard Worker    def __call__(self, *args, **kwargs):
504*635a8641SAndroid Build Coastguard Worker        # This requires a bit of explanation,  In the past we used to
505*635a8641SAndroid Build Coastguard Worker        # decide largely based on compile-time information if a macro is
506*635a8641SAndroid Build Coastguard Worker        # safe or unsafe.  While there was a volatile mode it was largely
507*635a8641SAndroid Build Coastguard Worker        # unused for deciding on escaping.  This turns out to be
508*635a8641SAndroid Build Coastguard Worker        # problemtic for macros because if a macro is safe or not not so
509*635a8641SAndroid Build Coastguard Worker        # much depends on the escape mode when it was defined but when it
510*635a8641SAndroid Build Coastguard Worker        # was used.
511*635a8641SAndroid Build Coastguard Worker        #
512*635a8641SAndroid Build Coastguard Worker        # Because however we export macros from the module system and
513*635a8641SAndroid Build Coastguard Worker        # there are historic callers that do not pass an eval context (and
514*635a8641SAndroid Build Coastguard Worker        # will continue to not pass one), we need to perform an instance
515*635a8641SAndroid Build Coastguard Worker        # check here.
516*635a8641SAndroid Build Coastguard Worker        #
517*635a8641SAndroid Build Coastguard Worker        # This is considered safe because an eval context is not a valid
518*635a8641SAndroid Build Coastguard Worker        # argument to callables otherwise anwyays.  Worst case here is
519*635a8641SAndroid Build Coastguard Worker        # that if no eval context is passed we fall back to the compile
520*635a8641SAndroid Build Coastguard Worker        # time autoescape flag.
521*635a8641SAndroid Build Coastguard Worker        if args and isinstance(args[0], EvalContext):
522*635a8641SAndroid Build Coastguard Worker            autoescape = args[0].autoescape
523*635a8641SAndroid Build Coastguard Worker            args = args[1:]
524*635a8641SAndroid Build Coastguard Worker        else:
525*635a8641SAndroid Build Coastguard Worker            autoescape = self._default_autoescape
526*635a8641SAndroid Build Coastguard Worker
527*635a8641SAndroid Build Coastguard Worker        # try to consume the positional arguments
528*635a8641SAndroid Build Coastguard Worker        arguments = list(args[:self._argument_count])
529*635a8641SAndroid Build Coastguard Worker        off = len(arguments)
530*635a8641SAndroid Build Coastguard Worker
531*635a8641SAndroid Build Coastguard Worker        # For information why this is necessary refer to the handling
532*635a8641SAndroid Build Coastguard Worker        # of caller in the `macro_body` handler in the compiler.
533*635a8641SAndroid Build Coastguard Worker        found_caller = False
534*635a8641SAndroid Build Coastguard Worker
535*635a8641SAndroid Build Coastguard Worker        # if the number of arguments consumed is not the number of
536*635a8641SAndroid Build Coastguard Worker        # arguments expected we start filling in keyword arguments
537*635a8641SAndroid Build Coastguard Worker        # and defaults.
538*635a8641SAndroid Build Coastguard Worker        if off != self._argument_count:
539*635a8641SAndroid Build Coastguard Worker            for idx, name in enumerate(self.arguments[len(arguments):]):
540*635a8641SAndroid Build Coastguard Worker                try:
541*635a8641SAndroid Build Coastguard Worker                    value = kwargs.pop(name)
542*635a8641SAndroid Build Coastguard Worker                except KeyError:
543*635a8641SAndroid Build Coastguard Worker                    value = missing
544*635a8641SAndroid Build Coastguard Worker                if name == 'caller':
545*635a8641SAndroid Build Coastguard Worker                    found_caller = True
546*635a8641SAndroid Build Coastguard Worker                arguments.append(value)
547*635a8641SAndroid Build Coastguard Worker        else:
548*635a8641SAndroid Build Coastguard Worker            found_caller = self.explicit_caller
549*635a8641SAndroid Build Coastguard Worker
550*635a8641SAndroid Build Coastguard Worker        # it's important that the order of these arguments does not change
551*635a8641SAndroid Build Coastguard Worker        # if not also changed in the compiler's `function_scoping` method.
552*635a8641SAndroid Build Coastguard Worker        # the order is caller, keyword arguments, positional arguments!
553*635a8641SAndroid Build Coastguard Worker        if self.caller and not found_caller:
554*635a8641SAndroid Build Coastguard Worker            caller = kwargs.pop('caller', None)
555*635a8641SAndroid Build Coastguard Worker            if caller is None:
556*635a8641SAndroid Build Coastguard Worker                caller = self._environment.undefined('No caller defined',
557*635a8641SAndroid Build Coastguard Worker                                                     name='caller')
558*635a8641SAndroid Build Coastguard Worker            arguments.append(caller)
559*635a8641SAndroid Build Coastguard Worker
560*635a8641SAndroid Build Coastguard Worker        if self.catch_kwargs:
561*635a8641SAndroid Build Coastguard Worker            arguments.append(kwargs)
562*635a8641SAndroid Build Coastguard Worker        elif kwargs:
563*635a8641SAndroid Build Coastguard Worker            if 'caller' in kwargs:
564*635a8641SAndroid Build Coastguard Worker                raise TypeError('macro %r was invoked with two values for '
565*635a8641SAndroid Build Coastguard Worker                                'the special caller argument.  This is '
566*635a8641SAndroid Build Coastguard Worker                                'most likely a bug.' % self.name)
567*635a8641SAndroid Build Coastguard Worker            raise TypeError('macro %r takes no keyword argument %r' %
568*635a8641SAndroid Build Coastguard Worker                            (self.name, next(iter(kwargs))))
569*635a8641SAndroid Build Coastguard Worker        if self.catch_varargs:
570*635a8641SAndroid Build Coastguard Worker            arguments.append(args[self._argument_count:])
571*635a8641SAndroid Build Coastguard Worker        elif len(args) > self._argument_count:
572*635a8641SAndroid Build Coastguard Worker            raise TypeError('macro %r takes not more than %d argument(s)' %
573*635a8641SAndroid Build Coastguard Worker                            (self.name, len(self.arguments)))
574*635a8641SAndroid Build Coastguard Worker
575*635a8641SAndroid Build Coastguard Worker        return self._invoke(arguments, autoescape)
576*635a8641SAndroid Build Coastguard Worker
577*635a8641SAndroid Build Coastguard Worker    def _invoke(self, arguments, autoescape):
578*635a8641SAndroid Build Coastguard Worker        """This method is being swapped out by the async implementation."""
579*635a8641SAndroid Build Coastguard Worker        rv = self._func(*arguments)
580*635a8641SAndroid Build Coastguard Worker        if autoescape:
581*635a8641SAndroid Build Coastguard Worker            rv = Markup(rv)
582*635a8641SAndroid Build Coastguard Worker        return rv
583*635a8641SAndroid Build Coastguard Worker
584*635a8641SAndroid Build Coastguard Worker    def __repr__(self):
585*635a8641SAndroid Build Coastguard Worker        return '<%s %s>' % (
586*635a8641SAndroid Build Coastguard Worker            self.__class__.__name__,
587*635a8641SAndroid Build Coastguard Worker            self.name is None and 'anonymous' or repr(self.name)
588*635a8641SAndroid Build Coastguard Worker        )
589*635a8641SAndroid Build Coastguard Worker
590*635a8641SAndroid Build Coastguard Worker
591*635a8641SAndroid Build Coastguard Worker@implements_to_string
592*635a8641SAndroid Build Coastguard Workerclass Undefined(object):
593*635a8641SAndroid Build Coastguard Worker    """The default undefined type.  This undefined type can be printed and
594*635a8641SAndroid Build Coastguard Worker    iterated over, but every other access will raise an :exc:`jinja2.exceptions.UndefinedError`:
595*635a8641SAndroid Build Coastguard Worker
596*635a8641SAndroid Build Coastguard Worker    >>> foo = Undefined(name='foo')
597*635a8641SAndroid Build Coastguard Worker    >>> str(foo)
598*635a8641SAndroid Build Coastguard Worker    ''
599*635a8641SAndroid Build Coastguard Worker    >>> not foo
600*635a8641SAndroid Build Coastguard Worker    True
601*635a8641SAndroid Build Coastguard Worker    >>> foo + 42
602*635a8641SAndroid Build Coastguard Worker    Traceback (most recent call last):
603*635a8641SAndroid Build Coastguard Worker      ...
604*635a8641SAndroid Build Coastguard Worker    jinja2.exceptions.UndefinedError: 'foo' is undefined
605*635a8641SAndroid Build Coastguard Worker    """
606*635a8641SAndroid Build Coastguard Worker    __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
607*635a8641SAndroid Build Coastguard Worker                 '_undefined_exception')
608*635a8641SAndroid Build Coastguard Worker
609*635a8641SAndroid Build Coastguard Worker    def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
610*635a8641SAndroid Build Coastguard Worker        self._undefined_hint = hint
611*635a8641SAndroid Build Coastguard Worker        self._undefined_obj = obj
612*635a8641SAndroid Build Coastguard Worker        self._undefined_name = name
613*635a8641SAndroid Build Coastguard Worker        self._undefined_exception = exc
614*635a8641SAndroid Build Coastguard Worker
615*635a8641SAndroid Build Coastguard Worker    @internalcode
616*635a8641SAndroid Build Coastguard Worker    def _fail_with_undefined_error(self, *args, **kwargs):
617*635a8641SAndroid Build Coastguard Worker        """Regular callback function for undefined objects that raises an
618*635a8641SAndroid Build Coastguard Worker        `jinja2.exceptions.UndefinedError` on call.
619*635a8641SAndroid Build Coastguard Worker        """
620*635a8641SAndroid Build Coastguard Worker        if self._undefined_hint is None:
621*635a8641SAndroid Build Coastguard Worker            if self._undefined_obj is missing:
622*635a8641SAndroid Build Coastguard Worker                hint = '%r is undefined' % self._undefined_name
623*635a8641SAndroid Build Coastguard Worker            elif not isinstance(self._undefined_name, string_types):
624*635a8641SAndroid Build Coastguard Worker                hint = '%s has no element %r' % (
625*635a8641SAndroid Build Coastguard Worker                    object_type_repr(self._undefined_obj),
626*635a8641SAndroid Build Coastguard Worker                    self._undefined_name
627*635a8641SAndroid Build Coastguard Worker                )
628*635a8641SAndroid Build Coastguard Worker            else:
629*635a8641SAndroid Build Coastguard Worker                hint = '%r has no attribute %r' % (
630*635a8641SAndroid Build Coastguard Worker                    object_type_repr(self._undefined_obj),
631*635a8641SAndroid Build Coastguard Worker                    self._undefined_name
632*635a8641SAndroid Build Coastguard Worker                )
633*635a8641SAndroid Build Coastguard Worker        else:
634*635a8641SAndroid Build Coastguard Worker            hint = self._undefined_hint
635*635a8641SAndroid Build Coastguard Worker        raise self._undefined_exception(hint)
636*635a8641SAndroid Build Coastguard Worker
637*635a8641SAndroid Build Coastguard Worker    @internalcode
638*635a8641SAndroid Build Coastguard Worker    def __getattr__(self, name):
639*635a8641SAndroid Build Coastguard Worker        if name[:2] == '__':
640*635a8641SAndroid Build Coastguard Worker            raise AttributeError(name)
641*635a8641SAndroid Build Coastguard Worker        return self._fail_with_undefined_error()
642*635a8641SAndroid Build Coastguard Worker
643*635a8641SAndroid Build Coastguard Worker    __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
644*635a8641SAndroid Build Coastguard Worker        __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
645*635a8641SAndroid Build Coastguard Worker        __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
646*635a8641SAndroid Build Coastguard Worker        __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
647*635a8641SAndroid Build Coastguard Worker        __float__ = __complex__ = __pow__ = __rpow__ = __sub__ = \
648*635a8641SAndroid Build Coastguard Worker        __rsub__ = _fail_with_undefined_error
649*635a8641SAndroid Build Coastguard Worker
650*635a8641SAndroid Build Coastguard Worker    def __eq__(self, other):
651*635a8641SAndroid Build Coastguard Worker        return type(self) is type(other)
652*635a8641SAndroid Build Coastguard Worker
653*635a8641SAndroid Build Coastguard Worker    def __ne__(self, other):
654*635a8641SAndroid Build Coastguard Worker        return not self.__eq__(other)
655*635a8641SAndroid Build Coastguard Worker
656*635a8641SAndroid Build Coastguard Worker    def __hash__(self):
657*635a8641SAndroid Build Coastguard Worker        return id(type(self))
658*635a8641SAndroid Build Coastguard Worker
659*635a8641SAndroid Build Coastguard Worker    def __str__(self):
660*635a8641SAndroid Build Coastguard Worker        return u''
661*635a8641SAndroid Build Coastguard Worker
662*635a8641SAndroid Build Coastguard Worker    def __len__(self):
663*635a8641SAndroid Build Coastguard Worker        return 0
664*635a8641SAndroid Build Coastguard Worker
665*635a8641SAndroid Build Coastguard Worker    def __iter__(self):
666*635a8641SAndroid Build Coastguard Worker        if 0:
667*635a8641SAndroid Build Coastguard Worker            yield None
668*635a8641SAndroid Build Coastguard Worker
669*635a8641SAndroid Build Coastguard Worker    def __nonzero__(self):
670*635a8641SAndroid Build Coastguard Worker        return False
671*635a8641SAndroid Build Coastguard Worker    __bool__ = __nonzero__
672*635a8641SAndroid Build Coastguard Worker
673*635a8641SAndroid Build Coastguard Worker    def __repr__(self):
674*635a8641SAndroid Build Coastguard Worker        return 'Undefined'
675*635a8641SAndroid Build Coastguard Worker
676*635a8641SAndroid Build Coastguard Worker
677*635a8641SAndroid Build Coastguard Workerdef make_logging_undefined(logger=None, base=None):
678*635a8641SAndroid Build Coastguard Worker    """Given a logger object this returns a new undefined class that will
679*635a8641SAndroid Build Coastguard Worker    log certain failures.  It will log iterations and printing.  If no
680*635a8641SAndroid Build Coastguard Worker    logger is given a default logger is created.
681*635a8641SAndroid Build Coastguard Worker
682*635a8641SAndroid Build Coastguard Worker    Example::
683*635a8641SAndroid Build Coastguard Worker
684*635a8641SAndroid Build Coastguard Worker        logger = logging.getLogger(__name__)
685*635a8641SAndroid Build Coastguard Worker        LoggingUndefined = make_logging_undefined(
686*635a8641SAndroid Build Coastguard Worker            logger=logger,
687*635a8641SAndroid Build Coastguard Worker            base=Undefined
688*635a8641SAndroid Build Coastguard Worker        )
689*635a8641SAndroid Build Coastguard Worker
690*635a8641SAndroid Build Coastguard Worker    .. versionadded:: 2.8
691*635a8641SAndroid Build Coastguard Worker
692*635a8641SAndroid Build Coastguard Worker    :param logger: the logger to use.  If not provided, a default logger
693*635a8641SAndroid Build Coastguard Worker                   is created.
694*635a8641SAndroid Build Coastguard Worker    :param base: the base class to add logging functionality to.  This
695*635a8641SAndroid Build Coastguard Worker                 defaults to :class:`Undefined`.
696*635a8641SAndroid Build Coastguard Worker    """
697*635a8641SAndroid Build Coastguard Worker    if logger is None:
698*635a8641SAndroid Build Coastguard Worker        import logging
699*635a8641SAndroid Build Coastguard Worker        logger = logging.getLogger(__name__)
700*635a8641SAndroid Build Coastguard Worker        logger.addHandler(logging.StreamHandler(sys.stderr))
701*635a8641SAndroid Build Coastguard Worker    if base is None:
702*635a8641SAndroid Build Coastguard Worker        base = Undefined
703*635a8641SAndroid Build Coastguard Worker
704*635a8641SAndroid Build Coastguard Worker    def _log_message(undef):
705*635a8641SAndroid Build Coastguard Worker        if undef._undefined_hint is None:
706*635a8641SAndroid Build Coastguard Worker            if undef._undefined_obj is missing:
707*635a8641SAndroid Build Coastguard Worker                hint = '%s is undefined' % undef._undefined_name
708*635a8641SAndroid Build Coastguard Worker            elif not isinstance(undef._undefined_name, string_types):
709*635a8641SAndroid Build Coastguard Worker                hint = '%s has no element %s' % (
710*635a8641SAndroid Build Coastguard Worker                    object_type_repr(undef._undefined_obj),
711*635a8641SAndroid Build Coastguard Worker                    undef._undefined_name)
712*635a8641SAndroid Build Coastguard Worker            else:
713*635a8641SAndroid Build Coastguard Worker                hint = '%s has no attribute %s' % (
714*635a8641SAndroid Build Coastguard Worker                    object_type_repr(undef._undefined_obj),
715*635a8641SAndroid Build Coastguard Worker                    undef._undefined_name)
716*635a8641SAndroid Build Coastguard Worker        else:
717*635a8641SAndroid Build Coastguard Worker            hint = undef._undefined_hint
718*635a8641SAndroid Build Coastguard Worker        logger.warning('Template variable warning: %s', hint)
719*635a8641SAndroid Build Coastguard Worker
720*635a8641SAndroid Build Coastguard Worker    class LoggingUndefined(base):
721*635a8641SAndroid Build Coastguard Worker
722*635a8641SAndroid Build Coastguard Worker        def _fail_with_undefined_error(self, *args, **kwargs):
723*635a8641SAndroid Build Coastguard Worker            try:
724*635a8641SAndroid Build Coastguard Worker                return base._fail_with_undefined_error(self, *args, **kwargs)
725*635a8641SAndroid Build Coastguard Worker            except self._undefined_exception as e:
726*635a8641SAndroid Build Coastguard Worker                logger.error('Template variable error: %s', str(e))
727*635a8641SAndroid Build Coastguard Worker                raise e
728*635a8641SAndroid Build Coastguard Worker
729*635a8641SAndroid Build Coastguard Worker        def __str__(self):
730*635a8641SAndroid Build Coastguard Worker            rv = base.__str__(self)
731*635a8641SAndroid Build Coastguard Worker            _log_message(self)
732*635a8641SAndroid Build Coastguard Worker            return rv
733*635a8641SAndroid Build Coastguard Worker
734*635a8641SAndroid Build Coastguard Worker        def __iter__(self):
735*635a8641SAndroid Build Coastguard Worker            rv = base.__iter__(self)
736*635a8641SAndroid Build Coastguard Worker            _log_message(self)
737*635a8641SAndroid Build Coastguard Worker            return rv
738*635a8641SAndroid Build Coastguard Worker
739*635a8641SAndroid Build Coastguard Worker        if PY2:
740*635a8641SAndroid Build Coastguard Worker            def __nonzero__(self):
741*635a8641SAndroid Build Coastguard Worker                rv = base.__nonzero__(self)
742*635a8641SAndroid Build Coastguard Worker                _log_message(self)
743*635a8641SAndroid Build Coastguard Worker                return rv
744*635a8641SAndroid Build Coastguard Worker
745*635a8641SAndroid Build Coastguard Worker            def __unicode__(self):
746*635a8641SAndroid Build Coastguard Worker                rv = base.__unicode__(self)
747*635a8641SAndroid Build Coastguard Worker                _log_message(self)
748*635a8641SAndroid Build Coastguard Worker                return rv
749*635a8641SAndroid Build Coastguard Worker        else:
750*635a8641SAndroid Build Coastguard Worker            def __bool__(self):
751*635a8641SAndroid Build Coastguard Worker                rv = base.__bool__(self)
752*635a8641SAndroid Build Coastguard Worker                _log_message(self)
753*635a8641SAndroid Build Coastguard Worker                return rv
754*635a8641SAndroid Build Coastguard Worker
755*635a8641SAndroid Build Coastguard Worker    return LoggingUndefined
756*635a8641SAndroid Build Coastguard Worker
757*635a8641SAndroid Build Coastguard Worker
758*635a8641SAndroid Build Coastguard Worker@implements_to_string
759*635a8641SAndroid Build Coastguard Workerclass DebugUndefined(Undefined):
760*635a8641SAndroid Build Coastguard Worker    """An undefined that returns the debug info when printed.
761*635a8641SAndroid Build Coastguard Worker
762*635a8641SAndroid Build Coastguard Worker    >>> foo = DebugUndefined(name='foo')
763*635a8641SAndroid Build Coastguard Worker    >>> str(foo)
764*635a8641SAndroid Build Coastguard Worker    '{{ foo }}'
765*635a8641SAndroid Build Coastguard Worker    >>> not foo
766*635a8641SAndroid Build Coastguard Worker    True
767*635a8641SAndroid Build Coastguard Worker    >>> foo + 42
768*635a8641SAndroid Build Coastguard Worker    Traceback (most recent call last):
769*635a8641SAndroid Build Coastguard Worker      ...
770*635a8641SAndroid Build Coastguard Worker    jinja2.exceptions.UndefinedError: 'foo' is undefined
771*635a8641SAndroid Build Coastguard Worker    """
772*635a8641SAndroid Build Coastguard Worker    __slots__ = ()
773*635a8641SAndroid Build Coastguard Worker
774*635a8641SAndroid Build Coastguard Worker    def __str__(self):
775*635a8641SAndroid Build Coastguard Worker        if self._undefined_hint is None:
776*635a8641SAndroid Build Coastguard Worker            if self._undefined_obj is missing:
777*635a8641SAndroid Build Coastguard Worker                return u'{{ %s }}' % self._undefined_name
778*635a8641SAndroid Build Coastguard Worker            return '{{ no such element: %s[%r] }}' % (
779*635a8641SAndroid Build Coastguard Worker                object_type_repr(self._undefined_obj),
780*635a8641SAndroid Build Coastguard Worker                self._undefined_name
781*635a8641SAndroid Build Coastguard Worker            )
782*635a8641SAndroid Build Coastguard Worker        return u'{{ undefined value printed: %s }}' % self._undefined_hint
783*635a8641SAndroid Build Coastguard Worker
784*635a8641SAndroid Build Coastguard Worker
785*635a8641SAndroid Build Coastguard Worker@implements_to_string
786*635a8641SAndroid Build Coastguard Workerclass StrictUndefined(Undefined):
787*635a8641SAndroid Build Coastguard Worker    """An undefined that barks on print and iteration as well as boolean
788*635a8641SAndroid Build Coastguard Worker    tests and all kinds of comparisons.  In other words: you can do nothing
789*635a8641SAndroid Build Coastguard Worker    with it except checking if it's defined using the `defined` test.
790*635a8641SAndroid Build Coastguard Worker
791*635a8641SAndroid Build Coastguard Worker    >>> foo = StrictUndefined(name='foo')
792*635a8641SAndroid Build Coastguard Worker    >>> str(foo)
793*635a8641SAndroid Build Coastguard Worker    Traceback (most recent call last):
794*635a8641SAndroid Build Coastguard Worker      ...
795*635a8641SAndroid Build Coastguard Worker    jinja2.exceptions.UndefinedError: 'foo' is undefined
796*635a8641SAndroid Build Coastguard Worker    >>> not foo
797*635a8641SAndroid Build Coastguard Worker    Traceback (most recent call last):
798*635a8641SAndroid Build Coastguard Worker      ...
799*635a8641SAndroid Build Coastguard Worker    jinja2.exceptions.UndefinedError: 'foo' is undefined
800*635a8641SAndroid Build Coastguard Worker    >>> foo + 42
801*635a8641SAndroid Build Coastguard Worker    Traceback (most recent call last):
802*635a8641SAndroid Build Coastguard Worker      ...
803*635a8641SAndroid Build Coastguard Worker    jinja2.exceptions.UndefinedError: 'foo' is undefined
804*635a8641SAndroid Build Coastguard Worker    """
805*635a8641SAndroid Build Coastguard Worker    __slots__ = ()
806*635a8641SAndroid Build Coastguard Worker    __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
807*635a8641SAndroid Build Coastguard Worker        __ne__ = __bool__ = __hash__ = \
808*635a8641SAndroid Build Coastguard Worker        Undefined._fail_with_undefined_error
809*635a8641SAndroid Build Coastguard Worker
810*635a8641SAndroid Build Coastguard Worker
811*635a8641SAndroid Build Coastguard Worker# remove remaining slots attributes, after the metaclass did the magic they
812*635a8641SAndroid Build Coastguard Worker# are unneeded and irritating as they contain wrong data for the subclasses.
813*635a8641SAndroid Build Coastguard Workerdel Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__
814