Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jinja2/runtime.py: 35%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

487 statements  

1"""The runtime functions and state used by compiled templates.""" 

2 

3import functools 

4import sys 

5import typing as t 

6from collections import abc 

7from itertools import chain 

8 

9from markupsafe import escape # noqa: F401 

10from markupsafe import Markup 

11from markupsafe import soft_str 

12 

13from .async_utils import auto_aiter 

14from .async_utils import auto_await # noqa: F401 

15from .exceptions import TemplateNotFound # noqa: F401 

16from .exceptions import TemplateRuntimeError # noqa: F401 

17from .exceptions import UndefinedError 

18from .nodes import EvalContext 

19from .utils import _PassArg 

20from .utils import concat 

21from .utils import internalcode 

22from .utils import missing 

23from .utils import Namespace # noqa: F401 

24from .utils import object_type_repr 

25from .utils import pass_eval_context 

26 

27V = t.TypeVar("V") 

28F = t.TypeVar("F", bound=t.Callable[..., t.Any]) 

29 

30if t.TYPE_CHECKING: 

31 import logging 

32 

33 import typing_extensions as te 

34 

35 from .environment import Environment 

36 

37 class LoopRenderFunc(te.Protocol): 

38 def __call__( 

39 self, 

40 reciter: t.Iterable[V], 

41 loop_render_func: "LoopRenderFunc", 

42 depth: int = 0, 

43 ) -> str: ... 

44 

45 

46# these variables are exported to the template runtime 

47exported = [ 

48 "LoopContext", 

49 "TemplateReference", 

50 "Macro", 

51 "Markup", 

52 "TemplateRuntimeError", 

53 "missing", 

54 "escape", 

55 "markup_join", 

56 "str_join", 

57 "identity", 

58 "TemplateNotFound", 

59 "Namespace", 

60 "Undefined", 

61 "internalcode", 

62] 

63async_exported = [ 

64 "AsyncLoopContext", 

65 "auto_aiter", 

66 "auto_await", 

67] 

68 

69 

70def identity(x: V) -> V: 

71 """Returns its argument. Useful for certain things in the 

72 environment. 

73 """ 

74 return x 

75 

76 

77def markup_join(seq: t.Iterable[t.Any]) -> str: 

78 """Concatenation that escapes if necessary and converts to string.""" 

79 buf = [] 

80 iterator = map(soft_str, seq) 

81 for arg in iterator: 

82 buf.append(arg) 

83 if hasattr(arg, "__html__"): 

84 return Markup("").join(chain(buf, iterator)) 

85 return concat(buf) 

86 

87 

88def str_join(seq: t.Iterable[t.Any]) -> str: 

89 """Simple args to string conversion and concatenation.""" 

90 return concat(map(str, seq)) 

91 

92 

93def new_context( 

94 environment: "Environment", 

95 template_name: t.Optional[str], 

96 blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]], 

97 vars: t.Optional[t.Dict[str, t.Any]] = None, 

98 shared: bool = False, 

99 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

100 locals: t.Optional[t.Mapping[str, t.Any]] = None, 

101) -> "Context": 

102 """Internal helper for context creation.""" 

103 if vars is None: 

104 vars = {} 

105 if shared: 

106 parent = vars 

107 else: 

108 parent = dict(globals or (), **vars) 

109 if locals: 

110 # if the parent is shared a copy should be created because 

111 # we don't want to modify the dict passed 

112 if shared: 

113 parent = dict(parent) 

114 for key, value in locals.items(): 

115 if value is not missing: 

116 parent[key] = value 

117 return environment.context_class( 

118 environment, parent, template_name, blocks, globals=globals 

119 ) 

120 

121 

122class TemplateReference: 

123 """The `self` in templates.""" 

124 

125 def __init__(self, context: "Context") -> None: 

126 self.__context = context 

127 

128 def __getitem__(self, name: str) -> t.Any: 

129 blocks = self.__context.blocks[name] 

130 return BlockReference(name, self.__context, blocks, 0) 

131 

132 def __repr__(self) -> str: 

133 return f"<{type(self).__name__} {self.__context.name!r}>" 

134 

135 

136def _dict_method_all(dict_method: F) -> F: 

137 @functools.wraps(dict_method) 

138 def f_all(self: "Context") -> t.Any: 

139 return dict_method(self.get_all()) 

140 

141 return t.cast(F, f_all) 

142 

143 

144@abc.Mapping.register 

145class Context: 

