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