blob: b1972f8c7d4d5b0a04447ba70bc1251960d68292 [file] [log] [blame]
Armin Ronachere791c2a2008-04-07 18:39:54 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.runtime
4 ~~~~~~~~~~~~~~
5
6 Runtime helpers.
7
Armin Ronacherbbe0a412017-01-07 16:17:14 +01008 :copyright: (c) 2017 by the Jinja Team.
Armin Ronacherd7764372008-07-15 00:11:14 +02009 :license: BSD.
Armin Ronachere791c2a2008-04-07 18:39:54 +020010"""
Armin Ronacherd2641be2014-06-06 22:00:04 +060011import sys
12
Thomas Waldmann7d295622013-05-18 00:06:22 +020013from itertools import chain
Adrian Moennicha8a9ec22017-03-15 19:19:04 +010014from types import MethodType
15
Armin Ronacher5a5ce732010-05-23 22:58:28 +020016from jinja2.nodes import EvalContext, _context_function_types
Daniel Neuhäuserd0708db2013-05-18 12:52:40 +020017from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
Adrian Moennichc2ee56d2017-02-26 16:45:54 +010018 internalcode, object_type_repr, evalcontextfunction, Namespace
Armin Ronacher37f58ce2008-12-27 13:10:38 +010019from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
20 TemplateNotFound
Armin Ronacherb89d1a82013-05-20 16:54:48 +010021from jinja2._compat import imap, text_type, iteritems, \
Armin Ronacherc6ddeb72017-01-12 20:10:58 +010022 implements_iterator, implements_to_string, string_types, PY2, \
Florian Bruhin31bf9b72018-06-27 15:30:54 +020023 with_metaclass, abc
Armin Ronachere791c2a2008-04-07 18:39:54 +020024
25
Armin Ronacher2feed1d2008-04-26 16:26:52 +020026# these variables are exported to the template runtime
Armin Ronacher74a0cd92009-02-19 15:56:53 +010027__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
Armin Ronacher19cf9c22008-05-01 12:49:53 +020028 'TemplateRuntimeError', 'missing', 'concat', 'escape',
Armin Ronacher4da90342010-05-29 17:35:10 +020029 'markup_join', 'unicode_join', 'to_string', 'identity',
Adrian Moennichc2ee56d2017-02-26 16:45:54 +010030 'TemplateNotFound', 'Namespace']
Armin Ronacher0611e492008-04-25 23:44:14 +020031
Armin Ronacherbd357722009-08-05 20:25:06 +020032#: the name of the function that is used to convert something into
Armin Ronacher28c74882013-05-20 01:51:26 +010033#: a string. We can just use the text type here.
34to_string = text_type
Armin Ronacherbd357722009-08-05 20:25:06 +020035
Armin Ronacher4da90342010-05-29 17:35:10 +020036#: the identity function. Useful for certain things in the environment
37identity = lambda x: x
38
Adrian Moennich9bdb5472017-02-01 21:05:03 +010039_first_iteration = object()
Armin Ronacher99b22852012-01-25 00:42:54 +010040_last_iteration = object()
41
Armin Ronacher0611e492008-04-25 23:44:14 +020042
Armin Ronacherdc02b642008-05-15 22:47:27 +020043def markup_join(seq):
Armin Ronacherd1342312008-04-28 12:20:12 +020044 """Concatenation that escapes if necessary and converts to unicode."""
45 buf = []
Armin Ronachere9098672013-05-19 14:16:13 +010046 iterator = imap(soft_unicode, seq)
Armin Ronacherd1342312008-04-28 12:20:12 +020047 for arg in iterator:
48 buf.append(arg)
49 if hasattr(arg, '__html__'):
50 return Markup(u'').join(chain(buf, iterator))
51 return concat(buf)
52
53
Armin Ronacherdc02b642008-05-15 22:47:27 +020054def unicode_join(seq):
Armin Ronacherd1342312008-04-28 12:20:12 +020055 """Simple args to unicode conversion and concatenation."""
Armin Ronachere9098672013-05-19 14:16:13 +010056 return concat(imap(text_type, seq))
Armin Ronacherd1342312008-04-28 12:20:12 +020057
58
Armin Ronacher74a0cd92009-02-19 15:56:53 +010059def new_context(environment, template_name, blocks, vars=None,
60 shared=None, globals=None, locals=None):
61 """Internal helper to for context creation."""
62 if vars is None:
63 vars = {}
64 if shared:
65 parent = vars
66 else:
67 parent = dict(globals or (), **vars)
68 if locals:
69 # if the parent is shared a copy should be created because
70 # we don't want to modify the dict passed
71 if shared:
72 parent = dict(parent)
Armin Ronachercb4b5512017-01-06 20:57:30 +010073 for key, value in iteritems(locals):
74 if value is not missing:
75 parent[key] = value
ThiefMasterf22fdd52015-04-06 14:08:46 +020076 return environment.context_class(environment, parent, template_name,
77 blocks)
Armin Ronacher74a0cd92009-02-19 15:56:53 +010078
79
80class TemplateReference(object):
81 """The `self` in templates."""
82
83 def __init__(self, context):
84 self.__context = context
85
86 def __getitem__(self, name):
87 blocks = self.__context.blocks[name]
Armin Ronacher74a0cd92009-02-19 15:56:53 +010088 return BlockReference(name, self.__context, blocks, 0)
89
90 def __repr__(self):
91 return '<%s %r>' % (
92 self.__class__.__name__,
93 self.__context.name
94 )
95
96
Armin Ronacherc6ddeb72017-01-12 20:10:58 +010097def _get_func(x):
98 return getattr(x, '__func__', x)
99
100
101class ContextMeta(type):
102
103 def __new__(cls, name, bases, d):
104 rv = type.__new__(cls, name, bases, d)
105 if bases == ():
106 return rv
107
108 resolve = _get_func(rv.resolve)
109 default_resolve = _get_func(Context.resolve)
110 resolve_or_missing = _get_func(rv.resolve_or_missing)
111 default_resolve_or_missing = _get_func(Context.resolve_or_missing)
112
113 # If we have a changed resolve but no changed default or missing
114 # resolve we invert the call logic.
115 if resolve is not default_resolve and \
116 resolve_or_missing is default_resolve_or_missing:
117 rv._legacy_resolve_mode = True
118 elif resolve is default_resolve and \
119 resolve_or_missing is default_resolve_or_missing:
120 rv._fast_resolve_mode = True
121
122 return rv
123
124
125def resolve_or_missing(context, key, missing=missing):
126 if key in context.vars:
127 return context.vars[key]
128 if key in context.parent:
129 return context.parent[key]
130 return missing
131
132
133class Context(with_metaclass(ContextMeta)):
Armin Ronacher7259c762008-04-30 13:03:59 +0200134 """The template context holds the variables of a template. It stores the
135 values passed to the template and also the names the template exports.
136 Creating instances is neither supported nor useful as it's created
137 automatically at various stages of the template evaluation and should not
138 be created by hand.
Armin Ronacherc9705c22008-04-27 21:28:03 +0200139
Armin Ronacher7259c762008-04-30 13:03:59 +0200140 The context is immutable. Modifications on :attr:`parent` **must not**
141 happen and modifications on :attr:`vars` are allowed from generated
142 template code only. Template filters and global functions marked as
Armin Ronacherbe167862017-01-08 23:40:38 +0100143 :func:`contextfunction`\\s get the active context passed as first argument
Armin Ronacher7259c762008-04-30 13:03:59 +0200144 and are allowed to access the context read-only.
145
146 The template context supports read only dict operations (`get`,
Armin Ronacherf35e2812008-05-06 16:04:10 +0200147 `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
148 `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
149 method that doesn't fail with a `KeyError` but returns an
150 :class:`Undefined` object for missing variables.
Armin Ronacher9706fab2008-04-08 18:49:56 +0200151 """
Armin Ronacherc6ddeb72017-01-12 20:10:58 +0100152 # XXX: we want to eventually make this be a deprecation warning and
153 # remove it.
154 _legacy_resolve_mode = False
155 _fast_resolve_mode = False
Armin Ronachere791c2a2008-04-07 18:39:54 +0200156
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200157 def __init__(self, environment, parent, name, blocks):
158 self.parent = parent
Armin Ronacher2f0d6592009-10-26 11:53:27 +0100159 self.vars = {}
Armin Ronacherc63243e2008-04-14 22:53:58 +0200160 self.environment = environment
Armin Ronacher1da23d12010-04-05 18:11:18 +0200161 self.eval_ctx = EvalContext(self.environment, name)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200162 self.exported_vars = set()
Armin Ronacher68f77672008-04-17 11:50:39 +0200163 self.name = name
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200164
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200165 # create the initial mapping of blocks. Whenever template inheritance
166 # takes place the runtime will update this mapping with the new blocks
167 # from the template.
Armin Ronachere9098672013-05-19 14:16:13 +0100168 self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
Armin Ronacherf059ec12008-04-11 22:21:00 +0200169
Armin Ronacherc6ddeb72017-01-12 20:10:58 +0100170 # In case we detect the fast resolve mode we can set up an alias
171 # here that bypasses the legacy code logic.
172 if self._fast_resolve_mode:
Adrian Moennicha8a9ec22017-03-15 19:19:04 +0100173 self.resolve_or_missing = MethodType(resolve_or_missing, self)
Armin Ronacherc6ddeb72017-01-12 20:10:58 +0100174
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200175 def super(self, name, current):
Armin Ronacher62f8a292008-04-13 23:18:05 +0200176 """Render a parent block."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200177 try:
178 blocks = self.blocks[name]
Armin Ronacherc347ed02008-09-20 12:04:53 +0200179 index = blocks.index(current) + 1
180 blocks[index]
Armin Ronacherc9705c22008-04-27 21:28:03 +0200181 except LookupError:
Armin Ronacher9a822052008-04-17 18:44:07 +0200182 return self.environment.undefined('there is no parent block '
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200183 'called %r.' % name,
184 name='super')
Armin Ronacherc347ed02008-09-20 12:04:53 +0200185 return BlockReference(name, self, blocks, index)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200186
Armin Ronacher53042292008-04-26 18:30:19 +0200187 def get(self, key, default=None):
Armin Ronacher7259c762008-04-30 13:03:59 +0200188 """Returns an item from the template context, if it doesn't exist
189 `default` is returned.
190 """
Armin Ronacherf35e2812008-05-06 16:04:10 +0200191 try:
192 return self[key]
193 except KeyError:
194 return default
195
196 def resolve(self, key):
197 """Looks up a variable like `__getitem__` or `get` but returns an
198 :class:`Undefined` object with the name of the name looked up.
199 """
Armin Ronacherc6ddeb72017-01-12 20:10:58 +0100200 if self._legacy_resolve_mode:
201 rv = resolve_or_missing(self, key)
202 else:
203 rv = self.resolve_or_missing(key)
Armin Ronacher1205e642017-01-02 12:09:52 +0100204 if rv is missing:
205 return self.environment.undefined(name=key)
206 return rv
207
208 def resolve_or_missing(self, key):
209 """Resolves a variable like :meth:`resolve` but returns the
210 special `missing` value if it cannot be found.
211 """
Armin Ronacherc6ddeb72017-01-12 20:10:58 +0100212 if self._legacy_resolve_mode:
213 rv = self.resolve(key)
214 if isinstance(rv, Undefined):
215 rv = missing
216 return rv
217 return resolve_or_missing(self, key)
Armin Ronacherb5124e62008-04-25 00:36:14 +0200218
Armin Ronacher9706fab2008-04-08 18:49:56 +0200219 def get_exported(self):
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200220 """Get a new dict with the exported variables."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200221 return dict((k, self.vars[k]) for k in self.exported_vars)
Armin Ronacher9706fab2008-04-08 18:49:56 +0200222
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200223 def get_all(self):
Armin Ronacherd67f0fd2017-01-07 15:35:21 +0100224 """Return the complete context as dict including the exported
225 variables. For optimizations reasons this might not return an
226 actual copy so be careful with using it.
Armin Ronacher7259c762008-04-30 13:03:59 +0200227 """
Armin Ronacherd67f0fd2017-01-07 15:35:21 +0100228 if not self.vars:
229 return self.parent
230 if not self.parent:
231 return self.vars
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200232 return dict(self.parent, **self.vars)
233
Armin Ronacherd416a972009-02-24 22:58:00 +0100234 @internalcode
Armin Ronacherfd310492008-05-25 00:16:51 +0200235 def call(__self, __obj, *args, **kwargs):
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200236 """Call the callable with the arguments and keyword arguments
237 provided but inject the active context or environment as first
238 argument if the callable is a :func:`contextfunction` or
239 :func:`environmentfunction`.
240 """
Armin Ronacher24b65582008-05-26 13:35:58 +0200241 if __debug__:
Armin Ronacherd2641be2014-06-06 22:00:04 +0600242 __traceback_hide__ = True # noqa
Armin Ronacher9962c102013-05-18 11:58:12 +0100243
Richard Eames71fc2282013-04-15 23:49:02 -0600244 # Allow callable classes to take a context
Daniel P. Berrange91255f82015-10-13 16:52:07 +0100245 if hasattr(__obj, '__call__'):
246 fn = __obj.__call__
247 for fn_type in ('contextfunction',
248 'evalcontextfunction',
249 'environmentfunction'):
250 if hasattr(fn, fn_type):
251 __obj = fn
252 break
Armin Ronacher9962c102013-05-18 11:58:12 +0100253
Armin Ronacher24b65582008-05-26 13:35:58 +0200254 if isinstance(__obj, _context_function_types):
255 if getattr(__obj, 'contextfunction', 0):
256 args = (__self,) + args
Armin Ronacher8346bd72010-03-14 19:43:47 +0100257 elif getattr(__obj, 'evalcontextfunction', 0):
258 args = (__self.eval_ctx,) + args
Armin Ronacher24b65582008-05-26 13:35:58 +0200259 elif getattr(__obj, 'environmentfunction', 0):
260 args = (__self.environment,) + args
Armin Ronacher3351a932010-06-05 14:32:06 +0200261 try:
262 return __obj(*args, **kwargs)
263 except StopIteration:
264 return __self.environment.undefined('value was undefined because '
265 'a callable raised a '
266 'StopIteration exception')
Armin Ronacherfd310492008-05-25 00:16:51 +0200267
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100268 def derived(self, locals=None):
Armin Ronacherb1a56de2017-01-08 11:21:32 +0100269 """Internal helper function to create a derived context. This is
270 used in situations where the system needs a new context in the same
271 template that is independent.
272 """
Armin Ronacher3f1d8f12009-02-19 16:11:11 +0100273 context = new_context(self.environment, self.name, {},
Armin Ronacherb1a56de2017-01-08 11:21:32 +0100274 self.get_all(), True, None, locals)
Armin Ronacher8346bd72010-03-14 19:43:47 +0100275 context.eval_ctx = self.eval_ctx
Armin Ronachere9098672013-05-19 14:16:13 +0100276 context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
Armin Ronacher3f1d8f12009-02-19 16:11:11 +0100277 return context
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100278
Armin Ronacherf35e2812008-05-06 16:04:10 +0200279 def _all(meth):
Armin Ronachere9411b42008-05-15 16:22:07 +0200280 proxy = lambda self: getattr(self.get_all(), meth)()
Armin Ronacherf35e2812008-05-06 16:04:10 +0200281 proxy.__doc__ = getattr(dict, meth).__doc__
282 proxy.__name__ = meth
283 return proxy
284
285 keys = _all('keys')
286 values = _all('values')
287 items = _all('items')
Armin Ronacher42a19882009-08-05 18:45:39 +0200288
289 # not available on python 3
Armin Ronacherff0b5f52013-05-20 02:15:04 +0100290 if PY2:
Armin Ronacher42a19882009-08-05 18:45:39 +0200291 iterkeys = _all('iterkeys')
292 itervalues = _all('itervalues')
293 iteritems = _all('iteritems')
Armin Ronacherf35e2812008-05-06 16:04:10 +0200294 del _all
295
Armin Ronacherb5124e62008-04-25 00:36:14 +0200296 def __contains__(self, name):
297 return name in self.vars or name in self.parent
298
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200299 def __getitem__(self, key):
Armin Ronacherbbbe0622008-05-19 00:23:37 +0200300 """Lookup a variable or raise `KeyError` if the variable is
301 undefined.
302 """
Armin Ronacher1205e642017-01-02 12:09:52 +0100303 item = self.resolve_or_missing(key)
304 if item is missing:
Armin Ronacherbbbe0622008-05-19 00:23:37 +0200305 raise KeyError(key)
306 return item
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200307
Armin Ronacherf059ec12008-04-11 22:21:00 +0200308 def __repr__(self):
309 return '<%s %s of %r>' % (
310 self.__class__.__name__,
Armin Ronacher963f97d2008-04-25 11:44:59 +0200311 repr(self.get_all()),
Armin Ronacher68f77672008-04-17 11:50:39 +0200312 self.name
Armin Ronacherf059ec12008-04-11 22:21:00 +0200313 )
314
315
Florian Bruhin31bf9b72018-06-27 15:30:54 +0200316abc.Mapping.register(Context)
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200317
318
Armin Ronacherc347ed02008-09-20 12:04:53 +0200319class BlockReference(object):
320 """One block on a template reference."""
321
322 def __init__(self, name, context, stack, depth):
323 self.name = name
324 self._context = context
325 self._stack = stack
326 self._depth = depth
327
328 @property
329 def super(self):
330 """Super the block."""
331 if self._depth + 1 >= len(self._stack):
332 return self._context.environment. \
333 undefined('there is no parent block called %r.' %
334 self.name, name='super')
335 return BlockReference(self.name, self._context, self._stack,
336 self._depth + 1)
337
Armin Ronacherd416a972009-02-24 22:58:00 +0100338 @internalcode
Armin Ronacherc347ed02008-09-20 12:04:53 +0200339 def __call__(self):
340 rv = concat(self._stack[self._depth](self._context))
Armin Ronacher1da23d12010-04-05 18:11:18 +0200341 if self._context.eval_ctx.autoescape:
Armin Ronacherc347ed02008-09-20 12:04:53 +0200342 rv = Markup(rv)
343 return rv
344
345
Armin Ronacherd4e14fc2016-12-28 20:06:34 +0100346class LoopContextBase(object):
Armin Ronacher32a910f2008-04-26 23:21:03 +0200347 """A loop context for dynamic iteration."""
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200348
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100349 _before = _first_iteration
350 _current = _first_iteration
Armin Ronacherd4e14fc2016-12-28 20:06:34 +0100351 _after = _last_iteration
352 _length = None
353
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100354 def __init__(self, undefined, recurse=None, depth0=0):
355 self._undefined = undefined
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200356 self._recurse = recurse
Armin Ronacher32a910f2008-04-26 23:21:03 +0200357 self.index0 = -1
Armin Ronacher568352e2013-05-20 09:26:57 +0100358 self.depth0 = depth0
Adrian Moennichbc076b32017-02-01 21:47:17 +0100359 self._last_checked_value = missing
Armin Ronacher547d0b62008-07-04 16:35:10 +0200360
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200361 def cycle(self, *args):
Armin Ronachered1e0d42008-05-18 20:25:28 +0200362 """Cycles among the arguments with the current loop index."""
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200363 if not args:
364 raise TypeError('no items for cycling given')
365 return args[self.index0 % len(args)]
366
Adrian Moennichbc076b32017-02-01 21:47:17 +0100367 def changed(self, *value):
368 """Checks whether the value has changed since the last call."""
369 if self._last_checked_value != value:
370 self._last_checked_value = value
371 return True
372 return False
373
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200374 first = property(lambda x: x.index0 == 0)
Armin Ronacher99b22852012-01-25 00:42:54 +0100375 last = property(lambda x: x._after is _last_iteration)
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200376 index = property(lambda x: x.index0 + 1)
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200377 revindex = property(lambda x: x.length - x.index0)
378 revindex0 = property(lambda x: x.length - x.index)
Armin Ronacher568352e2013-05-20 09:26:57 +0100379 depth = property(lambda x: x.depth0 + 1)
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200380
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100381 @property
382 def previtem(self):
383 if self._before is _first_iteration:
384 return self._undefined('there is no previous item')
385 return self._before
386
387 @property
388 def nextitem(self):
389 if self._after is _last_iteration:
390 return self._undefined('there is no next item')
391 return self._after
392
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200393 def __len__(self):
394 return self.length
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200395
Armin Ronacherd416a972009-02-24 22:58:00 +0100396 @internalcode
Armin Ronacher66a93442008-05-11 23:42:19 +0200397 def loop(self, iterable):
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200398 if self._recurse is None:
399 raise TypeError('Tried to call non recursive loop. Maybe you '
Armin Ronacher66a93442008-05-11 23:42:19 +0200400 "forgot the 'recursive' modifier.")
Armin Ronacher568352e2013-05-20 09:26:57 +0100401 return self._recurse(iterable, self._recurse, self.depth0 + 1)
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200402
Armin Ronacher66a93442008-05-11 23:42:19 +0200403 # a nifty trick to enhance the error message if someone tried to call
404 # the the loop without or with too many arguments.
Armin Ronacher2966f172010-02-17 00:52:42 +0100405 __call__ = loop
406 del loop
Armin Ronacher66a93442008-05-11 23:42:19 +0200407
Armin Ronacheracab87a2016-12-28 21:49:00 +0100408 def __repr__(self):
409 return '<%s %r/%r>' % (
410 self.__class__.__name__,
411 self.index,
412 self.length
413 )
414
415
416class LoopContext(LoopContextBase):
417
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100418 def __init__(self, iterable, undefined, recurse=None, depth0=0):
419 LoopContextBase.__init__(self, undefined, recurse, depth0)
Armin Ronacheracab87a2016-12-28 21:49:00 +0100420 self._iterator = iter(iterable)
421
422 # try to get the length of the iterable early. This must be done
423 # here because there are some broken iterators around where there
424 # __len__ is the number of iterations left (i'm looking at your
425 # listreverseiterator!).
426 try:
427 self._length = len(iterable)
428 except (TypeError, AttributeError):
429 self._length = None
430 self._after = self._safe_next()
431
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200432 @property
433 def length(self):
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200434 if self._length is None:
Armin Ronacher547d0b62008-07-04 16:35:10 +0200435 # if was not possible to get the length of the iterator when
436 # the loop context was created (ie: iterating over a generator)
437 # we have to convert the iterable into a sequence and use the
Christoph Reiter4eb30f12014-03-30 17:40:08 +0200438 # length of that + the number of iterations so far.
Armin Ronacher547d0b62008-07-04 16:35:10 +0200439 iterable = tuple(self._iterator)
440 self._iterator = iter(iterable)
Christoph Reiter4eb30f12014-03-30 17:40:08 +0200441 iterations_done = self.index0 + 2
442 self._length = len(iterable) + iterations_done
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200443 return self._length
444
Armin Ronacherd4e14fc2016-12-28 20:06:34 +0100445 def __iter__(self):
446 return LoopContextIterator(self)
447
448 def _safe_next(self):
449 try:
450 return next(self._iterator)
451 except StopIteration:
452 return _last_iteration
453
454
Armin Ronacher28c74882013-05-20 01:51:26 +0100455@implements_iterator
456class LoopContextIterator(object):
Armin Ronachered1e0d42008-05-18 20:25:28 +0200457 """The iterator for a loop context."""
458 __slots__ = ('context',)
459
460 def __init__(self, context):
461 self.context = context
462
463 def __iter__(self):
464 return self
465
Thomas Waldmann7d295622013-05-18 00:06:22 +0200466 def __next__(self):
Armin Ronachered1e0d42008-05-18 20:25:28 +0200467 ctx = self.context
468 ctx.index0 += 1
Armin Ronacher99b22852012-01-25 00:42:54 +0100469 if ctx._after is _last_iteration:
470 raise StopIteration()
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100471 ctx._before = ctx._current
472 ctx._current = ctx._after
Jason Kotenko776567c2012-01-24 14:19:08 -0800473 ctx._after = ctx._safe_next()
Adrian Moennich9bdb5472017-02-01 21:05:03 +0100474 return ctx._current, ctx
Armin Ronachered1e0d42008-05-18 20:25:28 +0200475
476
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200477class Macro(object):
Armin Ronacher3351a932010-06-05 14:32:06 +0200478 """Wraps a macro function."""
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200479
Armin Ronacher9b2a4f42017-01-03 18:19:31 +0100480 def __init__(self, environment, func, name, arguments,
Armin Ronacherb9655a42017-01-06 14:29:23 +0100481 catch_kwargs, catch_varargs, caller,
482 default_autoescape=None):
Armin Ronacherc63243e2008-04-14 22:53:58 +0200483 self._environment = environment
Armin Ronacher71082072008-04-12 14:19:36 +0200484 self._func = func
Armin Ronacherd84ec462008-04-29 13:43:16 +0200485 self._argument_count = len(arguments)
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200486 self.name = name
487 self.arguments = arguments
Armin Ronacher963f97d2008-04-25 11:44:59 +0200488 self.catch_kwargs = catch_kwargs
489 self.catch_varargs = catch_varargs
Armin Ronacher71082072008-04-12 14:19:36 +0200490 self.caller = caller
Armin Ronacher62356442017-01-08 02:16:41 +0100491 self.explicit_caller = 'caller' in arguments
Armin Ronacherb9655a42017-01-06 14:29:23 +0100492 if default_autoescape is None:
493 default_autoescape = environment.autoescape
494 self._default_autoescape = default_autoescape
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200495
Armin Ronacherd416a972009-02-24 22:58:00 +0100496 @internalcode
Armin Ronacherb9655a42017-01-06 14:29:23 +0100497 @evalcontextfunction
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200498 def __call__(self, *args, **kwargs):
Armin Ronacherb9655a42017-01-06 14:29:23 +0100499 # This requires a bit of explanation, In the past we used to
500 # decide largely based on compile-time information if a macro is
501 # safe or unsafe. While there was a volatile mode it was largely
502 # unused for deciding on escaping. This turns out to be
503 # problemtic for macros because if a macro is safe or not not so
504 # much depends on the escape mode when it was defined but when it
505 # was used.
506 #
507 # Because however we export macros from the module system and
508 # there are historic callers that do not pass an eval context (and
509 # will continue to not pass one), we need to perform an instance
510 # check here.
511 #
512 # This is considered safe because an eval context is not a valid
513 # argument to callables otherwise anwyays. Worst case here is
514 # that if no eval context is passed we fall back to the compile
515 # time autoescape flag.
516 if args and isinstance(args[0], EvalContext):
517 autoescape = args[0].autoescape
518 args = args[1:]
519 else:
520 autoescape = self._default_autoescape
521
Armin Ronacher3351a932010-06-05 14:32:06 +0200522 # try to consume the positional arguments
523 arguments = list(args[:self._argument_count])
524 off = len(arguments)
525
Armin Ronacher62356442017-01-08 02:16:41 +0100526 # For information why this is necessary refer to the handling
527 # of caller in the `macro_body` handler in the compiler.
528 found_caller = False
529
Armin Ronacher3351a932010-06-05 14:32:06 +0200530 # if the number of arguments consumed is not the number of
531 # arguments expected we start filling in keyword arguments
532 # and defaults.
533 if off != self._argument_count:
534 for idx, name in enumerate(self.arguments[len(arguments):]):
Armin Ronacher9706fab2008-04-08 18:49:56 +0200535 try:
536 value = kwargs.pop(name)
Armin Ronacher3351a932010-06-05 14:32:06 +0200537 except KeyError:
Armin Ronacher9b2a4f42017-01-03 18:19:31 +0100538 value = missing
Armin Ronacher62356442017-01-08 02:16:41 +0100539 if name == 'caller':
540 found_caller = True
Armin Ronacher3351a932010-06-05 14:32:06 +0200541 arguments.append(value)
Armin Ronacher62356442017-01-08 02:16:41 +0100542 else:
543 found_caller = self.explicit_caller
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200544
545 # it's important that the order of these arguments does not change
546 # if not also changed in the compiler's `function_scoping` method.
547 # the order is caller, keyword arguments, positional arguments!
Armin Ronacher62356442017-01-08 02:16:41 +0100548 if self.caller and not found_caller:
Armin Ronacher71082072008-04-12 14:19:36 +0200549 caller = kwargs.pop('caller', None)
550 if caller is None:
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200551 caller = self._environment.undefined('No caller defined',
552 name='caller')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200553 arguments.append(caller)
Armin Ronacher62356442017-01-08 02:16:41 +0100554
Armin Ronacher963f97d2008-04-25 11:44:59 +0200555 if self.catch_kwargs:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200556 arguments.append(kwargs)
Armin Ronacher963f97d2008-04-25 11:44:59 +0200557 elif kwargs:
Armin Ronacher62356442017-01-08 02:16:41 +0100558 if 'caller' in kwargs:
559 raise TypeError('macro %r was invoked with two values for '
560 'the special caller argument. This is '
561 'most likely a bug.' % self.name)
Armin Ronacher963f97d2008-04-25 11:44:59 +0200562 raise TypeError('macro %r takes no keyword argument %r' %
Armin Ronacherbd357722009-08-05 20:25:06 +0200563 (self.name, next(iter(kwargs))))
Armin Ronacher963f97d2008-04-25 11:44:59 +0200564 if self.catch_varargs:
Armin Ronacherd84ec462008-04-29 13:43:16 +0200565 arguments.append(args[self._argument_count:])
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200566 elif len(args) > self._argument_count:
567 raise TypeError('macro %r takes not more than %d argument(s)' %
568 (self.name, len(self.arguments)))
Armin Ronacherb9655a42017-01-06 14:29:23 +0100569
Armin Ronacheradd79162017-01-28 15:33:09 +0100570 return self._invoke(arguments, autoescape)
571
572 def _invoke(self, arguments, autoescape):
573 """This method is being swapped out by the async implementation."""
Armin Ronacherb9655a42017-01-06 14:29:23 +0100574 rv = self._func(*arguments)
575 if autoescape:
576 rv = Markup(rv)
577 return rv
Armin Ronacher71082072008-04-12 14:19:36 +0200578
579 def __repr__(self):
580 return '<%s %s>' % (
581 self.__class__.__name__,
582 self.name is None and 'anonymous' or repr(self.name)
583 )
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200584
585
Armin Ronacher28c74882013-05-20 01:51:26 +0100586@implements_to_string
587class Undefined(object):
Armin Ronacherd1342312008-04-28 12:20:12 +0200588 """The default undefined type. This undefined type can be printed and
Étienne Pelletier19133d42019-05-08 10:47:33 -0400589 iterated over, but every other access will raise an :exc:`UndefinedError`:
Armin Ronacherd1342312008-04-28 12:20:12 +0200590
591 >>> foo = Undefined(name='foo')
592 >>> str(foo)
593 ''
594 >>> not foo
595 True
596 >>> foo + 42
597 Traceback (most recent call last):
598 ...
Markus Unterwaditzer599c1362015-03-22 14:22:40 +0100599 jinja2.exceptions.UndefinedError: 'foo' is undefined
Armin Ronacherc63243e2008-04-14 22:53:58 +0200600 """
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200601 __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
602 '_undefined_exception')
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200603
Armin Ronacher48559082010-04-12 13:51:33 +0200604 def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
Armin Ronacher9a822052008-04-17 18:44:07 +0200605 self._undefined_hint = hint
606 self._undefined_obj = obj
607 self._undefined_name = name
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200608 self._undefined_exception = exc
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200609
Armin Ronacherd416a972009-02-24 22:58:00 +0100610 @internalcode
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200611 def _fail_with_undefined_error(self, *args, **kwargs):
612 """Regular callback function for undefined objects that raises an
Étienne Pelletier19133d42019-05-08 10:47:33 -0400613 `UndefinedError` on call.
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200614 """
615 if self._undefined_hint is None:
Armin Ronacher48559082010-04-12 13:51:33 +0200616 if self._undefined_obj is missing:
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200617 hint = '%r is undefined' % self._undefined_name
Armin Ronachere9098672013-05-19 14:16:13 +0100618 elif not isinstance(self._undefined_name, string_types):
Armin Ronacher98dbf5f2010-04-12 15:49:59 +0200619 hint = '%s has no element %r' % (
620 object_type_repr(self._undefined_obj),
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200621 self._undefined_name
622 )
623 else:
Armin Ronacher98dbf5f2010-04-12 15:49:59 +0200624 hint = '%r has no attribute %r' % (
625 object_type_repr(self._undefined_obj),
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200626 self._undefined_name
627 )
628 else:
629 hint = self._undefined_hint
630 raise self._undefined_exception(hint)
631
Armin Ronacher6a3e95d2010-11-19 13:51:38 +0100632 @internalcode
633 def __getattr__(self, name):
634 if name[:2] == '__':
635 raise AttributeError(name)
636 return self._fail_with_undefined_error()
637
Armin Ronacherc63243e2008-04-14 22:53:58 +0200638 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
Armin Ronacherd2641be2014-06-06 22:00:04 +0600639 __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
640 __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
641 __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
Nick Garciadd857612016-01-07 15:23:26 -0800642 __float__ = __complex__ = __pow__ = __rpow__ = __sub__ = \
Armin Ronacherebed13e2017-01-03 19:33:25 +0100643 __rsub__ = _fail_with_undefined_error
Armin Ronacherc63243e2008-04-14 22:53:58 +0200644
Armin Ronacher563fd2e2013-08-07 12:48:37 +0100645 def __eq__(self, other):
646 return type(self) is type(other)
647
648 def __ne__(self, other):
649 return not self.__eq__(other)
650
651 def __hash__(self):
652 return id(type(self))
653
Armin Ronacher28c74882013-05-20 01:51:26 +0100654 def __str__(self):
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200655 return u''
656
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200657 def __len__(self):
658 return 0
659
660 def __iter__(self):
661 if 0:
662 yield None
Armin Ronacherc63243e2008-04-14 22:53:58 +0200663
664 def __nonzero__(self):
665 return False
Armin Ronacher7b32f8f2014-06-06 22:17:05 +0600666 __bool__ = __nonzero__
Armin Ronacherc63243e2008-04-14 22:53:58 +0200667
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200668 def __repr__(self):
669 return 'Undefined'
670
Armin Ronacherc63243e2008-04-14 22:53:58 +0200671
Armin Ronacherd2641be2014-06-06 22:00:04 +0600672def make_logging_undefined(logger=None, base=None):
Armin Ronacher6e9dfbf2014-06-06 22:14:45 +0600673 """Given a logger object this returns a new undefined class that will
674 log certain failures. It will log iterations and printing. If no
675 logger is given a default logger is created.
676
677 Example::
678
679 logger = logging.getLogger(__name__)
680 LoggingUndefined = make_logging_undefined(
681 logger=logger,
682 base=Undefined
683 )
684
685 .. versionadded:: 2.8
686
687 :param logger: the logger to use. If not provided, a default logger
688 is created.
689 :param base: the base class to add logging functionality to. This
690 defaults to :class:`Undefined`.
Armin Ronacherd2641be2014-06-06 22:00:04 +0600691 """
692 if logger is None:
693 import logging
694 logger = logging.getLogger(__name__)
695 logger.addHandler(logging.StreamHandler(sys.stderr))
696 if base is None:
697 base = Undefined
698
Armin Ronacher6e9dfbf2014-06-06 22:14:45 +0600699 def _log_message(undef):
700 if undef._undefined_hint is None:
701 if undef._undefined_obj is missing:
702 hint = '%s is undefined' % undef._undefined_name
703 elif not isinstance(undef._undefined_name, string_types):
704 hint = '%s has no element %s' % (
705 object_type_repr(undef._undefined_obj),
706 undef._undefined_name)
Armin Ronacherd2641be2014-06-06 22:00:04 +0600707 else:
Armin Ronacher6e9dfbf2014-06-06 22:14:45 +0600708 hint = '%s has no attribute %s' % (
709 object_type_repr(undef._undefined_obj),
710 undef._undefined_name)
711 else:
712 hint = undef._undefined_hint
713 logger.warning('Template variable warning: %s', hint)
714
715 class LoggingUndefined(base):
716
717 def _fail_with_undefined_error(self, *args, **kwargs):
718 try:
719 return base._fail_with_undefined_error(self, *args, **kwargs)
720 except self._undefined_exception as e:
721 logger.error('Template variable error: %s', str(e))
722 raise e
723
724 def __str__(self):
725 rv = base.__str__(self)
726 _log_message(self)
727 return rv
728
Armin Ronacher6e9dfbf2014-06-06 22:14:45 +0600729 def __iter__(self):
730 rv = base.__iter__(self)
731 _log_message(self)
732 return rv
733
Armin Ronacher7b32f8f2014-06-06 22:17:05 +0600734 if PY2:
735 def __nonzero__(self):
736 rv = base.__nonzero__(self)
737 _log_message(self)
738 return rv
739
740 def __unicode__(self):
741 rv = base.__unicode__(self)
742 _log_message(self)
743 return rv
744 else:
745 def __bool__(self):
746 rv = base.__bool__(self)
747 _log_message(self)
748 return rv
Armin Ronacherd2641be2014-06-06 22:00:04 +0600749
750 return LoggingUndefined
751
752
Étienne Pelletier19133d42019-05-08 10:47:33 -0400753# No @implements_to_string decorator here because __str__
754# is not overwritten from Undefined in this class.
755# This would cause a recursion error in Python 2.
756class ChainableUndefined(Undefined):
757 """An undefined that is chainable, where both
758 __getattr__ and __getitem__ return itself rather than
759 raising an :exc:`UndefinedError`:
760
761 >>> foo = ChainableUndefined(name='foo')
762 >>> str(foo.bar['baz'])
763 ''
764 >>> foo.bar['baz'] + 42
765 Traceback (most recent call last):
766 ...
767 jinja2.exceptions.UndefinedError: 'foo' is undefined
768
769 .. versionadded:: 2.11
770 """
771 __slots__ = ()
772
773 def __getattr__(self, _):
774 return self
775
776 __getitem__ = __getattr__
777
778
Armin Ronacher28c74882013-05-20 01:51:26 +0100779@implements_to_string
Armin Ronacherc63243e2008-04-14 22:53:58 +0200780class DebugUndefined(Undefined):
Armin Ronacherd1342312008-04-28 12:20:12 +0200781 """An undefined that returns the debug info when printed.
782
783 >>> foo = DebugUndefined(name='foo')
784 >>> str(foo)
785 '{{ foo }}'
786 >>> not foo
787 True
788 >>> foo + 42
789 Traceback (most recent call last):
790 ...
Markus Unterwaditzer599c1362015-03-22 14:22:40 +0100791 jinja2.exceptions.UndefinedError: 'foo' is undefined
Armin Ronacherd1342312008-04-28 12:20:12 +0200792 """
Armin Ronacher53042292008-04-26 18:30:19 +0200793 __slots__ = ()
Armin Ronacherc63243e2008-04-14 22:53:58 +0200794
Armin Ronacher28c74882013-05-20 01:51:26 +0100795 def __str__(self):
Armin Ronacher9a822052008-04-17 18:44:07 +0200796 if self._undefined_hint is None:
Armin Ronacher48559082010-04-12 13:51:33 +0200797 if self._undefined_obj is missing:
Armin Ronacher9a822052008-04-17 18:44:07 +0200798 return u'{{ %s }}' % self._undefined_name
799 return '{{ no such element: %s[%r] }}' % (
Armin Ronacher98dbf5f2010-04-12 15:49:59 +0200800 object_type_repr(self._undefined_obj),
Armin Ronacher9a822052008-04-17 18:44:07 +0200801 self._undefined_name
802 )
803 return u'{{ undefined value printed: %s }}' % self._undefined_hint
Armin Ronacherc63243e2008-04-14 22:53:58 +0200804
805
Armin Ronacher28c74882013-05-20 01:51:26 +0100806@implements_to_string
Armin Ronacherc63243e2008-04-14 22:53:58 +0200807class StrictUndefined(Undefined):
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200808 """An undefined that barks on print and iteration as well as boolean
Armin Ronacher53042292008-04-26 18:30:19 +0200809 tests and all kinds of comparisons. In other words: you can do nothing
810 with it except checking if it's defined using the `defined` test.
Armin Ronacherd1342312008-04-28 12:20:12 +0200811
812 >>> foo = StrictUndefined(name='foo')
813 >>> str(foo)
814 Traceback (most recent call last):
815 ...
Markus Unterwaditzer599c1362015-03-22 14:22:40 +0100816 jinja2.exceptions.UndefinedError: 'foo' is undefined
Armin Ronacherd1342312008-04-28 12:20:12 +0200817 >>> not foo
818 Traceback (most recent call last):
819 ...
Markus Unterwaditzer599c1362015-03-22 14:22:40 +0100820 jinja2.exceptions.UndefinedError: 'foo' is undefined
Armin Ronacherd1342312008-04-28 12:20:12 +0200821 >>> foo + 42
822 Traceback (most recent call last):
823 ...
Markus Unterwaditzer599c1362015-03-22 14:22:40 +0100824 jinja2.exceptions.UndefinedError: 'foo' is undefined
Priit Laes4149a0e2008-04-17 19:04:44 +0200825 """
Armin Ronacher53042292008-04-26 18:30:19 +0200826 __slots__ = ()
Armin Ronacher28c74882013-05-20 01:51:26 +0100827 __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
Armin Ronacher563fd2e2013-08-07 12:48:37 +0100828 __ne__ = __bool__ = __hash__ = \
829 Undefined._fail_with_undefined_error
Armin Ronacherc63243e2008-04-14 22:53:58 +0200830
Armin Ronacher53042292008-04-26 18:30:19 +0200831
832# remove remaining slots attributes, after the metaclass did the magic they
833# are unneeded and irritating as they contain wrong data for the subclasses.
Étienne Pelletier19133d42019-05-08 10:47:33 -0400834del Undefined.__slots__, ChainableUndefined.__slots__, \
835 DebugUndefined.__slots__, StrictUndefined.__slots__