Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/jinja2/nodes.py: 56%

555 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

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""" 

5import inspect 

6import operator 

7import typing as t 

8from collections import deque 

9 

10from markupsafe import Markup 

11 

12from .utils import _PassArg 

13 

14if t.TYPE_CHECKING: 14 ↛ 15line 14 didn't jump to line 15, because the condition on line 14 was never true

15 import typing_extensions as te 

16 from .environment import Environment 

17 

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

19 

20_binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { 

21 "*": operator.mul, 

22 "/": operator.truediv, 

23 "//": operator.floordiv, 

24 "**": operator.pow, 

25 "%": operator.mod, 

26 "+": operator.add, 

27 "-": operator.sub, 

28} 

29 

30_uaop_to_func: t.Dict[str, t.Callable[[t.Any], t.Any]] = { 

31 "not": operator.not_, 

32 "+": operator.pos, 

33 "-": operator.neg, 

34} 

35 

36_cmpop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { 36 ↛ exitline 36 didn't jump to the function exit

37 "eq": operator.eq, 

38 "ne": operator.ne, 

39 "gt": operator.gt, 

40 "gteq": operator.ge, 

41 "lt": operator.lt, 

42 "lteq": operator.le, 

43 "in": lambda a, b: a in b, 

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

45} 

46 

47 

48class Impossible(Exception): 

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

50 

51 

52class NodeType(type): 

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

54 inheritance. fields and attributes from the parent class are 

55 automatically forwarded to the child.""" 

56 

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

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

59 storage = [] 

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

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

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

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

64 d[attr] = tuple(storage) 

65 d.setdefault("abstract", False) 

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

67 

68 

69class EvalContext: 

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

71 to it in extensions. 

72 """ 

73 

74 def __init__( 

75 self, environment: "Environment", template_name: t.Optional[str] = None 

76 ) -> None: 

77 self.environment = environment 

78 if callable(environment.autoescape): 

79 self.autoescape = environment.autoescape(template_name) 

80 else: 

81 self.autoescape = environment.autoescape 

82 self.volatile = False 

83 

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

85 return self.__dict__.copy() 

86 

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

88 self.__dict__.clear() 

89 self.__dict__.update(old) 

90 

91 

92def get_eval_context(node: "Node", ctx: t.Optional[EvalContext]) -> EvalContext: 

93 if ctx is None: 

94 if node.environment is None: 

95 raise RuntimeError( 

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

97 " attached environment." 

98 ) 

99 return EvalContext(node.environment) 

100 return ctx 

101 

102 

103class Node(metaclass=NodeType): 

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

105 of different types. There are four major types: 

106 

107 - :class:`Stmt`: statements 

108 - :class:`Expr`: expressions 

109 - :class:`Helper`: helper nodes 

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

111 

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

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

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

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

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

117 all nodes automatically. 

118 """ 

119 

120 fields: t.Tuple[str, ...] = () 

121 attributes: t.Tuple[str, ...] = ("lineno", "environment") 

122 abstract = True 

123 

124 lineno: int 

125 environment: t.Optional["Environment"] 

126 

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

128 if self.abstract: 

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

130 if fields: 

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

132 if not self.fields: 

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

134 raise TypeError( 

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

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

137 ) 

138 for name, arg in zip(self.fields, fields): 

139 setattr(self, name, arg) 

140 for attr in self.attributes: 

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

142 if attributes: 

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

144 

145 def iter_fields( 

146 self, 

147 exclude: t.Optional[t.Container[str]] = None, 

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

149 ) -> t.Iterator[t.Tuple[str, t.Any]]: 

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

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

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

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

154 should be sets or tuples of field names. 

155 """ 

156 for name in self.fields: 

157 if ( 

158 (exclude is None and only is None) 

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

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

161 ): 

162 try: 

163 yield name, getattr(self, name) 

164 except AttributeError: 

165 pass 

166 

167 def iter_child_nodes( 

168 self, 

169 exclude: t.Optional[t.Container[str]] = None, 

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

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

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

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

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

175 """ 

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

177 if isinstance(item, list): 

