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

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

556 statements  

1"""AST nodes generated by the parser for the compiler. Also provides 

2some node tree helper functions used by the parser and compiler in order 

3to normalize nodes. 

4""" 

5 

6import inspect 

7import operator 

8import typing as t 

9from collections import deque 

10 

11from markupsafe import Markup 

12 

13from .utils import _PassArg 

14 

15if t.TYPE_CHECKING: 

16 import typing_extensions as te 

17 

18 from .environment import Environment 

19 

20_NodeBound = t.TypeVar("_NodeBound", bound="Node") 

21 

22_binop_to_func: dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { 

23 "*": operator.mul, 

24 "/": operator.truediv, 

25 "//": operator.floordiv, 

26 "**": operator.pow, 

27 "%": operator.mod, 

28 "+": operator.add, 

29 "-": operator.sub, 

30} 

31 

32_uaop_to_func: dict[str, t.Callable[[t.Any], t.Any]] = { 

33 "not": operator.not_, 

34 "+": operator.pos, 

35 "-": operator.neg, 

36} 

37 

38_cmpop_to_func: dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { 

39 "eq": operator.eq, 

40 "ne": operator.ne, 

41 "gt": operator.gt, 

42 "gteq": operator.ge, 

43 "lt": operator.lt, 

44 "lteq": operator.le, 

45 "in": lambda a, b: a in b, 

46 "notin": lambda a, b: a not in b, 

47} 

48 

49 

50class Impossible(Exception): 

51 """Raised if the node could not perform a requested action.""" 

52 

53 

54class NodeType(type): 

55 """A metaclass for nodes that handles the field and attribute 

56 inheritance. fields and attributes from the parent class are 

57 automatically forwarded to the child.""" 

58 

59 def __new__(mcs, name, bases, d): # type: ignore 

60 for attr in "fields", "attributes": 

61 storage: list[tuple[str, ...]] = [] 

62 storage.extend(getattr(bases[0] if bases else object, attr, ())) 

63 storage.extend(d.get(attr, ())) 

64 assert len(bases) <= 1, "multiple inheritance not allowed" 

65 assert len(storage) == len(set(storage)), "layout conflict" 

66 d[attr] = tuple(storage) 

67 d.setdefault("abstract", False) 

68 return type.__new__(mcs, name, bases, d) 

69 

70 

71class EvalContext: 

72 """Holds evaluation time information. Custom attributes can be attached 

73 to it in extensions. 

74 """ 

75 

76 def __init__( 

77 self, environment: "Environment", template_name: str | None = None 

78 ) -> None: 

79 self.environment = environment 

80 if callable(environment.autoescape): 

81 self.autoescape = environment.autoescape(template_name) 

82 else: 

83 self.autoescape = environment.autoescape 

84 self.volatile = False 

85 

86 def save(self) -> t.Mapping[str, t.Any]: 

87 return self.__dict__.copy() 

88 

89 def revert(self, old: t.Mapping[str, t.Any]) -> None: 

90 self.__dict__.clear() 

91 self.__dict__.update(old) 

92 

93 

94def get_eval_context(node: "Node", ctx: EvalContext | None) -> EvalContext: 

95 if ctx is None: 

96 if node.environment is None: 

97 raise RuntimeError( 

98 "if no eval context is passed, the node must have an" 

99 " attached environment." 

100 ) 

101 return EvalContext(node.environment) 

102 return ctx 

103 

104 

105class Node(metaclass=NodeType): 

106 """Baseclass for all Jinja nodes. There are a number of nodes available 

107 of different types. There are four major types: 

108 

109 - :class:`Stmt`: statements 

110 - :class:`Expr`: expressions 

111 - :class:`Helper`: helper nodes 

112 - :class:`Template`: the outermost wrapper node 

113 

114 All nodes have fields and attributes. Fields may be other nodes, lists, 

115 or arbitrary values. Fields are passed to the constructor as regular 

116 positional arguments, attributes as keyword arguments. Each node has 

117 two attributes: `lineno` (the line number of the node) and `environment`. 

118 The `environment` attribute is set at the end of the parsing process for 

119 all nodes automatically. 

120 """ 

121 

122 fields: tuple[str, ...] = () 

123 attributes: tuple[str, ...] = ("lineno", "environment") 

124 abstract = True 

125 

126 lineno: int 

127 environment: t.Optional["Environment"] 

128 

129 def __init__(self, *fields: t.Any, **attributes: t.Any) -> None: 

130 if self.abstract: 

131 raise TypeError("abstract nodes are not instantiable") 

132 if fields: 

133 if len(fields) != len(self.fields): 

134 if not self.fields: 

135 raise TypeError(f"{type(self).__name__!r} takes 0 arguments") 

