runtime.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. """The runtime functions and state used by compiled templates."""
  2. import functools
  3. import sys
  4. import typing as t
  5. from collections import abc
  6. from itertools import chain
  7. from markupsafe import escape # noqa: F401
  8. from markupsafe import Markup
  9. from markupsafe import soft_str
  10. from .async_utils import auto_aiter
  11. from .async_utils import auto_await # noqa: F401
  12. from .exceptions import TemplateNotFound # noqa: F401
  13. from .exceptions import TemplateRuntimeError # noqa: F401
  14. from .exceptions import UndefinedError
  15. from .nodes import EvalContext
  16. from .utils import _PassArg
  17. from .utils import concat
  18. from .utils import internalcode
  19. from .utils import missing
  20. from .utils import Namespace # noqa: F401
  21. from .utils import object_type_repr
  22. from .utils import pass_eval_context
  23. V = t.TypeVar("V")
  24. F = t.TypeVar("F", bound=t.Callable[..., t.Any])
  25. if t.TYPE_CHECKING:
  26. import logging
  27. import typing_extensions as te
  28. from .environment import Environment
  29. class LoopRenderFunc(te.Protocol):
  30. def __call__(
  31. self,
  32. reciter: t.Iterable[V],
  33. loop_render_func: "LoopRenderFunc",
  34. depth: int = 0,
  35. ) -> str: ...
  36. # these variables are exported to the template runtime
  37. exported = [
  38. "LoopContext",
  39. "TemplateReference",
  40. "Macro",
  41. "Markup",
  42. "TemplateRuntimeError",
  43. "missing",
  44. "escape",
  45. "markup_join",
  46. "str_join",
  47. "identity",
  48. "TemplateNotFound",
  49. "Namespace",
  50. "Undefined",
  51. "internalcode",
  52. ]
  53. async_exported = [
  54. "AsyncLoopContext",
  55. "auto_aiter",
  56. "auto_await",
  57. ]
  58. def identity(x: V) -> V:
  59. """Returns its argument. Useful for certain things in the
  60. environment.
  61. """
  62. return x
  63. def markup_join(seq: t.Iterable[t.Any]) -> str:
  64. """Concatenation that escapes if necessary and converts to string."""
  65. buf = []
  66. iterator = map(soft_str, seq)
  67. for arg in iterator:
  68. buf.append(arg)
  69. if hasattr(arg, "__html__"):
  70. return Markup("").join(chain(buf, iterator))
  71. return concat(buf)
  72. def str_join(seq: t.Iterable[t.Any]) -> str:
  73. """Simple args to string conversion and concatenation."""
  74. return concat(map(str, seq))
  75. def new_context(
  76. environment: "Environment",
  77. template_name: t.Optional[str],
  78. blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]],
  79. vars: t.Optional[t.Dict[str, t.Any]] = None,
  80. shared: bool = False,
  81. globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
  82. locals: t.Optional[t.Mapping[str, t.Any]] = None,
  83. ) -> "Context":
  84. """Internal helper for context creation."""
  85. if vars is None:
  86. vars = {}
  87. if shared:
  88. parent = vars
  89. else:
  90. parent = dict(globals or (), **vars)
  91. if locals:
  92. # if the parent is shared a copy should be created because
  93. # we don't want to modify the dict passed
  94. if shared:
  95. parent = dict(parent)
  96. for key, value in locals.items():
  97. if value is not missing:
  98. parent[key] = value
  99. return environment.context_class(
  100. environment, parent, template_name, blocks, globals=globals
  101. )
  102. class TemplateReference:
  103. """The `self` in templates."""
  104. def __init__(self, context: "Context") -> None:
  105. self.__context = context
  106. def __getitem__(self, name: str) -> t.Any:
  107. blocks = self.__context.blocks[name]
  108. return BlockReference(name, self.__context, blocks, 0)
  109. def __repr__(self) -> str:
  110. return f"<{type(self).__name__} {self.__context.name!r}>"
  111. def _dict_method_all(dict_method: F) -> F:
  112. @functools.wraps(dict_method)
  113. def f_all(self: "Context") -> t.Any:
  114. return dict_method(self.get_all())
  115. return t.cast(F, f_all)
  116. @abc.Mapping.register
  117. class Context:
  118. """The template context holds the variables of a template. It stores the
  119. values passed to the template and also the names the template exports.
  120. Creating instances is neither supported nor useful as it's created
  121. automatically at various stages of the template evaluation and should not
  122. be created by hand.
  123. The context is immutable. Modifications on :attr:`parent` **must not**
  124. happen and modifications on :attr:`vars` are allowed from generated
  125. template code only. Template filters and global functions marked as
  126. :func:`pass_context` get the active context passed as first argument
  127. and are allowed to access the context read-only.
  128. The template context supports read only dict operations (`get`,
  129. `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
  130. `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
  131. method that doesn't fail with a `KeyError` but returns an
  132. :class:`Undefined` object for missing variables.
  133. """
  134. def __init__(
  135. self,
  136. environment: "Environment",
  137. parent: t.Dict[str, t.Any],
  138. name: t.Optional[str],
  139. blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]],
  140. globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
  141. ):
  142. self.parent = parent
  143. self.vars: t.Dict[str, t.Any] = {}
  144. self.environment: Environment = environment
  145. self.eval_ctx = EvalContext(self.environment, name)
  146. self.exported_vars: t.Set[str] = set()
  147. self.name = name
  148. self.globals_keys = set() if globals is None else set(globals)
  149. # create the initial mapping of blocks. Whenever template inheritance
  150. # takes place the runtime will update this mapping with the new blocks
  151. # from the template.
  152. self.blocks = {k: [v] for k, v in blocks.items()}
  153. def super(
  154. self, name: str, current: t.Callable[["Context"], t.Iterator[str]]
  155. ) -> t.Union["BlockReference", "Undefined"]:
  156. """Render a parent block."""
  157. try:
  158. blocks = self.blocks[name]
  159. index = blocks.index(current) + 1
  160. blocks[index]
  161. except LookupError:
  162. return self.environment.undefined(
  163. f"there is no parent block called {name!r}.", name="super"
  164. )
  165. return BlockReference(name, self, blocks, index)
  166. def get(self, key: str, default: t.Any = None) -> t.Any:
  167. """Look up a variable by name, or return a default if the key is
  168. not found.
  169. :param key: The variable name to look up.
  170. :param default: The value to return if the key is not found.
  171. """
  172. try:
  173. return self[key]
  174. except KeyError:
  175. return default
  176. def resolve(self, key: str) -> t.Union[t.Any, "Undefined"]:
  177. """Look up a variable by name, or return an :class:`Undefined`
  178. object if the key is not found.
  179. If you need to add custom behavior, override
  180. :meth:`resolve_or_missing`, not this method. The various lookup
  181. functions use that method, not this one.
  182. :param key: The variable name to look up.
  183. """
  184. rv = self.resolve_or_missing(key)
  185. if rv is missing:
  186. return self.environment.undefined(name=key)
  187. return rv
  188. def resolve_or_missing(self, key: str) -> t.Any:
  189. """Look up a variable by name, or return a ``missing`` sentinel
  190. if the key is not found.
  191. Override this method to add custom lookup behavior.
  192. :meth:`resolve`, :meth:`get`, and :meth:`__getitem__` use this
  193. method. Don't call this method directly.
  194. :param key: The variable name to look up.
  195. """
  196. if key in self.vars:
  197. return self.vars[key]
  198. if key in self.parent:
  199. return self.parent[key]
  200. return missing
  201. def get_exported(self) -> t.Dict[str, t.Any]:
  202. """Get a new dict with the exported variables."""
  203. return {k: self.vars[k] for k in self.exported_vars}
  204. def get_all(self) -> t.Dict[str, t.Any]:
  205. """Return the complete context as dict including the exported
  206. variables. For optimizations reasons this might not return an
  207. actual copy so be careful with using it.
  208. """
  209. if not self.vars:
  210. return self.parent
  211. if not self.parent:
  212. return self.vars
  213. return dict(self.parent, **self.vars)
  214. @internalcode
  215. def call(
  216. __self,
  217. __obj: t.Callable[..., t.Any],
  218. *args: t.Any,
  219. **kwargs: t.Any, # noqa: B902
  220. ) -> t.Union[t.Any, "Undefined"]:
  221. """Call the callable with the arguments and keyword arguments
  222. provided but inject the active context or environment as first
  223. argument if the callable has :func:`pass_context` or
  224. :func:`pass_environment`.
  225. """
  226. if __debug__:
  227. __traceback_hide__ = True # noqa
  228. # Allow callable classes to take a context
  229. if (
  230. hasattr(__obj, "__call__") # noqa: B004
  231. and _PassArg.from_obj(__obj.__call__) is not None
  232. ):
  233. __obj = __obj.__call__
  234. pass_arg = _PassArg.from_obj(__obj)
  235. if pass_arg is _PassArg.context:
  236. # the active context should have access to variables set in
  237. # loops and blocks without mutating the context itself
  238. if kwargs.get("_loop_vars"):
  239. __self = __self.derived(kwargs["_loop_vars"])
  240. if kwargs.get("_block_vars"):
  241. __self = __self.derived(kwargs["_block_vars"])
  242. args = (__self,) + args
  243. elif pass_arg is _PassArg.eval_context:
  244. args = (__self.eval_ctx,) + args
  245. elif pass_arg is _PassArg.environment:
  246. args = (__self.environment,) + args
  247. kwargs.pop("_block_vars", None)
  248. kwargs.pop("_loop_vars", None)
  249. try:
  250. return __obj(*args, **kwargs)
  251. except StopIteration:
  252. return __self.environment.undefined(
  253. "value was undefined because a callable raised a"
  254. " StopIteration exception"
  255. )
  256. def derived(self, locals: t.Optional[t.Dict[str, t.Any]] = None) -> "Context":
  257. """Internal helper function to create a derived context. This is
  258. used in situations where the system needs a new context in the same
  259. template that is independent.
  260. """
  261. context = new_context(
  262. self.environment, self.name, {}, self.get_all(), True, None, locals
  263. )
  264. context.eval_ctx = self.eval_ctx
  265. context.blocks.update((k, list(v)) for k, v in self.blocks.items())
  266. return context
  267. keys = _dict_method_all(dict.keys)
  268. values = _dict_method_all(dict.values)
  269. items = _dict_method_all(dict.items)
  270. def __contains__(self, name: str) -> bool:
  271. return name in self.vars or name in self.parent
  272. def __getitem__(self, key: str) -> t.Any:
  273. """Look up a variable by name with ``[]`` syntax, or raise a
  274. ``KeyError`` if the key is not found.
  275. """
  276. item = self.resolve_or_missing(key)
  277. if item is missing:
  278. raise KeyError(key)
  279. return item
  280. def __repr__(self) -> str:
  281. return f"<{type(self).__name__} {self.get_all()!r} of {self.name!r}>"
  282. class BlockReference:
  283. """One block on a template reference."""
  284. def __init__(
  285. self,
  286. name: str,
  287. context: "Context",
  288. stack: t.List[t.Callable[["Context"], t.Iterator[str]]],
  289. depth: int,
  290. ) -> None:
  291. self.name = name
  292. self._context = context
  293. self._stack = stack
  294. self._depth = depth
  295. @property
  296. def super(self) -> t.Union["BlockReference", "Undefined"]:
  297. """Super the block."""
  298. if self._depth + 1 >= len(self._stack):
  299. return self._context.environment.undefined(
  300. f"there is no parent block called {self.name!r}.", name="super"
  301. )
  302. return BlockReference(self.name, self._context, self._stack, self._depth + 1)
  303. @internalcode
  304. async def _async_call(self) -> str:
  305. rv = self._context.environment.concat( # type: ignore
  306. [x async for x in self._stack[self._depth](self._context)] # type: ignore
  307. )
  308. if self._context.eval_ctx.autoescape:
  309. return Markup(rv)
  310. return rv
  311. @internalcode
  312. def __call__(self) -> str:
  313. if self._context.environment.is_async:
  314. return self._async_call() # type: ignore
  315. rv = self._context.environment.concat( # type: ignore
  316. self._stack[self._depth](self._context)
  317. )
  318. if self._context.eval_ctx.autoescape:
  319. return Markup(rv)
  320. return rv
  321. class LoopContext:
  322. """A wrapper iterable for dynamic ``for`` loops, with information
  323. about the loop and iteration.
  324. """
  325. #: Current iteration of the loop, starting at 0.
  326. index0 = -1
  327. _length: t.Optional[int] = None
  328. _after: t.Any = missing
  329. _current: t.Any = missing
  330. _before: t.Any = missing
  331. _last_changed_value: t.Any = missing
  332. def __init__(
  333. self,
  334. iterable: t.Iterable[V],
  335. undefined: t.Type["Undefined"],
  336. recurse: t.Optional["LoopRenderFunc"] = None,
  337. depth0: int = 0,
  338. ) -> None:
  339. """
  340. :param iterable: Iterable to wrap.
  341. :param undefined: :class:`Undefined` class to use for next and
  342. previous items.
  343. :param recurse: The function to render the loop body when the
  344. loop is marked recursive.
  345. :param depth0: Incremented when looping recursively.
  346. """
  347. self._iterable = iterable
  348. self._iterator = self._to_iterator(iterable)
  349. self._undefined = undefined
  350. self._recurse = recurse
  351. #: How many levels deep a recursive loop currently is, starting at 0.
  352. self.depth0 = depth0
  353. @staticmethod
  354. def _to_iterator(iterable: t.Iterable[V]) -> t.Iterator[V]:
  355. return iter(iterable)
  356. @property
  357. def length(self) -> int:
  358. """Length of the iterable.
  359. If the iterable is a generator or otherwise does not have a
  360. size, it is eagerly evaluated to get a size.
  361. """
  362. if self._length is not None:
  363. return self._length
  364. try:
  365. self._length = len(self._iterable) # type: ignore
  366. except TypeError:
  367. iterable = list(self._iterator)
  368. self._iterator = self._to_iterator(iterable)
  369. self._length = len(iterable) + self.index + (self._after is not missing)
  370. return self._length
  371. def __len__(self) -> int:
  372. return self.length
  373. @property
  374. def depth(self) -> int:
  375. """How many levels deep a recursive loop currently is, starting at 1."""
  376. return self.depth0 + 1
  377. @property
  378. def index(self) -> int:
  379. """Current iteration of the loop, starting at 1."""
  380. return self.index0 + 1
  381. @property
  382. def revindex0(self) -> int:
  383. """Number of iterations from the end of the loop, ending at 0.
  384. Requires calculating :attr:`length`.
  385. """
  386. return self.length - self.index
  387. @property
  388. def revindex(self) -> int:
  389. """Number of iterations from the end of the loop, ending at 1.
  390. Requires calculating :attr:`length`.
  391. """
  392. return self.length - self.index0
  393. @property
  394. def first(self) -> bool:
  395. """Whether this is the first iteration of the loop."""
  396. return self.index0 == 0
  397. def _peek_next(self) -> t.Any:
  398. """Return the next element in the iterable, or :data:`missing`
  399. if the iterable is exhausted. Only peeks one item ahead, caching
  400. the result in :attr:`_last` for use in subsequent checks. The
  401. cache is reset when :meth:`__next__` is called.
  402. """
  403. if self._after is not missing:
  404. return self._after
  405. self._after = next(self._iterator, missing)
  406. return self._after
  407. @property
  408. def last(self) -> bool:
  409. """Whether this is the last iteration of the loop.
  410. Causes the iterable to advance early. See
  411. :func:`itertools.groupby` for issues this can cause.
  412. The :func:`groupby` filter avoids that issue.
  413. """
  414. return self._peek_next() is missing
  415. @property
  416. def previtem(self) -> t.Union[t.Any, "Undefined"]:
  417. """The item in the previous iteration. Undefined during the
  418. first iteration.
  419. """
  420. if self.first:
  421. return self._undefined("there is no previous item")
  422. return self._before
  423. @property
  424. def nextitem(self) -> t.Union[t.Any, "Undefined"]:
  425. """The item in the next iteration. Undefined during the last
  426. iteration.
  427. Causes the iterable to advance early. See
  428. :func:`itertools.groupby` for issues this can cause.
  429. The :func:`jinja-filters.groupby` filter avoids that issue.
  430. """
  431. rv = self._peek_next()
  432. if rv is missing:
  433. return self._undefined("there is no next item")
  434. return rv
  435. def cycle(self, *args: V) -> V:
  436. """Return a value from the given args, cycling through based on
  437. the current :attr:`index0`.
  438. :param args: One or more values to cycle through.
  439. """
  440. if not args:
  441. raise TypeError("no items for cycling given")
  442. return args[self.index0 % len(args)]
  443. def changed(self, *value: t.Any) -> bool:
  444. """Return ``True`` if previously called with a different value
  445. (including when called for the first time).
  446. :param value: One or more values to compare to the last call.
  447. """
  448. if self._last_changed_value != value:
  449. self._last_changed_value = value
  450. return True
  451. return False
  452. def __iter__(self) -> "LoopContext":
  453. return self
  454. def __next__(self) -> t.Tuple[t.Any, "LoopContext"]:
  455. if self._after is not missing:
  456. rv = self._after
  457. self._after = missing
  458. else:
  459. rv = next(self._iterator)
  460. self.index0 += 1
  461. self._before = self._current
  462. self._current = rv
  463. return rv, self
  464. @internalcode
  465. def __call__(self, iterable: t.Iterable[V]) -> str:
  466. """When iterating over nested data, render the body of the loop
  467. recursively with the given inner iterable data.
  468. The loop must have the ``recursive`` marker for this to work.
  469. """
  470. if self._recurse is None:
  471. raise TypeError(
  472. "The loop must have the 'recursive' marker to be called recursively."
  473. )
  474. return self._recurse(iterable, self._recurse, depth=self.depth)
  475. def __repr__(self) -> str:
  476. return f"<{type(self).__name__} {self.index}/{self.length}>"
  477. class AsyncLoopContext(LoopContext):
  478. _iterator: t.AsyncIterator[t.Any] # type: ignore
  479. @staticmethod
  480. def _to_iterator( # type: ignore
  481. iterable: t.Union[t.Iterable[V], t.AsyncIterable[V]],
  482. ) -> t.AsyncIterator[V]:
  483. return auto_aiter(iterable)
  484. @property
  485. async def length(self) -> int: # type: ignore
  486. if self._length is not None:
  487. return self._length
  488. try:
  489. self._length = len(self._iterable) # type: ignore
  490. except TypeError:
  491. iterable = [x async for x in self._iterator]
  492. self._iterator = self._to_iterator(iterable)
  493. self._length = len(iterable) + self.index + (self._after is not missing)
  494. return self._length
  495. @property
  496. async def revindex0(self) -> int: # type: ignore
  497. return await self.length - self.index
  498. @property
  499. async def revindex(self) -> int: # type: ignore
  500. return await self.length - self.index0
  501. async def _peek_next(self) -> t.Any:
  502. if self._after is not missing:
  503. return self._after
  504. try:
  505. self._after = await self._iterator.__anext__()
  506. except StopAsyncIteration:
  507. self._after = missing
  508. return self._after
  509. @property
  510. async def last(self) -> bool: # type: ignore
  511. return await self._peek_next() is missing
  512. @property
  513. async def nextitem(self) -> t.Union[t.Any, "Undefined"]:
  514. rv = await self._peek_next()
  515. if rv is missing:
  516. return self._undefined("there is no next item")
  517. return rv
  518. def __aiter__(self) -> "AsyncLoopContext":
  519. return self
  520. async def __anext__(self) -> t.Tuple[t.Any, "AsyncLoopContext"]:
  521. if self._after is not missing:
  522. rv = self._after
  523. self._after = missing
  524. else:
  525. rv = await self._iterator.__anext__()
  526. self.index0 += 1
  527. self._before = self._current
  528. self._current = rv
  529. return rv, self
  530. class Macro:
  531. """Wraps a macro function."""
  532. def __init__(
  533. self,
  534. environment: "Environment",
  535. func: t.Callable[..., str],
  536. name: str,
  537. arguments: t.List[str],
  538. catch_kwargs: bool,
  539. catch_varargs: bool,
  540. caller: bool,
  541. default_autoescape: t.Optional[bool] = None,
  542. ):
  543. self._environment = environment
  544. self._func = func
  545. self._argument_count = len(arguments)
  546. self.name = name
  547. self.arguments = arguments
  548. self.catch_kwargs = catch_kwargs
  549. self.catch_varargs = catch_varargs
  550. self.caller = caller
  551. self.explicit_caller = "caller" in arguments
  552. if default_autoescape is None:
  553. if callable(environment.autoescape):
  554. default_autoescape = environment.autoescape(None)
  555. else:
  556. default_autoescape = environment.autoescape
  557. self._default_autoescape = default_autoescape
  558. @internalcode
  559. @pass_eval_context
  560. def __call__(self, *args: t.Any, **kwargs: t.Any) -> str:
  561. # This requires a bit of explanation, In the past we used to
  562. # decide largely based on compile-time information if a macro is
  563. # safe or unsafe. While there was a volatile mode it was largely
  564. # unused for deciding on escaping. This turns out to be
  565. # problematic for macros because whether a macro is safe depends not
  566. # on the escape mode when it was defined, but rather when it was used.
  567. #
  568. # Because however we export macros from the module system and
  569. # there are historic callers that do not pass an eval context (and
  570. # will continue to not pass one), we need to perform an instance
  571. # check here.
  572. #
  573. # This is considered safe because an eval context is not a valid
  574. # argument to callables otherwise anyway. Worst case here is
  575. # that if no eval context is passed we fall back to the compile
  576. # time autoescape flag.
  577. if args and isinstance(args[0], EvalContext):
  578. autoescape = args[0].autoescape
  579. args = args[1:]
  580. else:
  581. autoescape = self._default_autoescape
  582. # try to consume the positional arguments
  583. arguments = list(args[: self._argument_count])
  584. off = len(arguments)
  585. # For information why this is necessary refer to the handling
  586. # of caller in the `macro_body` handler in the compiler.
  587. found_caller = False
  588. # if the number of arguments consumed is not the number of
  589. # arguments expected we start filling in keyword arguments
  590. # and defaults.
  591. if off != self._argument_count:
  592. for name in self.arguments[len(arguments) :]:
  593. try:
  594. value = kwargs.pop(name)
  595. except KeyError:
  596. value = missing
  597. if name == "caller":
  598. found_caller = True
  599. arguments.append(value)
  600. else:
  601. found_caller = self.explicit_caller
  602. # it's important that the order of these arguments does not change
  603. # if not also changed in the compiler's `function_scoping` method.
  604. # the order is caller, keyword arguments, positional arguments!
  605. if self.caller and not found_caller:
  606. caller = kwargs.pop("caller", None)
  607. if caller is None:
  608. caller = self._environment.undefined("No caller defined", name="caller")
  609. arguments.append(caller)
  610. if self.catch_kwargs:
  611. arguments.append(kwargs)
  612. elif kwargs:
  613. if "caller" in kwargs:
  614. raise TypeError(
  615. f"macro {self.name!r} was invoked with two values for the special"
  616. " caller argument. This is most likely a bug."
  617. )
  618. raise TypeError(
  619. f"macro {self.name!r} takes no keyword argument {next(iter(kwargs))!r}"
  620. )
  621. if self.catch_varargs:
  622. arguments.append(args[self._argument_count :])
  623. elif len(args) > self._argument_count:
  624. raise TypeError(
  625. f"macro {self.name!r} takes not more than"
  626. f" {len(self.arguments)} argument(s)"
  627. )
  628. return self._invoke(arguments, autoescape)
  629. async def _async_invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str:
  630. rv = await self._func(*arguments) # type: ignore
  631. if autoescape:
  632. return Markup(rv)
  633. return rv # type: ignore
  634. def _invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str:
  635. if self._environment.is_async:
  636. return self._async_invoke(arguments, autoescape) # type: ignore
  637. rv = self._func(*arguments)
  638. if autoescape:
  639. rv = Markup(rv)
  640. return rv
  641. def __repr__(self) -> str:
  642. name = "anonymous" if self.name is None else repr(self.name)
  643. return f"<{type(self).__name__} {name}>"
  644. class Undefined:
  645. """The default undefined type. This can be printed, iterated, and treated as
  646. a boolean. Any other operation will raise an :exc:`UndefinedError`.
  647. >>> foo = Undefined(name='foo')
  648. >>> str(foo)
  649. ''
  650. >>> not foo
  651. True
  652. >>> foo + 42
  653. Traceback (most recent call last):
  654. ...
  655. jinja2.exceptions.UndefinedError: 'foo' is undefined
  656. """
  657. __slots__ = (
  658. "_undefined_hint",
  659. "_undefined_obj",
  660. "_undefined_name",
  661. "_undefined_exception",
  662. )
  663. def __init__(
  664. self,
  665. hint: t.Optional[str] = None,
  666. obj: t.Any = missing,
  667. name: t.Optional[str] = None,
  668. exc: t.Type[TemplateRuntimeError] = UndefinedError,
  669. ) -> None:
  670. self._undefined_hint = hint
  671. self._undefined_obj = obj
  672. self._undefined_name = name
  673. self._undefined_exception = exc
  674. @property
  675. def _undefined_message(self) -> str:
  676. """Build a message about the undefined value based on how it was
  677. accessed.
  678. """
  679. if self._undefined_hint:
  680. return self._undefined_hint
  681. if self._undefined_obj is missing:
  682. return f"{self._undefined_name!r} is undefined"
  683. if not isinstance(self._undefined_name, str):
  684. return (
  685. f"{object_type_repr(self._undefined_obj)} has no"
  686. f" element {self._undefined_name!r}"
  687. )
  688. return (
  689. f"{object_type_repr(self._undefined_obj)!r} has no"
  690. f" attribute {self._undefined_name!r}"
  691. )
  692. @internalcode
  693. def _fail_with_undefined_error(
  694. self, *args: t.Any, **kwargs: t.Any
  695. ) -> "te.NoReturn":
  696. """Raise an :exc:`UndefinedError` when operations are performed
  697. on the undefined value.
  698. """
  699. raise self._undefined_exception(self._undefined_message)
  700. @internalcode
  701. def __getattr__(self, name: str) -> t.Any:
  702. # Raise AttributeError on requests for names that appear to be unimplemented
  703. # dunder methods to keep Python's internal protocol probing behaviors working
  704. # properly in cases where another exception type could cause unexpected or
  705. # difficult-to-diagnose failures.
  706. if name[:2] == "__" and name[-2:] == "__":
  707. raise AttributeError(name)
  708. return self._fail_with_undefined_error()
  709. __add__ = __radd__ = __sub__ = __rsub__ = _fail_with_undefined_error
  710. __mul__ = __rmul__ = __div__ = __rdiv__ = _fail_with_undefined_error
  711. __truediv__ = __rtruediv__ = _fail_with_undefined_error
  712. __floordiv__ = __rfloordiv__ = _fail_with_undefined_error
  713. __mod__ = __rmod__ = _fail_with_undefined_error
  714. __pos__ = __neg__ = _fail_with_undefined_error
  715. __call__ = __getitem__ = _fail_with_undefined_error
  716. __lt__ = __le__ = __gt__ = __ge__ = _fail_with_undefined_error
  717. __int__ = __float__ = __complex__ = _fail_with_undefined_error
  718. __pow__ = __rpow__ = _fail_with_undefined_error
  719. def __eq__(self, other: t.Any) -> bool:
  720. return type(self) is type(other)
  721. def __ne__(self, other: t.Any) -> bool:
  722. return not self.__eq__(other)
  723. def __hash__(self) -> int:
  724. return id(type(self))
  725. def __str__(self) -> str:
  726. return ""
  727. def __len__(self) -> int:
  728. return 0
  729. def __iter__(self) -> t.Iterator[t.Any]:
  730. yield from ()
  731. async def __aiter__(self) -> t.AsyncIterator[t.Any]:
  732. for _ in ():
  733. yield
  734. def __bool__(self) -> bool:
  735. return False
  736. def __repr__(self) -> str:
  737. return "Undefined"
  738. def make_logging_undefined(
  739. logger: t.Optional["logging.Logger"] = None, base: t.Type[Undefined] = Undefined
  740. ) -> t.Type[Undefined]:
  741. """Given a logger object this returns a new undefined class that will
  742. log certain failures. It will log iterations and printing. If no
  743. logger is given a default logger is created.
  744. Example::
  745. logger = logging.getLogger(__name__)
  746. LoggingUndefined = make_logging_undefined(
  747. logger=logger,
  748. base=Undefined
  749. )
  750. .. versionadded:: 2.8
  751. :param logger: the logger to use. If not provided, a default logger
  752. is created.
  753. :param base: the base class to add logging functionality to. This
  754. defaults to :class:`Undefined`.
  755. """
  756. if logger is None:
  757. import logging
  758. logger = logging.getLogger(__name__)
  759. logger.addHandler(logging.StreamHandler(sys.stderr))
  760. def _log_message(undef: Undefined) -> None:
  761. logger.warning("Template variable warning: %s", undef._undefined_message)
  762. class LoggingUndefined(base): # type: ignore
  763. __slots__ = ()
  764. def _fail_with_undefined_error( # type: ignore
  765. self, *args: t.Any, **kwargs: t.Any
  766. ) -> "te.NoReturn":
  767. try:
  768. super()._fail_with_undefined_error(*args, **kwargs)
  769. except self._undefined_exception as e:
  770. logger.error("Template variable error: %s", e) # type: ignore
  771. raise e
  772. def __str__(self) -> str:
  773. _log_message(self)
  774. return super().__str__() # type: ignore
  775. def __iter__(self) -> t.Iterator[t.Any]:
  776. _log_message(self)
  777. return super().__iter__() # type: ignore
  778. def __bool__(self) -> bool:
  779. _log_message(self)
  780. return super().__bool__() # type: ignore
  781. return LoggingUndefined
  782. class ChainableUndefined(Undefined):
  783. """An undefined that is chainable, where both ``__getattr__`` and
  784. ``__getitem__`` return itself rather than raising an
  785. :exc:`UndefinedError`.
  786. >>> foo = ChainableUndefined(name='foo')
  787. >>> str(foo.bar['baz'])
  788. ''
  789. >>> foo.bar['baz'] + 42
  790. Traceback (most recent call last):
  791. ...
  792. jinja2.exceptions.UndefinedError: 'foo' is undefined
  793. .. versionadded:: 2.11.0
  794. """
  795. __slots__ = ()
  796. def __html__(self) -> str:
  797. return str(self)
  798. def __getattr__(self, name: str) -> "ChainableUndefined":
  799. # Raise AttributeError on requests for names that appear to be unimplemented
  800. # dunder methods to avoid confusing Python with truthy non-method objects that
  801. # do not implement the protocol being probed for. e.g., copy.copy(Undefined())
  802. # fails spectacularly if getattr(Undefined(), '__setstate__') returns an
  803. # Undefined object instead of raising AttributeError to signal that it does not
  804. # support that style of object initialization.
  805. if name[:2] == "__" and name[-2:] == "__":
  806. raise AttributeError(name)
  807. return self
  808. def __getitem__(self, _name: str) -> "ChainableUndefined": # type: ignore[override]
  809. return self
  810. class DebugUndefined(Undefined):
  811. """An undefined that returns the debug info when printed.
  812. >>> foo = DebugUndefined(name='foo')
  813. >>> str(foo)
  814. '{{ foo }}'
  815. >>> not foo
  816. True
  817. >>> foo + 42
  818. Traceback (most recent call last):
  819. ...
  820. jinja2.exceptions.UndefinedError: 'foo' is undefined
  821. """
  822. __slots__ = ()
  823. def __str__(self) -> str:
  824. if self._undefined_hint:
  825. message = f"undefined value printed: {self._undefined_hint}"
  826. elif self._undefined_obj is missing:
  827. message = self._undefined_name # type: ignore
  828. else:
  829. message = (
  830. f"no such element: {object_type_repr(self._undefined_obj)}"
  831. f"[{self._undefined_name!r}]"
  832. )
  833. return f"{{{{ {message} }}}}"
  834. class StrictUndefined(Undefined):
  835. """An undefined that barks on print and iteration as well as boolean
  836. tests and all kinds of comparisons. In other words: you can do nothing
  837. with it except checking if it's defined using the `defined` test.
  838. >>> foo = StrictUndefined(name='foo')
  839. >>> str(foo)
  840. Traceback (most recent call last):
  841. ...
  842. jinja2.exceptions.UndefinedError: 'foo' is undefined
  843. >>> not foo
  844. Traceback (most recent call last):
  845. ...
  846. jinja2.exceptions.UndefinedError: 'foo' is undefined
  847. >>> foo + 42
  848. Traceback (most recent call last):
  849. ...
  850. jinja2.exceptions.UndefinedError: 'foo' is undefined
  851. """
  852. __slots__ = ()
  853. __iter__ = __str__ = __len__ = Undefined._fail_with_undefined_error
  854. __eq__ = __ne__ = __bool__ = __hash__ = Undefined._fail_with_undefined_error
  855. __contains__ = Undefined._fail_with_undefined_error