178 for n in item: 

179 if isinstance(n, Node): 

180 yield n 

181 elif isinstance(item, Node): 

182 yield item 

183 

184 def find(self, node_type: t.Type[_NodeBound]) -> t.Optional[_NodeBound]: 

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

186 return value is `None`. 

187 """ 

188 for result in self.find_all(node_type): 

189 return result 

190 

191 return None 

192 

193 def find_all( 

194 self, node_type: t.Union[t.Type[_NodeBound], t.Tuple[t.Type[_NodeBound], ...]] 

195 ) -> t.Iterator[_NodeBound]: 

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

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

198 """ 

199 for child in self.iter_child_nodes(): 

200 if isinstance(child, node_type): 

201 yield child # type: ignore 

202 yield from child.find_all(node_type) 

203 

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

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

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

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

208 targets and other nodes to a store context. 

209 """ 

210 todo = deque([self]) 

211 while todo: 

212 node = todo.popleft() 

213 if "ctx" in node.fields: 

214 node.ctx = ctx # type: ignore 

215 todo.extend(node.iter_child_nodes()) 

216 return self 

217 

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

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

220 todo = deque([self]) 

221 while todo: 

222 node = todo.popleft() 

223 if "lineno" in node.attributes: 

224 if node.lineno is None or override: 

225 node.lineno = lineno 

226 todo.extend(node.iter_child_nodes()) 

227 return self 

228 

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

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

231 todo = deque([self]) 

232 while todo: 

233 node = todo.popleft() 

234 node.environment = environment 

235 todo.extend(node.iter_child_nodes()) 

236 return self 

237 

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

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

240 return NotImplemented 

241 

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

243 

244 __hash__ = object.__hash__ 

245 

246 def __repr__(self) -> str: 

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

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

249 

250 def dump(self) -> str: 

251 def _dump(node: t.Union[Node, t.Any]) -> None: 

252 if not isinstance(node, Node): 

253 buf.append(repr(node)) 

254 return 

255 

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

257 if not node.fields: 

258 buf.append(")") 

259 return 

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

261 if idx: 

262 buf.append(", ") 

263 value = getattr(node, field) 

264 if isinstance(value, list): 

265 buf.append("[") 

266 for idx, item in enumerate(value): 

267 if idx: 

268 buf.append(", ") 

269 _dump(item) 

270 buf.append("]") 

271 else: 

272 _dump(value) 

273 buf.append(")") 

274 

275 buf: t.List[str] = [] 

276 _dump(self) 

277 return "".join(buf) 

278 

279 

280class Stmt(Node): 

281 """Base node for all statements.""" 

282 

283 abstract = True 

284 

285 

286class Helper(Node): 

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

288 

289 abstract = True 

290 

291 

292class Template(Node): 

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

294 is passed to the compiler. 

295 """ 

296 

297 fields = ("body",) 

298 body: t.List[Node] 

299 

300 

301class Output(Stmt): 

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

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

304 """ 

305 

306 fields = ("nodes",) 

307 nodes: t.List["Expr"] 

308 

309 

310class Extends(Stmt): 

311 """Represents an extends statement.""" 

312 

313 fields = ("template",) 

314 template: "Expr" 

315 

316 

317class For(Stmt): 

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

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

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

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

322 

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

324 """ 

325 

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

327 target: Node 

328 iter: Node 

329 body: t.List[Node] 

330 else_: t.List[Node] 

331 test: t.Optional[Node] 

332 recursive: bool 

333 

334 

335class If(Stmt): 

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

337 

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

339 test: Node 

340 body: t.List[Node] 

341 elif_: t.List["If"] 

342 else_: t.List[Node] 

343 

344 

345class Macro(Stmt): 

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

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

348 a list of nodes for the macro body. 

349 """ 

350 

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

352 name: str 

353 args: t.List["Name"] 

354 defaults: t.List["Expr"] 

355 body: t.List[Node] 

356 

357 

358class CallBlock(Stmt): 

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

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

361 """ 

362 

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

364 call: "Call" 

365 args: t.List["Name"] 

