Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/jinja2/nodes.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 """AST nodes generated by the parser for the compiler. Also provides | |
| 3 some node tree helper functions used by the parser and compiler in order | |
| 4 to normalize nodes. | |
| 5 """ | |
| 6 import operator | |
| 7 from collections import deque | |
| 8 | |
| 9 from markupsafe import Markup | |
| 10 | |
| 11 from ._compat import izip | |
| 12 from ._compat import PY2 | |
| 13 from ._compat import text_type | |
| 14 from ._compat import with_metaclass | |
| 15 | |
| 16 _binop_to_func = { | |
| 17 "*": operator.mul, | |
| 18 "/": operator.truediv, | |
| 19 "//": operator.floordiv, | |
| 20 "**": operator.pow, | |
| 21 "%": operator.mod, | |
| 22 "+": operator.add, | |
| 23 "-": operator.sub, | |
| 24 } | |
| 25 | |
| 26 _uaop_to_func = {"not": operator.not_, "+": operator.pos, "-": operator.neg} | |
| 27 | |
| 28 _cmpop_to_func = { | |
| 29 "eq": operator.eq, | |
| 30 "ne": operator.ne, | |
| 31 "gt": operator.gt, | |
| 32 "gteq": operator.ge, | |
| 33 "lt": operator.lt, | |
| 34 "lteq": operator.le, | |
| 35 "in": lambda a, b: a in b, | |
| 36 "notin": lambda a, b: a not in b, | |
| 37 } | |
| 38 | |
| 39 | |
| 40 class Impossible(Exception): | |
| 41 """Raised if the node could not perform a requested action.""" | |
| 42 | |
| 43 | |
| 44 class NodeType(type): | |
| 45 """A metaclass for nodes that handles the field and attribute | |
| 46 inheritance. fields and attributes from the parent class are | |
| 47 automatically forwarded to the child.""" | |
| 48 | |
| 49 def __new__(mcs, name, bases, d): | |
| 50 for attr in "fields", "attributes": | |
| 51 storage = [] | |
| 52 storage.extend(getattr(bases[0], attr, ())) | |
| 53 storage.extend(d.get(attr, ())) | |
| 54 assert len(bases) == 1, "multiple inheritance not allowed" | |
| 55 assert len(storage) == len(set(storage)), "layout conflict" | |
| 56 d[attr] = tuple(storage) | |
| 57 d.setdefault("abstract", False) | |
| 58 return type.__new__(mcs, name, bases, d) | |
| 59 | |
| 60 | |
| 61 class EvalContext(object): | |
| 62 """Holds evaluation time information. Custom attributes can be attached | |
| 63 to it in extensions. | |
| 64 """ | |
| 65 | |
| 66 def __init__(self, environment, template_name=None): | |
| 67 self.environment = environment | |
| 68 if callable(environment.autoescape): | |
| 69 self.autoescape = environment.autoescape(template_name) | |
| 70 else: | |
| 71 self.autoescape = environment.autoescape | |
| 72 self.volatile = False | |
| 73 | |
| 74 def save(self): | |
| 75 return self.__dict__.copy() | |
| 76 | |
| 77 def revert(self, old): | |
| 78 self.__dict__.clear() | |
| 79 self.__dict__.update(old) | |
| 80 | |
| 81 | |
| 82 def get_eval_context(node, ctx): | |
| 83 if ctx is None: | |
| 84 if node.environment is None: | |
| 85 raise RuntimeError( | |
| 86 "if no eval context is passed, the " | |
| 87 "node must have an attached " | |
| 88 "environment." | |
| 89 ) | |
| 90 return EvalContext(node.environment) | |
| 91 return ctx | |
| 92 | |
| 93 | |
| 94 class Node(with_metaclass(NodeType, object)): | |
| 95 """Baseclass for all Jinja nodes. There are a number of nodes available | |
| 96 of different types. There are four major types: | |
| 97 | |
| 98 - :class:`Stmt`: statements | |
| 99 - :class:`Expr`: expressions | |
| 100 - :class:`Helper`: helper nodes | |
| 101 - :class:`Template`: the outermost wrapper node | |
| 102 | |
| 103 All nodes have fields and attributes. Fields may be other nodes, lists, | |
| 104 or arbitrary values. Fields are passed to the constructor as regular | |
| 105 positional arguments, attributes as keyword arguments. Each node has | |
| 106 two attributes: `lineno` (the line number of the node) and `environment`. | |
| 107 The `environment` attribute is set at the end of the parsing process for | |
| 108 all nodes automatically. | |
| 109 """ | |
| 110 | |
| 111 fields = () | |
| 112 attributes = ("lineno", "environment") | |
| 113 abstract = True | |
| 114 | |
| 115 def __init__(self, *fields, **attributes): | |
| 116 if self.abstract: | |
| 117 raise TypeError("abstract nodes are not instantiable") | |
| 118 if fields: | |
| 119 if len(fields) != len(self.fields): | |
| 120 if not self.fields: | |
| 121 raise TypeError("%r takes 0 arguments" % self.__class__.__name__) | |
| 122 raise TypeError( | |
| 123 "%r takes 0 or %d argument%s" | |
| 124 % ( | |
| 125 self.__class__.__name__, | |
| 126 len(self.fields), | |
| 127 len(self.fields) != 1 and "s" or "", | |
| 128 ) | |
| 129 ) | |
| 130 for name, arg in izip(self.fields, fields): | |
| 131 setattr(self, name, arg) | |
| 132 for attr in self.attributes: | |
| 133 setattr(self, attr, attributes.pop(attr, None)) | |
| 134 if attributes: | |
| 135 raise TypeError("unknown attribute %r" % next(iter(attributes))) | |
| 136 | |
| 137 def iter_fields(self, exclude=None, only=None): | |
| 138 """This method iterates over all fields that are defined and yields | |
| 139 ``(key, value)`` tuples. Per default all fields are returned, but | |
| 140 it's possible to limit that to some fields by providing the `only` | |
| 141 parameter or to exclude some using the `exclude` parameter. Both | |
| 142 should be sets or tuples of field names. | |
| 143 """ | |
| 144 for name in self.fields: | |
| 145 if ( | |
| 146 (exclude is only is None) | |
| 147 or (exclude is not None and name not in exclude) | |
| 148 or (only is not None and name in only) | |
| 149 ): | |
| 150 try: | |
| 151 yield name, getattr(self, name) | |
| 152 except AttributeError: | |
| 153 pass | |
| 154 | |
| 155 def iter_child_nodes(self, exclude=None, only=None): | |
| 156 """Iterates over all direct child nodes of the node. This iterates | |
| 157 over all fields and yields the values of they are nodes. If the value | |
| 158 of a field is a list all the nodes in that list are returned. | |
| 159 """ | |
| 160 for _, item in self.iter_fields(exclude, only): | |
| 161 if isinstance(item, list): | |
| 162 for n in item: | |
| 163 if isinstance(n, Node): | |
| 164 yield n | |
| 165 elif isinstance(item, Node): | |
| 166 yield item | |
| 167 | |
| 168 def find(self, node_type): | |
| 169 """Find the first node of a given type. If no such node exists the | |
| 170 return value is `None`. | |
| 171 """ | |
| 172 for result in self.find_all(node_type): | |
| 173 return result | |
| 174 | |
| 175 def find_all(self, node_type): | |
| 176 """Find all the nodes of a given type. If the type is a tuple, | |
| 177 the check is performed for any of the tuple items. | |
| 178 """ | |
| 179 for child in self.iter_child_nodes(): | |
| 180 if isinstance(child, node_type): | |
| 181 yield child | |
| 182 for result in child.find_all(node_type): | |
| 183 yield result | |
| 184 | |
| 185 def set_ctx(self, ctx): | |
| 186 """Reset the context of a node and all child nodes. Per default the | |
| 187 parser will all generate nodes that have a 'load' context as it's the | |
| 188 most common one. This method is used in the parser to set assignment | |
| 189 targets and other nodes to a store context. | |
| 190 """ | |
| 191 todo = deque([self]) | |
| 192 while todo: | |
| 193 node = todo.popleft() | |
| 194 if "ctx" in node.fields: | |
| 195 node.ctx = ctx | |
| 196 todo.extend(node.iter_child_nodes()) | |
| 197 return self | |
| 198 | |
| 199 def set_lineno(self, lineno, override=False): | |
| 200 """Set the line numbers of the node and children.""" | |
| 201 todo = deque([self]) | |
| 202 while todo: | |
| 203 node = todo.popleft() | |
| 204 if "lineno" in node.attributes: | |
| 205 if node.lineno is None or override: | |
| 206 node.lineno = lineno | |
| 207 todo.extend(node.iter_child_nodes()) | |
| 208 return self | |
| 209 | |
| 210 def set_environment(self, environment): | |
| 211 """Set the environment for all nodes.""" | |
| 212 todo = deque([self]) | |
| 213 while todo: | |
| 214 node = todo.popleft() | |
| 215 node.environment = environment | |
| 216 todo.extend(node.iter_child_nodes()) | |
| 217 return self | |
| 218 | |
| 219 def __eq__(self, other): | |
| 220 return type(self) is type(other) and tuple(self.iter_fields()) == tuple( | |
| 221 other.iter_fields() | |
| 222 ) | |
| 223 | |
| 224 def __ne__(self, other): | |
| 225 return not self.__eq__(other) | |
| 226 | |
| 227 # Restore Python 2 hashing behavior on Python 3 | |
| 228 __hash__ = object.__hash__ | |
| 229 | |
| 230 def __repr__(self): | |
| 231 return "%s(%s)" % ( | |
| 232 self.__class__.__name__, | |
| 233 ", ".join("%s=%r" % (arg, getattr(self, arg, None)) for arg in self.fields), | |
| 234 ) | |
| 235 | |
| 236 def dump(self): | |
| 237 def _dump(node): | |
| 238 if not isinstance(node, Node): | |
| 239 buf.append(repr(node)) | |
| 240 return | |
| 241 | |
| 242 buf.append("nodes.%s(" % node.__class__.__name__) | |
| 243 if not node.fields: | |
| 244 buf.append(")") | |
| 245 return | |
| 246 for idx, field in enumerate(node.fields): | |
| 247 if idx: | |
| 248 buf.append(", ") | |
| 249 value = getattr(node, field) | |
| 250 if isinstance(value, list): | |
| 251 buf.append("[") | |
| 252 for idx, item in enumerate(value): | |
| 253 if idx: | |
| 254 buf.append(", ") | |
| 255 _dump(item) | |
| 256 buf.append("]") | |
| 257 else: | |
| 258 _dump(value) | |
| 259 buf.append(")") | |
| 260 | |
| 261 buf = [] | |
| 262 _dump(self) | |
| 263 return "".join(buf) | |
| 264 | |
| 265 | |
| 266 class Stmt(Node): | |
| 267 """Base node for all statements.""" | |
| 268 | |
| 269 abstract = True | |
| 270 | |
| 271 | |
| 272 class Helper(Node): | |
| 273 """Nodes that exist in a specific context only.""" | |
| 274 | |
| 275 abstract = True | |
| 276 | |
| 277 | |
| 278 class Template(Node): | |
| 279 """Node that represents a template. This must be the outermost node that | |
| 280 is passed to the compiler. | |
| 281 """ | |
| 282 | |
| 283 fields = ("body",) | |
| 284 | |
| 285 | |
| 286 class Output(Stmt): | |
| 287 """A node that holds multiple expressions which are then printed out. | |
| 288 This is used both for the `print` statement and the regular template data. | |
| 289 """ | |
| 290 | |
| 291 fields = ("nodes",) | |
| 292 | |
| 293 | |
| 294 class Extends(Stmt): | |
| 295 """Represents an extends statement.""" | |
| 296 | |
| 297 fields = ("template",) | |
| 298 | |
| 299 | |
| 300 class For(Stmt): | |
| 301 """The for loop. `target` is the target for the iteration (usually a | |
| 302 :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list | |
| 303 of nodes that are used as loop-body, and `else_` a list of nodes for the | |
| 304 `else` block. If no else node exists it has to be an empty list. | |
| 305 | |
| 306 For filtered nodes an expression can be stored as `test`, otherwise `None`. | |
| 307 """ | |
| 308 | |
| 309 fields = ("target", "iter", "body", "else_", "test", "recursive") | |
| 310 | |
| 311 | |
| 312 class If(Stmt): | |
| 313 """If `test` is true, `body` is rendered, else `else_`.""" | |
| 314 | |
| 315 fields = ("test", "body", "elif_", "else_") | |
| 316 | |
| 317 | |
| 318 class Macro(Stmt): | |
| 319 """A macro definition. `name` is the name of the macro, `args` a list of | |
| 320 arguments and `defaults` a list of defaults if there are any. `body` is | |
| 321 a list of nodes for the macro body. | |
| 322 """ | |
| 323 | |
| 324 fields = ("name", "args", "defaults", "body") | |
| 325 | |
| 326 | |
| 327 class CallBlock(Stmt): | |
| 328 """Like a macro without a name but a call instead. `call` is called with | |
| 329 the unnamed macro as `caller` argument this node holds. | |
| 330 """ | |
| 331 | |
| 332 fields = ("call", "args", "defaults", "body") | |
| 333 | |
| 334 | |
| 335 class FilterBlock(Stmt): | |
| 336 """Node for filter sections.""" | |
| 337 | |
| 338 fields = ("body", "filter") | |
| 339 | |
| 340 | |
| 341 class With(Stmt): | |
| 342 """Specific node for with statements. In older versions of Jinja the | |
| 343 with statement was implemented on the base of the `Scope` node instead. | |
| 344 | |
| 345 .. versionadded:: 2.9.3 | |
| 346 """ | |
| 347 | |
| 348 fields = ("targets", "values", "body") | |
| 349 | |
| 350 | |
| 351 class Block(Stmt): | |
| 352 """A node that represents a block.""" | |
| 353 | |
| 354 fields = ("name", "body", "scoped") | |
| 355 | |
| 356 | |
| 357 class Include(Stmt): | |
| 358 """A node that represents the include tag.""" | |
| 359 | |
| 360 fields = ("template", "with_context", "ignore_missing") | |
| 361 | |
| 362 | |
| 363 class Import(Stmt): | |
| 364 """A node that represents the import tag.""" | |
| 365 | |
| 366 fields = ("template", "target", "with_context") | |
| 367 | |
| 368 | |
| 369 class FromImport(Stmt): | |
| 370 """A node that represents the from import tag. It's important to not | |
| 371 pass unsafe names to the name attribute. The compiler translates the | |
| 372 attribute lookups directly into getattr calls and does *not* use the | |
| 373 subscript callback of the interface. As exported variables may not | |
| 374 start with double underscores (which the parser asserts) this is not a | |
| 375 problem for regular Jinja code, but if this node is used in an extension | |
| 376 extra care must be taken. | |
| 377 | |
| 378 The list of names may contain tuples if aliases are wanted. | |
| 379 """ | |
| 380 | |
| 381 fields = ("template", "names", "with_context") | |
| 382 | |
| 383 | |
| 384 class ExprStmt(Stmt): | |
| 385 """A statement that evaluates an expression and discards the result.""" | |
| 386 | |
| 387 fields = ("node",) | |
| 388 | |
| 389 | |
| 390 class Assign(Stmt): | |
| 391 """Assigns an expression to a target.""" | |
| 392 | |
| 393 fields = ("target", "node") | |
| 394 | |
| 395 | |
| 396 class AssignBlock(Stmt): | |
| 397 """Assigns a block to a target.""" | |
| 398 | |
| 399 fields = ("target", "filter", "body") | |
| 400 | |
| 401 | |
| 402 class Expr(Node): | |
| 403 """Baseclass for all expressions.""" | |
| 404 | |
| 405 abstract = True | |
| 406 | |
| 407 def as_const(self, eval_ctx=None): | |
| 408 """Return the value of the expression as constant or raise | |
| 409 :exc:`Impossible` if this was not possible. | |
| 410 | |
| 411 An :class:`EvalContext` can be provided, if none is given | |
| 412 a default context is created which requires the nodes to have | |
| 413 an attached environment. | |
| 414 | |
| 415 .. versionchanged:: 2.4 | |
| 416 the `eval_ctx` parameter was added. | |
| 417 """ | |
| 418 raise Impossible() | |
| 419 | |
| 420 def can_assign(self): | |
| 421 """Check if it's possible to assign something to this node.""" | |
| 422 return False | |
| 423 | |
| 424 | |
| 425 class BinExpr(Expr): | |
| 426 """Baseclass for all binary expressions.""" | |
| 427 | |
| 428 fields = ("left", "right") | |
| 429 operator = None | |
| 430 abstract = True | |
| 431 | |
| 432 def as_const(self, eval_ctx=None): | |
| 433 eval_ctx = get_eval_context(self, eval_ctx) | |
| 434 # intercepted operators cannot be folded at compile time | |
| 435 if ( | |
| 436 self.environment.sandboxed | |
| 437 and self.operator in self.environment.intercepted_binops | |
| 438 ): | |
| 439 raise Impossible() | |
| 440 f = _binop_to_func[self.operator] | |
| 441 try: | |
| 442 return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) | |
| 443 except Exception: | |
| 444 raise Impossible() | |
| 445 | |
| 446 | |
| 447 class UnaryExpr(Expr): | |
| 448 """Baseclass for all unary expressions.""" | |
| 449 | |
| 450 fields = ("node",) | |
| 451 operator = None | |
| 452 abstract = True | |
| 453 | |
| 454 def as_const(self, eval_ctx=None): | |
| 455 eval_ctx = get_eval_context(self, eval_ctx) | |
| 456 # intercepted operators cannot be folded at compile time | |
| 457 if ( | |
| 458 self.environment.sandboxed | |
| 459 and self.operator in self.environment.intercepted_unops | |
| 460 ): | |
| 461 raise Impossible() | |
| 462 f = _uaop_to_func[self.operator] | |
| 463 try: | |
| 464 return f(self.node.as_const(eval_ctx)) | |
| 465 except Exception: | |
| 466 raise Impossible() | |
| 467 | |
| 468 | |
| 469 class Name(Expr): | |
| 470 """Looks up a name or stores a value in a name. | |
| 471 The `ctx` of the node can be one of the following values: | |
| 472 | |
| 473 - `store`: store a value in the name | |
| 474 - `load`: load that name | |
| 475 - `param`: like `store` but if the name was defined as function parameter. | |
| 476 """ | |
| 477 | |
| 478 fields = ("name", "ctx") | |
| 479 | |
| 480 def can_assign(self): | |
| 481 return self.name not in ("true", "false", "none", "True", "False", "None") | |
| 482 | |
| 483 | |
| 484 class NSRef(Expr): | |
| 485 """Reference to a namespace value assignment""" | |
| 486 | |
| 487 fields = ("name", "attr") | |
| 488 | |
| 489 def can_assign(self): | |
| 490 # We don't need any special checks here; NSRef assignments have a | |
| 491 # runtime check to ensure the target is a namespace object which will | |
| 492 # have been checked already as it is created using a normal assignment | |
| 493 # which goes through a `Name` node. | |
| 494 return True | |
| 495 | |
| 496 | |
| 497 class Literal(Expr): | |
| 498 """Baseclass for literals.""" | |
| 499 | |
| 500 abstract = True | |
| 501 | |
| 502 | |
| 503 class Const(Literal): | |
| 504 """All constant values. The parser will return this node for simple | |
| 505 constants such as ``42`` or ``"foo"`` but it can be used to store more | |
| 506 complex values such as lists too. Only constants with a safe | |
| 507 representation (objects where ``eval(repr(x)) == x`` is true). | |
| 508 """ | |
| 509 | |
| 510 fields = ("value",) | |
| 511 | |
| 512 def as_const(self, eval_ctx=None): | |
| 513 rv = self.value | |
| 514 if ( | |
| 515 PY2 | |
| 516 and type(rv) is text_type | |
| 517 and self.environment.policies["compiler.ascii_str"] | |
| 518 ): | |
| 519 try: | |
| 520 rv = rv.encode("ascii") | |
| 521 except UnicodeError: | |
| 522 pass | |
| 523 return rv | |
| 524 | |
| 525 @classmethod | |
| 526 def from_untrusted(cls, value, lineno=None, environment=None): | |
| 527 """Return a const object if the value is representable as | |
| 528 constant value in the generated code, otherwise it will raise | |
| 529 an `Impossible` exception. | |
| 530 """ | |
| 531 from .compiler import has_safe_repr | |
| 532 | |
| 533 if not has_safe_repr(value): | |
| 534 raise Impossible() | |
| 535 return cls(value, lineno=lineno, environment=environment) | |
| 536 | |
| 537 | |
| 538 class TemplateData(Literal): | |
| 539 """A constant template string.""" | |
| 540 | |
| 541 fields = ("data",) | |
| 542 | |
| 543 def as_const(self, eval_ctx=None): | |
| 544 eval_ctx = get_eval_context(self, eval_ctx) | |
| 545 if eval_ctx.volatile: | |
| 546 raise Impossible() | |
| 547 if eval_ctx.autoescape: | |
| 548 return Markup(self.data) | |
| 549 return self.data | |
| 550 | |
| 551 | |
| 552 class Tuple(Literal): | |
| 553 """For loop unpacking and some other things like multiple arguments | |
| 554 for subscripts. Like for :class:`Name` `ctx` specifies if the tuple | |
| 555 is used for loading the names or storing. | |
| 556 """ | |
| 557 | |
| 558 fields = ("items", "ctx") | |
| 559 | |
| 560 def as_const(self, eval_ctx=None): | |
| 561 eval_ctx = get_eval_context(self, eval_ctx) | |
| 562 return tuple(x.as_const(eval_ctx) for x in self.items) | |
| 563 | |
| 564 def can_assign(self): | |
| 565 for item in self.items: | |
| 566 if not item.can_assign(): | |
| 567 return False | |
| 568 return True | |
| 569 | |
| 570 | |
| 571 class List(Literal): | |
| 572 """Any list literal such as ``[1, 2, 3]``""" | |
| 573 | |
| 574 fields = ("items",) | |
| 575 | |
| 576 def as_const(self, eval_ctx=None): | |
| 577 eval_ctx = get_eval_context(self, eval_ctx) | |
| 578 return [x.as_const(eval_ctx) for x in self.items] | |
| 579 | |
| 580 | |
| 581 class Dict(Literal): | |
| 582 """Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of | |
| 583 :class:`Pair` nodes. | |
| 584 """ | |
| 585 | |
| 586 fields = ("items",) | |
| 587 | |
| 588 def as_const(self, eval_ctx=None): | |
| 589 eval_ctx = get_eval_context(self, eval_ctx) | |
| 590 return dict(x.as_const(eval_ctx) for x in self.items) | |
| 591 | |
| 592 | |
| 593 class Pair(Helper): | |
| 594 """A key, value pair for dicts.""" | |
| 595 | |
| 596 fields = ("key", "value") | |
| 597 | |
| 598 def as_const(self, eval_ctx=None): | |
| 599 eval_ctx = get_eval_context(self, eval_ctx) | |
| 600 return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx) | |
| 601 | |
| 602 | |
| 603 class Keyword(Helper): | |
| 604 """A key, value pair for keyword arguments where key is a string.""" | |
| 605 | |
| 606 fields = ("key", "value") | |
| 607 | |
| 608 def as_const(self, eval_ctx=None): | |
| 609 eval_ctx = get_eval_context(self, eval_ctx) | |
| 610 return self.key, self.value.as_const(eval_ctx) | |
| 611 | |
| 612 | |
| 613 class CondExpr(Expr): | |
| 614 """A conditional expression (inline if expression). (``{{ | |
| 615 foo if bar else baz }}``) | |
| 616 """ | |
| 617 | |
| 618 fields = ("test", "expr1", "expr2") | |
| 619 | |
| 620 def as_const(self, eval_ctx=None): | |
| 621 eval_ctx = get_eval_context(self, eval_ctx) | |
| 622 if self.test.as_const(eval_ctx): | |
| 623 return self.expr1.as_const(eval_ctx) | |
| 624 | |
| 625 # if we evaluate to an undefined object, we better do that at runtime | |
| 626 if self.expr2 is None: | |
| 627 raise Impossible() | |
| 628 | |
| 629 return self.expr2.as_const(eval_ctx) | |
| 630 | |
| 631 | |
| 632 def args_as_const(node, eval_ctx): | |
| 633 args = [x.as_const(eval_ctx) for x in node.args] | |
| 634 kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs) | |
| 635 | |
| 636 if node.dyn_args is not None: | |
| 637 try: | |
| 638 args.extend(node.dyn_args.as_const(eval_ctx)) | |
| 639 except Exception: | |
| 640 raise Impossible() | |
| 641 | |
| 642 if node.dyn_kwargs is not None: | |
| 643 try: | |
| 644 kwargs.update(node.dyn_kwargs.as_const(eval_ctx)) | |
| 645 except Exception: | |
| 646 raise Impossible() | |
| 647 | |
| 648 return args, kwargs | |
| 649 | |
| 650 | |
| 651 class Filter(Expr): | |
| 652 """This node applies a filter on an expression. `name` is the name of | |
| 653 the filter, the rest of the fields are the same as for :class:`Call`. | |
| 654 | |
| 655 If the `node` of a filter is `None` the contents of the last buffer are | |
| 656 filtered. Buffers are created by macros and filter blocks. | |
| 657 """ | |
| 658 | |
| 659 fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
| 660 | |
| 661 def as_const(self, eval_ctx=None): | |
| 662 eval_ctx = get_eval_context(self, eval_ctx) | |
| 663 | |
| 664 if eval_ctx.volatile or self.node is None: | |
| 665 raise Impossible() | |
| 666 | |
| 667 # we have to be careful here because we call filter_ below. | |
| 668 # if this variable would be called filter, 2to3 would wrap the | |
| 669 # call in a list because it is assuming we are talking about the | |
| 670 # builtin filter function here which no longer returns a list in | |
| 671 # python 3. because of that, do not rename filter_ to filter! | |
| 672 filter_ = self.environment.filters.get(self.name) | |
| 673 | |
| 674 if filter_ is None or getattr(filter_, "contextfilter", False) is True: | |
| 675 raise Impossible() | |
| 676 | |
| 677 # We cannot constant handle async filters, so we need to make sure | |
| 678 # to not go down this path. | |
| 679 if eval_ctx.environment.is_async and getattr( | |
| 680 filter_, "asyncfiltervariant", False | |
| 681 ): | |
| 682 raise Impossible() | |
| 683 | |
| 684 args, kwargs = args_as_const(self, eval_ctx) | |
| 685 args.insert(0, self.node.as_const(eval_ctx)) | |
| 686 | |
| 687 if getattr(filter_, "evalcontextfilter", False) is True: | |
| 688 args.insert(0, eval_ctx) | |
| 689 elif getattr(filter_, "environmentfilter", False) is True: | |
| 690 args.insert(0, self.environment) | |
| 691 | |
| 692 try: | |
| 693 return filter_(*args, **kwargs) | |
| 694 except Exception: | |
| 695 raise Impossible() | |
| 696 | |
| 697 | |
| 698 class Test(Expr): | |
| 699 """Applies a test on an expression. `name` is the name of the test, the | |
| 700 rest of the fields are the same as for :class:`Call`. | |
| 701 """ | |
| 702 | |
| 703 fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
| 704 | |
| 705 def as_const(self, eval_ctx=None): | |
| 706 test = self.environment.tests.get(self.name) | |
| 707 | |
| 708 if test is None: | |
| 709 raise Impossible() | |
| 710 | |
| 711 eval_ctx = get_eval_context(self, eval_ctx) | |
| 712 args, kwargs = args_as_const(self, eval_ctx) | |
| 713 args.insert(0, self.node.as_const(eval_ctx)) | |
| 714 | |
| 715 try: | |
| 716 return test(*args, **kwargs) | |
| 717 except Exception: | |
| 718 raise Impossible() | |
| 719 | |
| 720 | |
| 721 class Call(Expr): | |
| 722 """Calls an expression. `args` is a list of arguments, `kwargs` a list | |
| 723 of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args` | |
| 724 and `dyn_kwargs` has to be either `None` or a node that is used as | |
| 725 node for dynamic positional (``*args``) or keyword (``**kwargs``) | |
| 726 arguments. | |
| 727 """ | |
| 728 | |
| 729 fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
| 730 | |
| 731 | |
| 732 class Getitem(Expr): | |
| 733 """Get an attribute or item from an expression and prefer the item.""" | |
| 734 | |
| 735 fields = ("node", "arg", "ctx") | |
| 736 | |
| 737 def as_const(self, eval_ctx=None): | |
| 738 eval_ctx = get_eval_context(self, eval_ctx) | |
| 739 if self.ctx != "load": | |
| 740 raise Impossible() | |
| 741 try: | |
| 742 return self.environment.getitem( | |
| 743 self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) | |
| 744 ) | |
| 745 except Exception: | |
| 746 raise Impossible() | |
| 747 | |
| 748 def can_assign(self): | |
| 749 return False | |
| 750 | |
| 751 | |
| 752 class Getattr(Expr): | |
| 753 """Get an attribute or item from an expression that is a ascii-only | |
| 754 bytestring and prefer the attribute. | |
| 755 """ | |
| 756 | |
| 757 fields = ("node", "attr", "ctx") | |
| 758 | |
| 759 def as_const(self, eval_ctx=None): | |
| 760 if self.ctx != "load": | |
| 761 raise Impossible() | |
| 762 try: | |
| 763 eval_ctx = get_eval_context(self, eval_ctx) | |
| 764 return self.environment.getattr(self.node.as_const(eval_ctx), self.attr) | |
| 765 except Exception: | |
| 766 raise Impossible() | |
| 767 | |
| 768 def can_assign(self): | |
| 769 return False | |
| 770 | |
| 771 | |
| 772 class Slice(Expr): | |
| 773 """Represents a slice object. This must only be used as argument for | |
| 774 :class:`Subscript`. | |
| 775 """ | |
| 776 | |
| 777 fields = ("start", "stop", "step") | |
| 778 | |
| 779 def as_const(self, eval_ctx=None): | |
| 780 eval_ctx = get_eval_context(self, eval_ctx) | |
| 781 | |
| 782 def const(obj): | |
| 783 if obj is None: | |
| 784 return None | |
| 785 return obj.as_const(eval_ctx) | |
| 786 | |
| 787 return slice(const(self.start), const(self.stop), const(self.step)) | |
| 788 | |
| 789 | |
| 790 class Concat(Expr): | |
| 791 """Concatenates the list of expressions provided after converting them to | |
| 792 unicode. | |
| 793 """ | |
| 794 | |
| 795 fields = ("nodes",) | |
| 796 | |
| 797 def as_const(self, eval_ctx=None): | |
| 798 eval_ctx = get_eval_context(self, eval_ctx) | |
| 799 return "".join(text_type(x.as_const(eval_ctx)) for x in self.nodes) | |
| 800 | |
| 801 | |
| 802 class Compare(Expr): | |
| 803 """Compares an expression with some other expressions. `ops` must be a | |
| 804 list of :class:`Operand`\\s. | |
| 805 """ | |
| 806 | |
| 807 fields = ("expr", "ops") | |
| 808 | |
| 809 def as_const(self, eval_ctx=None): | |
| 810 eval_ctx = get_eval_context(self, eval_ctx) | |
| 811 result = value = self.expr.as_const(eval_ctx) | |
| 812 | |
| 813 try: | |
| 814 for op in self.ops: | |
| 815 new_value = op.expr.as_const(eval_ctx) | |
| 816 result = _cmpop_to_func[op.op](value, new_value) | |
| 817 | |
| 818 if not result: | |
| 819 return False | |
| 820 | |
| 821 value = new_value | |
| 822 except Exception: | |
| 823 raise Impossible() | |
| 824 | |
| 825 return result | |
| 826 | |
| 827 | |
| 828 class Operand(Helper): | |
| 829 """Holds an operator and an expression.""" | |
| 830 | |
| 831 fields = ("op", "expr") | |
| 832 | |
| 833 | |
| 834 if __debug__: | |
| 835 Operand.__doc__ += "\nThe following operators are available: " + ", ".join( | |
| 836 sorted( | |
| 837 "``%s``" % x | |
| 838 for x in set(_binop_to_func) | set(_uaop_to_func) | set(_cmpop_to_func) | |
| 839 ) | |
| 840 ) | |
| 841 | |
| 842 | |
| 843 class Mul(BinExpr): | |
| 844 """Multiplies the left with the right node.""" | |
| 845 | |
| 846 operator = "*" | |
| 847 | |
| 848 | |
| 849 class Div(BinExpr): | |
| 850 """Divides the left by the right node.""" | |
| 851 | |
| 852 operator = "/" | |
| 853 | |
| 854 | |
| 855 class FloorDiv(BinExpr): | |
| 856 """Divides the left by the right node and truncates conver the | |
| 857 result into an integer by truncating. | |
| 858 """ | |
| 859 | |
| 860 operator = "//" | |
| 861 | |
| 862 | |
| 863 class Add(BinExpr): | |
| 864 """Add the left to the right node.""" | |
| 865 | |
| 866 operator = "+" | |
| 867 | |
| 868 | |
| 869 class Sub(BinExpr): | |
| 870 """Subtract the right from the left node.""" | |
| 871 | |
| 872 operator = "-" | |
| 873 | |
| 874 | |
| 875 class Mod(BinExpr): | |
| 876 """Left modulo right.""" | |
| 877 | |
| 878 operator = "%" | |
| 879 | |
| 880 | |
| 881 class Pow(BinExpr): | |
| 882 """Left to the power of right.""" | |
| 883 | |
| 884 operator = "**" | |
| 885 | |
| 886 | |
| 887 class And(BinExpr): | |
| 888 """Short circuited AND.""" | |
| 889 | |
| 890 operator = "and" | |
| 891 | |
| 892 def as_const(self, eval_ctx=None): | |
| 893 eval_ctx = get_eval_context(self, eval_ctx) | |
| 894 return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) | |
| 895 | |
| 896 | |
| 897 class Or(BinExpr): | |
| 898 """Short circuited OR.""" | |
| 899 | |
| 900 operator = "or" | |
| 901 | |
| 902 def as_const(self, eval_ctx=None): | |
| 903 eval_ctx = get_eval_context(self, eval_ctx) | |
| 904 return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) | |
| 905 | |
| 906 | |
| 907 class Not(UnaryExpr): | |
| 908 """Negate the expression.""" | |
| 909 | |
| 910 operator = "not" | |
| 911 | |
| 912 | |
| 913 class Neg(UnaryExpr): | |
| 914 """Make the expression negative.""" | |
| 915 | |
| 916 operator = "-" | |
| 917 | |
| 918 | |
| 919 class Pos(UnaryExpr): | |
| 920 """Make the expression positive (noop for most expressions)""" | |
| 921 | |
| 922 operator = "+" | |
| 923 | |
| 924 | |
| 925 # Helpers for extensions | |
| 926 | |
| 927 | |
| 928 class EnvironmentAttribute(Expr): | |
| 929 """Loads an attribute from the environment object. This is useful for | |
| 930 extensions that want to call a callback stored on the environment. | |
| 931 """ | |
| 932 | |
| 933 fields = ("name",) | |
| 934 | |
| 935 | |
| 936 class ExtensionAttribute(Expr): | |
| 937 """Returns the attribute of an extension bound to the environment. | |
| 938 The identifier is the identifier of the :class:`Extension`. | |
| 939 | |
| 940 This node is usually constructed by calling the | |
| 941 :meth:`~jinja2.ext.Extension.attr` method on an extension. | |
| 942 """ | |
| 943 | |
| 944 fields = ("identifier", "name") | |
| 945 | |
| 946 | |
| 947 class ImportedName(Expr): | |
| 948 """If created with an import name the import name is returned on node | |
| 949 access. For example ``ImportedName('cgi.escape')`` returns the `escape` | |
| 950 function from the cgi module on evaluation. Imports are optimized by the | |
| 951 compiler so there is no need to assign them to local variables. | |
| 952 """ | |
| 953 | |
| 954 fields = ("importname",) | |
| 955 | |
| 956 | |
| 957 class InternalName(Expr): | |
| 958 """An internal name in the compiler. You cannot create these nodes | |
| 959 yourself but the parser provides a | |
| 960 :meth:`~jinja2.parser.Parser.free_identifier` method that creates | |
| 961 a new identifier for you. This identifier is not available from the | |
| 962 template and is not threated specially by the compiler. | |
| 963 """ | |
| 964 | |
| 965 fields = ("name",) | |
| 966 | |
| 967 def __init__(self): | |
| 968 raise TypeError( | |
| 969 "Can't create internal names. Use the " | |
| 970 "`free_identifier` method on a parser." | |
| 971 ) | |
| 972 | |
| 973 | |
| 974 class MarkSafe(Expr): | |
| 975 """Mark the wrapped expression as safe (wrap it as `Markup`).""" | |
| 976 | |
| 977 fields = ("expr",) | |
| 978 | |
| 979 def as_const(self, eval_ctx=None): | |
| 980 eval_ctx = get_eval_context(self, eval_ctx) | |
| 981 return Markup(self.expr.as_const(eval_ctx)) | |
| 982 | |
| 983 | |
| 984 class MarkSafeIfAutoescape(Expr): | |
| 985 """Mark the wrapped expression as safe (wrap it as `Markup`) but | |
| 986 only if autoescaping is active. | |
| 987 | |
| 988 .. versionadded:: 2.5 | |
| 989 """ | |
| 990 | |
| 991 fields = ("expr",) | |
| 992 | |
| 993 def as_const(self, eval_ctx=None): | |
| 994 eval_ctx = get_eval_context(self, eval_ctx) | |
| 995 if eval_ctx.volatile: | |
| 996 raise Impossible() | |
| 997 expr = self.expr.as_const(eval_ctx) | |
| 998 if eval_ctx.autoescape: | |
| 999 return Markup(expr) | |
| 1000 return expr | |
| 1001 | |
| 1002 | |
| 1003 class ContextReference(Expr): | |
| 1004 """Returns the current template context. It can be used like a | |
| 1005 :class:`Name` node, with a ``'load'`` ctx and will return the | |
| 1006 current :class:`~jinja2.runtime.Context` object. | |
| 1007 | |
| 1008 Here an example that assigns the current template name to a | |
| 1009 variable named `foo`:: | |
| 1010 | |
| 1011 Assign(Name('foo', ctx='store'), | |
| 1012 Getattr(ContextReference(), 'name')) | |
| 1013 | |
| 1014 This is basically equivalent to using the | |
| 1015 :func:`~jinja2.contextfunction` decorator when using the | |
| 1016 high-level API, which causes a reference to the context to be passed | |
| 1017 as the first argument to a function. | |
| 1018 """ | |
| 1019 | |
| 1020 | |
| 1021 class DerivedContextReference(Expr): | |
| 1022 """Return the current template context including locals. Behaves | |
| 1023 exactly like :class:`ContextReference`, but includes local | |
| 1024 variables, such as from a ``for`` loop. | |
| 1025 | |
| 1026 .. versionadded:: 2.11 | |
| 1027 """ | |
| 1028 | |
| 1029 | |
| 1030 class Continue(Stmt): | |
| 1031 """Continue a loop.""" | |
| 1032 | |
| 1033 | |
| 1034 class Break(Stmt): | |
| 1035 """Break a loop.""" | |
| 1036 | |
| 1037 | |
| 1038 class Scope(Stmt): | |
| 1039 """An artificial scope.""" | |
| 1040 | |
| 1041 fields = ("body",) | |
| 1042 | |
| 1043 | |
| 1044 class OverlayScope(Stmt): | |
| 1045 """An overlay scope for extensions. This is a largely unoptimized scope | |
| 1046 that however can be used to introduce completely arbitrary variables into | |
| 1047 a sub scope from a dictionary or dictionary like object. The `context` | |
| 1048 field has to evaluate to a dictionary object. | |
| 1049 | |
| 1050 Example usage:: | |
| 1051 | |
| 1052 OverlayScope(context=self.call_method('get_context'), | |
| 1053 body=[...]) | |
| 1054 | |
| 1055 .. versionadded:: 2.10 | |
| 1056 """ | |
| 1057 | |
| 1058 fields = ("context", "body") | |
| 1059 | |
| 1060 | |
| 1061 class EvalContextModifier(Stmt): | |
| 1062 """Modifies the eval context. For each option that should be modified, | |
| 1063 a :class:`Keyword` has to be added to the :attr:`options` list. | |
| 1064 | |
| 1065 Example to change the `autoescape` setting:: | |
| 1066 | |
| 1067 EvalContextModifier(options=[Keyword('autoescape', Const(True))]) | |
| 1068 """ | |
| 1069 | |
| 1070 fields = ("options",) | |
| 1071 | |
| 1072 | |
| 1073 class ScopedEvalContextModifier(EvalContextModifier): | |
| 1074 """Modifies the eval context and reverts it later. Works exactly like | |
| 1075 :class:`EvalContextModifier` but will only modify the | |
| 1076 :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`. | |
| 1077 """ | |
| 1078 | |
| 1079 fields = ("body",) | |
| 1080 | |
| 1081 | |
| 1082 # make sure nobody creates custom nodes | |
| 1083 def _failing_new(*args, **kwargs): | |
| 1084 raise TypeError("can't create custom node types") | |
| 1085 | |
| 1086 | |
| 1087 NodeType.__new__ = staticmethod(_failing_new) | |
| 1088 del _failing_new |
