PyBARE
A declarative implementation of the BARE message
format for Python 3.10+
pybare is a general purpose library for strongly typed primitives in Python that
supports serializing to and from BARE messages.
pip install pybare
Goals
- Provide a declarative structure for defining types
- Validation on value updates
- Support streaming messages
Status
pybare fully implements all BARE types for both encoding and decoding. This
includes reading multiple messages from the same BinaryIO
stream.
It is well tested and in use on production systems.
Gotchas
We use "Array" / "array" instead of "List" / "list" to avoid conflicts with Python's
common builtin type of the same name.
Examples
An example that defines the types used as an example in the RFC may be found in
example.py
pybare currently requires you define your structures by hand. Examples can be
found in the
tests.
Quickstart
The general convention is type identifiers start with a capital letter and anonymous
generating functions begin with a lowercase. This follows general "pythonic" style for
classes vs functions.
from bare import Struct, map, Str, UInt, optional, data, array, Void, struct, U8
PubKey = data(64)
class User(Struct):
username = Field(Str)
userid = Field(Int)
email = Field(optional(Str))
keys = Field(map(Str, PubKey))
repos = Field(array(Str))
friends = Field(array(struct(name=Str, age=U8)))
noah = User(username="chiefnoah", userid=1, email=Void(), keys={}, repos=[], friends=[])
noah.username == 'chiefnoah'
noah.username = 'someoneelse'
noah.username == 'someoneelse'
noah.userid == 1
noah.username = 1
noah.keys
noah.keys['my key'] = bytes(64)
noah.keys['oops'] = bytes(1)
noah.email == Void()
noah.email = 12345
noah.pack()
Note, you must wrap the desired type in a Field
to get its 'magic' behavior.
Class or instance fields that are not wrapped in a Field
will be ignored by the pack
and unpack
methods.
To contribute, send patches to ~chiefnoah/inbox@lists.sr.ht