5c39984170509b6ef56aa283874b845dac0cabbe
[jinja2.git] / jinja2 / runtime.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.runtime
4     ~~~~~~~~~~~~~~
5
6     Runtime helpers.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD.
10 """
11 from itertools import chain, imap
12 from jinja2.nodes import EvalContext, _context_function_types
13 from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
14      concat, internalcode, next, object_type_repr
15 from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
16      TemplateNotFound
17
18
19 # these variables are exported to the template runtime
20 __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
21            'TemplateRuntimeError', 'missing', 'concat', 'escape',
22            'markup_join', 'unicode_join', 'to_string', 'identity',
23            'TemplateNotFound']
24
25 #: the name of the function that is used to convert something into
26 #: a string.  2to3 will adopt that automatically and the generated
27 #: code can take advantage of it.
28 to_string = unicode
29
30 #: the identity function.  Useful for certain things in the environment
31 identity = lambda x: x
32
33 _last_iteration = object()
34
35
36 def markup_join(seq):
37     """Concatenation that escapes if necessary and converts to unicode."""
38     buf = []
39     iterator = imap(soft_unicode, seq)
40     for arg in iterator:
41         buf.append(arg)
42         if hasattr(arg, '__html__'):
43             return Markup(u'').join(chain(buf, iterator))
44     return concat(buf)
45
46
47 def unicode_join(seq):
48     """Simple args to unicode conversion and concatenation."""
49     return concat(imap(unicode, seq))
50
51
52 def new_context(environment, template_name, blocks, vars=None,
53                 shared=None, globals=None, locals=None):
54     """Internal helper to for context creation."""
55     if vars is None:
56         vars = {}
57     if shared:
58         parent = vars
59     else:
60         parent = dict(globals or (), **vars)
61     if locals:
62         # if the parent is shared a copy should be created because
63         # we don't want to modify the dict passed
64         if shared:
65             parent = dict(parent)
66         for key, value in locals.iteritems():
67             if key[:2] == 'l_' and value is not missing:
68                 parent[key[2:]] = value
69     return Context(environment, parent, template_name, blocks)
70
71
72 class TemplateReference(object):
73     """The `self` in templates."""
74
75     def __init__(self, context):
76         self.__context = context
77
78     def __getitem__(self, name):
79         blocks = self.__context.blocks[name]
80         return BlockReference(name, self.__context, blocks, 0)
81
82     def __repr__(self):
83         return '<%s %r>' % (
84             self.__class__.__name__,
85             self.__context.name
86         )
87
88
89 class Context(object):
90     """The template context holds the variables of a template.  It stores the
91     values passed to the template and also the names the template exports.
92     Creating instances is neither supported nor useful as it's created
93     automatically at various stages of the template evaluation and should not
94     be created by hand.
95
96     The context is immutable.  Modifications on :attr:`parent` **must not**
97     happen and modifications on :attr:`vars` are allowed from generated
98     template code only.  Template filters and global functions marked as
99     :func:`contextfunction`\s get the active context passed as first argument
100     and are allowed to access the context read-only.
101
102     The template context supports read only dict operations (`get`,
103     `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
104     `__getitem__`, `__contains__`).  Additionally there is a :meth:`resolve`
105     method that doesn't fail with a `KeyError` but returns an
106     :class:`Undefined` object for missing variables.
107     """
108     __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
109                  'name', 'blocks', '__weakref__')
110
111     def __init__(self, environment, parent, name, blocks):
112         self.parent = parent
113         self.vars = {}
114         self.environment = environment
115         self.eval_ctx = EvalContext(self.environment, name)
116         self.exported_vars = set()
117         self.name = name
118
119         # create the initial mapping of blocks.  Whenever template inheritance
120         # takes place the runtime will update this mapping with the new blocks
121         # from the template.
122         self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
123
124     def super(self, name, current):
125         """Render a parent block."""
126         try:
127             blocks = self.blocks[name]
128             index = blocks.index(current) + 1
129             blocks[index]
130         except LookupError:
131             return self.environment.undefined('there is no parent block '
132                                               'called %r.' % name,
133                                               name='super')
134         return BlockReference(name, self, blocks, index)
135
136     def get(self, key, default=None):
137         """Returns an item from the template context, if it doesn't exist
138         `default` is returned.
139         """
140         try:
141             return self[key]
142         except KeyError:
143             return default
144
145     def resolve(self, key):
146         """Looks up a variable like `__getitem__` or `get` but returns an
147         :class:`Undefined` object with the name of the name looked up.
148         """
149         if key in self.vars:
150             return self.vars[key]
151         if key in self.parent:
152             return self.parent[key]
153         return self.environment.undefined(name=key)
154
155     def get_exported(self):
156         """Get a new dict with the exported variables."""
157         return dict((k, self.vars[k]) for k in self.exported_vars)
158
159     def get_all(self):
160         """Return a copy of the complete context as dict including the
161         exported variables.
162         """
163         return dict(self.parent, **self.vars)
164
165     @internalcode
166     def call(__self, __obj, *args, **kwargs):
167         """Call the callable with the arguments and keyword arguments
168         provided but inject the active context or environment as first
169         argument if the callable is a :func:`contextfunction` or
170         :func:`environmentfunction`.
171         """
172         if __debug__:
173             __traceback_hide__ = True
174         if isinstance(__obj, _context_function_types):
175             if getattr(__obj, 'contextfunction', 0):
176                 args = (__self,) + args
177             elif getattr(__obj, 'evalcontextfunction', 0):
178                 args = (__self.eval_ctx,) + args
179             elif getattr(__obj, 'environmentfunction', 0):
180                 args = (__self.environment,) + args
181         try:
182             return __obj(*args, **kwargs)
183         except StopIteration:
184             return __self.environment.undefined('value was undefined because '
185                                                 'a callable raised a '
186                                                 'StopIteration exception')
187
188     def derived(self, locals=None):
189         """Internal helper function to create a derived context."""
190         context = new_context(self.environment, self.name, {},
191                               self.parent, True, None, locals)
192         context.vars.update(self.vars)
193         context.eval_ctx = self.eval_ctx
194         context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
195         return context
196
197     def _all(meth):
198         proxy = lambda self: getattr(self.get_all(), meth)()
199         proxy.__doc__ = getattr(dict, meth).__doc__
200         proxy.__name__ = meth
201         return proxy
202
203     keys = _all('keys')
204     values = _all('values')
205     items = _all('items')
206
207     # not available on python 3
208     if hasattr(dict, 'iterkeys'):
209         iterkeys = _all('iterkeys')
210         itervalues = _all('itervalues')
211         iteritems = _all('iteritems')
212     del _all
213
214     def __contains__(self, name):
215         return name in self.vars or name in self.parent
216
217     def __getitem__(self, key):
218         """Lookup a variable or raise `KeyError` if the variable is
219         undefined.
220         """
221         item = self.resolve(key)
222         if isinstance(item, Undefined):
223             raise KeyError(key)
224         return item
225
226     def __repr__(self):
227         return '<%s %s of %r>' % (
228             self.__class__.__name__,
229             repr(self.get_all()),
230             self.name
231         )
232
233
234 # register the context as mapping if possible
235 try:
236     from collections import Mapping
237     Mapping.register(Context)
238 except ImportError:
239     pass
240
241
242 class BlockReference(object):
243     """One block on a template reference."""
244
245     def __init__(self, name, context, stack, depth):
246         self.name = name
247         self._context = context
248         self._stack = stack
249         self._depth = depth
250
251     @property
252     def super(self):
253         """Super the block."""
254         if self._depth + 1 >= len(self._stack):
255             return self._context.environment. \
256                 undefined('there is no parent block called %r.' %
257                           self.name, name='super')
258         return BlockReference(self.name, self._context, self._stack,
259                               self._depth + 1)
260
261     @internalcode
262     def __call__(self):
263         rv = concat(self._stack[self._depth](self._context))
264         if self._context.eval_ctx.autoescape:
265             rv = Markup(rv)
266         return rv
267
268
269 class LoopContext(object):
270     """A loop context for dynamic iteration."""
271
272     def __init__(self, iterable, recurse=None):
273         self._iterator = iter(iterable)
274         self._recurse = recurse
275         self._after = self._safe_next()
276         self.index0 = -1
277
278         # try to get the length of the iterable early.  This must be done
279         # here because there are some broken iterators around where there
280         # __len__ is the number of iterations left (i'm looking at your
281         # listreverseiterator!).
282         try:
283             self._length = len(iterable)
284         except (TypeError, AttributeError):
285             self._length = None
286
287     def cycle(self, *args):
288         """Cycles among the arguments with the current loop index."""
289         if not args:
290             raise TypeError('no items for cycling given')
291         return args[self.index0 % len(args)]
292
293     first = property(lambda x: x.index0 == 0)
294     last = property(lambda x: x._after is _last_iteration)
295     index = property(lambda x: x.index0 + 1)
296     revindex = property(lambda x: x.length - x.index0)
297     revindex0 = property(lambda x: x.length - x.index)
298
299     def __len__(self):
300         return self.length
301
302     def __iter__(self):
303         return LoopContextIterator(self)
304
305     def _safe_next(self):
306         try:
307             return next(self._iterator)
308         except StopIteration:
309             return _last_iteration
310
311     @internalcode
312     def loop(self, iterable):
313         if self._recurse is None:
314             raise TypeError('Tried to call non recursive loop.  Maybe you '
315                             "forgot the 'recursive' modifier.")
316         return self._recurse(iterable, self._recurse)
317
318     # a nifty trick to enhance the error message if someone tried to call
319     # the the loop without or with too many arguments.
320     __call__ = loop
321     del loop
322
323     @property
324     def length(self):
325         if self._length is None:
326             # if was not possible to get the length of the iterator when
327             # the loop context was created (ie: iterating over a generator)
328             # we have to convert the iterable into a sequence and use the
329             # length of that.
330             iterable = tuple(self._iterator)
331             self._iterator = iter(iterable)
332             self._length = len(iterable) + self.index0 + 1
333         return self._length
334
335     def __repr__(self):
336         return '<%s %r/%r>' % (
337             self.__class__.__name__,
338             self.index,
339             self.length
340         )
341
342
343 class LoopContextIterator(object):
344     """The iterator for a loop context."""
345     __slots__ = ('context',)
346
347     def __init__(self, context):
348         self.context = context
349
350     def __iter__(self):
351         return self
352
353     def next(self):
354         ctx = self.context
355         ctx.index0 += 1
356         if ctx._after is _last_iteration:
357             raise StopIteration()
358         next_elem = ctx._after
359         ctx._after = ctx._safe_next()
360         return next_elem, ctx
361
362
363 class Macro(object):
364     """Wraps a macro function."""
365
366     def __init__(self, environment, func, name, arguments, defaults,
367                  catch_kwargs, catch_varargs, caller):
368         self._environment = environment
369         self._func = func
370         self._argument_count = len(arguments)
371         self.name = name
372         self.arguments = arguments
373         self.defaults = defaults
374         self.catch_kwargs = catch_kwargs
375         self.catch_varargs = catch_varargs
376         self.caller = caller
377
378     @internalcode
379     def __call__(self, *args, **kwargs):
380         # try to consume the positional arguments
381         arguments = list(args[:self._argument_count])
382         off = len(arguments)
383
384         # if the number of arguments consumed is not the number of
385         # arguments expected we start filling in keyword arguments
386         # and defaults.
387         if off != self._argument_count:
388             for idx, name in enumerate(self.arguments[len(arguments):]):
389                 try:
390                     value = kwargs.pop(name)
391                 except KeyError:
392                     try:
393                         value = self.defaults[idx - self._argument_count + off]
394                     except IndexError:
395                         value = self._environment.undefined(
396                             'parameter %r was not provided' % name, name=name)
397                 arguments.append(value)
398
399         # it's important that the order of these arguments does not change
400         # if not also changed in the compiler's `function_scoping` method.
401         # the order is caller, keyword arguments, positional arguments!
402         if self.caller:
403             caller = kwargs.pop('caller', None)
404             if caller is None:
405                 caller = self._environment.undefined('No caller defined',
406                                                      name='caller')
407             arguments.append(caller)
408         if self.catch_kwargs:
409             arguments.append(kwargs)
410         elif kwargs:
411             raise TypeError('macro %r takes no keyword argument %r' %
412                             (self.name, next(iter(kwargs))))
413         if self.catch_varargs:
414             arguments.append(args[self._argument_count:])
415         elif len(args) > self._argument_count:
416             raise TypeError('macro %r takes not more than %d argument(s)' %
417                             (self.name, len(self.arguments)))
418         return self._func(*arguments)
419
420     def __repr__(self):
421         return '<%s %s>' % (
422             self.__class__.__name__,
423             self.name is None and 'anonymous' or repr(self.name)
424         )
425
426
427 class Undefined(object):
428     """The default undefined type.  This undefined type can be printed and
429     iterated over, but every other access will raise an :exc:`UndefinedError`:
430
431     >>> foo = Undefined(name='foo')
432     >>> str(foo)
433     ''
434     >>> not foo
435     True
436     >>> foo + 42
437     Traceback (most recent call last):
438       ...
439     UndefinedError: 'foo' is undefined
440     """
441     __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
442                  '_undefined_exception')
443
444     def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
445         self._undefined_hint = hint
446         self._undefined_obj = obj
447         self._undefined_name = name
448         self._undefined_exception = exc
449
450     @internalcode
451     def _fail_with_undefined_error(self, *args, **kwargs):
452         """Regular callback function for undefined objects that raises an
453         `UndefinedError` on call.
454         """
455         if self._undefined_hint is None:
456             if self._undefined_obj is missing:
457                 hint = '%r is undefined' % self._undefined_name
458             elif not isinstance(self._undefined_name, basestring):
459                 hint = '%s has no element %r' % (
460                     object_type_repr(self._undefined_obj),
461                     self._undefined_name
462                 )
463             else:
464                 hint = '%r has no attribute %r' % (
465                     object_type_repr(self._undefined_obj),
466                     self._undefined_name
467                 )
468         else:
469             hint = self._undefined_hint
470         raise self._undefined_exception(hint)
471
472     @internalcode
473     def __getattr__(self, name):
474         if name[:2] == '__':
475             raise AttributeError(name)
476         return self._fail_with_undefined_error()
477
478     __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
479     __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
480     __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
481     __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
482     __float__ = __complex__ = __pow__ = __rpow__ = \
483         _fail_with_undefined_error
484
485     def __str__(self):
486         return unicode(self).encode('utf-8')
487
488     # unicode goes after __str__ because we configured 2to3 to rename
489     # __unicode__ to __str__.  because the 2to3 tree is not designed to
490     # remove nodes from it, we leave the above __str__ around and let
491     # it override at runtime.
492     def __unicode__(self):
493         return u''
494
495     def __len__(self):
496         return 0
497
498     def __iter__(self):
499         if 0:
500             yield None
501
502     def __nonzero__(self):
503         return False
504
505     def __repr__(self):
506         return 'Undefined'
507
508
509 class DebugUndefined(Undefined):
510     """An undefined that returns the debug info when printed.
511
512     >>> foo = DebugUndefined(name='foo')
513     >>> str(foo)
514     '{{ foo }}'
515     >>> not foo
516     True
517     >>> foo + 42
518     Traceback (most recent call last):
519       ...
520     UndefinedError: 'foo' is undefined
521     """
522     __slots__ = ()
523
524     def __unicode__(self):
525         if self._undefined_hint is None:
526             if self._undefined_obj is missing:
527                 return u'{{ %s }}' % self._undefined_name
528             return '{{ no such element: %s[%r] }}' % (
529                 object_type_repr(self._undefined_obj),
530                 self._undefined_name
531             )
532         return u'{{ undefined value printed: %s }}' % self._undefined_hint
533
534
535 class StrictUndefined(Undefined):
536     """An undefined that barks on print and iteration as well as boolean
537     tests and all kinds of comparisons.  In other words: you can do nothing
538     with it except checking if it's defined using the `defined` test.
539
540     >>> foo = StrictUndefined(name='foo')
541     >>> str(foo)
542     Traceback (most recent call last):
543       ...
544     UndefinedError: 'foo' is undefined
545     >>> not foo
546     Traceback (most recent call last):
547       ...
548     UndefinedError: 'foo' is undefined
549     >>> foo + 42
550     Traceback (most recent call last):
551       ...
552     UndefinedError: 'foo' is undefined
553     """
554     __slots__ = ()
555     __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
556         __ne__ = __bool__ = Undefined._fail_with_undefined_error
557
558
559 # remove remaining slots attributes, after the metaclass did the magic they
560 # are unneeded and irritating as they contain wrong data for the subclasses.
561 del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__