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

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

555 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: t.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: t.Dict[str, t.Callable[[t.Any], t.Any]] = { 

33 "not": operator.not_, 

34 "+": operator.pos, 

35 "-": operator.neg, 

36} 

37 

38_cmpop_to_func: t.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: t.List[t.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: t.Optional[str] = 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: t.Optional[EvalContext]) -> 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: t.Tuple[str, ...] = () 

123 attributes: t.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): 

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.Optional[t.Container[str]] = None, 

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

151 ) -> t.Iterator[t.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.Optional[t.Container[str]] = None, 

172 only: t.Optional[t.Container[str]] = 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: t.Type[_NodeBound]) -> t.Optional[_NodeBound]: 

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: t.Union[t.Type[_NodeBound], t.Tuple[t.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: t.Union[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: t.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: t.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: t.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: t.List[Node] 

332 else_: t.List[Node] 

333 test: t.Optional[Node] 

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: t.List[Node] 

343 elif_: t.List["If"] 

344 else_: t.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: t.List["Name"] 

356 defaults: t.List["Expr"] 

357 body: t.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: t.List["Name"] 

368 defaults: t.List["Expr"] 

369 body: t.List[Node] 

370 

371 

372class FilterBlock(Stmt): 

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

374 

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

376 body: t.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: t.List["Expr"] 

389 values: t.List["Expr"] 

390 body: t.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: t.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: t.List[t.Union[str, t.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: t.List[Node] 

465 

466 

467class Expr(Node): 

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

469 

470 abstract = True 

471 

472 def as_const(self, eval_ctx: t.Optional[EvalContext] = 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: t.Optional[EvalContext] = 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: t.Optional[EvalContext] = 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: t.Optional[EvalContext] = None) -> t.Any: 

588 return self.value 

589 

590 @classmethod 

591 def from_untrusted( 

592 cls, 

593 value: t.Any, 

594 lineno: t.Optional[int] = None, 

595 environment: "t.Optional[Environment]" = 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: t.Optional[EvalContext] = 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: t.List[Expr] 

631 ctx: str 

632 

633 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.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: t.List[Expr] 

649 

650 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.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: t.List["Pair"] 

662 

663 def as_const( 

664 self, eval_ctx: t.Optional[EvalContext] = None 

665 ) -> t.Dict[t.Any, t.Any]: 

666 eval_ctx = get_eval_context(self, eval_ctx) 

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

668 

669 

670class Pair(Helper): 

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

672 

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

674 key: Expr 

675 value: Expr 

676 

677 def as_const( 

678 self, eval_ctx: t.Optional[EvalContext] = None 

679 ) -> t.Tuple[t.Any, t.Any]: 

680 eval_ctx = get_eval_context(self, eval_ctx) 

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

682 

683 

684class Keyword(Helper): 

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

686 

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

688 key: str 

689 value: Expr 

690 

691 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[str, t.Any]: 

692 eval_ctx = get_eval_context(self, eval_ctx) 

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

694 

695 

696class CondExpr(Expr): 

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

698 foo if bar else baz }}``) 

699 """ 

700 

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

702 test: Expr 

703 expr1: Expr 

704 expr2: t.Optional[Expr] 

705 

706 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

707 eval_ctx = get_eval_context(self, eval_ctx) 

708 if self.test.as_const(eval_ctx): 

709 return self.expr1.as_const(eval_ctx) 

710 

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

712 if self.expr2 is None: 

713 raise Impossible() 

714 

715 return self.expr2.as_const(eval_ctx) 

716 

717 

718def args_as_const( 

719 node: t.Union["_FilterTestCommon", "Call"], eval_ctx: t.Optional[EvalContext] 

720) -> t.Tuple[t.List[t.Any], t.Dict[t.Any, t.Any]]: 

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

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

723 

724 if node.dyn_args is not None: 

725 try: 

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

727 except Exception as e: 

728 raise Impossible() from e 

729 

730 if node.dyn_kwargs is not None: 

731 try: 

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

733 except Exception as e: 

734 raise Impossible() from e 

735 

736 return args, kwargs 

737 

738 

739class _FilterTestCommon(Expr): 

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

741 node: Expr 

742 name: str 

743 args: t.List[Expr] 

744 kwargs: t.List[Pair] 

745 dyn_args: t.Optional[Expr] 

746 dyn_kwargs: t.Optional[Expr] 

747 abstract = True 

748 _is_filter = True 

749 

750 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

751 eval_ctx = get_eval_context(self, eval_ctx) 

752 

753 if eval_ctx.volatile: 

754 raise Impossible() 

755 

756 if self._is_filter: 

757 env_map = eval_ctx.environment.filters 

758 else: 

759 env_map = eval_ctx.environment.tests 

760 

761 func = env_map.get(self.name) 

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

763 

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

765 raise Impossible() 

766 

767 if eval_ctx.environment.is_async and ( 

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

769 or inspect.iscoroutinefunction(func) 

770 ): 

771 raise Impossible() 

772 

773 args, kwargs = args_as_const(self, eval_ctx) 

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

775 

776 if pass_arg is _PassArg.eval_context: 

777 args.insert(0, eval_ctx) 

778 elif pass_arg is _PassArg.environment: 

779 args.insert(0, eval_ctx.environment) 

780 

781 try: 

782 return func(*args, **kwargs) 

783 except Exception as e: 

784 raise Impossible() from e 

785 

786 

787class Filter(_FilterTestCommon): 

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

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

790 

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

792 and is applied to the content of the block. 

793 """ 

794 

795 node: t.Optional[Expr] # type: ignore 

796 

797 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

798 if self.node is None: 

799 raise Impossible() 

800 

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

802 

803 

804class Test(_FilterTestCommon): 

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

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

807 

808 .. versionchanged:: 3.0 

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

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

811 decorators. 

812 """ 

813 

814 _is_filter = False 

815 

816 

817class Call(Expr): 

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

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

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

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

822 arguments. 

823 """ 

824 

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

826 node: Expr 

827 args: t.List[Expr] 

828 kwargs: t.List[Keyword] 

829 dyn_args: t.Optional[Expr] 

830 dyn_kwargs: t.Optional[Expr] 

831 

832 

833class Getitem(Expr): 

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

835 

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

837 node: Expr 

838 arg: Expr 

839 ctx: str 

840 

841 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

842 if self.ctx != "load": 

843 raise Impossible() 

844 

845 eval_ctx = get_eval_context(self, eval_ctx) 

846 

847 try: 

848 return eval_ctx.environment.getitem( 

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

850 ) 

851 except Exception as e: 

852 raise Impossible() from e 

853 

854 

855class Getattr(Expr): 

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

857 bytestring and prefer the attribute. 

858 """ 

859 

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

861 node: Expr 

862 attr: str 

863 ctx: str 

864 

865 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

866 if self.ctx != "load": 

867 raise Impossible() 

868 

869 eval_ctx = get_eval_context(self, eval_ctx) 

870 

871 try: 

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

873 except Exception as e: 

874 raise Impossible() from e 

875 

876 

877class Slice(Expr): 

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

879 :class:`Subscript`. 

880 """ 

881 

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

883 start: t.Optional[Expr] 

884 stop: t.Optional[Expr] 

885 step: t.Optional[Expr] 

886 

887 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> slice: 

888 eval_ctx = get_eval_context(self, eval_ctx) 

889 

890 def const(obj: t.Optional[Expr]) -> t.Optional[t.Any]: 

891 if obj is None: 

892 return None 

893 return obj.as_const(eval_ctx) 

894 

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

896 

897 

898class Concat(Expr): 

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

900 them to strings. 

901 """ 

902 

903 fields = ("nodes",) 

904 nodes: t.List[Expr] 

905 

906 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: 

907 eval_ctx = get_eval_context(self, eval_ctx) 

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

909 

910 

911class Compare(Expr): 

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

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

914 """ 

915 

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

917 expr: Expr 

918 ops: t.List["Operand"] 

919 

920 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

921 eval_ctx = get_eval_context(self, eval_ctx) 

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

923 

924 try: 

925 for op in self.ops: 

926 new_value = op.expr.as_const(eval_ctx) 

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

928 

929 if not result: 

930 return False 

931 

932 value = new_value 

933 except Exception as e: 

934 raise Impossible() from e 

935 

936 return result 

937 

938 

939class Operand(Helper): 

940 """Holds an operator and an expression.""" 

941 

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

943 op: str 

944 expr: Expr 

945 

946 

947class Mul(BinExpr): 

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

949 

950 operator = "*" 

951 

952 

953class Div(BinExpr): 

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

955 

956 operator = "/" 

957 

958 

959class FloorDiv(BinExpr): 

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

961 result into an integer by truncating. 

962 """ 

963 

964 operator = "//" 

965 

966 

967class Add(BinExpr): 

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

969 

970 operator = "+" 

971 

972 

973class Sub(BinExpr): 

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

975 

976 operator = "-" 

977 

978 

979class Mod(BinExpr): 

980 """Left modulo right.""" 

981 

982 operator = "%" 

983 

984 

985class Pow(BinExpr): 

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

987 

988 operator = "**" 

989 

990 

991class And(BinExpr): 

992 """Short circuited AND.""" 

993 

994 operator = "and" 

995 

996 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

997 eval_ctx = get_eval_context(self, eval_ctx) 

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

999 

1000 

1001class Or(BinExpr): 

1002 """Short circuited OR.""" 

1003 

1004 operator = "or" 

1005 

1006 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: 

1007 eval_ctx = get_eval_context(self, eval_ctx) 

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

1009 

1010 

1011class Not(UnaryExpr): 

1012 """Negate the expression.""" 

1013 

1014 operator = "not" 

1015 

1016 

1017class Neg(UnaryExpr): 

1018 """Make the expression negative.""" 

1019 

1020 operator = "-" 

1021 

1022 

1023class Pos(UnaryExpr): 

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

1025 

1026 operator = "+" 

1027 

1028 

1029# Helpers for extensions 

1030 

1031 

1032class EnvironmentAttribute(Expr): 

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

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

1035 """ 

1036 

1037 fields = ("name",) 

1038 name: str 

1039 

1040 

1041class ExtensionAttribute(Expr): 

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

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

1044 

1045 This node is usually constructed by calling the 

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

1047 """ 

1048 

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

1050 identifier: str 

1051 name: str 

1052 

1053 

1054class ImportedName(Expr): 

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

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

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

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

1059 """ 

1060 

1061 fields = ("importname",) 

1062 importname: str 

1063 

1064 

1065class InternalName(Expr): 

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

1067 yourself but the parser provides a 

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

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

1070 template and is not treated specially by the compiler. 

1071 """ 

1072 

1073 fields = ("name",) 

1074 name: str 

1075 

1076 def __init__(self) -> None: 

1077 raise TypeError( 

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

1079 "`free_identifier` method on a parser." 

1080 ) 

1081 

1082 

1083class MarkSafe(Expr): 

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

1085 

1086 fields = ("expr",) 

1087 expr: Expr 

1088 

1089 def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> Markup: 

1090 eval_ctx = get_eval_context(self, eval_ctx) 

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

1092 

1093 

1094class MarkSafeIfAutoescape(Expr): 

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

1096 only if autoescaping is active. 

1097 

1098 .. versionadded:: 2.5 

1099 """ 

1100 

1101 fields = ("expr",) 

1102 expr: Expr 

1103 

1104 def as_const( 

1105 self, eval_ctx: t.Optional[EvalContext] = None 

1106 ) -> t.Union[Markup, t.Any]: 

1107 eval_ctx = get_eval_context(self, eval_ctx) 

1108 if eval_ctx.volatile: 

1109 raise Impossible() 

1110 expr = self.expr.as_const(eval_ctx) 

1111 if eval_ctx.autoescape: 

1112 return Markup(expr) 

1113 return expr 

1114 

1115 

1116class ContextReference(Expr): 

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

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

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

1120 

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

1122 variable named `foo`:: 

1123 

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

1125 Getattr(ContextReference(), 'name')) 

1126 

1127 This is basically equivalent to using the 

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

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

1130 first argument to a function. 

1131 """ 

1132 

1133 

1134class DerivedContextReference(Expr): 

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

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

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

1138 

1139 .. versionadded:: 2.11 

1140 """ 

1141 

1142 

1143class Continue(Stmt): 

1144 """Continue a loop.""" 

1145 

1146 

1147class Break(Stmt): 

1148 """Break a loop.""" 

1149 

1150 

1151class Scope(Stmt): 

1152 """An artificial scope.""" 

1153 

1154 fields = ("body",) 

1155 body: t.List[Node] 

1156 

1157 

1158class OverlayScope(Stmt): 

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

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

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

1162 field has to evaluate to a dictionary object. 

1163 

1164 Example usage:: 

1165 

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

1167 body=[...]) 

1168 

1169 .. versionadded:: 2.10 

1170 """ 

1171 

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

1173 context: Expr 

1174 body: t.List[Node] 

1175 

1176 

1177class EvalContextModifier(Stmt): 

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

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

1180 

1181 Example to change the `autoescape` setting:: 

1182 

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

1184 """ 

1185 

1186 fields = ("options",) 

1187 options: t.List[Keyword] 

1188 

1189 

1190class ScopedEvalContextModifier(EvalContextModifier): 

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

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

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

1194 """ 

1195 

1196 fields = ("body",) 

1197 body: t.List[Node] 

1198 

1199 

1200# make sure nobody creates custom nodes 

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

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

1203 

1204 

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

1206del _failing_new