136 raise TypeError( 

137 f"{type(self).__name__!r} takes 0 or {len(self.fields)}" 

138 f" argument{'s' if len(self.fields) != 1 else ''}" 

139 ) 

140 for name, arg in zip(self.fields, fields, strict=False): 

141 setattr(self, name, arg) 

142 for attr in self.attributes: 

143 setattr(self, attr, attributes.pop(attr, None)) 

144 if attributes: 

145 raise TypeError(f"unknown attribute {next(iter(attributes))!r}") 

146 

147 def iter_fields( 

148 self, 

149 exclude: t.Container[str] | None = None, 

150 only: t.Container[str] | None = None, 

151 ) -> t.Iterator[tuple[str, t.Any]]: 

152 """This method iterates over all fields that are defined and yields 

153 ``(key, value)`` tuples. Per default all fields are returned, but 

154 it's possible to limit that to some fields by providing the `only` 

155 parameter or to exclude some using the `exclude` parameter. Both 

156 should be sets or tuples of field names. 

157 """ 

158 for name in self.fields: 

159 if ( 

160 (exclude is None and only is None) 

161 or (exclude is not None and name not in exclude) 

162 or (only is not None and name in only) 

163 ): 

164 try: 

165 yield name, getattr(self, name) 

166 except AttributeError: 

167 pass 

168 

169 def iter_child_nodes( 

170 self, 

171 exclude: t.Container[str] | None = None, 

172 only: t.Container[str] | None = None, 

173 ) -> t.Iterator["Node"]: 

174 """Iterates over all direct child nodes of the node. This iterates 

175 over all fields and yields the values of they are nodes. If the value 

176 of a field is a list all the nodes in that list are returned. 

177 """ 

178 for _, item in self.iter_fields(exclude, only): 

179 if isinstance(item, list): 

180 for n in item: 

181 if isinstance(n, Node): 

182 yield n 

183 elif isinstance(item, Node): 

184 yield item 

185 

186 def find(self, node_type: type[_NodeBound]) -> _NodeBound | None: 

187 """Find the first node of a given type. If no such node exists the 

188 return value is `None`. 

189 """ 

190 for result in self.find_all(node_type): 

191 return result 

192 

193 return None 

194 

195 def find_all( 

196 self, node_type: type[_NodeBound] | tuple[type[_NodeBound], ...] 

197 ) -> t.Iterator[_NodeBound]: 

198 """Find all the nodes of a given type. If the type is a tuple, 

199 the check is performed for any of the tuple items. 

200 """ 

201 for child in self.iter_child_nodes(): 

202 if isinstance(child, node_type): 

203 yield child # type: ignore 

204 yield from child.find_all(node_type) 

205 

206 def set_ctx(self, ctx: str) -> "Node": 

207 """Reset the context of a node and all child nodes. Per default the 

208 parser will all generate nodes that have a 'load' context as it's the 

209 most common one. This method is used in the parser to set assignment 

210 targets and other nodes to a store context. 

211 """ 

212 todo = deque([self]) 

213 while todo: 

214 node = todo.popleft() 

215 if "ctx" in node.fields: 

216 node.ctx = ctx # type: ignore 

217 todo.extend(node.iter_child_nodes()) 

218 return self 

219 

220 def set_lineno(self, lineno: int, override: bool = False) -> "Node": 

221 """Set the line numbers of the node and children.""" 

222 todo = deque([self]) 

223 while todo: 

224 node = todo.popleft() 

225 if "lineno" in node.attributes: 

226 if node.lineno is None or override: 

227 node.lineno = lineno 

228 todo.extend(node.iter_child_nodes()) 

229 return self 

230 

231 def set_environment(self, environment: "Environment") -> "Node": 

232 """Set the environment for all nodes.""" 

233 todo = deque([self]) 

234 while todo: 

235 node = todo.popleft() 

236 node.environment = environment 

237 todo.extend(node.iter_child_nodes()) 

238 return self 

239 

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

241 if type(self) is not type(other): 

242 return NotImplemented 

243 

244 return tuple(self.iter_fields()) == tuple(other.iter_fields()) 

245 

246 __hash__ = object.__hash__ 

247 

248 def __repr__(self) -> str: 

249 args_str = ", ".join(f"{a}={getattr(self, a, None)!r}" for a in self.fields) 

250 return f"{type(self).__name__}({args_str})" 

251 

252 def dump(self) -> str: 

253 def _dump(node: Node | t.Any) -> None: 

254 if not isinstance(node, Node): 

255 buf.append(repr(node)) 

256 return 

257 

258 buf.append(f"nodes.{type(node).__name__}(") 

259 if not node.fields: 

260 buf.append(")") 

261 return 

262 for idx, field in enumerate(node.fields): 

