runtime.py 23 KB

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