Skip to content

Visitors

A visitor defines how a concrete node type is evaluated. Register visitors in a VisitorDispatcher mapping from the node class to the visitor instance.

Each visitor receives:

  • node — the node being evaluated
  • dispatch — callback to evaluate child nodes
  • context — runtime input data passed to the dispatcher

dynamic_expressions.visitors.Visitor

Base class for node evaluation strategies.

Implement visit for a concrete Node subtype and register the visitor in VisitorDispatcher.

Example
dispatcher = VisitorDispatcher(
    visitors={LiteralNode: LiteralVisitor()},
)
result = await dispatcher.visit(LiteralNode(value=1), None)

visit(*, node, dispatch, context) abstractmethod async

Evaluate node using dispatch for child nodes.

Parameters:

Name Type Description Default
node TNode

Node instance handled by this visitor.

required
dispatch Dispatch[TContext]

Callback for evaluating nested nodes.

required
context TContext

Evaluation context supplied by the dispatcher.

required

Returns:

Type Description
Any

The computed value for node.

dynamic_expressions.visitors.Dispatch

Callable that evaluates a child node within the current visit.

__call__(node, context) async

Evaluate node with context.

Parameters:

Name Type Description Default
node Node

Child node to evaluate.

required
context TContext

Context passed through the dispatcher.

required

Returns:

Type Description
Any

The evaluated result of node.

Built-in visitors

Visitor Node Behavior
LiteralVisitor LiteralNode Returns the constant; resolves nested nodes in collections
AnyOfVisitor AnyOfNode Logical OR — returns True if at least one child is truthy
AllOfVisitor AllOfNode Logical AND — returns True if all children are truthy
UnaryExpressionVisitor UnaryExpressionNode Applies unary operator
BinaryExpressionVisitor BinaryExpressionNode Applies binary operator
CoalesceVisitor CoalesceNode First truthy child, or None
MatchVisitor MatchNode First matching case value, or default
CaseVisitor CaseNode Raises ValueError — must live inside MatchNode
FromContextNodeVisitor FromContextNode Reads field_name from context

Literal

dynamic_expressions.visitors.LiteralVisitor

Evaluate LiteralNode constants.

Any Of

dynamic_expressions.visitors.AnyOfVisitor

Evaluate AnyOfNode as logical OR.

All Of

dynamic_expressions.visitors.AllOfVisitor

Evaluate AllOfNode as logical AND.

Unary Expression

dynamic_expressions.visitors.UnaryExpressionVisitor

Evaluate unary operators on a single child expression.

Attributes:

Name Type Description
operator_mapping Mapping[UnaryExpressionOperator, Callable[[Any], object]]

Built-in Python callables keyed by operator name.

Binary Expression

dynamic_expressions.visitors.BinaryExpressionVisitor

Evaluate binary operators on two child expressions.

Attributes:

Name Type Description
operator_mapping Mapping[BinaryExpressionOperator, Callable[[Any, Any], object]]

Built-in Python callables keyed by operator name.

Coalesce

dynamic_expressions.visitors.CoalesceVisitor

Evaluate CoalesceNode branches.

Match

dynamic_expressions.visitors.MatchVisitor

Evaluate MatchNode pattern matching.

Case

dynamic_expressions.visitors.CaseVisitor

Guard visitor that rejects direct CaseNode evaluation.

From Context

dynamic_expressions.visitors.FromContextNodeVisitor

Resolve FromContextNode from context.

Overriding behavior

Subclass a built-in visitor and override visit, or replace operator_mapping on unary/binary visitors. Register the subclass in the dispatcher:

class StrictBinaryVisitor(BinaryExpressionVisitor):
    async def visit(self, *, node, dispatch, context):
        result = await super().visit(node=node, dispatch=dispatch, context=context)
        if result is None:
            raise ValueError("Null results are not allowed")
        return result

dispatcher = VisitorDispatcher(
    visitors={
        BinaryExpressionNode: StrictBinaryVisitor(),
        # ... other visitors
    },
)

See Custom nodes for adding entirely new node types.