263 if idx: 

264 buf.append(", ") 

265 value = getattr(node, field) 

266 if isinstance(value, list): 

267 buf.append("[") 

268 for idx, item in enumerate(value): 

269 if idx: 

270 buf.append(", ") 

271 _dump(item) 

272 buf.append("]") 

273 else: 

274 _dump(value) 

275 buf.append(")") 

276 

277 buf: list[str] = [] 

278 _dump(self) 

279 return "".join(buf) 

280 

281 

282class Stmt(Node): 

283 """Base node for all statements.""" 

284 

285 abstract = True 

286 

287 

288class Helper(Node): 

289 """Nodes that exist in a specific context only.""" 

290 

291 abstract = True 

292 

293 

294class Template(Node): 

295 """Node that represents a template. This must be the outermost node that 

296 is passed to the compiler. 

297 """ 

298 

299 fields = ("body",) 

300 body: list[Node] 

301 

302 

303class Output(Stmt): 

304 """A node that holds multiple expressions which are then printed out. 

305 This is used both for the `print` statement and the regular template data. 

306 """ 

307 

308 fields = ("nodes",) 

309 nodes: list["Expr"] 

310 

311 

312class Extends(Stmt): 

313 """Represents an extends statement.""" 

314 

315 fields = ("template",) 

316 template: "Expr" 

317 

318 

319class For(Stmt): 

320 """The for loop. `target` is the target for the iteration (usually a 

321 :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list 

322 of nodes that are used as loop-body, and `else_` a list of nodes for the 

323 `else` block. If no else node exists it has to be an empty list. 

324 

325 For filtered nodes an expression can be stored as `test`, otherwise `None`. 

326 """ 

327 

328 fields = ("target", "iter", "body", "else_", "test", "recursive") 

329 target: Node 

330 iter: Node 

331 body: list[Node] 

332 else_: list[Node] 

333 test: Node | None 

334 recursive: bool 

335 

336 

337class If(Stmt): 

338 """If `test` is true, `body` is rendered, else `else_`.""" 

339 

340 fields = ("test", "body", "elif_", "else_") 

341 test: Node 

342 body: list[Node] 

343 elif_: list["If"] 

344 else_: list[Node] 

345 

346 

347class Macro(Stmt): 

348 """A macro definition. `name` is the name of the macro, `args` a list of 

349 arguments and `defaults` a list of defaults if there are any. `body` is 

350 a list of nodes for the macro body. 

351 """ 

352 

353 fields = ("name", "args", "defaults", "body") 

354 name: str 

355 args: list["Name"] 

356 defaults: list["Expr"] 

357 body: list[Node] 

358 

359 

360class CallBlock(Stmt): 

361 """Like a macro without a name but a call instead. `call` is called with 

362 the unnamed macro as `caller` argument this node holds. 

363 """ 

364 

365 fields = ("call", "args", "defaults", "body") 

366 call: "Call" 

367 args: list["Name"] 

368 defaults: list["Expr"] 

369 body: list[Node] 

370 

371 

372class FilterBlock(Stmt): 

373 """Node for filter sections.""" 

374 

375 fields = ("body", "filter") 

376 body: list[Node] 

377 filter: "Filter" 

378 

379 

380class With(Stmt): 

381 """Specific node for with statements. In older versions of Jinja the 

382 with statement was implemented on the base of the `Scope` node instead. 

383 

384 .. versionadded:: 2.9.3 

385 """ 

386 

387 fields = ("targets", "values", "body") 

388 targets: list["Expr"] 

389 values: list["Expr"] 

390 body: list[Node] 

391 

392 

393class Block(Stmt): 

394 """A node that represents a block. 

395 

396 .. versionchanged:: 3.0.0 

397 the `required` field was added. 

398 """ 

399 

400 fields = ("name", "body", "scoped", "required") 

401 name: str 

402 body: list[Node] 

403 scoped: bool 

404 required: bool 

405 

406 

407class Include(Stmt): 

408 """A node that represents the include tag.""" 

409 

410 fields = ("template", "with_context", "ignore_missing") 

411 template: "Expr" 

412 with_context: bool 

413 ignore_missing: bool 

414 

415 

416class Import(Stmt): 

417 """A node that represents the import tag.""" 

418 

419 fields = ("template", "target", "with_context") 

420 template: "Expr" 

421 target: str 

422 with_context: bool 

423 

424 

425class FromImport(Stmt): 

426 """A node that represents the from import tag. It's important to not 

427 pass unsafe names to the name attribute. The compiler translates the 

428 attribute lookups directly into getattr calls and does *not* use the 

429 subscript callback of the interface. As exported variables may not 

430 start with double underscores (which the parser asserts) this is not a 

431 problem for regular Jinja code, but if this node is used in an extension 

432 extra care must be taken. 

433 

434 The list of names may contain tuples if aliases are wanted. 

435 """ 