146 """The template context holds the variables of a template. It stores the 

147 values passed to the template and also the names the template exports. 

148 Creating instances is neither supported nor useful as it's created 

149 automatically at various stages of the template evaluation and should not 

150 be created by hand. 

151 

152 The context is immutable. Modifications on :attr:`parent` **must not** 

153 happen and modifications on :attr:`vars` are allowed from generated 

154 template code only. Template filters and global functions marked as 

155 :func:`pass_context` get the active context passed as first argument 

156 and are allowed to access the context read-only. 

157 

158 The template context supports read only dict operations (`get`, 

159 `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`, 

160 `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve` 

161 method that doesn't fail with a `KeyError` but returns an 

162 :class:`Undefined` object for missing variables. 

163 """ 

164 

165 def __init__( 

166 self, 

167 environment: "Environment", 

168 parent: t.Dict[str, t.Any], 

169 name: t.Optional[str], 

170 blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]], 

171 globals: t.Optional[t.MutableMapping[str, t.Any]] = None, 

172 ): 

173 self.parent = parent 

174 self.vars: t.Dict[str, t.Any] = {} 

175 self.environment: Environment = environment 

176 self.eval_ctx = EvalContext(self.environment, name) 

177 self.exported_vars: t.Set[str] = set() 

178 self.name = name 

179 self.globals_keys = set() if globals is None else set(globals) 

180 

181 # create the initial mapping of blocks. Whenever template inheritance 

182 # takes place the runtime will update this mapping with the new blocks 

183 # from the template. 

184 self.blocks = {k: [v] for k, v in blocks.items()} 

185 

186 def super( 

187 self, name: str, current: t.Callable[["Context"], t.Iterator[str]] 

188 ) -> t.Union["BlockReference", "Undefined"]: 

189 """Render a parent block.""" 

190 try: 

191 blocks = self.blocks[name] 

192 index = blocks.index(current) + 1 

193 blocks[index] 

194 except LookupError: 

195 return self.environment.undefined( 

196 f"there is no parent block called {name!r}.", name="super" 

197 ) 

198 return BlockReference(name, self, blocks, index) 

199 

200 def get(self, key: str, default: t.Any = None) -> t.Any: 

201 """Look up a variable by name, or return a default if the key is 

202 not found. 

203 

204 :param key: The variable name to look up. 

205 :param default: The value to return if the key is not found. 

206 """ 

207 try: 

208 return self[key] 

209 except KeyError: 

210 return default 

211 

212 def resolve(self, key: str) -> t.Union[t.Any, "Undefined"]: 

213 """Look up a variable by name, or return an :class:`Undefined` 

214 object if the key is not found. 

215 

216 If you need to add custom behavior, override 

217 :meth:`resolve_or_missing`, not this method. The various lookup 

218 functions use that method, not this one. 

219 

220 :param key: The variable name to look up. 

221 """ 

222 rv = self.resolve_or_missing(key) 

223 

224 if rv is missing: 

225 return self.environment.undefined(name=key) 

226 

227 return rv 

228 

229 def resolve_or_missing(self, key: str) -> t.Any: 

230 """Look up a variable by name, or return a ``missing`` sentinel 

231 if the key is not found. 

232 

233 Override this method to add custom lookup behavior. 

234 :meth:`resolve`, :meth:`get`, and :meth:`__getitem__` use this 

235 method. Don't call this method directly. 

236 

237 :param key: The variable name to look up. 

238 """ 

239 if key in self.vars: 

240 return self.vars[key] 

241 

242 if key in self.parent: 

243 return self.parent[key] 

244 

245 return missing 

246 

247 def get_exported(self) -> t.Dict[str, t.Any]: 

248 """Get a new dict with the exported variables.""" 

249 return {k: self.vars[k] for k in self.exported_vars} 

250 

251 def get_all(self) -> t.Dict[str, t.Any]: 

252 """Return the complete context as dict including the exported 

253 variables. For optimizations reasons this might not return an 

254 actual copy so be careful with using it. 

255 """ 

256 if not self.vars: 

257 return self.parent 

258 if not self.parent: 

259 return self.vars 

260 return dict(self.parent, **self.vars) 

261 

262 @internalcode 

263 def call( 

264 __self, 

265 __obj: t.Callable[..., t.Any], 

266 *args: t.Any, 

267 **kwargs: t.Any, # noqa: B902 

268 ) -> t.Union[t.Any, "Undefined"]: 

269 """Call the callable with the arguments and keyword arguments 

270 provided but inject the active context or environment as first 

271 argument if the callable has :func:`pass_context` or 

272 :func:`pass_environment`. 

273 """ 

