How to bridge models and objects¶
This guide shows you how to convert supported Python models and JavaScript objects to the core
Value form, host them in a Session, and generate TypeScript interfaces from Python types.
Use pydantic models¶
import transports
from pydantic import BaseModel
class Device(BaseModel):
name: str
on: bool = False
model = Device(name="lamp")
value = transports.to_value(model)
restored = transports.from_value(value, Device)
assert restored == model
Pydantic models are observed automatically when hosted:
session = transports.Session()
mid = session.host(model)
model.on = True
patches = session.drain()
Use dataclasses¶
from dataclasses import dataclass
import transports
@dataclass
class Reading:
sensor: str
value: float = 0.0
reading = Reading(sensor="temp")
session = transports.Session()
session.host(reading)
reading.value = 21.5
print(session.drain())
Dataclasses are observed automatically, including nested lists, dicts, and model fields.
Use msgspec structs¶
msgspec.Struct instances use slots, so automatic mutation watching is not available. Mutate the
struct and call Session.update(id).
import msgspec
import transports
class Reading(msgspec.Struct):
sensor: str
value: float = 0.0
reading = Reading(sensor="temp")
session = transports.Session()
mid = session.host(reading)
reading.value = 21.5
print(session.drain())
# []
print(session.update(mid))
# [(1, {'rev': 1, 'ops': [...]})]
Convert values manually¶
Use to_value when a lower-level API expects the core wire value. Use from_value to materialize a
mirrored value as a Python model.
value = transports.to_value(Device(name="lamp", on=True))
# {'Map': {'name': {'Str': 'lamp'}, 'on': {'Bool': True}}}
model = transports.from_value(value, Device)
Generate TypeScript from a Python model¶
schema = transports.schema_of(Device)
print(transports.schema_to_ts(schema))
Output:
export interface Device {
name: string;
on: boolean;
}
Bridge plain JavaScript objects¶
import { fromValue, toValue } from "1kbgz/transports";
const value = toValue({ name: "lamp", on: true });
// { Map: { name: { Str: "lamp" }, on: { Bool: true } } }
const object = fromValue(value);
// { name: "lamp", on: true }
Use the JavaScript bridge before calling Client.edit, because edits compare core Value objects:
ws.send(client.edit(id, toValue({ name: "lamp", on: false })));
Current bridge limits¶
Nested Python models are currently inlined as Map values. The Rust core has a Submodel value,
but the Python and JavaScript bridges do not yet emit submodel-by-id references.
JavaScript has one number type. Whole-valued JavaScript numbers encode as Int; other numbers
encode as Float.