1 # -*- coding: utf-8 -*-
8 :copyright: (c) 2010 by the Jinja Team.
12 from itertools import chain, imap
13 from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
14 concat, MethodType, FunctionType, internalcode, next
15 from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
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',
26 #: the types we support for context functions
27 _context_function_types = (FunctionType, MethodType)
29 #: the name of the function that is used to convert something into
30 #: a string. 2to3 will adopt that automatically and the generated
31 #: code can take advantage of it.
36 """Concatenation that escapes if necessary and converts to unicode."""
38 iterator = imap(soft_unicode, seq)
41 if hasattr(arg, '__html__'):
42 return Markup(u'').join(chain(buf, iterator))
46 def unicode_join(seq):
47 """Simple args to unicode conversion and concatenation."""
48 return concat(imap(unicode, seq))
51 def new_context(environment, template_name, blocks, vars=None,
52 shared=None, globals=None, locals=None):
53 """Internal helper to for context creation."""
59 parent = dict(globals or (), **vars)
61 # if the parent is shared a copy should be created because
62 # we don't want to modify the dict passed
65 for key, value in locals.iteritems():
66 if key[:2] == 'l_' and value is not missing:
67 parent[key[2:]] = value
68 return Context(environment, parent, template_name, blocks)
71 class TemplateReference(object):
72 """The `self` in templates."""
74 def __init__(self, context):
75 self.__context = context
77 def __getitem__(self, name):
78 blocks = self.__context.blocks[name]
79 wrap = self.__context.environment.autoescape and \
80 Markup or (lambda x: x)
81 return BlockReference(name, self.__context, blocks, 0)
85 self.__class__.__name__,
90 class Context(object):
91 """The template context holds the variables of a template. It stores the
92 values passed to the template and also the names the template exports.
93 Creating instances is neither supported nor useful as it's created
94 automatically at various stages of the template evaluation and should not
97 The context is immutable. Modifications on :attr:`parent` **must not**
98 happen and modifications on :attr:`vars` are allowed from generated
99 template code only. Template filters and global functions marked as
100 :func:`contextfunction`\s get the active context passed as first argument
101 and are allowed to access the context read-only.
103 The template context supports read only dict operations (`get`,
104 `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
105 `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
106 method that doesn't fail with a `KeyError` but returns an
107 :class:`Undefined` object for missing variables.
109 __slots__ = ('parent', 'vars', 'environment', 'exported_vars', 'name',
110 'blocks', '__weakref__')
112 def __init__(self, environment, parent, name, blocks):
115 self.environment = environment
116 self.exported_vars = set()
119 # create the initial mapping of blocks. Whenever template inheritance
120 # takes place the runtime will update this mapping with the new blocks
122 self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
124 def super(self, name, current):
125 """Render a parent block."""
127 blocks = self.blocks[name]
128 index = blocks.index(current) + 1
131 return self.environment.undefined('there is no parent block '
134 return BlockReference(name, self, blocks, index)
136 def get(self, key, default=None):
137 """Returns an item from the template context, if it doesn't exist
138 `default` is returned.
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.
150 return self.vars[key]
151 if key in self.parent:
152 return self.parent[key]
153 return self.environment.undefined(name=key)
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)
160 """Return a copy of the complete context as dict including the
163 return dict(self.parent, **self.vars)
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`.
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, 'environmentfunction', 0):
178 args = (__self.environment,) + args
179 return __obj(*args, **kwargs)
181 def derived(self, locals=None):
182 """Internal helper function to create a derived context."""
183 context = new_context(self.environment, self.name, {},
184 self.parent, True, None, locals)
185 context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
189 proxy = lambda self: getattr(self.get_all(), meth)()
190 proxy.__doc__ = getattr(dict, meth).__doc__
191 proxy.__name__ = meth
195 values = _all('values')
196 items = _all('items')
198 # not available on python 3
199 if hasattr(dict, 'iterkeys'):
200 iterkeys = _all('iterkeys')
201 itervalues = _all('itervalues')
202 iteritems = _all('iteritems')
205 def __contains__(self, name):
206 return name in self.vars or name in self.parent
208 def __getitem__(self, key):
209 """Lookup a variable or raise `KeyError` if the variable is
212 item = self.resolve(key)
213 if isinstance(item, Undefined):
218 return '<%s %s of %r>' % (
219 self.__class__.__name__,
220 repr(self.get_all()),
225 # register the context as mapping if possible
227 from collections import Mapping
228 Mapping.register(Context)
233 class BlockReference(object):
234 """One block on a template reference."""
236 def __init__(self, name, context, stack, depth):
238 self._context = context
244 """Super the block."""
245 if self._depth + 1 >= len(self._stack):
246 return self._context.environment. \
247 undefined('there is no parent block called %r.' %
248 self.name, name='super')
249 return BlockReference(self.name, self._context, self._stack,
254 rv = concat(self._stack[self._depth](self._context))
255 if self._context.environment.autoescape:
260 class LoopContext(object):
261 """A loop context for dynamic iteration."""
263 def __init__(self, iterable, recurse=None):
264 self._iterator = iter(iterable)
265 self._recurse = recurse
268 # try to get the length of the iterable early. This must be done
269 # here because there are some broken iterators around where there
270 # __len__ is the number of iterations left (i'm looking at your
271 # listreverseiterator!).
273 self._length = len(iterable)
274 except (TypeError, AttributeError):
277 def cycle(self, *args):
278 """Cycles among the arguments with the current loop index."""
280 raise TypeError('no items for cycling given')
281 return args[self.index0 % len(args)]
283 first = property(lambda x: x.index0 == 0)
284 last = property(lambda x: x.index0 + 1 == x.length)
285 index = property(lambda x: x.index0 + 1)
286 revindex = property(lambda x: x.length - x.index0)
287 revindex0 = property(lambda x: x.length - x.index)
293 return LoopContextIterator(self)
296 def loop(self, iterable):
297 if self._recurse is None:
298 raise TypeError('Tried to call non recursive loop. Maybe you '
299 "forgot the 'recursive' modifier.")
300 return self._recurse(iterable, self._recurse)
302 # a nifty trick to enhance the error message if someone tried to call
303 # the the loop without or with too many arguments.
304 __call__ = loop; del loop
308 if self._length is None:
309 # if was not possible to get the length of the iterator when
310 # the loop context was created (ie: iterating over a generator)
311 # we have to convert the iterable into a sequence and use the
313 iterable = tuple(self._iterator)
314 self._iterator = iter(iterable)
315 self._length = len(iterable) + self.index0 + 1
319 return '<%s %r/%r>' % (
320 self.__class__.__name__,
326 class LoopContextIterator(object):
327 """The iterator for a loop context."""
328 __slots__ = ('context',)
330 def __init__(self, context):
331 self.context = context
339 return next(ctx._iterator), ctx
345 def __init__(self, environment, func, name, arguments, defaults,
346 catch_kwargs, catch_varargs, caller):
347 self._environment = environment
349 self._argument_count = len(arguments)
351 self.arguments = arguments
352 self.defaults = defaults
353 self.catch_kwargs = catch_kwargs
354 self.catch_varargs = catch_varargs
358 def __call__(self, *args, **kwargs):
360 for idx, name in enumerate(self.arguments):
365 value = kwargs.pop(name)
368 value = self.defaults[idx - self._argument_count]
370 value = self._environment.undefined(
371 'parameter %r was not provided' % name, name=name)
372 arguments.append(value)
374 # it's important that the order of these arguments does not change
375 # if not also changed in the compiler's `function_scoping` method.
376 # the order is caller, keyword arguments, positional arguments!
378 caller = kwargs.pop('caller', None)
380 caller = self._environment.undefined('No caller defined',
382 arguments.append(caller)
383 if self.catch_kwargs:
384 arguments.append(kwargs)
386 raise TypeError('macro %r takes no keyword argument %r' %
387 (self.name, next(iter(kwargs))))
388 if self.catch_varargs:
389 arguments.append(args[self._argument_count:])
390 elif len(args) > self._argument_count:
391 raise TypeError('macro %r takes not more than %d argument(s)' %
392 (self.name, len(self.arguments)))
393 return self._func(*arguments)
397 self.__class__.__name__,
398 self.name is None and 'anonymous' or repr(self.name)
402 class Undefined(object):
403 """The default undefined type. This undefined type can be printed and
404 iterated over, but every other access will raise an :exc:`UndefinedError`:
406 >>> foo = Undefined(name='foo')
412 Traceback (most recent call last):
414 UndefinedError: 'foo' is undefined
416 __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
417 '_undefined_exception')
419 def __init__(self, hint=None, obj=None, name=None, exc=UndefinedError):
420 self._undefined_hint = hint
421 self._undefined_obj = obj
422 self._undefined_name = name
423 self._undefined_exception = exc
426 def _fail_with_undefined_error(self, *args, **kwargs):
427 """Regular callback function for undefined objects that raises an
428 `UndefinedError` on call.
430 if self._undefined_hint is None:
431 if self._undefined_obj is None:
432 hint = '%r is undefined' % self._undefined_name
433 elif not isinstance(self._undefined_name, basestring):
434 hint = '%r object has no element %r' % (
435 self._undefined_obj.__class__.__name__,
439 hint = '%r object has no attribute %r' % (
440 self._undefined_obj.__class__.__name__,
444 hint = self._undefined_hint
445 raise self._undefined_exception(hint)
447 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
448 __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
449 __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
450 __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
451 __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
452 _fail_with_undefined_error
455 return unicode(self).encode('utf-8')
457 # unicode goes after __str__ because we configured 2to3 to rename
458 # __unicode__ to __str__. because the 2to3 tree is not designed to
459 # remove nodes from it, we leave the above __str__ around and let
460 # it override at runtime.
461 def __unicode__(self):
471 def __nonzero__(self):
478 class DebugUndefined(Undefined):
479 """An undefined that returns the debug info when printed.
481 >>> foo = DebugUndefined(name='foo')
487 Traceback (most recent call last):
489 UndefinedError: 'foo' is undefined
493 def __unicode__(self):
494 if self._undefined_hint is None:
495 if self._undefined_obj is None:
496 return u'{{ %s }}' % self._undefined_name
497 return '{{ no such element: %s[%r] }}' % (
498 self._undefined_obj.__class__.__name__,
501 return u'{{ undefined value printed: %s }}' % self._undefined_hint
504 class StrictUndefined(Undefined):
505 """An undefined that barks on print and iteration as well as boolean
506 tests and all kinds of comparisons. In other words: you can do nothing
507 with it except checking if it's defined using the `defined` test.
509 >>> foo = StrictUndefined(name='foo')
511 Traceback (most recent call last):
513 UndefinedError: 'foo' is undefined
515 Traceback (most recent call last):
517 UndefinedError: 'foo' is undefined
519 Traceback (most recent call last):
521 UndefinedError: 'foo' is undefined
524 __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
525 __ne__ = Undefined._fail_with_undefined_error
528 # remove remaining slots attributes, after the metaclass did the magic they
529 # are unneeded and irritating as they contain wrong data for the subclasses.
530 del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__