274 if __debug__: 

275 __traceback_hide__ = True # noqa 

276 

277 # Allow callable classes to take a context 

278 if ( 

279 hasattr(__obj, "__call__") # noqa: B004 

280 and _PassArg.from_obj(__obj.__call__) is not None 

281 ): 

282 __obj = __obj.__call__ 

283 

284 pass_arg = _PassArg.from_obj(__obj) 

285 

286 if pass_arg is _PassArg.context: 

287 # the active context should have access to variables set in 

288 # loops and blocks without mutating the context itself 

289 if kwargs.get("_loop_vars"): 

290 __self = __self.derived(kwargs["_loop_vars"]) 

291 if kwargs.get("_block_vars"): 

292 __self = __self.derived(kwargs["_block_vars"]) 

293 args = (__self,) + args 

294 elif pass_arg is _PassArg.eval_context: 

295 args = (__self.eval_ctx,) + args 

296 elif pass_arg is _PassArg.environment: 

297 args = (__self.environment,) + args 

298 

299 kwargs.pop("_block_vars", None) 

300 kwargs.pop("_loop_vars", None) 

301 

302 try: 

303 return __obj(*args, **kwargs) 

304 except StopIteration: 

305 return __self.environment.undefined( 

306 "value was undefined because a callable raised a" 

307 " StopIteration exception" 

308 ) 

309 

310 def derived(self, locals: t.Optional[t.Dict[str, t.Any]] = None) -> "Context": 

311 """Internal helper function to create a derived context. This is 

312 used in situations where the system needs a new context in the same 

313 template that is independent. 

314 """ 

315 context = new_context( 

316 self.environment, self.name, {}, self.get_all(), True, None, locals 

317 ) 

318 context.eval_ctx = self.eval_ctx 

319 context.blocks.update((k, list(v)) for k, v in self.blocks.items()) 

320 return context 

321 

322 keys = _dict_method_all(dict.keys) 

323 values = _dict_method_all(dict.values) 

324 items = _dict_method_all(dict.items) 

325 

326 def __contains__(self, name: str) -> bool: 

327 return name in self.vars or name in self.parent 

328 

329 def __getitem__(self, key: str) -> t.Any: 

330 """Look up a variable by name with ``[]`` syntax, or raise a 

331 ``KeyError`` if the key is not found. 

332 """ 

333 item = self.resolve_or_missing(key) 

334 

335 if item is missing: 

336 raise KeyError(key) 

337 

338 return item 

339 

340 def __repr__(self) -> str: 

341 return f"<{type(self).__name__} {self.get_all()!r} of {self.name!r}>" 

342 

343 

344class BlockReference: 

345 """One block on a template reference.""" 

346 

347 def __init__( 

348 self, 

349 name: str, 

350 context: "Context", 

351 stack: t.List[t.Callable[["Context"], t.Iterator[str]]], 

352 depth: int, 

353 ) -> None: 

354 self.name = name 

355 self._context = context 

356 self._stack = stack 

357 self._depth = depth 

358 

359 @property 

360 def super(self) -> t.Union["BlockReference", "Undefined"]: 

361 """Super the block.""" 

362 if self._depth + 1 >= len(self._stack): 

363 return self._context.environment.undefined( 

364 f"there is no parent block called {self.name!r}.", name="super" 

365 ) 

366 return BlockReference(self.name, self._context, self._stack, self._depth + 1) 

367 

368 @internalcode 

369 async def _async_call(self) -> str: 

370 rv = self._context.environment.concat( # type: ignore 

371 [x async for x in self._stack[self._depth](self._context)] # type: ignore 

372 ) 

373 

374 if self._context.eval_ctx.autoescape: 

375 return Markup(rv) 

376 

377 return rv 

378 

379 @internalcode 

380 def __call__(self) -> str: 

381 if self._context.environment.is_async: 

382 return self._async_call() # type: ignore 

383 

384 rv = self._context.environment.concat( # type: ignore 

385 self._stack[self._depth](self._context) 

386 ) 

387 

388 if self._context.eval_ctx.autoescape: 

389 return Markup(rv) 

390 

391 return rv 

392 

393 

394class LoopContext: 

395 """A wrapper iterable for dynamic ``for`` loops, with information 

396 about the loop and iteration. 

397 """ 

398 

399 #: Current iteration of the loop, starting at 0. 

400 index0 = -1 

401 

402 _length: t.Optional[int] = None 

403 _after: t.Any = missing 

404 _current: t.Any = missing 

