Nodes and visitors
Node
Node is a class that stores the expression parameters.
All nodes must be hashable.
You can inherit from a base class dynamic_expressions.nodes.Node
Visitor
Visitor is a class that stores behavior for the concrete node.
Built-in nodes and visitors
Literal
Literal - constant value in the expression.
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True)
class LiteralNode(Node):
value: Any
def __hash__(self) -> int:
return hash((self.value, type(self.value)))
|
Source code in dynamic_expressions/visitors.py
| class LiteralVisitor(Visitor[LiteralNode, EmptyContext]):
async def visit(
self,
*,
node: LiteralNode,
dispatch: Dispatch[EmptyContext], # noqa: ARG002
context: EmptyContext, # noqa: ARG002
) -> Any: # noqa: ANN401
return node.value
|
Any Of
Sequence of the nodes. Returns True if at least one element equals True, else is False
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True, unsafe_hash=True)
class AnyOfNode(Node):
expressions: tuple[Node, ...]
|
Source code in dynamic_expressions/visitors.py
| class AnyOfVisitor(Visitor[AnyOfNode, EmptyContext]):
async def visit(
self,
*,
node: AnyOfNode,
dispatch: Dispatch[EmptyContext],
context: object,
) -> bool:
for expr in node.expressions:
value = await dispatch(expr, context)
if value:
return True
return False
|
All Of
Sequence of the nodes. Returns True if all elements equal True, else is False
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True, unsafe_hash=True)
class AllOfNode(Node):
expressions: tuple[Node, ...]
|
Source code in dynamic_expressions/visitors.py
| class AllOfVisitor(Visitor[AllOfNode, EmptyContext]):
async def visit(
self,
*,
node: AllOfNode,
dispatch: Dispatch[EmptyContext],
context: EmptyContext,
) -> bool:
for expr in node.expressions:
value = await dispatch(expr, context)
if not value:
return False
return True
|
Binary Expression
Binary operator. See the available operation in dynamic_expressions.types.BinaryExpressionOperator
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True, unsafe_hash=True)
class BinaryExpressionNode(Node):
operator: BinaryExpressionOperator
left: Node
right: Node
|
Source code in dynamic_expressions/visitors.py
| class BinaryExpressionVisitor(Visitor[BinaryExpressionNode, EmptyContext]):
operator_mapping: ClassVar[
Mapping[BinaryExpressionOperator, Callable[[Any, Any], object]]
] = {
"=": operator.eq,
">": operator.gt,
">=": operator.ge,
"<": operator.lt,
"<=": operator.le,
"!=": operator.ne,
"in": operator.contains,
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv,
"//": operator.floordiv,
"^": operator.pow,
"&": operator.and_,
"|": operator.or_,
"getitem": operator.getitem,
"getattr": _visit_getattr,
}
async def visit(
self,
*,
node: BinaryExpressionNode,
dispatch: Dispatch[EmptyContext],
context: EmptyContext,
) -> object:
left = await dispatch(node.left, context)
right = await dispatch(node.right, context)
operator_callable = self.operator_mapping.get(node.operator)
if operator_callable is None:
msg = f"Unknown operator '{node.operator}'"
raise ValueError(msg)
return operator_callable(left, right)
|
Coalesce
Analogue SQL Coalesce. Returns the first non null item
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True)
class CoalesceNode(Node):
items: tuple[Node, ...]
|
Source code in dynamic_expressions/visitors.py
| class CoalesceVisitor(Visitor[CoalesceNode, EmptyContext]):
async def visit(
self,
*,
node: CoalesceNode,
dispatch: Dispatch[EmptyContext],
context: EmptyContext,
) -> Any: # noqa: ANN401
for item in node.items:
node_result = await dispatch(item, context)
if node_result:
return node_result
return None
|
Match
Match case operator.
Returns the first value for which the expression returns true
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True)
class MatchNode(Node):
cases: tuple[CaseNode, ...]
default: Node | None = None
|
Source code in dynamic_expressions/visitors.py
| class MatchVisitor(Visitor[MatchNode, EmptyContext]):
async def visit(
self,
*,
node: MatchNode,
dispatch: Dispatch[EmptyContext],
context: EmptyContext,
) -> Any: # noqa: ANN401
for case_ in node.cases:
if await dispatch(case_.expression, context):
return await dispatch(case_.value, context)
if node.default is not None:
return await dispatch(node.default, context)
msg = "MatchCase doesn't find CaseNode with the appropriate expression"
raise ValueError(msg)
|
Case
Use only in Match operator
Source code in dynamic_expressions/nodes.py
| @dataclass(slots=True, frozen=True, kw_only=True)
class CaseNode(Node):
expression: Node
value: Node
|
Source code in dynamic_expressions/visitors.py
| class CaseVisitor(Visitor[CaseNode, EmptyContext]):
async def visit(
self,
*,
node: CaseNode, # noqa: ARG002
dispatch: Dispatch[EmptyContext], # noqa: ARG002
context: EmptyContext, # noqa: ARG002
) -> Any: # noqa: ANN401
msg = "Use CaseNode only in MatchNode"
raise ValueError(msg)
|