366 defaults: t.List["Expr"] 

367 body: t.List[Node] 

368 

369 

370class FilterBlock(Stmt): 

371 """Node for filter sections.""" 

372 

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

374 body: t.List[Node] 

375 filter: "Filter" 

376 

377 

378class With(Stmt): 

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

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

381 

382 .. versionadded:: 2.9.3 

383 """ 

384 

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

386 targets: t.List["Expr"] 

387 values: t.List["Expr"] 

388 body: t.List[Node] 

389 

390 

391class Block(Stmt): 

392 """A node that represents a block. 

393 

394 .. versionchanged:: 3.0.0 

395 the `required` field was added. 

396 """ 

397 

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

399 name: str 

400 body: t.List[Node] 

401 scoped: bool 

402 required: bool 

403 

404 

405class Include(Stmt): 

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

407 

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

409 template: "Expr" 

410 with_context: bool 

411 ignore_missing: bool 

412 

413 

414class Import(Stmt): 

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

416 

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

418 template: "Expr" 

419 target: str 

420 with_context: bool 

421 

422 

423class FromImport(Stmt): 

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

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

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

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

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

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

430 extra care must be taken. 

431 

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

433 """ 

434 

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

436 template: "Expr" 

437 names: t.List[t.Union[str, t.Tuple[str, str]]] 

438 with_context: bool 

439 

440 

441class ExprStmt(Stmt): 

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

443 

444 fields = ("node",) 

445 node: Node 

446 

447 

448class Assign(Stmt): 

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

450 

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

452 target: "Expr" 

453 node: Node 

454 

455 

456class AssignBlock(Stmt): 

457 """Assigns a block to a target.""" 

458 

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

460 target: "Expr" 

461 filter: t.Optional["Filter"] 

462 body: t.List[Node] 

463 

464 

465class Expr(Node): 

466 """Baseclass for all expressions.""" 

467 

468 abstract = True 

469 

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

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

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

473 

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

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

476 an attached environment. 

477 

478 .. versionchanged:: 2.4 

479 the `eval_ctx` parameter was added. 

480 """ 

481 raise Impossible() 

482 

483 def can_assign(self) -> bool: 

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

485 return False 

486 

487 

488class BinExpr(Expr): 

489 """Baseclass for all binary expressions.""" 

490 

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

492 left: Expr 

493 right: Expr 

494 operator: str 

495 abstract = True 

496 

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

498 eval_ctx = get_eval_context(self, eval_ctx) 

499 

500 # intercepted operators cannot be folded at compile time 

501 if ( 

502 eval_ctx.environment.sandboxed 

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

504 ): 

505 raise Impossible() 

506 f = _binop_to_func[self.operator] 

507 try: 

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

509 except Exception as e: 

510 raise Impossible() from e 

511 

512 

513class UnaryExpr(Expr): 

514 """Baseclass for all unary expressions.""" 

515 

516 fields = ("node",) 

517 node: Expr 

518 operator: str 

519 abstract = True 

520 

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

522 eval_ctx = get_eval_context(self, eval_ctx) 

523 

524 # intercepted operators cannot be folded at compile time 

525 if ( 

526 eval_ctx.environment.sandboxed 

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

528 ): 

529 raise Impossible() 

530 f = _uaop_to_func[self.operator] 

531 try: 

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

533 except Exception as e: 

534 raise Impossible() from e 

535 

536 

537class Name(Expr): 

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

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

540 

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

542 - `load`: load that name 

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

544 """ 

545 

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

547 name: str 

548 ctx: str 

549 

550 def can_assign(self) -> bool: 

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

552 

553 

554class NSRef(Expr): 

555 """Reference to a namespace value assignment""" 

556 

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

558 name: str 

559 attr: str 

560 

561 def can_assign(self) -> bool: 

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

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

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

565 # which goes through a `Name` node. 

566 return True 

567 

568 

569class Literal(Expr): 

570 """Baseclass for literals.""" 

571 

572 abstract = True 

573 

574 

575class Const(Literal): 

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

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

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

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

