blob: 7a1cf276d98933680a20893967c7110966ae5229 [file] [log] [blame]
Armin Ronachere791c2a2008-04-07 18:39:54 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.runtime
4 ~~~~~~~~~~~~~~
5
6 Runtime helpers.
7
8 :copyright: Copyright 2008 by Armin Ronacher.
9 :license: GNU GPL.
10"""
Armin Ronacher1ae4fdf2008-04-28 20:49:51 +020011import sys
Armin Ronacherd1342312008-04-28 12:20:12 +020012from itertools import chain, imap
Armin Ronacher7ceced52008-05-03 10:15:31 +020013from jinja2.utils import Markup, partial, soft_unicode, escape, missing, concat
Armin Ronacherd1342312008-04-28 12:20:12 +020014from jinja2.exceptions import UndefinedError, TemplateRuntimeError
Armin Ronachere791c2a2008-04-07 18:39:54 +020015
16
Armin Ronacher2feed1d2008-04-26 16:26:52 +020017# these variables are exported to the template runtime
Armin Ronacher19cf9c22008-05-01 12:49:53 +020018__all__ = ['LoopContext', 'Context', 'TemplateReference', 'Macro', 'Markup',
19 'TemplateRuntimeError', 'missing', 'concat', 'escape',
Armin Ronacherd1342312008-04-28 12:20:12 +020020 'markup_join', 'unicode_join']
Armin Ronacher0611e492008-04-25 23:44:14 +020021
22
Armin Ronacherdc02b642008-05-15 22:47:27 +020023def markup_join(seq):
Armin Ronacherd1342312008-04-28 12:20:12 +020024 """Concatenation that escapes if necessary and converts to unicode."""
25 buf = []
Armin Ronacherdc02b642008-05-15 22:47:27 +020026 iterator = imap(soft_unicode, seq)
Armin Ronacherd1342312008-04-28 12:20:12 +020027 for arg in iterator:
28 buf.append(arg)
29 if hasattr(arg, '__html__'):
30 return Markup(u'').join(chain(buf, iterator))
31 return concat(buf)
32
33
Armin Ronacherdc02b642008-05-15 22:47:27 +020034def unicode_join(seq):
Armin Ronacherd1342312008-04-28 12:20:12 +020035 """Simple args to unicode conversion and concatenation."""
Armin Ronacherdc02b642008-05-15 22:47:27 +020036 return concat(imap(unicode, seq))
Armin Ronacherd1342312008-04-28 12:20:12 +020037
38
Armin Ronacher19cf9c22008-05-01 12:49:53 +020039class Context(object):
Armin Ronacher7259c762008-04-30 13:03:59 +020040 """The template context holds the variables of a template. It stores the
41 values passed to the template and also the names the template exports.
42 Creating instances is neither supported nor useful as it's created
43 automatically at various stages of the template evaluation and should not
44 be created by hand.
Armin Ronacherc9705c22008-04-27 21:28:03 +020045
Armin Ronacher7259c762008-04-30 13:03:59 +020046 The context is immutable. Modifications on :attr:`parent` **must not**
47 happen and modifications on :attr:`vars` are allowed from generated
48 template code only. Template filters and global functions marked as
49 :func:`contextfunction`\s get the active context passed as first argument
50 and are allowed to access the context read-only.
51
52 The template context supports read only dict operations (`get`,
Armin Ronacherf35e2812008-05-06 16:04:10 +020053 `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
54 `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
55 method that doesn't fail with a `KeyError` but returns an
56 :class:`Undefined` object for missing variables.
Armin Ronacher9706fab2008-04-08 18:49:56 +020057 """
Armin Ronacher771c7502008-05-18 23:14:14 +020058 __slots__ = ('parent', 'vars', 'environment', 'exported_vars', 'name',
59 'blocks')
Armin Ronachere791c2a2008-04-07 18:39:54 +020060
Armin Ronacher203bfcb2008-04-24 21:54:44 +020061 def __init__(self, environment, parent, name, blocks):
62 self.parent = parent
Armin Ronacher2feed1d2008-04-26 16:26:52 +020063 self.vars = vars = {}
Armin Ronacherc63243e2008-04-14 22:53:58 +020064 self.environment = environment
Armin Ronacher203bfcb2008-04-24 21:54:44 +020065 self.exported_vars = set()
Armin Ronacher68f77672008-04-17 11:50:39 +020066 self.name = name
Armin Ronacher203bfcb2008-04-24 21:54:44 +020067
Armin Ronacher203bfcb2008-04-24 21:54:44 +020068 # create the initial mapping of blocks. Whenever template inheritance
69 # takes place the runtime will update this mapping with the new blocks
70 # from the template.
Armin Ronacher75cfb862008-04-11 13:47:22 +020071 self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
Armin Ronacherf059ec12008-04-11 22:21:00 +020072
Armin Ronacher203bfcb2008-04-24 21:54:44 +020073 def super(self, name, current):
Armin Ronacher62f8a292008-04-13 23:18:05 +020074 """Render a parent block."""
Armin Ronacherc9705c22008-04-27 21:28:03 +020075 try:
76 blocks = self.blocks[name]
Armin Ronacher83fbc0f2008-05-15 12:22:28 +020077 block = blocks[blocks.index(current) + 1]
Armin Ronacherc9705c22008-04-27 21:28:03 +020078 except LookupError:
Armin Ronacher9a822052008-04-17 18:44:07 +020079 return self.environment.undefined('there is no parent block '
Armin Ronacher19cf9c22008-05-01 12:49:53 +020080 'called %r.' % name,
81 name='super')
Armin Ronacherd1342312008-04-28 12:20:12 +020082 wrap = self.environment.autoescape and Markup or (lambda x: x)
Armin Ronacher83fbc0f2008-05-15 12:22:28 +020083 render = lambda: wrap(concat(block(self)))
Armin Ronacherc9705c22008-04-27 21:28:03 +020084 render.__name__ = render.name = name
85 return render
Armin Ronachere791c2a2008-04-07 18:39:54 +020086
Armin Ronacher53042292008-04-26 18:30:19 +020087 def get(self, key, default=None):
Armin Ronacher7259c762008-04-30 13:03:59 +020088 """Returns an item from the template context, if it doesn't exist
89 `default` is returned.
90 """
Armin Ronacherf35e2812008-05-06 16:04:10 +020091 try:
92 return self[key]
93 except KeyError:
94 return default
95
96 def resolve(self, key):
97 """Looks up a variable like `__getitem__` or `get` but returns an
98 :class:`Undefined` object with the name of the name looked up.
99 """
Armin Ronacher53042292008-04-26 18:30:19 +0200100 if key in self.vars:
101 return self.vars[key]
102 if key in self.parent:
103 return self.parent[key]
Armin Ronacherf35e2812008-05-06 16:04:10 +0200104 return self.environment.undefined(name=key)
Armin Ronacherb5124e62008-04-25 00:36:14 +0200105
Armin Ronacher9706fab2008-04-08 18:49:56 +0200106 def get_exported(self):
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200107 """Get a new dict with the exported variables."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200108 return dict((k, self.vars[k]) for k in self.exported_vars)
Armin Ronacher9706fab2008-04-08 18:49:56 +0200109
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200110 def get_all(self):
Armin Ronacher7259c762008-04-30 13:03:59 +0200111 """Return a copy of the complete context as dict including the
Armin Ronacher5411ce72008-05-25 11:36:22 +0200112 exported variables.
Armin Ronacher7259c762008-04-30 13:03:59 +0200113 """
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200114 return dict(self.parent, **self.vars)
115
Armin Ronacherfd310492008-05-25 00:16:51 +0200116 def call(__self, __obj, *args, **kwargs):
117 """Called by the template code to inject the current context
118 or environment as first arguments. Then forwards the call to
119 the object with the arguments and keyword arguments.
120 """
121 if getattr(__obj, 'contextfunction', 0):
122 args = (__self,) + args
123 elif getattr(__obj, 'environmentfunction', 0):
124 args = (__self.environment,) + args
125 return __obj(*args, **kwargs)
126
Armin Ronacherf35e2812008-05-06 16:04:10 +0200127 def _all(meth):
Armin Ronachere9411b42008-05-15 16:22:07 +0200128 proxy = lambda self: getattr(self.get_all(), meth)()
Armin Ronacherf35e2812008-05-06 16:04:10 +0200129 proxy.__doc__ = getattr(dict, meth).__doc__
130 proxy.__name__ = meth
131 return proxy
132
133 keys = _all('keys')
134 values = _all('values')
135 items = _all('items')
136 iterkeys = _all('iterkeys')
137 itervalues = _all('itervalues')
138 iteritems = _all('iteritems')
139 del _all
140
Armin Ronacherb5124e62008-04-25 00:36:14 +0200141 def __contains__(self, name):
142 return name in self.vars or name in self.parent
143
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200144 def __getitem__(self, key):
Armin Ronacherbbbe0622008-05-19 00:23:37 +0200145 """Lookup a variable or raise `KeyError` if the variable is
146 undefined.
147 """
148 item = self.resolve(key)
149 if isinstance(item, Undefined):
150 raise KeyError(key)
151 return item
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200152
Armin Ronacherf059ec12008-04-11 22:21:00 +0200153 def __repr__(self):
154 return '<%s %s of %r>' % (
155 self.__class__.__name__,
Armin Ronacher963f97d2008-04-25 11:44:59 +0200156 repr(self.get_all()),
Armin Ronacher68f77672008-04-17 11:50:39 +0200157 self.name
Armin Ronacherf059ec12008-04-11 22:21:00 +0200158 )
159
160
Armin Ronacherc9705c22008-04-27 21:28:03 +0200161class TemplateReference(object):
162 """The `self` in templates."""
Armin Ronacher62f8a292008-04-13 23:18:05 +0200163
Armin Ronacherc9705c22008-04-27 21:28:03 +0200164 def __init__(self, context):
165 self.__context = context
Armin Ronacher62f8a292008-04-13 23:18:05 +0200166
Armin Ronacherc9705c22008-04-27 21:28:03 +0200167 def __getitem__(self, name):
Armin Ronacher6df604e2008-05-23 22:18:38 +0200168 func = self.__context.blocks[name][0]
Armin Ronacherd1342312008-04-28 12:20:12 +0200169 wrap = self.__context.environment.autoescape and \
170 Markup or (lambda x: x)
171 render = lambda: wrap(concat(func(self.__context)))
Armin Ronacherc9705c22008-04-27 21:28:03 +0200172 render.__name__ = render.name = name
173 return render
Armin Ronacher62f8a292008-04-13 23:18:05 +0200174
175 def __repr__(self):
176 return '<%s %r>' % (
177 self.__class__.__name__,
Armin Ronacherc9705c22008-04-27 21:28:03 +0200178 self._context.name
Armin Ronacher62f8a292008-04-13 23:18:05 +0200179 )
180
181
Armin Ronacher32a910f2008-04-26 23:21:03 +0200182class LoopContext(object):
183 """A loop context for dynamic iteration."""
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200184
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200185 def __init__(self, iterable, enforce_length=False, recurse=None):
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200186 self._iterable = iterable
Armin Ronacher32a910f2008-04-26 23:21:03 +0200187 self._next = iter(iterable).next
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200188 self._length = None
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200189 self._recurse = recurse
Armin Ronacher32a910f2008-04-26 23:21:03 +0200190 self.index0 = -1
191 if enforce_length:
192 len(self)
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200193
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200194 def cycle(self, *args):
Armin Ronachered1e0d42008-05-18 20:25:28 +0200195 """Cycles among the arguments with the current loop index."""
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200196 if not args:
197 raise TypeError('no items for cycling given')
198 return args[self.index0 % len(args)]
199
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200200 first = property(lambda x: x.index0 == 0)
201 last = property(lambda x: x.revindex0 == 0)
202 index = property(lambda x: x.index0 + 1)
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200203 revindex = property(lambda x: x.length - x.index0)
204 revindex0 = property(lambda x: x.length - x.index)
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200205
206 def __len__(self):
207 return self.length
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200208
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200209 def __iter__(self):
Armin Ronachered1e0d42008-05-18 20:25:28 +0200210 return LoopContextIterator(self)
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200211
Armin Ronacher66a93442008-05-11 23:42:19 +0200212 def loop(self, iterable):
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200213 if self._recurse is None:
214 raise TypeError('Tried to call non recursive loop. Maybe you '
Armin Ronacher66a93442008-05-11 23:42:19 +0200215 "forgot the 'recursive' modifier.")
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200216 return self._recurse(iterable, self._recurse)
217
Armin Ronacher66a93442008-05-11 23:42:19 +0200218 # a nifty trick to enhance the error message if someone tried to call
219 # the the loop without or with too many arguments.
220 __call__ = loop; del loop
221
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200222 @property
223 def length(self):
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200224 if self._length is None:
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200225 try:
Armin Ronachered1e0d42008-05-18 20:25:28 +0200226 # first try to get the length from the iterable (if the
227 # iterable is a sequence)
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200228 length = len(self._iterable)
229 except TypeError:
Armin Ronachered1e0d42008-05-18 20:25:28 +0200230 # if that's not possible (ie: iterating over a generator)
231 # we have to convert the iterable into a sequence and
232 # use the length of that.
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200233 self._iterable = tuple(self._iterable)
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200234 self._next = iter(self._iterable).next
235 length = len(tuple(self._iterable)) + self.index0 + 1
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200236 self._length = length
237 return self._length
238
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200239 def __repr__(self):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200240 return '<%s %r/%r>' % (
241 self.__class__.__name__,
242 self.index,
243 self.length
244 )
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200245
Armin Ronacher180a1bd2008-04-09 12:14:24 +0200246
Armin Ronachered1e0d42008-05-18 20:25:28 +0200247class LoopContextIterator(object):
248 """The iterator for a loop context."""
249 __slots__ = ('context',)
250
251 def __init__(self, context):
252 self.context = context
253
254 def __iter__(self):
255 return self
256
257 def next(self):
258 ctx = self.context
259 ctx.index0 += 1
260 return ctx._next(), ctx
261
262
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200263class Macro(object):
Armin Ronacherd55ab532008-04-09 16:13:39 +0200264 """Wraps a macro."""
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200265
Armin Ronacher963f97d2008-04-25 11:44:59 +0200266 def __init__(self, environment, func, name, arguments, defaults,
267 catch_kwargs, catch_varargs, caller):
Armin Ronacherc63243e2008-04-14 22:53:58 +0200268 self._environment = environment
Armin Ronacher71082072008-04-12 14:19:36 +0200269 self._func = func
Armin Ronacherd84ec462008-04-29 13:43:16 +0200270 self._argument_count = len(arguments)
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200271 self.name = name
272 self.arguments = arguments
273 self.defaults = defaults
Armin Ronacher963f97d2008-04-25 11:44:59 +0200274 self.catch_kwargs = catch_kwargs
275 self.catch_varargs = catch_varargs
Armin Ronacher71082072008-04-12 14:19:36 +0200276 self.caller = caller
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200277
278 def __call__(self, *args, **kwargs):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200279 arguments = []
Armin Ronacher9706fab2008-04-08 18:49:56 +0200280 for idx, name in enumerate(self.arguments):
281 try:
282 value = args[idx]
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200283 except:
Armin Ronacher9706fab2008-04-08 18:49:56 +0200284 try:
285 value = kwargs.pop(name)
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200286 except:
Armin Ronacher9706fab2008-04-08 18:49:56 +0200287 try:
Armin Ronacherd84ec462008-04-29 13:43:16 +0200288 value = self.defaults[idx - self._argument_count]
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200289 except:
Armin Ronacher9a822052008-04-17 18:44:07 +0200290 value = self._environment.undefined(
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200291 'parameter %r was not provided' % name, name=name)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200292 arguments.append(value)
293
294 # it's important that the order of these arguments does not change
295 # if not also changed in the compiler's `function_scoping` method.
296 # the order is caller, keyword arguments, positional arguments!
Armin Ronacher71082072008-04-12 14:19:36 +0200297 if self.caller:
298 caller = kwargs.pop('caller', None)
299 if caller is None:
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200300 caller = self._environment.undefined('No caller defined',
301 name='caller')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200302 arguments.append(caller)
Armin Ronacher963f97d2008-04-25 11:44:59 +0200303 if self.catch_kwargs:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200304 arguments.append(kwargs)
Armin Ronacher963f97d2008-04-25 11:44:59 +0200305 elif kwargs:
306 raise TypeError('macro %r takes no keyword argument %r' %
307 (self.name, iter(kwargs).next()))
308 if self.catch_varargs:
Armin Ronacherd84ec462008-04-29 13:43:16 +0200309 arguments.append(args[self._argument_count:])
Armin Ronacher19cf9c22008-05-01 12:49:53 +0200310 elif len(args) > self._argument_count:
311 raise TypeError('macro %r takes not more than %d argument(s)' %
312 (self.name, len(self.arguments)))
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200313 return self._func(*arguments)
Armin Ronacher71082072008-04-12 14:19:36 +0200314
315 def __repr__(self):
316 return '<%s %s>' % (
317 self.__class__.__name__,
318 self.name is None and 'anonymous' or repr(self.name)
319 )
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200320
321
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200322def fail_with_undefined_error(self, *args, **kwargs):
323 """Regular callback function for undefined objects that raises an
324 `UndefinedError` on call.
325 """
326 if self._undefined_hint is None:
327 if self._undefined_obj is None:
328 hint = '%r is undefined' % self._undefined_name
329 elif not isinstance(self._undefined_name, basestring):
330 hint = '%r object has no element %r' % (
331 self._undefined_obj.__class__.__name__,
332 self._undefined_name
333 )
334 else:
335 hint = '%r object has no attribute %r' % (
336 self._undefined_obj.__class__.__name__,
337 self._undefined_name
338 )
339 else:
340 hint = self._undefined_hint
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200341 raise self._undefined_exception(hint)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200342
343
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200344class Undefined(object):
Armin Ronacherd1342312008-04-28 12:20:12 +0200345 """The default undefined type. This undefined type can be printed and
346 iterated over, but every other access will raise an :exc:`UndefinedError`:
347
348 >>> foo = Undefined(name='foo')
349 >>> str(foo)
350 ''
351 >>> not foo
352 True
353 >>> foo + 42
354 Traceback (most recent call last):
355 ...
356 jinja2.exceptions.UndefinedError: 'foo' is undefined
Armin Ronacherc63243e2008-04-14 22:53:58 +0200357 """
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200358 __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
359 '_undefined_exception')
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200360
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200361 def __init__(self, hint=None, obj=None, name=None, exc=UndefinedError):
Armin Ronacher9a822052008-04-17 18:44:07 +0200362 self._undefined_hint = hint
363 self._undefined_obj = obj
364 self._undefined_name = name
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200365 self._undefined_exception = exc
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200366
Armin Ronacherc63243e2008-04-14 22:53:58 +0200367 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
368 __realdiv__ = __rrealdiv__ = __floordiv__ = __rfloordiv__ = \
369 __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
Armin Ronacher53042292008-04-26 18:30:19 +0200370 __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
371 fail_with_undefined_error
Armin Ronacherc63243e2008-04-14 22:53:58 +0200372
373 def __str__(self):
374 return self.__unicode__().encode('utf-8')
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200375
376 def __repr__(self):
Priit Laes4149a0e2008-04-17 19:04:44 +0200377 return 'Undefined'
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200378
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200379 def __unicode__(self):
380 return u''
381
Armin Ronacherd1d2f3d2008-04-09 14:02:55 +0200382 def __len__(self):
383 return 0
384
385 def __iter__(self):
386 if 0:
387 yield None
Armin Ronacherc63243e2008-04-14 22:53:58 +0200388
389 def __nonzero__(self):
390 return False
391
392
393class DebugUndefined(Undefined):
Armin Ronacherd1342312008-04-28 12:20:12 +0200394 """An undefined that returns the debug info when printed.
395
396 >>> foo = DebugUndefined(name='foo')
397 >>> str(foo)
398 '{{ foo }}'
399 >>> not foo
400 True
401 >>> foo + 42
402 Traceback (most recent call last):
403 ...
404 jinja2.exceptions.UndefinedError: 'foo' is undefined
405 """
Armin Ronacher53042292008-04-26 18:30:19 +0200406 __slots__ = ()
Armin Ronacherc63243e2008-04-14 22:53:58 +0200407
408 def __unicode__(self):
Armin Ronacher9a822052008-04-17 18:44:07 +0200409 if self._undefined_hint is None:
410 if self._undefined_obj is None:
411 return u'{{ %s }}' % self._undefined_name
412 return '{{ no such element: %s[%r] }}' % (
413 self._undefined_obj.__class__.__name__,
414 self._undefined_name
415 )
416 return u'{{ undefined value printed: %s }}' % self._undefined_hint
Armin Ronacherc63243e2008-04-14 22:53:58 +0200417
418
419class StrictUndefined(Undefined):
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200420 """An undefined that barks on print and iteration as well as boolean
Armin Ronacher53042292008-04-26 18:30:19 +0200421 tests and all kinds of comparisons. In other words: you can do nothing
422 with it except checking if it's defined using the `defined` test.
Armin Ronacherd1342312008-04-28 12:20:12 +0200423
424 >>> foo = StrictUndefined(name='foo')
425 >>> str(foo)
426 Traceback (most recent call last):
427 ...
428 jinja2.exceptions.UndefinedError: 'foo' is undefined
429 >>> not foo
430 Traceback (most recent call last):
431 ...
432 jinja2.exceptions.UndefinedError: 'foo' is undefined
433 >>> foo + 42
434 Traceback (most recent call last):
435 ...
436 jinja2.exceptions.UndefinedError: 'foo' is undefined
Priit Laes4149a0e2008-04-17 19:04:44 +0200437 """
Armin Ronacher53042292008-04-26 18:30:19 +0200438 __slots__ = ()
439 __iter__ = __unicode__ = __len__ = __nonzero__ = __eq__ = __ne__ = \
440 fail_with_undefined_error
Armin Ronacherc63243e2008-04-14 22:53:58 +0200441
Armin Ronacher53042292008-04-26 18:30:19 +0200442
443# remove remaining slots attributes, after the metaclass did the magic they
444# are unneeded and irritating as they contain wrong data for the subclasses.
445del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__