405 _before: t.Any = missing 

406 _last_changed_value: t.Any = missing 

407 

408 def __init__( 

409 self, 

410 iterable: t.Iterable[V], 

411 undefined: t.Type["Undefined"], 

412 recurse: t.Optional["LoopRenderFunc"] = None, 

413 depth0: int = 0, 

414 ) -> None: 

415 """ 

416 :param iterable: Iterable to wrap. 

417 :param undefined: :class:`Undefined` class to use for next and 

418 previous items. 

419 :param recurse: The function to render the loop body when the 

420 loop is marked recursive. 

421 :param depth0: Incremented when looping recursively. 

422 """ 

423 self._iterable = iterable 

424 self._iterator = self._to_iterator(iterable) 

425 self._undefined = undefined 

426 self._recurse = recurse 

427 #: How many levels deep a recursive loop currently is, starting at 0. 

428 self.depth0 = depth0 

429 

430 @staticmethod 

431 def _to_iterator(iterable: t.Iterable[V]) -> t.Iterator[V]: 

432 return iter(iterable) 

433 

434 @property 

435 def length(self) -> int: 

436 """Length of the iterable. 

437 

438 If the iterable is a generator or otherwise does not have a 

439 size, it is eagerly evaluated to get a size. 

440 """ 

441 if self._length is not None: 

442 return self._length 

443 

444 try: 

445 self._length = len(self._iterable) # type: ignore 

446 except TypeError: 

447 iterable = list(self._iterator) 

448 self._iterator = self._to_iterator(iterable) 

449 self._length = len(iterable) + self.index + (self._after is not missing) 

450 

451 return self._length 

452 

453 def __len__(self) -> int: 

454 return self.length 

455 

456 @property 

457 def depth(self) -> int: 

458 """How many levels deep a recursive loop currently is, starting at 1.""" 

459 return self.depth0 + 1 

460 

461 @property 

462 def index(self) -> int: 

463 """Current iteration of the loop, starting at 1.""" 

464 return self.index0 + 1 

465 

466 @property 

467 def revindex0(self) -> int: 

468 """Number of iterations from the end of the loop, ending at 0. 

469 

470 Requires calculating :attr:`length`. 

471 """ 

472 return self.length - self.index 

473 

474 @property 

475 def revindex(self) -> int: 

476 """Number of iterations from the end of the loop, ending at 1. 

477 

478 Requires calculating :attr:`length`. 

479 """ 

480 return self.length - self.index0 

481 

482 @property 

483 def first(self) -> bool: 

484 """Whether this is the first iteration of the loop.""" 

485 return self.index0 == 0 

486 

487 def _peek_next(self) -> t.Any: 

488 """Return the next element in the iterable, or :data:`missing` 

489 if the iterable is exhausted. Only peeks one item ahead, caching 

490 the result in :attr:`_last` for use in subsequent checks. The 

491 cache is reset when :meth:`__next__` is called. 

492 """ 

493 if self._after is not missing: 

494 return self._after 

495 

496 self._after = next(self._iterator, missing) 

497 return self._after 

498 

499 @property 

500 def last(self) -> bool: 

501 """Whether this is the last iteration of the loop. 

502 

503 Causes the iterable to advance early. See 

504 :func:`itertools.groupby` for issues this can cause. 

505 The :func:`groupby` filter avoids that issue. 

506 """ 

507 return self._peek_next() is missing 

508 

509 @property 

510 def previtem(self) -> t.Union[t.Any, "Undefined"]: 

511 """The item in the previous iteration. Undefined during the 

512 first iteration. 

513 """ 

514 if self.first: 

515 return self._undefined("there is no previous item") 

516 

517 return self._before 

518 

519 @property 

520 def nextitem(self) -> t.Union[t.Any, "Undefined"]: 

521 """The item in the next iteration. Undefined during the last 

522 iteration. 

523 

524 Causes the iterable to advance early. See 

525 :func:`itertools.groupby` for issues this can cause. 

526 The :func:`jinja-filters.groupby` filter avoids that issue. 

527 """ 

528 rv = self._peek_next() 

529 

530 if rv is missing: 

531 return self._undefined("there is no next item") 

532 

533 return rv 

534 

535 def cycle(self, *args: V) -> V: 

536 """Return a value from the given args, cycling through based on 

537 the current :attr:`index0`. 

538 

539 :param args: One or more values to cycle through. 

540 """ 

541 if not args: 

542 raise TypeError("no items for cycling given") 

543 

544 return args[self.index0 % len(args)] 