580 """ 

581 

582 fields = ("value",) 

583 value: t.Any 

584 

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

586 return self.value 

587 

588 @classmethod 

589 def from_untrusted( 

590 cls, 

591 value: t.Any, 

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

593 environment: "t.Optional[Environment]" = None, 

594 ) -> "Const": 

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

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

597 an `Impossible` exception. 

598 """ 

599 from .compiler import has_safe_repr 

600 

601 if not has_safe_repr(value): 

602 raise Impossible() 

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

604 

605 

606class TemplateData(Literal): 

607 """A constant template string.""" 

608 

609 fields = ("data",) 

610 data: str 

611 

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

613 eval_ctx = get_eval_context(self, eval_ctx) 

614 if eval_ctx.volatile: 

615 raise Impossible() 

616 if eval_ctx.autoescape: 

617 return Markup(self.data) 

618 return self.data 

619 

620 

621class Tuple(Literal): 

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

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

624 is used for loading the names or storing. 

625 """ 

626 

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

628 items: t.List[Expr] 

629 ctx: str 

630 

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

632 eval_ctx = get_eval_context(self, eval_ctx) 

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

634 

635 def can_assign(self) -> bool: 

636 for item in self.items: 

637 if not item.can_assign(): 

638 return False 

639 return True 

640 

641 

642class List(Literal): 

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

644 

645 fields = ("items",) 

646 items: t.List[Expr] 

647 

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

649 eval_ctx = get_eval_context(self, eval_ctx) 

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

651 

652 

653class Dict(Literal): 

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

655 :class:`Pair` nodes. 

656 """ 

657 

658 fields = ("items",) 

659 items: t.List["Pair"] 

660 

661 def as_const( 

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

663 ) -> t.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( 

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

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

678 eval_ctx = get_eval_context(self, eval_ctx) 

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

680 

681 

682class Keyword(Helper): 

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

684 

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

686 key: str 

687 value: Expr 

688 

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

690 eval_ctx = get_eval_context(self, eval_ctx) 

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

692 

693 

694class CondExpr(Expr): 

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

696 foo if bar else baz }}``) 

697 """ 

698 

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

700 test: Expr 

701 expr1: Expr 

702 expr2: t.Optional[Expr] 

703 

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

705 eval_ctx = get_eval_context(self, eval_ctx) 

706 if self.test.as_const(eval_ctx): 

707 return self.expr1.as_const(eval_ctx) 

708 

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

710 if self.expr2 is None: 

711 raise Impossible() 

712 

713 return self.expr2.as_const(eval_ctx) 

714 

715 

716def args_as_const( 

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

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

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

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

721 

722 if node.dyn_args is not None: 

723 try: 

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

725 except Exception as e: 

726 raise Impossible() from e 

727 

728 if node.dyn_kwargs is not None: 

729 try: 

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

731 except Exception as e: 

732 raise Impossible() from e 

733 

734 return args, kwargs 

735 

736 

737class _FilterTestCommon(Expr): 

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

739 node: Expr 

740 name: str 

741 args: t.List[Expr] 

742 kwargs: t.List[Pair] 

743 dyn_args: t.Optional[Expr] 

744 dyn_kwargs: t.Optional[Expr] 

745 abstract = True 

746 _is_filter = True 

747 

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

749 eval_ctx = get_eval_context(self, eval_ctx) 

750 

751 if eval_ctx.volatile: 

752 raise Impossible() 

753 

754 if self._is_filter: 

755 env_map = eval_ctx.environment.filters 

756 else: 

757 env_map = eval_ctx.environment.tests 

758 

759 func = env_map.get(self.name) 

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

761 

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

763 raise Impossible() 

764 

765 if eval_ctx.environment.is_async and ( 

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

767 or inspect.iscoroutinefunction(func) 

768 ): 

769 raise Impossible() 

770 

771 args, kwargs = args_as_const(self, eval_ctx) 

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

773 

774 if pass_arg is _PassArg.eval_context: 

775 args.insert(0, eval_ctx) 

776 elif pass_arg is _PassArg.environment: 

777 args.insert(0, eval_ctx.environment) 

778 

779 try: 

780 return func(*args, **kwargs) 

781 except Exception as e: 

782 raise Impossible() from e 

783 

784 

785class Filter(_FilterTestCommon): 

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

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

788 

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

790 and is applied to the content of the block. 

791 """ 