436 

437 fields = ("template", "names", "with_context") 

438 template: "Expr" 

439 names: list[str | tuple[str, str]] 

440 with_context: bool 

441 

442 

443class ExprStmt(Stmt): 

444 """A statement that evaluates an expression and discards the result.""" 

445 

446 fields = ("node",) 

447 node: Node 

448 

449 

450class Assign(Stmt): 

451 """Assigns an expression to a target.""" 

452 

453 fields = ("target", "node") 

454 target: "Expr" 

455 node: Node 

456 

457 

458class AssignBlock(Stmt): 

459 """Assigns a block to a target.""" 

460 

461 fields = ("target", "filter", "body") 

462 target: "Expr" 

463 filter: t.Optional["Filter"] 

464 body: list[Node] 

465 

466 

467class Expr(Node): 

468 """Baseclass for all expressions.""" 

469 

470 abstract = True 

471 

472 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

473 """Return the value of the expression as constant or raise 

474 :exc:`Impossible` if this was not possible. 

475 

476 An :class:`EvalContext` can be provided, if none is given 

477 a default context is created which requires the nodes to have 

478 an attached environment. 

479 

480 .. versionchanged:: 2.4 

481 the `eval_ctx` parameter was added. 

482 """ 

483 raise Impossible() 

484 

485 def can_assign(self) -> bool: 

486 """Check if it's possible to assign something to this node.""" 

487 return False 

488 

489 

490class BinExpr(Expr): 

491 """Baseclass for all binary expressions.""" 

492 

493 fields = ("left", "right") 

494 left: Expr 

495 right: Expr 

496 operator: str 

497 abstract = True 

498 

499 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

500 eval_ctx = get_eval_context(self, eval_ctx) 

501 

502 # intercepted operators cannot be folded at compile time 

503 if ( 

504 eval_ctx.environment.sandboxed 

505 and self.operator in eval_ctx.environment.intercepted_binops # type: ignore 

506 ): 

507 raise Impossible() 

508 f = _binop_to_func[self.operator] 

509 try: 

510 return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) 

511 except Exception as e: 

512 raise Impossible() from e 

513 

514 

515class UnaryExpr(Expr): 

516 """Baseclass for all unary expressions.""" 

517 

518 fields = ("node",) 

519 node: Expr 

520 operator: str 

521 abstract = True 

522 

523 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

524 eval_ctx = get_eval_context(self, eval_ctx) 

525 

526 # intercepted operators cannot be folded at compile time 

527 if ( 

528 eval_ctx.environment.sandboxed 

529 and self.operator in eval_ctx.environment.intercepted_unops # type: ignore 

530 ): 

531 raise Impossible() 

532 f = _uaop_to_func[self.operator] 

533 try: 

534 return f(self.node.as_const(eval_ctx)) 

535 except Exception as e: 

536 raise Impossible() from e 

537 

538 

539class Name(Expr): 

540 """Looks up a name or stores a value in a name. 

541 The `ctx` of the node can be one of the following values: 

542 

543 - `store`: store a value in the name 

544 - `load`: load that name 

545 - `param`: like `store` but if the name was defined as function parameter. 

546 """ 

547 

548 fields = ("name", "ctx") 

549 name: str 

550 ctx: str 

551 

552 def can_assign(self) -> bool: 

553 return self.name not in {"true", "false", "none", "True", "False", "None"} 

554 

555 

556class NSRef(Expr): 

557 """Reference to a namespace value assignment""" 

558 

559 fields = ("name", "attr") 

560 name: str 

561 attr: str 

562 

563 def can_assign(self) -> bool: 

564 # We don't need any special checks here; NSRef assignments have a 

565 # runtime check to ensure the target is a namespace object which will 

566 # have been checked already as it is created using a normal assignment 

567 # which goes through a `Name` node. 

568 return True 

569 

570 

571class Literal(Expr): 

572 """Baseclass for literals.""" 

573 

574 abstract = True 

575 

576 

577class Const(Literal): 

578 """All constant values. The parser will return this node for simple 

579 constants such as ``42`` or ``"foo"`` but it can be used to store more 

580 complex values such as lists too. Only constants with a safe 

581 representation (objects where ``eval(repr(x)) == x`` is true). 

582 """ 

583 

584 fields = ("value",) 

585 value: t.Any 

586 

587 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

588 return self.value 

589 

590 @classmethod 

591 def from_untrusted( 

592 cls, 

593 value: t.Any, 

594 lineno: int | None = None, 

595 environment: "Environment | None" = None, 

596 ) -> "Const": 