545 

546 def changed(self, *value: t.Any) -> bool: 

547 """Return ``True`` if previously called with a different value 

548 (including when called for the first time). 

549 

550 :param value: One or more values to compare to the last call. 

551 """ 

552 if self._last_changed_value != value: 

553 self._last_changed_value = value 

554 return True 

555 

556 return False 

557 

558 def __iter__(self) -> "LoopContext": 

559 return self 

560 

561 def __next__(self) -> t.Tuple[t.Any, "LoopContext"]: 

562 if self._after is not missing: 

563 rv = self._after 

564 self._after = missing 

565 else: 

566 rv = next(self._iterator) 

567 

568 self.index0 += 1 

569 self._before = self._current 

570 self._current = rv 

571 return rv, self 

572 

573 @internalcode 

574 def __call__(self, iterable: t.Iterable[V]) -> str: 

575 """When iterating over nested data, render the body of the loop 

576 recursively with the given inner iterable data. 

577 

578 The loop must have the ``recursive`` marker for this to work. 

579 """ 

580 if self._recurse is None: 

581 raise TypeError( 

582 "The loop must have the 'recursive' marker to be called recursively." 

583 ) 

584 

585 return self._recurse(iterable, self._recurse, depth=self.depth) 

586 

587 def __repr__(self) -> str: 

588 return f"<{type(self).__name__} {self.index}/{self.length}>" 

589 

590 

591class AsyncLoopContext(LoopContext): 

592 _iterator: t.AsyncIterator[t.Any] # type: ignore 

593 

594 @staticmethod 

595 def _to_iterator( # type: ignore 

596 iterable: t.Union[t.Iterable[V], t.AsyncIterable[V]], 

597 ) -> t.AsyncIterator[V]: 

598 return auto_aiter(iterable) 

599 

600 @property 

601 async def length(self) -> int: # type: ignore 

602 if self._length is not None: 

603 return self._length 

604 

605 try: 

606 self._length = len(self._iterable) # type: ignore 

607 except TypeError: 

608 iterable = [x async for x in self._iterator] 

609 self._iterator = self._to_iterator(iterable) 

610 self._length = len(iterable) + self.index + (self._after is not missing) 

611 

612 return self._length 

613 

614 @property 

615 async def revindex0(self) -> int: # type: ignore 

616 return await self.length - self.index 

617 

618 @property 

619 async def revindex(self) -> int: # type: ignore 

620 return await self.length - self.index0 

621 

622 async def _peek_next(self) -> t.Any: 

623 if self._after is not missing: 

624 return self._after 

625 

626 try: 

627 self._after = await self._iterator.__anext__() 

628 except StopAsyncIteration: 

629 self._after = missing 

630 

631 return self._after 

632 

633 @property 

634 async def last(self) -> bool: # type: ignore 

635 return await self._peek_next() is missing 

636 

637 @property 

638 async def nextitem(self) -> t.Union[t.Any, "Undefined"]: 

639 rv = await self._peek_next() 

640 

641 if rv is missing: 

642 return self._undefined("there is no next item") 

643 

644 return rv 

645 

646 def __aiter__(self) -> "AsyncLoopContext": 

647 return self 

648 

649 async def __anext__(self) -> t.Tuple[t.Any, "AsyncLoopContext"]: 

650 if self._after is not missing: 

651 rv = self._after 

652 self._after = missing 

653 else: 

654 rv = await self._iterator.__anext__() 

655 

656 self.index0 += 1 

657 self._before = self._current 

658 self._current = rv 

659 return rv, self 

660 

661 

662class Macro: 

663 """Wraps a macro function.""" 

664 

665 def __init__( 

666 self, 

667 environment: "Environment", 

668 func: t.Callable[..., str], 

669 name: str, 

670 arguments: t.List[str], 

671 catch_kwargs: bool, 

672 catch_varargs: bool, 

673 caller: bool, 

674 default_autoescape: t.Optional[bool] = None, 

675 ): 

676 self._environment = environment 

677 self._func = func 

678 self._argument_count = len(arguments) 

679 self.name = name 

680 self.arguments = arguments 

681 self.catch_kwargs = catch_kwargs 

682 self.catch_varargs = catch_varargs 

683 self.caller = caller 

684 self.explicit_caller = "caller" in arguments 

685 

686 if default_autoescape is None: 

687 if callable(environment.autoescape): 

688 default_autoescape = environment.autoescape(None) 

689 else: 

690 default_autoescape = environment.autoescape 

691 

692 self._default_autoescape = default_autoescape 

