Putting a message together¶
Now let us combine the features we have covered: an author model, a list of tags, and an optional note. You can run this example as a complete script.
from bytespec import ProtoModel, field
from bytespec.types import UInt32
class User(ProtoModel):
id: UInt32
name: str
class Message(ProtoModel):
author: User
text: str
tags: list[str] = field(default_factory=list)
note: str | None = field(flag=0)
message = Message(
author=User(id=42, name="Anna"),
text="Hello!",
tags=["news"],
)
encoded = message.encode()
decoded = Message.decode(encoded)
print(decoded.author.name) # Anna
print(decoded.text) # Hello!
print(decoded.tags) # ['news']
print(decoded.note) # None
Creation and decoding work just as they did for the first model. Tags are restored as a list, the author as a User, and the omitted note as None. These structures needed no separate serialization calls.
Let us change the note and encode the message again:
decoded.note = "Updated"
updated = Message.decode(decoded.encode())
print(updated.note) # Updated
Try this example with empty tags and with note="": both values are preserved. Only note=None removes the optional field from the message.
You can now try a model on a single packet from your own protocol. Headers and framing shows how to configure framing bytes; Validating model values explains how to check relationships between fields; Handling errors covers error handling. To read several messages from one buffer, open Files and multiple messages.