597 """Return a const object if the value is representable as 

598 constant value in the generated code, otherwise it will raise 

599 an `Impossible` exception. 

600 """ 

601 from .compiler import has_safe_repr 

602 

603 if not has_safe_repr(value): 

604 raise Impossible() 

605 return cls(value, lineno=lineno, environment=environment) 

606 

607 

608class TemplateData(Literal): 

609 """A constant template string.""" 

610 

611 fields = ("data",) 

612 data: str 

613 

614 def as_const(self, eval_ctx: EvalContext | None = None) -> str: 

615 eval_ctx = get_eval_context(self, eval_ctx) 

616 if eval_ctx.volatile: 

617 raise Impossible() 

618 if eval_ctx.autoescape: 

619 return Markup(self.data) 

620 return self.data 

621 

622 

623class Tuple(Literal): 

624 """For loop unpacking and some other things like multiple arguments 

625 for subscripts. Like for :class:`Name` `ctx` specifies if the tuple 

626 is used for loading the names or storing. 

627 """ 

628 

629 fields = ("items", "ctx") 

630 items: list[Expr] 

631 ctx: str 

632 

633 def as_const(self, eval_ctx: EvalContext | None = None) -> tuple[t.Any, ...]: 

634 eval_ctx = get_eval_context(self, eval_ctx) 

635 return tuple(x.as_const(eval_ctx) for x in self.items) 

636 

637 def can_assign(self) -> bool: 

638 for item in self.items: 

639 if not item.can_assign(): 

640 return False 

641 return True 

642 

643 

644class List(Literal): 

645 """Any list literal such as ``[1, 2, 3]``""" 

646 

647 fields = ("items",) 

648 items: list[Expr] 

649 

650 def as_const(self, eval_ctx: EvalContext | None = None) -> list[t.Any]: 

651 eval_ctx = get_eval_context(self, eval_ctx) 

652 return [x.as_const(eval_ctx) for x in self.items] 

653 

654 

655class Dict(Literal): 

656 """Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of 

657 :class:`Pair` nodes. 

658 """ 

659 

660 fields = ("items",) 

661 items: list["Pair"] 

662 

663 def as_const(self, eval_ctx: EvalContext | None = None) -> dict[t.Any, t.Any]: 

664 eval_ctx = get_eval_context(self, eval_ctx) 

665 return dict(x.as_const(eval_ctx) for x in self.items) 

666 

667 

668class Pair(Helper): 

669 """A key, value pair for dicts.""" 

670 

671 fields = ("key", "value") 

672 key: Expr 

673 value: Expr 

674 

675 def as_const(self, eval_ctx: EvalContext | None = None) -> tuple[t.Any, t.Any]: 

676 eval_ctx = get_eval_context(self, eval_ctx) 

677 return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx) 

678 

679 

680class Keyword(Helper): 

681 """A key, value pair for keyword arguments where key is a string.""" 

682 

683 fields = ("key", "value") 

684 key: str 

685 value: Expr 

686 

687 def as_const(self, eval_ctx: EvalContext | None = None) -> tuple[str, t.Any]: 

688 eval_ctx = get_eval_context(self, eval_ctx) 

689 return self.key, self.value.as_const(eval_ctx) 

690 

691 

692class CondExpr(Expr): 

693 """A conditional expression (inline if expression). (``{{ 

694 foo if bar else baz }}``) 

695 """ 

696 

697 fields = ("test", "expr1", "expr2") 

698 test: Expr 

699 expr1: Expr 

700 expr2: Expr | None 

701 

702 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

703 eval_ctx = get_eval_context(self, eval_ctx) 

704 if self.test.as_const(eval_ctx): 

705 return self.expr1.as_const(eval_ctx) 

706 

707 # if we evaluate to an undefined object, we better do that at runtime 

708 if self.expr2 is None: 

709 raise Impossible() 

710 

711 return self.expr2.as_const(eval_ctx) 

712 

713 

714def args_as_const( 

715 node: t.Union["_FilterTestCommon", "Call"], eval_ctx: EvalContext | None 

716) -> tuple[list[t.Any], dict[t.Any, t.Any]]: 

717 args = [x.as_const(eval_ctx) for x in node.args] 

718 kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs) 

719 

720 if node.dyn_args is not None: 

721 try: 

722 args.extend(node.dyn_args.as_const(eval_ctx)) 

723 except Exception as e: 

724 raise Impossible() from e 

725 

726 if node.dyn_kwargs is not None: 

727 try: 

728 kwargs.update(node.dyn_kwargs.as_const(eval_ctx)) 

729 except Exception as e: 

730 raise Impossible() from e 

731 

732 return args, kwargs 

733 

734 

735class _FilterTestCommon(Expr): 