693 

694 @internalcode 

695 @pass_eval_context 

696 def __call__(self, *args: t.Any, **kwargs: t.Any) -> str: 

697 # This requires a bit of explanation, In the past we used to 

698 # decide largely based on compile-time information if a macro is 

699 # safe or unsafe. While there was a volatile mode it was largely 

700 # unused for deciding on escaping. This turns out to be 

701 # problematic for macros because whether a macro is safe depends not 

702 # on the escape mode when it was defined, but rather when it was used. 

703 # 

704 # Because however we export macros from the module system and 

705 # there are historic callers that do not pass an eval context (and 

706 # will continue to not pass one), we need to perform an instance 

707 # check here. 

708 # 

709 # This is considered safe because an eval context is not a valid 

710 # argument to callables otherwise anyway. Worst case here is 

711 # that if no eval context is passed we fall back to the compile 

712 # time autoescape flag. 

713 if args and isinstance(args[0], EvalContext): 

714 autoescape = args[0].autoescape 

715 args = args[1:] 

716 else: 

717 autoescape = self._default_autoescape 

718 

719 # try to consume the positional arguments 

720 arguments = list(args[: self._argument_count]) 

721 off = len(arguments) 

722 

723 # For information why this is necessary refer to the handling 

724 # of caller in the `macro_body` handler in the compiler. 

725 found_caller = False 

726 

727 # if the number of arguments consumed is not the number of 

728 # arguments expected we start filling in keyword arguments 

729 # and defaults. 

730 if off != self._argument_count: 

731 for name in self.arguments[len(arguments) :]: 

732 try: 

733 value = kwargs.pop(name) 

734 except KeyError: 

735 value = missing 

736 if name == "caller": 

737 found_caller = True 

738 arguments.append(value) 

739 else: 

740 found_caller = self.explicit_caller 

741 

742 # it's important that the order of these arguments does not change 

743 # if not also changed in the compiler's `function_scoping` method. 

744 # the order is caller, keyword arguments, positional arguments! 

745 if self.caller and not found_caller: 

746 caller = kwargs.pop("caller", None) 

747 if caller is None: 

748 caller = self._environment.undefined("No caller defined", name="caller") 

749 arguments.append(caller) 

750 

751 if self.catch_kwargs: 

752 arguments.append(kwargs) 

753 elif kwargs: 

754 if "caller" in kwargs: 

755 raise TypeError( 

756 f"macro {self.name!r} was invoked with two values for the special" 

757 " caller argument. This is most likely a bug." 

758 ) 

759 raise TypeError( 

760 f"macro {self.name!r} takes no keyword argument {next(iter(kwargs))!r}" 

761 ) 

762 if self.catch_varargs: 

763 arguments.append(args[self._argument_count :]) 

764 elif len(args) > self._argument_count: 

765 raise TypeError( 

766 f"macro {self.name!r} takes not more than" 

767 f" {len(self.arguments)} argument(s)" 

768 ) 

769 

770 return self._invoke(arguments, autoescape) 

771 

772 async def _async_invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str: 

773 rv = await self._func(*arguments) # type: ignore 

774 

775 if autoescape: 

776 return Markup(rv) 

777 

778 return rv # type: ignore 

779 

780 def _invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str: 

781 if self._environment.is_async: 

782 return self._async_invoke(arguments, autoescape) # type: ignore 

783 

784 rv = self._func(*arguments) 

785 

786 if autoescape: 

787 rv = Markup(rv) 

788 

789 return rv 

790 

791 def __repr__(self) -> str: 

792 name = "anonymous" if self.name is None else repr(self.name) 

793 return f"<{type(self).__name__} {name}>" 

794 

795 

796class Undefined: 

797 """The default undefined type. This can be printed, iterated, and treated as 

798 a boolean. Any other operation will raise an :exc:`UndefinedError`. 

799 

800 >>> foo = Undefined(name='foo') 

801 >>> str(foo) 

802 '' 

803 >>> not foo 

804 True 

805 >>> foo + 42 

806 Traceback (most recent call last): 

807 ... 

808 jinja2.exceptions.UndefinedError: 'foo' is undefined 

809 """ 

810 

811 __slots__ = ( 

812 "_undefined_hint", 

813 "_undefined_obj", 

814 "_undefined_name", 

815 "_undefined_exception", 

816 ) 

817 

818 def __init__( 

819 self, 

820 hint: t.Optional[str] = None, 

821 obj: t.Any = missing, 

822 name: t.Optional[str] = None, 

823 exc: t.Type[TemplateRuntimeError] = UndefinedError, 

824 ) -> None: 