792 

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

794 

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

796 if self.node is None: 

797 raise Impossible() 

798 

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

800 

801 

802class Test(_FilterTestCommon): 

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

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

805 

806 .. versionchanged:: 3.0 

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

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

809 decorators. 

810 """ 

811 

812 _is_filter = False 

813 

814 

815class Call(Expr): 

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

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

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

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

820 arguments. 

821 """ 

822 

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

824 node: Expr 

825 args: t.List[Expr] 

826 kwargs: t.List[Keyword] 

827 dyn_args: t.Optional[Expr] 

828 dyn_kwargs: t.Optional[Expr] 

829 

830 

831class Getitem(Expr): 

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

833 

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

835 node: Expr 

836 arg: Expr 

837 ctx: str 

838 

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

840 if self.ctx != "load": 

841 raise Impossible() 

842 

843 eval_ctx = get_eval_context(self, eval_ctx) 

844 

845 try: 

846 return eval_ctx.environment.getitem( 

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

848 ) 

849 except Exception as e: 

850 raise Impossible() from e 

851 

852 

853class Getattr(Expr): 

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

855 bytestring and prefer the attribute. 

856 """ 

857 

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

859 node: Expr 

860 attr: str 

861 ctx: str 

862 

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

864 if self.ctx != "load": 

865 raise Impossible() 

866 

867 eval_ctx = get_eval_context(self, eval_ctx) 

868 

869 try: 

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

871 except Exception as e: 

872 raise Impossible() from e 

873 

874 

875class Slice(Expr): 

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

877 :class:`Subscript`. 

878 """ 

879 

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

881 start: t.Optional[Expr] 

882 stop: t.Optional[Expr] 

883 step: t.Optional[Expr] 

884 

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

886 eval_ctx = get_eval_context(self, eval_ctx) 

887 

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

889 if obj is None: 

890 return None 

891 return obj.as_const(eval_ctx) 

892 

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

894 

895 

896class Concat(Expr): 

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

898 them to strings. 

899 """ 

900 

901 fields = ("nodes",) 

902 nodes: t.List[Expr] 

903 

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

905 eval_ctx = get_eval_context(self, eval_ctx) 

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

907 

908 

909class Compare(Expr): 

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

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

912 """ 

913 

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

915 expr: Expr 

916 ops: t.List["Operand"] 

917 

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

919 eval_ctx = get_eval_context(self, eval_ctx) 

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

921 

922 try: 

923 for op in self.ops: 

924 new_value = op.expr.as_const(eval_ctx) 

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

926 

927 if not result: 

928 return False 

929 

930 value = new_value 

931 except Exception as e: 

932 raise Impossible() from e 

933 

934 return result 

935 

936 

937class Operand(Helper): 

938 """Holds an operator and an expression.""" 

939 

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

941 op: str 

942 expr: Expr 

943 

944 

945class Mul(BinExpr): 

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

947 

948 operator = "*" 

949 

950 

951class Div(BinExpr): 

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

953 

954 operator = "/" 

955 

956 

957class FloorDiv(BinExpr): 

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

959 result into an integer by truncating. 

960 """ 

961 

962 operator = "//" 

963 

964 

965class Add(BinExpr): 

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

967 

968 operator = "+" 

969 

970 

971class Sub(BinExpr): 

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

973 

974 operator = "-" 

975 

976 

977class Mod(BinExpr): 

978 """Left modulo right.""" 

979 

980 operator = "%" 

981 

982 

983class Pow(BinExpr): 

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

985 

986 operator = "**" 

987 

988 

989class And(BinExpr): 

990 """Short circuited AND.""" 

991 

992 operator = "and" 

993 

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

995 eval_ctx = get_eval_context(self, eval_ctx) 

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

997 

998 

999class Or(BinExpr): 

1000 """Short circuited OR.""" 

1001 

1002 operator = "or" 

1003 

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

1005 eval_ctx = get_eval_context(self, eval_ctx) 

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

1007 

1008 

1009class Not(UnaryExpr): 

1010 """Negate the expression.""" 

1011 

1012 operator = "not" 

1013 

1014 

1015class Neg(UnaryExpr): 

1016 """Make the expression negative.""" 

1017 

1018 operator = "-" 

1019 

1020 

1021class Pos(UnaryExpr): 

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

1023 

1024 operator = "+" 

1025 

1026 

1027# Helpers for extensions 

1028 

1029 

1030class EnvironmentAttribute(Expr): 

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

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

1033 """ 