736 fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") 

737 node: Expr 

738 name: str 

739 args: list[Expr] 

740 kwargs: list[Pair] 

741 dyn_args: Expr | None 

742 dyn_kwargs: Expr | None 

743 abstract = True 

744 _is_filter = True 

745 

746 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

747 eval_ctx = get_eval_context(self, eval_ctx) 

748 

749 if eval_ctx.volatile: 

750 raise Impossible() 

751 

752 if self._is_filter: 

753 env_map = eval_ctx.environment.filters 

754 else: 

755 env_map = eval_ctx.environment.tests 

756 

757 func = env_map.get(self.name) 

758 pass_arg = _PassArg.from_obj(func) # type: ignore 

759 

760 if func is None or pass_arg is _PassArg.context: 

761 raise Impossible() 

762 

763 if eval_ctx.environment.is_async and ( 

764 getattr(func, "jinja_async_variant", False) is True 

765 or inspect.iscoroutinefunction(func) 

766 ): 

767 raise Impossible() 

768 

769 args, kwargs = args_as_const(self, eval_ctx) 

770 args.insert(0, self.node.as_const(eval_ctx)) 

771 

772 if pass_arg is _PassArg.eval_context: 

773 args.insert(0, eval_ctx) 

774 elif pass_arg is _PassArg.environment: 

775 args.insert(0, eval_ctx.environment) 

776 

777 try: 

778 return func(*args, **kwargs) 

779 except Exception as e: 

780 raise Impossible() from e 

781 

782 

783class Filter(_FilterTestCommon): 

784 """Apply a filter to an expression. ``name`` is the name of the 

785 filter, the other fields are the same as :class:`Call`. 

786 

787 If ``node`` is ``None``, the filter is being used in a filter block 

788 and is applied to the content of the block. 

789 """ 

790 

791 node: Expr | None # type: ignore 

792 

793 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

794 if self.node is None: 

795 raise Impossible() 

796 

797 return super().as_const(eval_ctx=eval_ctx) 

798 

799 

800class Test(_FilterTestCommon): 

801 """Apply a test to an expression. ``name`` is the name of the test, 

802 the other field are the same as :class:`Call`. 

803 

804 .. versionchanged:: 3.0 

805 ``as_const`` shares the same logic for filters and tests. Tests 

806 check for volatile, async, and ``@pass_context`` etc. 

807 decorators. 

808 """ 

809 

810 _is_filter = False 

811 

812 

813class Call(Expr): 

814 """Calls an expression. `args` is a list of arguments, `kwargs` a list 

815 of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args` 

816 and `dyn_kwargs` has to be either `None` or a node that is used as 

817 node for dynamic positional (``*args``) or keyword (``**kwargs``) 

818 arguments. 

819 """ 

820 

821 fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") 

822 node: Expr 

823 args: list[Expr] 

824 kwargs: list[Keyword] 

825 dyn_args: Expr | None 

826 dyn_kwargs: Expr | None 

827 

828 

829class Getitem(Expr): 

830 """Get an attribute or item from an expression and prefer the item.""" 

831 

832 fields = ("node", "arg", "ctx") 

833 node: Expr 

834 arg: Expr 

835 ctx: str 

836 

837 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

838 if self.ctx != "load": 

839 raise Impossible() 

840 

841 eval_ctx = get_eval_context(self, eval_ctx) 

842 

843 try: 

844 return eval_ctx.environment.getitem( 

845 self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) 

846 ) 

847 except Exception as e: 

848 raise Impossible() from e 

849 

850 

851class Getattr(Expr): 

852 """Get an attribute or item from an expression that is a ascii-only 

853 bytestring and prefer the attribute. 

854 """ 

855 

856 fields = ("node", "attr", "ctx") 

857 node: Expr 

858 attr: str 

859 ctx: str 

860 

861 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

862 if self.ctx != "load": 

863 raise Impossible() 

864 

865 eval_ctx = get_eval_context(self, eval_ctx) 

866 

867 try: 

868 return eval_ctx.environment.getattr(self.node.as_const(eval_ctx), self.attr) 

869 except Exception as e: 

870 raise Impossible() from e 

871 

872 

873class Slice(Expr): 

874 """Represents a slice object. This must only be used as argument for 

875 :class:`Subscript`. 

876 """ 

877 

878 fields = ("start", "stop", "step") 

879 start: Expr | None 

880 stop: Expr | None 

881 step: Expr | None 

882 

883 def as_const(self, eval_ctx: EvalContext | None = None) -> slice: 

884 eval_ctx = get_eval_context(self, eval_ctx) 

885 

886 def const(obj: Expr | None) -> t.Any | None: 

887 if obj is None: 

888 return None 

889 return obj.as_const(eval_ctx) 

