Expression Serialization¶
Grammar-based serialization converts expressions to/from compact string representations — useful for URL query strings, API parameters, and storing filters as text.
Grammar Reference¶
| Python Operator | Grammar Syntax | Example |
|---|---|---|
& (AND) |
; |
age>18;status=="active" |
\| (OR) |
, |
status=="active",status=="pending" |
~ (NOT) |
! |
!(age<18) |
== |
== |
age==18 |
!= |
!= |
status!="inactive" |
< |
< |
age<65 |
<= |
<= |
age<=65 |
> |
> |
age>18 |
>= |
>= |
age>=18 |
.is_in() |
=in= |
status=in=("active","pending") |
.matches() |
~regex |
email~regex(".*@example\\.com") |
.is_null() |
==null |
deleted_at==null |
.is_not_null() |
!=null |
created_at!=null |
TRUE |
true() |
true() |
FALSE |
false() |
false() |
Precedence: ! (NOT) > ; (AND) > , (OR)
Basic Usage¶
from therismos import F, Serializer, Eq, AllExpr, Gt
serializer = Serializer()
expr = Eq(F("age"), 18)
text = serializer.serialize(expr)
# "age==18"
expr = AllExpr(Eq(F("age"), 18), Gt(F("score"), 75))
text = serializer.serialize(expr)
# "(age==18;score>75)"
expr = serializer.deserialize("age==18")
# Eq(field=Field(name='age', type_=None), value=18)
URL Encoding¶
serializer = Serializer(url_encode=True)
expr = Eq(F("name"), "Alice Smith")
text = serializer.serialize(expr) # URL-encoded string
expr = serializer.deserialize(text) # automatically decoded
Type Annotations¶
age = F("age", int)
# Without annotations (default)
serializer = Serializer()
text = serializer.serialize(Eq(age, 18))
# "age==18"
# With all annotations
serializer = Serializer(include_all_types=True)
text = serializer.serialize(Eq(age, 18))
# "age{int}==18"
Custom Types¶
import uuid
from therismos import Serializer
serializer = Serializer()
serializer.register_custom_type(uuid.UUID, 'uuid.UUID')
expr = serializer.deserialize('user_id{uuid.UUID}=="550e8400-e29b-41d4-a716-446655440000"')
assert isinstance(expr.value, uuid.UUID)
Implicit Field Types¶
Define type mappings for field names to avoid repeating annotations:
from decimal import Decimal
implicit_field_types = {
"user_id": uuid.UUID,
"price": Decimal,
}
serializer = Serializer(implicit_field_types=implicit_field_types)
serializer.register_custom_type(uuid.UUID, 'uuid.UUID')
serializer.register_custom_type(Decimal, 'Decimal')
expr = serializer.deserialize('user_id=="550e8400-e29b-41d4-a716-446655440000"')
assert expr.field.type_ is uuid.UUID
# Programmatic registration
serializer.register_field_type("account_id", uuid.UUID)
# Explicit annotations always override implicit mappings
expr = serializer.deserialize('price{int}=="100"')
assert expr.field.type_ is int # not Decimal
Value Reference¶
| Value type | Syntax |
|---|---|
| String | "Alice" (double-quoted, JSON escapes) |
| Integer | 25 |
| Float | 3.14 |
| Boolean | true / false |
| Null | null |
| Identifier | active (unquoted, interpreted as string) |