microspec
A micro specification parser and data validator for TCP protocols. The protocol can be defined either inside the code or as a standalone JSON which can be loaded via Protocol.from_dict(...). Then, all the data payloads for all the defined endpoints are simply validated via protocol.validate_endpoint(endpoint, payload) -> ValidationError | None.
Usage:
- Via pip:
pip install microspec-py(the PyPI name ismicrospec-py; the import name ismicrospec) - From source code:
git clone https://gitlab.com/meehai/microspec # clone the source code
cd microspec # go in the cloned directory
python -m venv .venv && source .venv/bin/activate # make a virtual env, optional but useful
python -m pip install -e . # install microspec in this virtual env
python -m pytest test/ # run the unit & integration tests to verify installation
python microspec/microspec.py test/integration/protocol.json # smoke run: parse + validate the bundled spec
Docs: meehai.gitlab.io/microspec — built by
docs/build_docs.sh (pdoc; no sphinx/config). Build locally with
bash docs/build_docs.sh and open the printed file:// link.
Usage
Protocol:
{
"move": {
"input": {"control_input": {"dtype": "float32", "shape": [6], "range": [-100, 100]}},
"output": {"status": {"dtype": "str_enum", "enum": ["move_applied"]}, "new_state": {"dtype": "dict"}}
}
}
import json
from microspec import Protocol
# Can also be defined here manually via the `Endpoint`, `Field` classes and `Dtype` enum from the library.
protocol = Protocol.from_dict(json.load(open("test/integration/protocol.json")), n_max_robots=10)
err = protocol.validate_endpoint("move", {"control_input": [5, 5, 5, 3, 3, 3]})
if err is not None: # err is of type ValidationError (has .error, .endpoint, .field for context)
raise ValueError(f"payload is not valid: {err.endpoint}: {err.error}")
Spec format
Each command is an input / output map of name -> field. Errors are not per-command: every
endpoint shares one error shape, declared once as Protocol's error_field (default Field("error", Dtype.STR)).
{
"move": {
"input": {"control_input": {"dtype": "float32", "shape": [6], "range": [-100, 100]}},
"output": {"status": {"dtype": "str_enum", "enum": ["move_applied"]}, "new_state": {"dtype": "dict"}}
},
"robot_get_state": {
"input": {"robot_ix": {"dtype": "int32", "range": [0, "${n_max_robots}"]}},
"output": {"robot": {"dtype": "dict"}}
}
}
Field schema
| key | applies to | meaning |
|---|---|---|
dtype |
required | str int32 float32 bool dict bytes str_enum int_enum |
shape |
array dtypes | e.g. [6]; null = free first axis ([null, 6]) |
range |
int32 / float32 |
[min, max], inclusive (NaN always rejected; ±Inf only if outside the range) |
enum |
str_enum / int_enum |
non-empty list of allowed values (required for enum dtypes) |
min_len |
arrays with free axis | minimum length of the null axis |
fields |
dict |
optional nested name -> field map; omit for an opaque dict |
Notes: a shape key means "array" (numpy, exact dtype — np.float32, not int64); scalars have no
shape. A dict with fields is validated recursively (keys must match exactly, nested arrays are
list→ndarray converted); without fields it is opaque (any dict passes). ${var} is a single bare
variable filled at parse time (e.g. n_max_robots). The spec file is plain JSON.
Public API
Protocol, Endpoint, Field, Dtype, ValidationError. Everything else is internal.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file microspec_py-0.1.1.tar.gz.
File metadata
- Download URL: microspec_py-0.1.1.tar.gz
- Upload date:
- Size: 8.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/5.1.1 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b05baad1d64b1cb77dc97fbc1d9c80ba945a1e93f3b1c6178cbc3cd2ba5e02a
|
|
| MD5 |
b87e727805a0aa53b838ee7af36c9aa8
|
|
| BLAKE2b-256 |
a072e9a92141cd50be3a527fc4c38b934e7fbd15810bbaaa8ddfba13df6d9e52
|