890 

891 return slice(const(self.start), const(self.stop), const(self.step)) 

892 

893 

894class Concat(Expr): 

895 """Concatenates the list of expressions provided after converting 

896 them to strings. 

897 """ 

898 

899 fields = ("nodes",) 

900 nodes: list[Expr] 

901 

902 def as_const(self, eval_ctx: EvalContext | None = None) -> str: 

903 eval_ctx = get_eval_context(self, eval_ctx) 

904 return "".join(str(x.as_const(eval_ctx)) for x in self.nodes) 

905 

906 

907class Compare(Expr): 

908 """Compares an expression with some other expressions. `ops` must be a 

909 list of :class:`Operand`\\s. 

910 """ 

911 

912 fields = ("expr", "ops") 

913 expr: Expr 

914 ops: list["Operand"] 

915 

916 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

917 eval_ctx = get_eval_context(self, eval_ctx) 

918 result = value = self.expr.as_const(eval_ctx) 

919 

920 try: 

921 for op in self.ops: 

922 new_value = op.expr.as_const(eval_ctx) 

923 result = _cmpop_to_func[op.op](value, new_value) 

924 

925 if not result: 

926 return False 

927 

928 value = new_value 

929 except Exception as e: 

930 raise Impossible() from e 

931 

932 return result 

933 

934 

935class Operand(Helper): 

936 """Holds an operator and an expression.""" 

937 

938 fields = ("op", "expr") 

939 op: str 

940 expr: Expr 

941 

942 

943class Mul(BinExpr): 

944 """Multiplies the left with the right node.""" 

945 

946 operator = "*" 

947 

948 

949class Div(BinExpr): 

950 """Divides the left by the right node.""" 

951 

952 operator = "/" 

953 

954 

955class FloorDiv(BinExpr): 

956 """Divides the left by the right node and converts the 

957 result into an integer by truncating. 

958 """ 

959 

960 operator = "//" 

961 

962 

963class Add(BinExpr): 

964 """Add the left to the right node.""" 

965 

966 operator = "+" 

967 

968 

969class Sub(BinExpr): 

970 """Subtract the right from the left node.""" 

971 

972 operator = "-" 

973 

974 

975class Mod(BinExpr): 

976 """Left modulo right.""" 

977 

978 operator = "%" 

979 

980 

981class Pow(BinExpr): 

982 """Left to the power of right.""" 

983 

984 operator = "**" 

985 

986 

987class And(BinExpr): 

988 """Short circuited AND.""" 

989 

990 operator = "and" 

991 

992 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

993 eval_ctx = get_eval_context(self, eval_ctx) 

994 return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) 

995 

996 

997class Or(BinExpr): 

998 """Short circuited OR.""" 

999 

1000 operator = "or" 

1001 

1002 def as_const(self, eval_ctx: EvalContext | None = None) -> t.Any: 

1003 eval_ctx = get_eval_context(self, eval_ctx) 

1004 return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) 

1005 

1006 

1007class Not(UnaryExpr): 

1008 """Negate the expression.""" 

1009 

1010 operator = "not" 

1011 

1012 

1013class Neg(UnaryExpr): 

1014 """Make the expression negative.""" 

1015 

1016 operator = "-" 

1017 

1018 

1019class Pos(UnaryExpr): 

1020 """Make the expression positive (noop for most expressions)""" 

1021 

1022 operator = "+" 

1023 

1024 

1025# Helpers for extensions 

1026 

1027 

1028class EnvironmentAttribute(Expr): 

1029 """Loads an attribute from the environment object. This is useful for 

1030 extensions that want to call a callback stored on the environment. 

1031 """ 

1032 

1033 fields = ("name",) 

1034 name: str 

1035 

1036 

1037class ExtensionAttribute(Expr): 

1038 """Returns the attribute of an extension bound to the environment. 

1039 The identifier is the identifier of the :class:`Extension`. 

1040 

1041 This node is usually constructed by calling the 

1042 :meth:`~jinja2.ext.Extension.attr` method on an extension. 

1043 """ 

1044 

1045 fields = ("identifier", "name") 

1046 identifier: str 

1047 name: str 

1048 

1049 

1050class ImportedName(Expr): 

1051 """If created with an import name the import name is returned on node 

1052 access. For example ``ImportedName('cgi.escape')`` returns the `escape` 

1053 function from the cgi module on evaluation. Imports are optimized by the 

1054 compiler so there is no need to assign them to local variables. 

1055 """ 

1056 

1057 fields = ("importname",) 

1058 importname: str 

1059 

1060 

1061class InternalName(Expr): 