825 self._undefined_hint = hint 

826 self._undefined_obj = obj 

827 self._undefined_name = name 

828 self._undefined_exception = exc 

829 

830 @property 

831 def _undefined_message(self) -> str: 

832 """Build a message about the undefined value based on how it was 

833 accessed. 

834 """ 

835 if self._undefined_hint: 

836 return self._undefined_hint 

837 

838 if self._undefined_obj is missing: 

839 return f"{self._undefined_name!r} is undefined" 

840 

841 if not isinstance(self._undefined_name, str): 

842 return ( 

843 f"{object_type_repr(self._undefined_obj)} has no" 

844 f" element {self._undefined_name!r}" 

845 ) 

846 

847 return ( 

848 f"{object_type_repr(self._undefined_obj)!r} has no" 

849 f" attribute {self._undefined_name!r}" 

850 ) 

851 

852 @internalcode 

853 def _fail_with_undefined_error( 

854 self, *args: t.Any, **kwargs: t.Any 

855 ) -> "te.NoReturn": 

856 """Raise an :exc:`UndefinedError` when operations are performed 

857 on the undefined value. 

858 """ 

859 raise self._undefined_exception(self._undefined_message) 

860 

861 @internalcode 

862 def __getattr__(self, name: str) -> t.Any: 

863 # Raise AttributeError on requests for names that appear to be unimplemented 

864 # dunder methods to keep Python's internal protocol probing behaviors working 

865 # properly in cases where another exception type could cause unexpected or 

866 # difficult-to-diagnose failures. 

867 if name[:2] == "__" and name[-2:] == "__": 

868 raise AttributeError(name) 

869 

870 return self._fail_with_undefined_error() 

871 

872 __add__ = __radd__ = __sub__ = __rsub__ = _fail_with_undefined_error 

873 __mul__ = __rmul__ = __div__ = __rdiv__ = _fail_with_undefined_error 

874 __truediv__ = __rtruediv__ = _fail_with_undefined_error 

875 __floordiv__ = __rfloordiv__ = _fail_with_undefined_error 

876 __mod__ = __rmod__ = _fail_with_undefined_error 

877 __pos__ = __neg__ = _fail_with_undefined_error 

878 __call__ = __getitem__ = _fail_with_undefined_error 

879 __lt__ = __le__ = __gt__ = __ge__ = _fail_with_undefined_error 

880 __int__ = __float__ = __complex__ = _fail_with_undefined_error 

881 __pow__ = __rpow__ = _fail_with_undefined_error 

882 

883 def __eq__(self, other: t.Any) -> bool: 

884 return type(self) is type(other) 

885 

886 def __ne__(self, other: t.Any) -> bool: 

887 return not self.__eq__(other) 

888 

889 def __hash__(self) -> int: 

890 return id(type(self)) 

891 

892 def __str__(self) -> str: 

893 return "" 

894 

895 def __len__(self) -> int: 

896 return 0 

897 

898 def __iter__(self) -> t.Iterator[t.Any]: 

899 yield from () 

900 

901 async def __aiter__(self) -> t.AsyncIterator[t.Any]: 

902 for _ in (): 

903 yield 

904 

905 def __bool__(self) -> bool: 

906 return False 

907 

908 def __repr__(self) -> str: 

909 return "Undefined" 

910 

911 

912def make_logging_undefined( 

913 logger: t.Optional["logging.Logger"] = None, base: t.Type[Undefined] = Undefined 

914) -> t.Type[Undefined]: 

915 """Given a logger object this returns a new undefined class that will 

916 log certain failures. It will log iterations and printing. If no 

917 logger is given a default logger is created. 

918 

919 Example:: 

920 

921 logger = logging.getLogger(__name__) 

922 LoggingUndefined = make_logging_undefined( 

923 logger=logger, 

924 base=Undefined 

925 ) 

926 

927 .. versionadded:: 2.8 

928 

929 :param logger: the logger to use. If not provided, a default logger 

930 is created. 

931 :param base: the base class to add logging functionality to. This 

932 defaults to :class:`Undefined`. 

933 """ 

934 if logger is None: 

935 import logging 

936 

937 logger = logging.getLogger(__name__) 

938 logger.addHandler(logging.StreamHandler(sys.stderr)) 

939 

940 def _log_message(undef: Undefined) -> None: 

941 logger.warning("Template variable warning: %s", undef._undefined_message) 

942 

