1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# -*- coding: utf-8 -*- 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez""" 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jinja2.runtime 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~~~~~~~~~~~~~~ 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Runtime helpers. 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :copyright: (c) 2010 by the Jinja Team. 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :license: BSD. 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez""" 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom itertools import chain 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.nodes import EvalContext, _context_function_types 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.utils import Markup, soft_unicode, escape, missing, concat, \ 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez internalcode, object_type_repr 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.exceptions import UndefinedError, TemplateRuntimeError, \ 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TemplateNotFound 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2._compat import next, imap, text_type, iteritems, \ 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez implements_iterator, implements_to_string, string_types, PY2 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# these variables are exported to the template runtime 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup', 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'TemplateRuntimeError', 'missing', 'concat', 'escape', 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'markup_join', 'unicode_join', 'to_string', 'identity', 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'TemplateNotFound'] 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: the name of the function that is used to convert something into 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: a string. We can just use the text type here. 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezto_string = text_type 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: the identity function. Useful for certain things in the environment 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezidentity = lambda x: x 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_last_iteration = object() 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef markup_join(seq): 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Concatenation that escapes if necessary and converts to unicode.""" 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez buf = [] 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iterator = imap(soft_unicode, seq) 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for arg in iterator: 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez buf.append(arg) 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if hasattr(arg, '__html__'): 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return Markup(u'').join(chain(buf, iterator)) 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return concat(buf) 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef unicode_join(seq): 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Simple args to unicode conversion and concatenation.""" 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return concat(imap(text_type, seq)) 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef new_context(environment, template_name, blocks, vars=None, 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez shared=None, globals=None, locals=None): 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Internal helper to for context creation.""" 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if vars is None: 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez vars = {} 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if shared: 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent = vars 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent = dict(globals or (), **vars) 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if locals: 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # if the parent is shared a copy should be created because 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # we don't want to modify the dict passed 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if shared: 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent = dict(parent) 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for key, value in iteritems(locals): 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if key[:2] == 'l_' and value is not missing: 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent[key[2:]] = value 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return Context(environment, parent, template_name, blocks) 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass TemplateReference(object): 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The `self` in templates.""" 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, context): 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__context = context 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __getitem__(self, name): 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez blocks = self.__context.blocks[name] 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return BlockReference(name, self.__context, blocks, 0) 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __repr__(self): 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return '<%s %r>' % ( 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__class__.__name__, 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__context.name 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass Context(object): 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The template context holds the variables of a template. It stores the 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez values passed to the template and also the names the template exports. 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Creating instances is neither supported nor useful as it's created 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez automatically at various stages of the template evaluation and should not 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez be created by hand. 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez The context is immutable. Modifications on :attr:`parent` **must not** 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez happen and modifications on :attr:`vars` are allowed from generated 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez template code only. Template filters and global functions marked as 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :func:`contextfunction`\s get the active context passed as first argument 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez and are allowed to access the context read-only. 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez The template context supports read only dict operations (`get`, 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`, 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve` 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez method that doesn't fail with a `KeyError` but returns an 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :class:`Undefined` object for missing variables. 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars', 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'name', 'blocks', '__weakref__') 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, environment, parent, name, blocks): 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.parent = parent 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.vars = {} 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.environment = environment 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.eval_ctx = EvalContext(self.environment, name) 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.exported_vars = set() 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name = name 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # create the initial mapping of blocks. Whenever template inheritance 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # takes place the runtime will update this mapping with the new blocks 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # from the template. 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.blocks = dict((k, [v]) for k, v in iteritems(blocks)) 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def super(self, name, current): 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Render a parent block.""" 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez blocks = self.blocks[name] 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez index = blocks.index(current) + 1 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez blocks[index] 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except LookupError: 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.environment.undefined('there is no parent block ' 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'called %r.' % name, 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez name='super') 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return BlockReference(name, self, blocks, index) 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def get(self, key, default=None): 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Returns an item from the template context, if it doesn't exist 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `default` is returned. 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self[key] 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except KeyError: 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return default 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def resolve(self, key): 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Looks up a variable like `__getitem__` or `get` but returns an 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :class:`Undefined` object with the name of the name looked up. 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if key in self.vars: 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.vars[key] 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if key in self.parent: 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.parent[key] 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.environment.undefined(name=key) 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def get_exported(self): 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Get a new dict with the exported variables.""" 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return dict((k, self.vars[k]) for k in self.exported_vars) 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def get_all(self): 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Return a copy of the complete context as dict including the 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez exported variables. 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return dict(self.parent, **self.vars) 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def call(__self, __obj, *args, **kwargs): 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Call the callable with the arguments and keyword arguments 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez provided but inject the active context or environment as first 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez argument if the callable is a :func:`contextfunction` or 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :func:`environmentfunction`. 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if __debug__: 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __traceback_hide__ = True 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # Allow callable classes to take a context 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez fn = __obj.__call__ 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for fn_type in ('contextfunction', 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'evalcontextfunction', 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'environmentfunction'): 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if hasattr(fn, fn_type): 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __obj = fn 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(__obj, _context_function_types): 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if getattr(__obj, 'contextfunction', 0): 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez args = (__self,) + args 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif getattr(__obj, 'evalcontextfunction', 0): 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez args = (__self.eval_ctx,) + args 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif getattr(__obj, 'environmentfunction', 0): 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez args = (__self.environment,) + args 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return __obj(*args, **kwargs) 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except StopIteration: 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return __self.environment.undefined('value was undefined because ' 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'a callable raised a ' 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'StopIteration exception') 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def derived(self, locals=None): 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Internal helper function to create a derived context.""" 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez context = new_context(self.environment, self.name, {}, 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.parent, True, None, locals) 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez context.vars.update(self.vars) 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez context.eval_ctx = self.eval_ctx 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks)) 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return context 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def _all(meth): 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez proxy = lambda self: getattr(self.get_all(), meth)() 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez proxy.__doc__ = getattr(dict, meth).__doc__ 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez proxy.__name__ = meth 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return proxy 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez keys = _all('keys') 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez values = _all('values') 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez items = _all('items') 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # not available on python 3 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if PY2: 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iterkeys = _all('iterkeys') 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez itervalues = _all('itervalues') 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iteritems = _all('iteritems') 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez del _all 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __contains__(self, name): 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return name in self.vars or name in self.parent 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __getitem__(self, key): 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Lookup a variable or raise `KeyError` if the variable is 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez undefined. 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez item = self.resolve(key) 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(item, Undefined): 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise KeyError(key) 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return item 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __repr__(self): 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return '<%s %s of %r>' % ( 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__class__.__name__, 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez repr(self.get_all()), 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# register the context as mapping if possible 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztry: 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from collections import Mapping 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Mapping.register(Context) 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezexcept ImportError: 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass BlockReference(object): 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """One block on a template reference.""" 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, name, context, stack, depth): 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name = name 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._context = context 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._stack = stack 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._depth = depth 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @property 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def super(self): 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Super the block.""" 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._depth + 1 >= len(self._stack): 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self._context.environment. \ 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez undefined('there is no parent block called %r.' % 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name, name='super') 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return BlockReference(self.name, self._context, self._stack, 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._depth + 1) 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __call__(self): 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez rv = concat(self._stack[self._depth](self._context)) 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._context.eval_ctx.autoescape: 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez rv = Markup(rv) 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return rv 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass LoopContext(object): 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """A loop context for dynamic iteration.""" 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, iterable, recurse=None, depth0=0): 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._iterator = iter(iterable) 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._recurse = recurse 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._after = self._safe_next() 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.index0 = -1 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.depth0 = depth0 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # try to get the length of the iterable early. This must be done 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # here because there are some broken iterators around where there 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # __len__ is the number of iterations left (i'm looking at your 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # listreverseiterator!). 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._length = len(iterable) 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except (TypeError, AttributeError): 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._length = None 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def cycle(self, *args): 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Cycles among the arguments with the current loop index.""" 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if not args: 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise TypeError('no items for cycling given') 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return args[self.index0 % len(args)] 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez first = property(lambda x: x.index0 == 0) 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez last = property(lambda x: x._after is _last_iteration) 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez index = property(lambda x: x.index0 + 1) 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez revindex = property(lambda x: x.length - x.index0) 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez revindex0 = property(lambda x: x.length - x.index) 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez depth = property(lambda x: x.depth0 + 1) 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __len__(self): 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.length 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __iter__(self): 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return LoopContextIterator(self) 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def _safe_next(self): 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return next(self._iterator) 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except StopIteration: 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return _last_iteration 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def loop(self, iterable): 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._recurse is None: 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise TypeError('Tried to call non recursive loop. Maybe you ' 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "forgot the 'recursive' modifier.") 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self._recurse(iterable, self._recurse, self.depth0 + 1) 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # a nifty trick to enhance the error message if someone tried to call 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # the the loop without or with too many arguments. 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __call__ = loop 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez del loop 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @property 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def length(self): 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._length is None: 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # if was not possible to get the length of the iterator when 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # the loop context was created (ie: iterating over a generator) 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # we have to convert the iterable into a sequence and use the 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # length of that. 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iterable = tuple(self._iterator) 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._iterator = iter(iterable) 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._length = len(iterable) + self.index0 + 1 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self._length 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __repr__(self): 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return '<%s %r/%r>' % ( 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__class__.__name__, 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.index, 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.length 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@implements_iterator 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass LoopContextIterator(object): 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The iterator for a loop context.""" 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __slots__ = ('context',) 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, context): 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.context = context 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __iter__(self): 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __next__(self): 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ctx = self.context 369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ctx.index0 += 1 370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if ctx._after is _last_iteration: 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise StopIteration() 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez next_elem = ctx._after 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ctx._after = ctx._safe_next() 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return next_elem, ctx 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass Macro(object): 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Wraps a macro function.""" 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, environment, func, name, arguments, defaults, 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez catch_kwargs, catch_varargs, caller): 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._environment = environment 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._func = func 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._argument_count = len(arguments) 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name = name 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.arguments = arguments 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.defaults = defaults 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.catch_kwargs = catch_kwargs 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.catch_varargs = catch_varargs 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.caller = caller 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __call__(self, *args, **kwargs): 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # try to consume the positional arguments 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez arguments = list(args[:self._argument_count]) 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez off = len(arguments) 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # if the number of arguments consumed is not the number of 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # arguments expected we start filling in keyword arguments 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # and defaults. 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if off != self._argument_count: 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for idx, name in enumerate(self.arguments[len(arguments):]): 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez value = kwargs.pop(name) 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except KeyError: 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez value = self.defaults[idx - self._argument_count + off] 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except IndexError: 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez value = self._environment.undefined( 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'parameter %r was not provided' % name, name=name) 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez arguments.append(value) 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # it's important that the order of these arguments does not change 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # if not also changed in the compiler's `function_scoping` method. 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # the order is caller, keyword arguments, positional arguments! 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self.caller: 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez caller = kwargs.pop('caller', None) 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if caller is None: 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez caller = self._environment.undefined('No caller defined', 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez name='caller') 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez arguments.append(caller) 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self.catch_kwargs: 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez arguments.append(kwargs) 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif kwargs: 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise TypeError('macro %r takes no keyword argument %r' % 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (self.name, next(iter(kwargs)))) 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self.catch_varargs: 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez arguments.append(args[self._argument_count:]) 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif len(args) > self._argument_count: 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise TypeError('macro %r takes not more than %d argument(s)' % 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (self.name, len(self.arguments))) 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self._func(*arguments) 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __repr__(self): 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return '<%s %s>' % ( 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.__class__.__name__, 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.name is None and 'anonymous' or repr(self.name) 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@implements_to_string 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass Undefined(object): 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The default undefined type. This undefined type can be printed and 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iterated over, but every other access will raise an :exc:`UndefinedError`: 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo = Undefined(name='foo') 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> str(foo) 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '' 449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> not foo 450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo + 42 452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traceback (most recent call last): 453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ... 454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UndefinedError: 'foo' is undefined 455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name', 457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '_undefined_exception') 458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError): 460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_hint = hint 461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_obj = obj 462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_name = name 463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_exception = exc 464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def _fail_with_undefined_error(self, *args, **kwargs): 467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Regular callback function for undefined objects that raises an 468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `UndefinedError` on call. 469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._undefined_hint is None: 471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._undefined_obj is missing: 472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez hint = '%r is undefined' % self._undefined_name 473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif not isinstance(self._undefined_name, string_types): 474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez hint = '%s has no element %r' % ( 475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez object_type_repr(self._undefined_obj), 476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_name 477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez hint = '%r has no attribute %r' % ( 480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez object_type_repr(self._undefined_obj), 481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_name 482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez hint = self._undefined_hint 485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise self._undefined_exception(hint) 486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @internalcode 488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __getattr__(self, name): 489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if name[:2] == '__': 490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise AttributeError(name) 491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self._fail_with_undefined_error() 492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \ 494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \ 495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \ 496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \ 497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __float__ = __complex__ = __pow__ = __rpow__ = \ 498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _fail_with_undefined_error 499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __eq__(self, other): 501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return type(self) is type(other) 502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __ne__(self, other): 504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return not self.__eq__(other) 505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __hash__(self): 507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return id(type(self)) 508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __str__(self): 510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return u'' 511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __len__(self): 513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 0 514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __iter__(self): 516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if 0: 517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez yield None 518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __nonzero__(self): 520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return False 521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __repr__(self): 523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 'Undefined' 524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@implements_to_string 527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass DebugUndefined(Undefined): 528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """An undefined that returns the debug info when printed. 529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo = DebugUndefined(name='foo') 531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> str(foo) 532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '{{ foo }}' 533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> not foo 534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo + 42 536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traceback (most recent call last): 537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ... 538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UndefinedError: 'foo' is undefined 539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __slots__ = () 541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __str__(self): 543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._undefined_hint is None: 544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self._undefined_obj is missing: 545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return u'{{ %s }}' % self._undefined_name 546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return '{{ no such element: %s[%r] }}' % ( 547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez object_type_repr(self._undefined_obj), 548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self._undefined_name 549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ) 550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return u'{{ undefined value printed: %s }}' % self._undefined_hint 551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@implements_to_string 554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass StrictUndefined(Undefined): 555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """An undefined that barks on print and iteration as well as boolean 556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tests and all kinds of comparisons. In other words: you can do nothing 557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez with it except checking if it's defined using the `defined` test. 558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo = StrictUndefined(name='foo') 560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> str(foo) 561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traceback (most recent call last): 562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ... 563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UndefinedError: 'foo' is undefined 564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> not foo 565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traceback (most recent call last): 566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ... 567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UndefinedError: 'foo' is undefined 568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> foo + 42 569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traceback (most recent call last): 570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ... 571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UndefinedError: 'foo' is undefined 572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __slots__ = () 574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \ 575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez __ne__ = __bool__ = __hash__ = \ 576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Undefined._fail_with_undefined_error 577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# remove remaining slots attributes, after the metaclass did the magic they 580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# are unneeded and irritating as they contain wrong data for the subclasses. 581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdel Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__ 582