1062 """An internal name in the compiler. You cannot create these nodes 

1063 yourself but the parser provides a 

1064 :meth:`~jinja2.parser.Parser.free_identifier` method that creates 

1065 a new identifier for you. This identifier is not available from the 

1066 template and is not treated specially by the compiler. 

1067 """ 

1068 

1069 fields = ("name",) 

1070 name: str 

1071 

1072 def __init__(self) -> None: 

1073 raise TypeError( 

1074 "Can't create internal names. Use the " 

1075 "`free_identifier` method on a parser." 

1076 ) 

1077 

1078 

1079class MarkSafe(Expr): 

1080 """Mark the wrapped expression as safe (wrap it as `Markup`).""" 

1081 

1082 fields = ("expr",) 

1083 expr: Expr 

1084 

1085 def as_const(self, eval_ctx: EvalContext | None = None) -> Markup: 

1086 eval_ctx = get_eval_context(self, eval_ctx) 

1087 return Markup(self.expr.as_const(eval_ctx)) 

1088 

1089 

1090class MarkSafeIfAutoescape(Expr): 

1091 """Mark the wrapped expression as safe (wrap it as `Markup`) but 

1092 only if autoescaping is active. 

1093 

1094 .. versionadded:: 2.5 

1095 """ 

1096 

1097 fields = ("expr",) 

1098 expr: Expr 

1099 

1100 def as_const(self, eval_ctx: EvalContext | None = None) -> Markup | t.Any: 

1101 eval_ctx = get_eval_context(self, eval_ctx) 

1102 if eval_ctx.volatile: 

1103 raise Impossible() 

1104 expr = self.expr.as_const(eval_ctx) 

1105 if eval_ctx.autoescape: 

1106 return Markup(expr) 

1107 return expr 

1108 

1109 

1110class ContextReference(Expr): 

1111 """Returns the current template context. It can be used like a 

1112 :class:`Name` node, with a ``'load'`` ctx and will return the 

1113 current :class:`~jinja2.runtime.Context` object. 

1114 

1115 Here an example that assigns the current template name to a 

1116 variable named `foo`:: 

1117 

1118 Assign(Name('foo', ctx='store'), 

1119 Getattr(ContextReference(), 'name')) 

1120 

1121 This is basically equivalent to using the 

1122 :func:`~jinja2.pass_context` decorator when using the high-level 

1123 API, which causes a reference to the context to be passed as the 

1124 first argument to a function. 

1125 """ 

1126 

1127 

1128class DerivedContextReference(Expr): 

1129 """Return the current template context including locals. Behaves 

1130 exactly like :class:`ContextReference`, but includes local 

1131 variables, such as from a ``for`` loop. 

1132 

1133 .. versionadded:: 2.11 

1134 """ 

1135 

1136 

1137class Continue(Stmt): 

1138 """Continue a loop.""" 

1139 

1140 

1141class Break(Stmt): 

1142 """Break a loop.""" 

1143 

1144 

1145class Scope(Stmt): 

1146 """An artificial scope.""" 

1147 

1148 fields = ("body",) 

1149 body: list[Node] 

1150 

1151 

1152class OverlayScope(Stmt): 

1153 """An overlay scope for extensions. This is a largely unoptimized scope 

1154 that however can be used to introduce completely arbitrary variables into 

1155 a sub scope from a dictionary or dictionary like object. The `context` 

1156 field has to evaluate to a dictionary object. 

1157 

1158 Example usage:: 

1159 

1160 OverlayScope(context=self.call_method('get_context'), 

1161 body=[...]) 

1162 

1163 .. versionadded:: 2.10 

1164 """ 

1165 

1166 fields = ("context", "body") 

1167 context: Expr 

1168 body: list[Node] 

1169 

1170 

1171class EvalContextModifier(Stmt): 

1172 """Modifies the eval context. For each option that should be modified, 

1173 a :class:`Keyword` has to be added to the :attr:`options` list. 

1174 

1175 Example to change the `autoescape` setting:: 

1176 

1177 EvalContextModifier(options=[Keyword('autoescape', Const(True))]) 

1178 """ 

1179 

1180 fields = ("options",) 

1181 options: list[Keyword] 

1182 

1183 

1184class ScopedEvalContextModifier(EvalContextModifier): 

1185 """Modifies the eval context and reverts it later. Works exactly like 

1186 :class:`EvalContextModifier` but will only modify the 

1187 :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`. 

1188 """ 

1189 

1190 fields = ("body",) 

1191 body: list[Node] 

1192 

1193 

1194# make sure nobody creates custom nodes 

1195def _failing_new(*args: t.Any, **kwargs: t.Any) -> "te.NoReturn": 

1196 raise TypeError("can't create custom node types") 

1197 

1198 

1199NodeType.__new__ = staticmethod(_failing_new) # type: ignore 

1200del _failing_new