Skip to content

Visitors

Therismos uses the visitor pattern for extensible backend conversions.

Custom Visitors

Implement ExprVisitor to convert expressions to any format:

from therismos import ExprVisitor

class SQLVisitor:
    def visit_eq(self, expr):
        return f"{expr.field.name} = ?"

    def visit_all(self, expr):
        parts = [e.accept(self) for e in expr.exprs]
        return " AND ".join(parts)

    # ... implement other visit methods

visitor = SQLVisitor()
sql = expr.accept(visitor)

Built-in Visitors

StringVisitor

Converts expressions to human-readable strings:

from therismos import F, StringVisitor

age = F("age")
name = F("name")
expr = (age > 18) & (name == "Alice")

visitor = StringVisitor()
result = expr.accept(visitor)
# Output: "(age > 18 AND name = 'Alice')"

CountVisitor

Counts the number of nodes in an expression tree:

from therismos import F, CountVisitor

expr = (age > 18) & (name == "Alice")
count = expr.accept(CountVisitor())
# Output: 3 (1 AllExpr + 2 atomic expressions)

DictVisitor

Converts expressions to a dictionary representation:

from therismos import F, DictVisitor

expr = age > 18
result = expr.accept(DictVisitor())
# {"type": "gt", "field": "age", "value": 18}

expr = (age > 18) & (name == "Alice")
result = expr.accept(DictVisitor())
# {
#     "type": "and",
#     "exprs": [
#         {"type": "gt", "field": "age", "value": 18},
#         {"type": "eq", "field": "name", "value": "Alice"}
#     ]
# }

FieldGathererVisitor

Collects all unique field names used in an expression tree:

from therismos import F, FieldGathererVisitor

age = F("age")
name = F("name")
status = F("status")
expr = (age > 18) & (name == "Alice") | (status == "active")

visitor = FieldGathererVisitor()
expr.accept(visitor)
field_names = visitor.field_names
# {"age", "name", "status"}

Useful for validating that all referenced fields exist in your schema, determining required permissions, or generating metadata.

Backend Visitors