Metadata-Version: 2.1
Name: pybare
Version: 1.2.2
Summary: A declarative implementation of BARE for Python
Home-page: https://sr.ht/~chiefnoah/pybare/
Author: Noah Pederson
Author-email: noah@packetlost.dev
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE

# PyBARE
[![builds.sr.ht status](https://builds.sr.ht/~chiefnoah/pybare.svg)](https://builds.sr.ht/~chiefnoah/pybare?)

A declarative implementation of the [BARE](https://baremessages.org/) message
format for Python 3.11+

---

pybare is a general purpose library for strongly typed primitives in Python that
supports serializing to and from BARE messages.

```shell
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.

### TODO

- [ ] Codegen based on `.schema` files
- [ ] Better documentation
- [ ] More tests
- [ ] Fast C implementation for encoding

## Examples

pybare currently requires you define your structures by hand. Examples can be
found in the
[tests](https://git.sr.ht/~chiefnoah/pybare/tree/master/bare/test_encoder.py).

### Quickstart

```python
from bare import Struct, map, Str, UInt, optional, data, array, Void

# Alternatively, class Data(size=64): ...
PubKey = data(64) # 512 bits

class User(Struct):
    username = Filed(Str)
    userid = Field(Int)
    email = Field(optional(Str))
    keys = Field(map(Str, PubKey))
    repos = Field(array(Str)) # variable length array


noah = User(username="chiefnoah", userid=1, email=Void(), keys={}, repos=[])
noah.username == 'chiefnoah'
noah.username = 'someoneelse'
noah.username == 'someoneelse'
noah.userid == 1 # True
noah.username = 1 # raise: bare.ValidationError
noah.keys # {} (empty dict)
noah.keys['my key'] = bytes(64) #\x00\x00...
noah.keys['oops'] = bytes(1) # raise: bare.ValidationError
noah.email == Void() # True
noah.email = 12345 # raise: bare.ValidationError
noah.pack() # \x00\x01 ... (binary data)
```

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](mailto:~chiefnoah/inbox@lists.sr.ht)
