Skip to content

Dynamic-Expressions

A Python library for building, evaluating, and serializing expression trees. Compose rules as immutable AST nodes, evaluate them asynchronously with a visitor dispatcher, persist them as JSON and parse the ones from python-like code or JSON.

Features

  • Immutable node trees — hashable dataclasses suitable for caching and comparison
  • Visitor pattern — swap evaluation behavior per node type without changing the tree
  • Context DSL — compose rules with Python operators (&, |, ==, in_, …)
  • Serialization & Parsing — Pydantic JSON schemas and AST string parsers
  • Caching — Redis-backed cache extensions with configurable policies
  • Middlewares — wrap visitor calls for logging, timing, etc

Installation

pip install dynamic-expressions

With all optional dependencies:

pip install dynamic-expressions[cache-redis,serialization-pydantic,serialization-msgspec]

Minimal example

import asyncio

from dynamic_expressions.dispatcher import VisitorDispatcher
from dynamic_expressions.nodes import BinaryExpressionNode, LiteralNode
from dynamic_expressions.types import EmptyContext
from dynamic_expressions.visitors import BinaryExpressionVisitor, LiteralVisitor

dispatcher = VisitorDispatcher[EmptyContext](
    visitors={
        LiteralNode: LiteralVisitor(),
        BinaryExpressionNode: BinaryExpressionVisitor(),
    },
)

node = BinaryExpressionNode(
    operator="+",
    left=LiteralNode(value=1),
    right=LiteralNode(value=2),
)

async def main() -> None:
    result = await dispatcher.visit(node, None)
    assert result == 3

asyncio.run(main())

Documentation map

Section Description
Getting started Quickstart in five minutes
Concepts Architecture, nodes, visitors, dispatcher, DSL
Advanced Custom nodes, extensions, middlewares
Serialization Pydantic, AST, MsgSpec
Cookbook End-to-end recipes

Next steps

Continue with Getting started or jump to the Basic cookbook for a typed access-control scenario.