943 class LoggingUndefined(base): # type: ignore 

944 __slots__ = () 

945 

946 def _fail_with_undefined_error( # type: ignore 

947 self, *args: t.Any, **kwargs: t.Any 

948 ) -> "te.NoReturn": 

949 try: 

950 super()._fail_with_undefined_error(*args, **kwargs) 

951 except self._undefined_exception as e: 

952 logger.error("Template variable error: %s", e) # type: ignore 

953 raise e 

954 

955 def __str__(self) -> str: 

956 _log_message(self) 

957 return super().__str__() # type: ignore 

958 

959 def __iter__(self) -> t.Iterator[t.Any]: 

960 _log_message(self) 

961 return super().__iter__() # type: ignore 

962 

963 def __bool__(self) -> bool: 

964 _log_message(self) 

965 return super().__bool__() # type: ignore 

966 

967 return LoggingUndefined 

968 

969 

970class ChainableUndefined(Undefined): 

971 """An undefined that is chainable, where both ``__getattr__`` and 

972 ``__getitem__`` return itself rather than raising an 

973 :exc:`UndefinedError`. 

974 

975 >>> foo = ChainableUndefined(name='foo') 

976 >>> str(foo.bar['baz']) 

977 '' 

978 >>> foo.bar['baz'] + 42 

979 Traceback (most recent call last): 

980 ... 

981 jinja2.exceptions.UndefinedError: 'foo' is undefined 

982 

983 .. versionadded:: 2.11.0 

984 """ 

985 

986 __slots__ = () 

987 

988 def __html__(self) -> str: 

989 return str(self) 

990 

991 def __getattr__(self, name: str) -> "ChainableUndefined": 

992 # Raise AttributeError on requests for names that appear to be unimplemented 

993 # dunder methods to avoid confusing Python with truthy non-method objects that 

994 # do not implement the protocol being probed for. e.g., copy.copy(Undefined()) 

995 # fails spectacularly if getattr(Undefined(), '__setstate__') returns an 

996 # Undefined object instead of raising AttributeError to signal that it does not 

997 # support that style of object initialization. 

998 if name[:2] == "__" and name[-2:] == "__": 

999 raise AttributeError(name) 

1000 

1001 return self 

1002 

1003 def __getitem__(self, _name: str) -> "ChainableUndefined": # type: ignore[override] 

1004 return self 

1005 

1006 

1007class DebugUndefined(Undefined): 

1008 """An undefined that returns the debug info when printed. 

1009 

1010 >>> foo = DebugUndefined(name='foo') 

1011 >>> str(foo) 

1012 '{{ foo }}' 

1013 >>> not foo 

1014 True 

1015 >>> foo + 42 

1016 Traceback (most recent call last): 

1017 ... 

1018 jinja2.exceptions.UndefinedError: 'foo' is undefined 

1019 """ 

1020 

1021 __slots__ = () 

1022 

1023 def __str__(self) -> str: 

1024 if self._undefined_hint: 

1025 message = f"undefined value printed: {self._undefined_hint}" 

1026 

1027 elif self._undefined_obj is missing: 

1028 message = self._undefined_name # type: ignore 

1029 

1030 else: 

1031 message = ( 

1032 f"no such element: {object_type_repr(self._undefined_obj)}" 

1033 f"[{self._undefined_name!r}]" 

1034 ) 

1035 

1036 return f"{{{{ {message} }}}}" 

1037 

1038 

1039class StrictUndefined(Undefined): 

1040 """An undefined that barks on print and iteration as well as boolean 

1041 tests and all kinds of comparisons. In other words: you can do nothing 

1042 with it except checking if it's defined using the `defined` test. 

1043 

1044 >>> foo = StrictUndefined(name='foo') 

1045 >>> str(foo) 

1046 Traceback (most recent call last): 

1047 ... 

1048 jinja2.exceptions.UndefinedError: 'foo' is undefined 

1049 >>> not foo 

1050 Traceback (most recent call last): 

1051 ... 

1052 jinja2.exceptions.UndefinedError: 'foo' is undefined 

1053 >>> foo + 42 

1054 Traceback (most recent call last): 

1055 ... 

1056 jinja2.exceptions.UndefinedError: 'foo' is undefined 

1057 """ 

1058 

1059 __slots__ = () 

1060 __iter__ = __str__ = __len__ = Undefined._fail_with_undefined_error 

1061 __eq__ = __ne__ = __bool__ = __hash__ = Undefined._fail_with_undefined_error 

1062 __contains__ = Undefined._fail_with_undefined_error