ESC

Type to search...

Extra Data Types

Handle UUID, datetime, date, time, timedelta, bytes, Decimal in handlers.

UUID Fields

Use UUID for unique identifiers:

from uuid import UUID
from pydantic import BaseModel
from evoid.web.route import Service, get, post

class User(BaseModel):
    id: UUID
    name: str
    email: str

app = Service("api")

@app.get("/users/{user_id}")
async def get_user(user_id: UUID):
    return {"user_id": str(user_id), "name": "Alice"}

@app.post("/users/")
async def create_user(user: User):
    return {"status": "created", "user_id": str(user.id)}

DateTime Fields

Handle datetime objects for timestamps:

from datetime import datetime, timezone
from pydantic import BaseModel, Field
from evoid.web.route import Service, post

class Event(BaseModel):
    name: str
    start_time: datetime
    end_time: datetime | None = None
    timezone: str = "UTC"

app = Service("api")

@app.post("/events/")
async def create_event(event: Event):
    # Validate that end_time is after start_time
    if event.end_time and event.end_time <= event.start_time:
        raise ValueError("end_time must be after start_time")
    
    return {
        "status": "created",
        "event": event.name,
        "start": event.start_time.isoformat()
    }

Decimal Fields

Use Decimal for precise numeric calculations:

from decimal import Decimal
from pydantic import BaseModel, Field
from evoid.web.route import Service, post

class Payment(BaseModel):
    amount: Decimal = Field(ge=Decimal("0.01"), max_digits=10, decimal_places=2)
    currency: str = "USD"
    tax_rate: Decimal = Field(default=Decimal("0.0"), ge=Decimal("0"), le=Decimal("1"))

app = Service("api")

@app.post("/payments/")
async def process_payment(payment: Payment):
    tax = payment.amount * payment.tax_rate
    total = payment.amount + tax
    return {
        "status": "processed",
        "amount": str(payment.amount),
        "tax": str(tax),
        "total": str(total)
    }

Native IOP Style

In IOP, type conversion belongs in a processor — handlers receive already-typed data:

from uuid import UUID
from datetime import datetime
from decimal import Decimal
from evoid.native import create_service, on
from evoid import Intent, Level, Context

app = create_service("api")

# 1. Processor converts types automatically
async def convert_payment_types(ctx: Context) -> dict:
    body = ctx.metadata.get("body", {})
    ctx.metadata["body"] = {
        "amount": Decimal(str(body.get("amount", "0.00"))),
        "payment_id": UUID(body.get("payment_id", "")),
        "created_at": datetime.fromisoformat(body.get("created_at", "")),
    }
    return {"converted": True}

# 2. Intent with type converter in pipeline
CREATE_PAYMENT = Intent(
    name="POST:/payments",
    level=Level.STANDARD,
    metadata={
        "method": "POST",
        "path": "/payments",
        "processors": ("convert_payment_types",),
    },
)

# 3. Handler — receives already-typed data
async def handle_create_payment(intent: Intent) -> dict:
    body = intent.metadata["body"]  # already typed
    return {
        "status": "processed",
        "payment_id": str(body["payment_id"]),
        "amount": str(body["amount"]),
    }

on(app, CREATE_PAYMENT, handle_create_payment)

Summary

TypeUse CaseExample
UUIDUnique identifiersuser_id: UUID
datetimeTimestampscreated_at: datetime
dateCalendar datesbirth_date: date
timeTime of daystart_time: time
timedeltaDurationsduration: timedelta
bytesBinary datacontent: bytes
DecimalPrecise decimalsamount: Decimal