diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/Jinja2/py3/jinja2/nodes.py | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/Jinja2/py3/jinja2/nodes.py')
-rw-r--r-- | contrib/python/Jinja2/py3/jinja2/nodes.py | 1026 |
1 files changed, 513 insertions, 513 deletions
diff --git a/contrib/python/Jinja2/py3/jinja2/nodes.py b/contrib/python/Jinja2/py3/jinja2/nodes.py index b2f88d9d9c..fcb5acfc78 100644 --- a/contrib/python/Jinja2/py3/jinja2/nodes.py +++ b/contrib/python/Jinja2/py3/jinja2/nodes.py @@ -1,47 +1,47 @@ -"""AST nodes generated by the parser for the compiler. Also provides -some node tree helper functions used by the parser and compiler in order -to normalize nodes. +"""AST nodes generated by the parser for the compiler. Also provides +some node tree helper functions used by the parser and compiler in order +to normalize nodes. """ -import inspect +import inspect import operator -import typing as t +import typing as t from collections import deque -from markupsafe import Markup - -from .utils import _PassArg - -if t.TYPE_CHECKING: - import typing_extensions as te - from .environment import Environment - -_NodeBound = t.TypeVar("_NodeBound", bound="Node") - -_binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { - "*": operator.mul, - "/": operator.truediv, - "//": operator.floordiv, - "**": operator.pow, - "%": operator.mod, - "+": operator.add, - "-": operator.sub, +from markupsafe import Markup + +from .utils import _PassArg + +if t.TYPE_CHECKING: + import typing_extensions as te + from .environment import Environment + +_NodeBound = t.TypeVar("_NodeBound", bound="Node") + +_binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { + "*": operator.mul, + "/": operator.truediv, + "//": operator.floordiv, + "**": operator.pow, + "%": operator.mod, + "+": operator.add, + "-": operator.sub, } -_uaop_to_func: t.Dict[str, t.Callable[[t.Any], t.Any]] = { - "not": operator.not_, - "+": operator.pos, - "-": operator.neg, -} - -_cmpop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { - "eq": operator.eq, - "ne": operator.ne, - "gt": operator.gt, - "gteq": operator.ge, - "lt": operator.lt, - "lteq": operator.le, - "in": lambda a, b: a in b, - "notin": lambda a, b: a not in b, +_uaop_to_func: t.Dict[str, t.Callable[[t.Any], t.Any]] = { + "not": operator.not_, + "+": operator.pos, + "-": operator.neg, +} + +_cmpop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { + "eq": operator.eq, + "ne": operator.ne, + "gt": operator.gt, + "gteq": operator.ge, + "lt": operator.lt, + "lteq": operator.le, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, } @@ -54,26 +54,26 @@ class NodeType(type): inheritance. fields and attributes from the parent class are automatically forwarded to the child.""" - def __new__(mcs, name, bases, d): # type: ignore - for attr in "fields", "attributes": + def __new__(mcs, name, bases, d): # type: ignore + for attr in "fields", "attributes": storage = [] - storage.extend(getattr(bases[0] if bases else object, attr, ())) + storage.extend(getattr(bases[0] if bases else object, attr, ())) storage.extend(d.get(attr, ())) - assert len(bases) <= 1, "multiple inheritance not allowed" - assert len(storage) == len(set(storage)), "layout conflict" + assert len(bases) <= 1, "multiple inheritance not allowed" + assert len(storage) == len(set(storage)), "layout conflict" d[attr] = tuple(storage) - d.setdefault("abstract", False) - return type.__new__(mcs, name, bases, d) + d.setdefault("abstract", False) + return type.__new__(mcs, name, bases, d) -class EvalContext: +class EvalContext: """Holds evaluation time information. Custom attributes can be attached to it in extensions. """ - def __init__( - self, environment: "Environment", template_name: t.Optional[str] = None - ) -> None: + def __init__( + self, environment: "Environment", template_name: t.Optional[str] = None + ) -> None: self.environment = environment if callable(environment.autoescape): self.autoescape = environment.autoescape(template_name) @@ -81,27 +81,27 @@ class EvalContext: self.autoescape = environment.autoescape self.volatile = False - def save(self) -> t.Mapping[str, t.Any]: + def save(self) -> t.Mapping[str, t.Any]: return self.__dict__.copy() - def revert(self, old: t.Mapping[str, t.Any]) -> None: + def revert(self, old: t.Mapping[str, t.Any]) -> None: self.__dict__.clear() self.__dict__.update(old) -def get_eval_context(node: "Node", ctx: t.Optional[EvalContext]) -> EvalContext: +def get_eval_context(node: "Node", ctx: t.Optional[EvalContext]) -> EvalContext: if ctx is None: if node.environment is None: - raise RuntimeError( - "if no eval context is passed, the node must have an" - " attached environment." - ) + raise RuntimeError( + "if no eval context is passed, the node must have an" + " attached environment." + ) return EvalContext(node.environment) return ctx -class Node(metaclass=NodeType): - """Baseclass for all Jinja nodes. There are a number of nodes available +class Node(metaclass=NodeType): + """Baseclass for all Jinja nodes. There are a number of nodes available of different types. There are four major types: - :class:`Stmt`: statements @@ -116,37 +116,37 @@ class Node(metaclass=NodeType): The `environment` attribute is set at the end of the parsing process for all nodes automatically. """ - - fields: t.Tuple[str, ...] = () - attributes: t.Tuple[str, ...] = ("lineno", "environment") + + fields: t.Tuple[str, ...] = () + attributes: t.Tuple[str, ...] = ("lineno", "environment") abstract = True - lineno: int - environment: t.Optional["Environment"] - - def __init__(self, *fields: t.Any, **attributes: t.Any) -> None: + lineno: int + environment: t.Optional["Environment"] + + def __init__(self, *fields: t.Any, **attributes: t.Any) -> None: if self.abstract: - raise TypeError("abstract nodes are not instantiable") + raise TypeError("abstract nodes are not instantiable") if fields: if len(fields) != len(self.fields): if not self.fields: - raise TypeError(f"{type(self).__name__!r} takes 0 arguments") - raise TypeError( - f"{type(self).__name__!r} takes 0 or {len(self.fields)}" - f" argument{'s' if len(self.fields) != 1 else ''}" - ) - for name, arg in zip(self.fields, fields): + raise TypeError(f"{type(self).__name__!r} takes 0 arguments") + raise TypeError( + f"{type(self).__name__!r} takes 0 or {len(self.fields)}" + f" argument{'s' if len(self.fields) != 1 else ''}" + ) + for name, arg in zip(self.fields, fields): setattr(self, name, arg) for attr in self.attributes: setattr(self, attr, attributes.pop(attr, None)) if attributes: - raise TypeError(f"unknown attribute {next(iter(attributes))!r}") + raise TypeError(f"unknown attribute {next(iter(attributes))!r}") - def iter_fields( - self, - exclude: t.Optional[t.Container[str]] = None, - only: t.Optional[t.Container[str]] = None, - ) -> t.Iterator[t.Tuple[str, t.Any]]: + def iter_fields( + self, + exclude: t.Optional[t.Container[str]] = None, + only: t.Optional[t.Container[str]] = None, + ) -> t.Iterator[t.Tuple[str, t.Any]]: """This method iterates over all fields that are defined and yields ``(key, value)`` tuples. Per default all fields are returned, but it's possible to limit that to some fields by providing the `only` @@ -154,26 +154,26 @@ class Node(metaclass=NodeType): should be sets or tuples of field names. """ for name in self.fields: - if ( - (exclude is None and only is None) - or (exclude is not None and name not in exclude) - or (only is not None and name in only) - ): + if ( + (exclude is None and only is None) + or (exclude is not None and name not in exclude) + or (only is not None and name in only) + ): try: yield name, getattr(self, name) except AttributeError: pass - def iter_child_nodes( - self, - exclude: t.Optional[t.Container[str]] = None, - only: t.Optional[t.Container[str]] = None, - ) -> t.Iterator["Node"]: + def iter_child_nodes( + self, + exclude: t.Optional[t.Container[str]] = None, + only: t.Optional[t.Container[str]] = None, + ) -> t.Iterator["Node"]: """Iterates over all direct child nodes of the node. This iterates over all fields and yields the values of they are nodes. If the value of a field is a list all the nodes in that list are returned. """ - for _, item in self.iter_fields(exclude, only): + for _, item in self.iter_fields(exclude, only): if isinstance(item, list): for n in item: if isinstance(n, Node): @@ -181,27 +181,27 @@ class Node(metaclass=NodeType): elif isinstance(item, Node): yield item - def find(self, node_type: t.Type[_NodeBound]) -> t.Optional[_NodeBound]: + def find(self, node_type: t.Type[_NodeBound]) -> t.Optional[_NodeBound]: """Find the first node of a given type. If no such node exists the return value is `None`. """ for result in self.find_all(node_type): return result - return None - - def find_all( - self, node_type: t.Union[t.Type[_NodeBound], t.Tuple[t.Type[_NodeBound], ...]] - ) -> t.Iterator[_NodeBound]: + return None + + def find_all( + self, node_type: t.Union[t.Type[_NodeBound], t.Tuple[t.Type[_NodeBound], ...]] + ) -> t.Iterator[_NodeBound]: """Find all the nodes of a given type. If the type is a tuple, the check is performed for any of the tuple items. """ for child in self.iter_child_nodes(): if isinstance(child, node_type): - yield child # type: ignore - yield from child.find_all(node_type) + yield child # type: ignore + yield from child.find_all(node_type) - def set_ctx(self, ctx: str) -> "Node": + def set_ctx(self, ctx: str) -> "Node": """Reset the context of a node and all child nodes. Per default the parser will all generate nodes that have a 'load' context as it's the most common one. This method is used in the parser to set assignment @@ -210,23 +210,23 @@ class Node(metaclass=NodeType): todo = deque([self]) while todo: node = todo.popleft() - if "ctx" in node.fields: - node.ctx = ctx # type: ignore + if "ctx" in node.fields: + node.ctx = ctx # type: ignore todo.extend(node.iter_child_nodes()) return self - def set_lineno(self, lineno: int, override: bool = False) -> "Node": + def set_lineno(self, lineno: int, override: bool = False) -> "Node": """Set the line numbers of the node and children.""" todo = deque([self]) while todo: node = todo.popleft() - if "lineno" in node.attributes: + if "lineno" in node.attributes: if node.lineno is None or override: node.lineno = lineno todo.extend(node.iter_child_nodes()) return self - def set_environment(self, environment: "Environment") -> "Node": + def set_environment(self, environment: "Environment") -> "Node": """Set the environment for all nodes.""" todo = deque([self]) while todo: @@ -235,57 +235,57 @@ class Node(metaclass=NodeType): todo.extend(node.iter_child_nodes()) return self - def __eq__(self, other: t.Any) -> bool: - if type(self) is not type(other): - return NotImplemented + def __eq__(self, other: t.Any) -> bool: + if type(self) is not type(other): + return NotImplemented - return tuple(self.iter_fields()) == tuple(other.iter_fields()) + return tuple(self.iter_fields()) == tuple(other.iter_fields()) __hash__ = object.__hash__ - def __repr__(self) -> str: - args_str = ", ".join(f"{a}={getattr(self, a, None)!r}" for a in self.fields) - return f"{type(self).__name__}({args_str})" + def __repr__(self) -> str: + args_str = ", ".join(f"{a}={getattr(self, a, None)!r}" for a in self.fields) + return f"{type(self).__name__}({args_str})" - def dump(self) -> str: - def _dump(node: t.Union[Node, t.Any]) -> None: + def dump(self) -> str: + def _dump(node: t.Union[Node, t.Any]) -> None: if not isinstance(node, Node): buf.append(repr(node)) return - buf.append(f"nodes.{type(node).__name__}(") + buf.append(f"nodes.{type(node).__name__}(") if not node.fields: - buf.append(")") + buf.append(")") return for idx, field in enumerate(node.fields): if idx: - buf.append(", ") + buf.append(", ") value = getattr(node, field) if isinstance(value, list): - buf.append("[") + buf.append("[") for idx, item in enumerate(value): if idx: - buf.append(", ") + buf.append(", ") _dump(item) - buf.append("]") + buf.append("]") else: _dump(value) - buf.append(")") - - buf: t.List[str] = [] + buf.append(")") + + buf: t.List[str] = [] _dump(self) - return "".join(buf) + return "".join(buf) class Stmt(Node): """Base node for all statements.""" - + abstract = True class Helper(Node): """Nodes that exist in a specific context only.""" - + abstract = True @@ -294,26 +294,26 @@ class Template(Node): is passed to the compiler. """ - fields = ("body",) - body: t.List[Node] - + fields = ("body",) + body: t.List[Node] + class Output(Stmt): """A node that holds multiple expressions which are then printed out. This is used both for the `print` statement and the regular template data. """ - fields = ("nodes",) - nodes: t.List["Expr"] - + fields = ("nodes",) + nodes: t.List["Expr"] + class Extends(Stmt): """Represents an extends statement.""" - fields = ("template",) - template: "Expr" - + fields = ("template",) + template: "Expr" + class For(Stmt): """The for loop. `target` is the target for the iteration (usually a :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list @@ -323,58 +323,58 @@ class For(Stmt): For filtered nodes an expression can be stored as `test`, otherwise `None`. """ - fields = ("target", "iter", "body", "else_", "test", "recursive") - target: Node - iter: Node - body: t.List[Node] - else_: t.List[Node] - test: t.Optional[Node] - recursive: bool - + fields = ("target", "iter", "body", "else_", "test", "recursive") + target: Node + iter: Node + body: t.List[Node] + else_: t.List[Node] + test: t.Optional[Node] + recursive: bool + class If(Stmt): """If `test` is true, `body` is rendered, else `else_`.""" - fields = ("test", "body", "elif_", "else_") - test: Node - body: t.List[Node] - elif_: t.List["If"] - else_: t.List[Node] - + fields = ("test", "body", "elif_", "else_") + test: Node + body: t.List[Node] + elif_: t.List["If"] + else_: t.List[Node] + class Macro(Stmt): """A macro definition. `name` is the name of the macro, `args` a list of arguments and `defaults` a list of defaults if there are any. `body` is a list of nodes for the macro body. """ - fields = ("name", "args", "defaults", "body") - name: str - args: t.List["Name"] - defaults: t.List["Expr"] - body: t.List[Node] - + fields = ("name", "args", "defaults", "body") + name: str + args: t.List["Name"] + defaults: t.List["Expr"] + body: t.List[Node] + class CallBlock(Stmt): """Like a macro without a name but a call instead. `call` is called with the unnamed macro as `caller` argument this node holds. """ - fields = ("call", "args", "defaults", "body") - call: "Call" - args: t.List["Name"] - defaults: t.List["Expr"] - body: t.List[Node] - + fields = ("call", "args", "defaults", "body") + call: "Call" + args: t.List["Name"] + defaults: t.List["Expr"] + body: t.List[Node] + class FilterBlock(Stmt): """Node for filter sections.""" - fields = ("body", "filter") - body: t.List[Node] - filter: "Filter" - + fields = ("body", "filter") + body: t.List[Node] + filter: "Filter" + class With(Stmt): """Specific node for with statements. In older versions of Jinja the with statement was implemented on the base of the `Scope` node instead. @@ -382,44 +382,44 @@ class With(Stmt): .. versionadded:: 2.9.3 """ - fields = ("targets", "values", "body") - targets: t.List["Expr"] - values: t.List["Expr"] - body: t.List[Node] - + fields = ("targets", "values", "body") + targets: t.List["Expr"] + values: t.List["Expr"] + body: t.List[Node] + class Block(Stmt): - """A node that represents a block. - - .. versionchanged:: 3.0.0 - the `required` field was added. - """ - - fields = ("name", "body", "scoped", "required") - name: str - body: t.List[Node] - scoped: bool - required: bool - - + """A node that represents a block. + + .. versionchanged:: 3.0.0 + the `required` field was added. + """ + + fields = ("name", "body", "scoped", "required") + name: str + body: t.List[Node] + scoped: bool + required: bool + + class Include(Stmt): """A node that represents the include tag.""" - fields = ("template", "with_context", "ignore_missing") - template: "Expr" - with_context: bool - ignore_missing: bool - + fields = ("template", "with_context", "ignore_missing") + template: "Expr" + with_context: bool + ignore_missing: bool + class Import(Stmt): """A node that represents the import tag.""" - fields = ("template", "target", "with_context") - template: "Expr" - target: str - with_context: bool - + fields = ("template", "target", "with_context") + template: "Expr" + target: str + with_context: bool + class FromImport(Stmt): """A node that represents the from import tag. It's important to not pass unsafe names to the name attribute. The compiler translates the @@ -432,42 +432,42 @@ class FromImport(Stmt): The list of names may contain tuples if aliases are wanted. """ - fields = ("template", "names", "with_context") - template: "Expr" - names: t.List[t.Union[str, t.Tuple[str, str]]] - with_context: bool - + fields = ("template", "names", "with_context") + template: "Expr" + names: t.List[t.Union[str, t.Tuple[str, str]]] + with_context: bool + class ExprStmt(Stmt): """A statement that evaluates an expression and discards the result.""" - fields = ("node",) - node: Node - + fields = ("node",) + node: Node + class Assign(Stmt): """Assigns an expression to a target.""" - fields = ("target", "node") - target: "Expr" - node: Node - + fields = ("target", "node") + target: "Expr" + node: Node + class AssignBlock(Stmt): """Assigns a block to a target.""" - fields = ("target", "filter", "body") - target: "Expr" - filter: t.Optional["Filter"] - body: t.List[Node] - + fields = ("target", "filter", "body") + target: "Expr" + filter: t.Optional["Filter"] + body: t.List[Node] + class Expr(Node): """Baseclass for all expressions.""" - + abstract = True - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: """Return the value of the expression as constant or raise :exc:`Impossible` if this was not possible. @@ -480,58 +480,58 @@ class Expr(Node): """ raise Impossible() - def can_assign(self) -> bool: + def can_assign(self) -> bool: """Check if it's possible to assign something to this node.""" return False class BinExpr(Expr): """Baseclass for all binary expressions.""" - - fields = ("left", "right") - left: Expr - right: Expr - operator: str + + fields = ("left", "right") + left: Expr + right: Expr + operator: str abstract = True - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) - + # intercepted operators cannot be folded at compile time - if ( - eval_ctx.environment.sandboxed - and self.operator in eval_ctx.environment.intercepted_binops # type: ignore - ): + if ( + eval_ctx.environment.sandboxed + and self.operator in eval_ctx.environment.intercepted_binops # type: ignore + ): raise Impossible() f = _binop_to_func[self.operator] try: return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) - except Exception as e: - raise Impossible() from e + except Exception as e: + raise Impossible() from e class UnaryExpr(Expr): """Baseclass for all unary expressions.""" - - fields = ("node",) - node: Expr - operator: str + + fields = ("node",) + node: Expr + operator: str abstract = True - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) - + # intercepted operators cannot be folded at compile time - if ( - eval_ctx.environment.sandboxed - and self.operator in eval_ctx.environment.intercepted_unops # type: ignore - ): + if ( + eval_ctx.environment.sandboxed + and self.operator in eval_ctx.environment.intercepted_unops # type: ignore + ): raise Impossible() f = _uaop_to_func[self.operator] try: return f(self.node.as_const(eval_ctx)) - except Exception as e: - raise Impossible() from e + except Exception as e: + raise Impossible() from e class Name(Expr): @@ -543,22 +543,22 @@ class Name(Expr): - `param`: like `store` but if the name was defined as function parameter. """ - fields = ("name", "ctx") - name: str - ctx: str - - def can_assign(self) -> bool: - return self.name not in {"true", "false", "none", "True", "False", "None"} + fields = ("name", "ctx") + name: str + ctx: str + + def can_assign(self) -> bool: + return self.name not in {"true", "false", "none", "True", "False", "None"} class NSRef(Expr): """Reference to a namespace value assignment""" - fields = ("name", "attr") - name: str - attr: str - - def can_assign(self) -> bool: + fields = ("name", "attr") + name: str + attr: str + + def can_assign(self) -> bool: # We don't need any special checks here; NSRef assignments have a # runtime check to ensure the target is a namespace object which will # have been checked already as it is created using a normal assignment @@ -568,7 +568,7 @@ class NSRef(Expr): class Literal(Expr): """Baseclass for literals.""" - + abstract = True @@ -579,25 +579,25 @@ class Const(Literal): representation (objects where ``eval(repr(x)) == x`` is true). """ - fields = ("value",) - value: t.Any - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: - return self.value + fields = ("value",) + value: t.Any + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + return self.value @classmethod - def from_untrusted( - cls, - value: t.Any, - lineno: t.Optional[int] = None, - environment: "t.Optional[Environment]" = None, - ) -> "Const": + def from_untrusted( + cls, + value: t.Any, + lineno: t.Optional[int] = None, + environment: "t.Optional[Environment]" = None, + ) -> "Const": """Return a const object if the value is representable as constant value in the generated code, otherwise it will raise an `Impossible` exception. """ from .compiler import has_safe_repr - + if not has_safe_repr(value): raise Impossible() return cls(value, lineno=lineno, environment=environment) @@ -606,10 +606,10 @@ class Const(Literal): class TemplateData(Literal): """A constant template string.""" - fields = ("data",) - data: str - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: + fields = ("data",) + data: str + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: eval_ctx = get_eval_context(self, eval_ctx) if eval_ctx.volatile: raise Impossible() @@ -624,15 +624,15 @@ class Tuple(Literal): is used for loading the names or storing. """ - fields = ("items", "ctx") - items: t.List[Expr] - ctx: str - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[t.Any, ...]: + fields = ("items", "ctx") + items: t.List[Expr] + ctx: str + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[t.Any, ...]: eval_ctx = get_eval_context(self, eval_ctx) return tuple(x.as_const(eval_ctx) for x in self.items) - def can_assign(self) -> bool: + def can_assign(self) -> bool: for item in self.items: if not item.can_assign(): return False @@ -642,10 +642,10 @@ class Tuple(Literal): class List(Literal): """Any list literal such as ``[1, 2, 3]``""" - fields = ("items",) - items: t.List[Expr] - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.List[t.Any]: + fields = ("items",) + items: t.List[Expr] + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.List[t.Any]: eval_ctx = get_eval_context(self, eval_ctx) return [x.as_const(eval_ctx) for x in self.items] @@ -655,12 +655,12 @@ class Dict(Literal): :class:`Pair` nodes. """ - fields = ("items",) - items: t.List["Pair"] - - def as_const( - self, eval_ctx: t.Optional[EvalContext] = None - ) -> t.Dict[t.Any, t.Any]: + fields = ("items",) + items: t.List["Pair"] + + def as_const( + self, eval_ctx: t.Optional[EvalContext] = None + ) -> t.Dict[t.Any, t.Any]: eval_ctx = get_eval_context(self, eval_ctx) return dict(x.as_const(eval_ctx) for x in self.items) @@ -668,13 +668,13 @@ class Dict(Literal): class Pair(Helper): """A key, value pair for dicts.""" - fields = ("key", "value") - key: Expr - value: Expr - - def as_const( - self, eval_ctx: t.Optional[EvalContext] = None - ) -> t.Tuple[t.Any, t.Any]: + fields = ("key", "value") + key: Expr + value: Expr + + def as_const( + self, eval_ctx: t.Optional[EvalContext] = None + ) -> t.Tuple[t.Any, t.Any]: eval_ctx = get_eval_context(self, eval_ctx) return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx) @@ -682,11 +682,11 @@ class Pair(Helper): class Keyword(Helper): """A key, value pair for keyword arguments where key is a string.""" - fields = ("key", "value") - key: str - value: Expr - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[str, t.Any]: + fields = ("key", "value") + key: str + value: Expr + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[str, t.Any]: eval_ctx = get_eval_context(self, eval_ctx) return self.key, self.value.as_const(eval_ctx) @@ -696,12 +696,12 @@ class CondExpr(Expr): foo if bar else baz }}``) """ - fields = ("test", "expr1", "expr2") - test: Expr - expr1: Expr - expr2: t.Optional[Expr] - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + fields = ("test", "expr1", "expr2") + test: Expr + expr1: Expr + expr2: t.Optional[Expr] + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) if self.test.as_const(eval_ctx): return self.expr1.as_const(eval_ctx) @@ -713,105 +713,105 @@ class CondExpr(Expr): return self.expr2.as_const(eval_ctx) -def args_as_const( - node: t.Union["_FilterTestCommon", "Call"], eval_ctx: t.Optional[EvalContext] -) -> t.Tuple[t.List[t.Any], t.Dict[t.Any, t.Any]]: +def args_as_const( + node: t.Union["_FilterTestCommon", "Call"], eval_ctx: t.Optional[EvalContext] +) -> t.Tuple[t.List[t.Any], t.Dict[t.Any, t.Any]]: args = [x.as_const(eval_ctx) for x in node.args] kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs) if node.dyn_args is not None: try: args.extend(node.dyn_args.as_const(eval_ctx)) - except Exception as e: - raise Impossible() from e + except Exception as e: + raise Impossible() from e if node.dyn_kwargs is not None: try: kwargs.update(node.dyn_kwargs.as_const(eval_ctx)) - except Exception as e: - raise Impossible() from e + except Exception as e: + raise Impossible() from e return args, kwargs -class _FilterTestCommon(Expr): - fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") - node: Expr - name: str - args: t.List[Expr] - kwargs: t.List[Pair] - dyn_args: t.Optional[Expr] - dyn_kwargs: t.Optional[Expr] - abstract = True - _is_filter = True +class _FilterTestCommon(Expr): + fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") + node: Expr + name: str + args: t.List[Expr] + kwargs: t.List[Pair] + dyn_args: t.Optional[Expr] + dyn_kwargs: t.Optional[Expr] + abstract = True + _is_filter = True - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) - if eval_ctx.volatile: + if eval_ctx.volatile: raise Impossible() - if self._is_filter: - env_map = eval_ctx.environment.filters - else: - env_map = eval_ctx.environment.tests - - func = env_map.get(self.name) - pass_arg = _PassArg.from_obj(func) # type: ignore + if self._is_filter: + env_map = eval_ctx.environment.filters + else: + env_map = eval_ctx.environment.tests - if func is None or pass_arg is _PassArg.context: + func = env_map.get(self.name) + pass_arg = _PassArg.from_obj(func) # type: ignore + + if func is None or pass_arg is _PassArg.context: raise Impossible() - if eval_ctx.environment.is_async and ( - getattr(func, "jinja_async_variant", False) is True - or inspect.iscoroutinefunction(func) + if eval_ctx.environment.is_async and ( + getattr(func, "jinja_async_variant", False) is True + or inspect.iscoroutinefunction(func) ): raise Impossible() args, kwargs = args_as_const(self, eval_ctx) args.insert(0, self.node.as_const(eval_ctx)) - if pass_arg is _PassArg.eval_context: + if pass_arg is _PassArg.eval_context: args.insert(0, eval_ctx) - elif pass_arg is _PassArg.environment: - args.insert(0, eval_ctx.environment) + elif pass_arg is _PassArg.environment: + args.insert(0, eval_ctx.environment) try: - return func(*args, **kwargs) - except Exception as e: - raise Impossible() from e + return func(*args, **kwargs) + except Exception as e: + raise Impossible() from e -class Filter(_FilterTestCommon): - """Apply a filter to an expression. ``name`` is the name of the - filter, the other fields are the same as :class:`Call`. - - If ``node`` is ``None``, the filter is being used in a filter block - and is applied to the content of the block. +class Filter(_FilterTestCommon): + """Apply a filter to an expression. ``name`` is the name of the + filter, the other fields are the same as :class:`Call`. + + If ``node`` is ``None``, the filter is being used in a filter block + and is applied to the content of the block. """ - node: t.Optional[Expr] # type: ignore + node: t.Optional[Expr] # type: ignore - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: - if self.node is None: + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + if self.node is None: raise Impossible() - return super().as_const(eval_ctx=eval_ctx) - + return super().as_const(eval_ctx=eval_ctx) -class Test(_FilterTestCommon): - """Apply a test to an expression. ``name`` is the name of the test, - the other field are the same as :class:`Call`. - - .. versionchanged:: 3.0 - ``as_const`` shares the same logic for filters and tests. Tests - check for volatile, async, and ``@pass_context`` etc. - decorators. - """ - - _is_filter = False +class Test(_FilterTestCommon): + """Apply a test to an expression. ``name`` is the name of the test, + the other field are the same as :class:`Call`. + .. versionchanged:: 3.0 + ``as_const`` shares the same logic for filters and tests. Tests + check for volatile, async, and ``@pass_context`` etc. + decorators. + """ + + _is_filter = False + + class Call(Expr): """Calls an expression. `args` is a list of arguments, `kwargs` a list of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args` @@ -820,34 +820,34 @@ class Call(Expr): arguments. """ - fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") - node: Expr - args: t.List[Expr] - kwargs: t.List[Keyword] - dyn_args: t.Optional[Expr] - dyn_kwargs: t.Optional[Expr] - + fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") + node: Expr + args: t.List[Expr] + kwargs: t.List[Keyword] + dyn_args: t.Optional[Expr] + dyn_kwargs: t.Optional[Expr] + class Getitem(Expr): """Get an attribute or item from an expression and prefer the item.""" - fields = ("node", "arg", "ctx") - node: Expr - arg: Expr - ctx: str - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: - if self.ctx != "load": + fields = ("node", "arg", "ctx") + node: Expr + arg: Expr + ctx: str + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + if self.ctx != "load": raise Impossible() - - eval_ctx = get_eval_context(self, eval_ctx) - + + eval_ctx = get_eval_context(self, eval_ctx) + try: - return eval_ctx.environment.getitem( - self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) - ) - except Exception as e: - raise Impossible() from e + return eval_ctx.environment.getitem( + self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) + ) + except Exception as e: + raise Impossible() from e class Getattr(Expr): @@ -855,21 +855,21 @@ class Getattr(Expr): bytestring and prefer the attribute. """ - fields = ("node", "attr", "ctx") - node: Expr - attr: str - ctx: str - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: - if self.ctx != "load": + fields = ("node", "attr", "ctx") + node: Expr + attr: str + ctx: str + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + if self.ctx != "load": raise Impossible() - - eval_ctx = get_eval_context(self, eval_ctx) - + + eval_ctx = get_eval_context(self, eval_ctx) + try: - return eval_ctx.environment.getattr(self.node.as_const(eval_ctx), self.attr) - except Exception as e: - raise Impossible() from e + return eval_ctx.environment.getattr(self.node.as_const(eval_ctx), self.attr) + except Exception as e: + raise Impossible() from e class Slice(Expr): @@ -877,33 +877,33 @@ class Slice(Expr): :class:`Subscript`. """ - fields = ("start", "stop", "step") - start: t.Optional[Expr] - stop: t.Optional[Expr] - step: t.Optional[Expr] - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> slice: + fields = ("start", "stop", "step") + start: t.Optional[Expr] + stop: t.Optional[Expr] + step: t.Optional[Expr] + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> slice: eval_ctx = get_eval_context(self, eval_ctx) - - def const(obj: t.Optional[Expr]) -> t.Optional[t.Any]: + + def const(obj: t.Optional[Expr]) -> t.Optional[t.Any]: if obj is None: return None return obj.as_const(eval_ctx) - + return slice(const(self.start), const(self.stop), const(self.step)) class Concat(Expr): - """Concatenates the list of expressions provided after converting - them to strings. + """Concatenates the list of expressions provided after converting + them to strings. """ - fields = ("nodes",) - nodes: t.List[Expr] - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: + fields = ("nodes",) + nodes: t.List[Expr] + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: eval_ctx = get_eval_context(self, eval_ctx) - return "".join(str(x.as_const(eval_ctx)) for x in self.nodes) + return "".join(str(x.as_const(eval_ctx)) for x in self.nodes) class Compare(Expr): @@ -911,87 +911,87 @@ class Compare(Expr): list of :class:`Operand`\\s. """ - fields = ("expr", "ops") - expr: Expr - ops: t.List["Operand"] - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + fields = ("expr", "ops") + expr: Expr + ops: t.List["Operand"] + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) result = value = self.expr.as_const(eval_ctx) - + try: for op in self.ops: new_value = op.expr.as_const(eval_ctx) result = _cmpop_to_func[op.op](value, new_value) - - if not result: - return False - + + if not result: + return False + value = new_value - except Exception as e: - raise Impossible() from e - + except Exception as e: + raise Impossible() from e + return result class Operand(Helper): """Holds an operator and an expression.""" - fields = ("op", "expr") - op: str - expr: Expr - - + fields = ("op", "expr") + op: str + expr: Expr + + class Mul(BinExpr): """Multiplies the left with the right node.""" - operator = "*" - + operator = "*" + class Div(BinExpr): """Divides the left by the right node.""" - operator = "/" - + operator = "/" + class FloorDiv(BinExpr): """Divides the left by the right node and converts the result into an integer by truncating. """ - operator = "//" - + operator = "//" + class Add(BinExpr): """Add the left to the right node.""" - operator = "+" - + operator = "+" + class Sub(BinExpr): """Subtract the right from the left node.""" - operator = "-" - + operator = "-" + class Mod(BinExpr): """Left modulo right.""" - operator = "%" - + operator = "%" + class Pow(BinExpr): """Left to the power of right.""" - operator = "**" - + operator = "**" + class And(BinExpr): """Short circuited AND.""" - operator = "and" - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + operator = "and" + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) @@ -999,9 +999,9 @@ class And(BinExpr): class Or(BinExpr): """Short circuited OR.""" - operator = "or" - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: + operator = "or" + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: eval_ctx = get_eval_context(self, eval_ctx) return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) @@ -1009,21 +1009,21 @@ class Or(BinExpr): class Not(UnaryExpr): """Negate the expression.""" - operator = "not" - + operator = "not" + class Neg(UnaryExpr): """Make the expression negative.""" - operator = "-" - + operator = "-" + class Pos(UnaryExpr): """Make the expression positive (noop for most expressions)""" - operator = "+" - + operator = "+" + # Helpers for extensions @@ -1032,10 +1032,10 @@ class EnvironmentAttribute(Expr): extensions that want to call a callback stored on the environment. """ - fields = ("name",) - name: str - + fields = ("name",) + name: str + class ExtensionAttribute(Expr): """Returns the attribute of an extension bound to the environment. The identifier is the identifier of the :class:`Extension`. @@ -1044,11 +1044,11 @@ class ExtensionAttribute(Expr): :meth:`~jinja2.ext.Extension.attr` method on an extension. """ - fields = ("identifier", "name") - identifier: str - name: str - + fields = ("identifier", "name") + identifier: str + name: str + class ImportedName(Expr): """If created with an import name the import name is returned on node access. For example ``ImportedName('cgi.escape')`` returns the `escape` @@ -1056,35 +1056,35 @@ class ImportedName(Expr): compiler so there is no need to assign them to local variables. """ - fields = ("importname",) - importname: str - + fields = ("importname",) + importname: str + class InternalName(Expr): """An internal name in the compiler. You cannot create these nodes yourself but the parser provides a :meth:`~jinja2.parser.Parser.free_identifier` method that creates a new identifier for you. This identifier is not available from the - template and is not treated specially by the compiler. + template and is not treated specially by the compiler. """ - fields = ("name",) - name: str - - def __init__(self) -> None: - raise TypeError( - "Can't create internal names. Use the " - "`free_identifier` method on a parser." - ) + fields = ("name",) + name: str + + def __init__(self) -> None: + raise TypeError( + "Can't create internal names. Use the " + "`free_identifier` method on a parser." + ) class MarkSafe(Expr): """Mark the wrapped expression as safe (wrap it as `Markup`).""" - fields = ("expr",) - expr: Expr - - def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> Markup: + fields = ("expr",) + expr: Expr + + def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> Markup: eval_ctx = get_eval_context(self, eval_ctx) return Markup(self.expr.as_const(eval_ctx)) @@ -1096,12 +1096,12 @@ class MarkSafeIfAutoescape(Expr): .. versionadded:: 2.5 """ - fields = ("expr",) - expr: Expr - - def as_const( - self, eval_ctx: t.Optional[EvalContext] = None - ) -> t.Union[Markup, t.Any]: + fields = ("expr",) + expr: Expr + + def as_const( + self, eval_ctx: t.Optional[EvalContext] = None + ) -> t.Union[Markup, t.Any]: eval_ctx = get_eval_context(self, eval_ctx) if eval_ctx.volatile: raise Impossible() @@ -1121,23 +1121,23 @@ class ContextReference(Expr): Assign(Name('foo', ctx='store'), Getattr(ContextReference(), 'name')) - - This is basically equivalent to using the - :func:`~jinja2.pass_context` decorator when using the high-level - API, which causes a reference to the context to be passed as the - first argument to a function. - """ - - -class DerivedContextReference(Expr): - """Return the current template context including locals. Behaves - exactly like :class:`ContextReference`, but includes local - variables, such as from a ``for`` loop. - - .. versionadded:: 2.11 + + This is basically equivalent to using the + :func:`~jinja2.pass_context` decorator when using the high-level + API, which causes a reference to the context to be passed as the + first argument to a function. """ +class DerivedContextReference(Expr): + """Return the current template context including locals. Behaves + exactly like :class:`ContextReference`, but includes local + variables, such as from a ``for`` loop. + + .. versionadded:: 2.11 + """ + + class Continue(Stmt): """Continue a loop.""" @@ -1149,10 +1149,10 @@ class Break(Stmt): class Scope(Stmt): """An artificial scope.""" - fields = ("body",) - body: t.List[Node] - + fields = ("body",) + body: t.List[Node] + class OverlayScope(Stmt): """An overlay scope for extensions. This is a largely unoptimized scope that however can be used to introduce completely arbitrary variables into @@ -1167,11 +1167,11 @@ class OverlayScope(Stmt): .. versionadded:: 2.10 """ - fields = ("context", "body") - context: Expr - body: t.List[Node] - + fields = ("context", "body") + context: Expr + body: t.List[Node] + class EvalContextModifier(Stmt): """Modifies the eval context. For each option that should be modified, a :class:`Keyword` has to be added to the :attr:`options` list. @@ -1181,24 +1181,24 @@ class EvalContextModifier(Stmt): EvalContextModifier(options=[Keyword('autoescape', Const(True))]) """ - fields = ("options",) - options: t.List[Keyword] - + fields = ("options",) + options: t.List[Keyword] + class ScopedEvalContextModifier(EvalContextModifier): """Modifies the eval context and reverts it later. Works exactly like :class:`EvalContextModifier` but will only modify the :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`. """ - fields = ("body",) - body: t.List[Node] - + fields = ("body",) + body: t.List[Node] + # make sure nobody creates custom nodes -def _failing_new(*args: t.Any, **kwargs: t.Any) -> "te.NoReturn": - raise TypeError("can't create custom node types") - - -NodeType.__new__ = staticmethod(_failing_new) # type: ignore -del _failing_new +def _failing_new(*args: t.Any, **kwargs: t.Any) -> "te.NoReturn": + raise TypeError("can't create custom node types") + + +NodeType.__new__ = staticmethod(_failing_new) # type: ignore +del _failing_new |