1034 

1035 fields = ("name",) 

1036 name: str 

1037 

1038 

1039class ExtensionAttribute(Expr): 

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

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

1042 

1043 This node is usually constructed by calling the 

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

1045 """ 

1046 

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

1048 identifier: str 

1049 name: str 

1050 

1051 

1052class ImportedName(Expr): 

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

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

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

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

1057 """ 

1058 

1059 fields = ("importname",) 

1060 importname: str 

1061 

1062 

1063class InternalName(Expr): 

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

1065 yourself but the parser provides a 

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

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

1068 template and is not treated specially by the compiler. 

1069 """ 

1070 

1071 fields = ("name",) 

1072 name: str 

1073 

1074 def __init__(self) -> None: 

1075 raise TypeError( 

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

1077 "`free_identifier` method on a parser." 

1078 ) 

1079 

1080 

1081class MarkSafe(Expr): 

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

1083 

1084 fields = ("expr",) 

1085 expr: Expr 

1086 

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

1088 eval_ctx = get_eval_context(self, eval_ctx) 

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

1090 

1091 

1092class MarkSafeIfAutoescape(Expr): 

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

1094 only if autoescaping is active. 

1095 

1096 .. versionadded:: 2.5 

1097 """ 

1098 

1099 fields = ("expr",) 

1100 expr: Expr 

1101 

1102 def as_const( 

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

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

1105 eval_ctx = get_eval_context(self, eval_ctx) 

1106 if eval_ctx.volatile: 

1107 raise Impossible() 

1108 expr = self.expr.as_const(eval_ctx) 

1109 if eval_ctx.autoescape: 

1110 return Markup(expr) 

1111 return expr 

1112 

1113 

1114class ContextReference(Expr): 

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

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

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

1118 

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

1120 variable named `foo`:: 

1121 

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

1123 Getattr(ContextReference(), 'name')) 

1124 

1125 This is basically equivalent to using the 

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

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

1128 first argument to a function. 

1129 """ 

1130 

1131 

1132class DerivedContextReference(Expr): 

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

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

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

1136 

1137 .. versionadded:: 2.11 

1138 """ 

1139 

1140 

1141class Continue(Stmt): 

1142 """Continue a loop.""" 

1143 

1144 

1145class Break(Stmt): 

1146 """Break a loop.""" 

1147 

1148 

1149class Scope(Stmt): 

1150 """An artificial scope.""" 

1151 

1152 fields = ("body",) 

1153 body: t.List[Node] 

1154 

1155 

1156class OverlayScope(Stmt): 

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

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

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

1160 field has to evaluate to a dictionary object. 

1161 

1162 Example usage:: 

1163 

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

1165 body=[...]) 

1166 

1167 .. versionadded:: 2.10 

1168 """ 

1169 

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

1171 context: Expr 

1172 body: t.List[Node] 

1173 

1174 

1175class EvalContextModifier(Stmt): 

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

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

1178 

1179 Example to change the `autoescape` setting:: 

1180 

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

1182 """ 

1183 

1184 fields = ("options",) 

1185 options: t.List[Keyword] 

1186 

1187 

1188class ScopedEvalContextModifier(EvalContextModifier): 

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

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

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

1192 """ 

1193 

1194 fields = ("body",) 

1195 body: t.List[Node] 

1196 

1197 

1198# make sure nobody creates custom nodes 

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

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

1201 

1202 

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

1204del _failing_new