FastProto is fast and efficient protobuf library for Python, built on the top of Rust.
Project description
FastProto
FastProto is a fast, ergonomic Protocol Buffers library for Python. Messages
are plain, readable @dataclass types — no generated getters/setters, no
Message reflection API to learn — while all encoding and decoding happens in
a compiled Rust core.
- Idiomatic messages. Generated code is a
@dataclass, annotated with plain Python types (str,int,list[...],dict[...],| None). Autocomplete, type checkers, andrepr()all just work. - Rust-powered wire codec. Encoding and decoding are implemented in Rust via PyO3, avoiding the overhead of pure-Python protobuf implementations.
- Wire-compatible. Bytes produced by FastProto are read correctly by
Google's reference
protobufruntime, and vice versa. - Drop-in
protocplugin. Reuses the standard.prototoolchain — runprotocwith--fastproto_outto generate typed dataclasses.
Installation
pip install fastproto
Generating code from .proto files also requires the protoc compiler and
the plugin's protobuf dependency:
pip install "fastproto[plugin]"
protoc itself isn't installed by pip — grab it from your package manager
(apt install protobuf-compiler, brew install protobuf, ...) or the
official releases.
Quick start
1. Write a .proto file (user.proto):
syntax = "proto3";
package example;
enum Role {
ROLE_UNSPECIFIED = 0;
ROLE_ADMIN = 1;
ROLE_USER = 2;
}
message Address {
string city = 1;
string street = 2;
}
message User {
int64 id = 1;
string name = 2;
optional string email = 3;
Role role = 4;
repeated string tags = 5;
Address address = 6;
map<string, int32> counters = 7;
}
2. Generate the Python module with protoc, using the fastproto plugin:
protoc --proto_path=. --fastproto_out=. user.proto
This produces user_pb.py — a plain, readable dataclass module:
# @generated by fastproto. DO NOT EDIT.
# source: user.proto
from dataclasses import dataclass, field
from enum import IntEnum
from fastproto import Message, Scalar, message
class Role(IntEnum):
ROLE_UNSPECIFIED = 0
ROLE_ADMIN = 1
ROLE_USER = 2
@message(_ADDRESS_DESCRIPTOR)
@dataclass(slots=True)
class Address(Message):
city: Scalar.String = ""
street: Scalar.String = ""
@message(_USER_DESCRIPTOR)
@dataclass(slots=True)
class User(Message):
id: Scalar.Int64 = 0
name: Scalar.String = ""
email: Scalar.String | None = None
role: Role = Role(0)
tags: list[Scalar.String] = field(default_factory=list)
address: "Address | None" = None
counters: dict[Scalar.String, Scalar.Int32] = field(default_factory=dict)
3. Use it like any other Python dataclass:
from user_pb import Address, Role, User
user = User(
id=42,
name="Ada",
email="ada@example.com",
role=Role.ROLE_ADMIN,
tags=["vip", "beta"],
address=Address(city="London", street="Baker St"),
counters={"logins": 7},
)
# Serialize to protobuf wire bytes.
data = user.to_bytes()
# Deserialize back into a `User` instance.
same_user = User.from_bytes(data)
assert same_user == user
That's it — no SerializeToString() / ParseFromString() ceremony, no
ListFields() reflection, just to_bytes() / from_bytes() on a dataclass
you can construct, compare, and pretty-print directly.
Field type mapping
Every proto scalar type has a corresponding alias under fastproto.Scalar.
Each alias is just the underlying Python type (int, str, ...) tagged with
an Annotated[...] marker, so it type-checks exactly as you'd expect while
still documenting the precise wire type:
| proto type | Python annotation |
|---|---|
double |
Scalar.Double |
float |
Scalar.Float |
int32 |
Scalar.Int32 |
int64 |
Scalar.Int64 |
uint32 |
Scalar.UInt32 |
uint64 |
Scalar.UInt64 |
sint32 |
Scalar.SInt32 |
sint64 |
Scalar.SInt64 |
fixed32 |
Scalar.Fixed32 |
fixed64 |
Scalar.Fixed64 |
sfixed32 |
Scalar.SFixed32 |
sfixed64 |
Scalar.SFixed64 |
bool |
Scalar.Bool |
string |
Scalar.String |
bytes |
Scalar.Bytes |
Composite fields map the way you'd hope:
repeated T→list[T]map<K, V>→dict[K, V]optional T/oneofmembers →T | None- nested/enum messages → the generated class or
IntEnum, referenced by name
Enums, nested messages, and oneof
Enums become IntEnum subclasses; message fields hold real instances of the
generated dataclass (or None when unset); oneof groups are represented as
plain optional fields, and FastProto enforces "at most one set" at encode
time:
from user_pb import User
# Setting more than one oneof member raises when you try to serialize it.
User(phone="123", telegram="abc").to_bytes() # raises ValueError: ... oneof ...
Presence semantics
FastProto follows proto3 field presence rules:
- Plain scalar fields (
string,int32, ...) use their zero value as the default and are not nullable — they always round-trip to a concrete value. optionalscalar fields, message fields, andoneofmembers are nullable (T | None) and track explicit presence, matching proto3 semantics exactly (an explicitly-set empty string is distinguishable from an unset field).
from user_pb import User
empty = User()
assert empty.to_bytes() == b"" # all-default messages encode to zero bytes
assert User.from_bytes(b"") == empty
assert empty.email is None # optional, unset
How linking works
Generated dataclasses reference sibling messages and enums by name (as
forward references), since a message can reference a type defined later in
the same file, or itself (recursively). FastProto resolves these references
lazily, on first to_bytes() / from_bytes() call, by looking them up in the
generated module's namespace — you never need to call anything yourself.
Development
The project is a mixed Rust/Python codebase built with maturin, managed with uv.
git clone https://github.com/pkozhem/fastproto
cd fastproto
uv sync # installs dev dependencies and builds the extension
uv run maturin develop # rebuild the Rust extension in-place after changes
uv run pytest # run the test suite
uv run ruff check . # lint
uv run ty check # type-check
Test fixtures under tests/generated/ are themselves @generated output,
committed so the plugin's golden tests can diff against them. After editing a
.proto file under tests/protos/ or the plugin itself, regenerate them
with:
uv run python scripts/regen.py
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastproto-0.1.2.tar.gz.
File metadata
- Download URL: fastproto-0.1.2.tar.gz
- Upload date:
- Size: 41.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96be4bdb60be723af0f2366fb009aadd23ca1a57f2a2aa2d2db4a3bb4e114eb6
|
|
| MD5 |
649d00038e2271f5b18e9b77871117e5
|
|
| BLAKE2b-256 |
734904d8be1af29466552f14389655458ee0bb5bc87d151fe115a2c4d4646508
|
Provenance
The following attestation bundles were made for fastproto-0.1.2.tar.gz:
Publisher:
release.yml on pkozhem/fastproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastproto-0.1.2.tar.gz -
Subject digest:
96be4bdb60be723af0f2366fb009aadd23ca1a57f2a2aa2d2db4a3bb4e114eb6 - Sigstore transparency entry: 2063169307
- Sigstore integration time:
-
Permalink:
pkozhem/fastproto@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pkozhem
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastproto-0.1.2-cp312-abi3-win_amd64.whl.
File metadata
- Download URL: fastproto-0.1.2-cp312-abi3-win_amd64.whl
- Upload date:
- Size: 167.8 kB
- Tags: CPython 3.12+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06b112b164a2983369179a454ea168870e94f1f31d7e9ffdd1187e6c4e98df54
|
|
| MD5 |
58f55da307670ab2ff58aa6a6bd6ccdd
|
|
| BLAKE2b-256 |
4df0b27c8a6329661d248cb742288823384c10ad419e448bfbbff9a52650ac1e
|
Provenance
The following attestation bundles were made for fastproto-0.1.2-cp312-abi3-win_amd64.whl:
Publisher:
release.yml on pkozhem/fastproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastproto-0.1.2-cp312-abi3-win_amd64.whl -
Subject digest:
06b112b164a2983369179a454ea168870e94f1f31d7e9ffdd1187e6c4e98df54 - Sigstore transparency entry: 2063169382
- Sigstore integration time:
-
Permalink:
pkozhem/fastproto@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pkozhem
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastproto-0.1.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: fastproto-0.1.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 310.5 kB
- Tags: CPython 3.12+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6c86750b0f749367b3306bf80fe434b15581afe956d5100ef1b3f7f49ea6de9
|
|
| MD5 |
2a318735b12daa4931d78648f1e476b3
|
|
| BLAKE2b-256 |
4040815b8a46a7b15665bde4a0603d3459515fd85d2a9da57e5984ef205b0c7b
|
Provenance
The following attestation bundles were made for fastproto-0.1.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on pkozhem/fastproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastproto-0.1.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
b6c86750b0f749367b3306bf80fe434b15581afe956d5100ef1b3f7f49ea6de9 - Sigstore transparency entry: 2063169323
- Sigstore integration time:
-
Permalink:
pkozhem/fastproto@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pkozhem
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastproto-0.1.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: fastproto-0.1.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 307.3 kB
- Tags: CPython 3.12+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f9a231ef53ada0011ea1f434011dfc44f5acda818c8103c3ba3477562d09433
|
|
| MD5 |
30f6e51232470e01e0b055a3f582c3eb
|
|
| BLAKE2b-256 |
f2d0b32712f0950065496fcc194c577ad401d71717f3465f8713d878c55eeebc
|
Provenance
The following attestation bundles were made for fastproto-0.1.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on pkozhem/fastproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastproto-0.1.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
2f9a231ef53ada0011ea1f434011dfc44f5acda818c8103c3ba3477562d09433 - Sigstore transparency entry: 2063169413
- Sigstore integration time:
-
Permalink:
pkozhem/fastproto@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pkozhem
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastproto-0.1.2-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: fastproto-0.1.2-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 532.8 kB
- Tags: CPython 3.12+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2cb07a24a5f1020b486fea794abb855b8a28c5c9c0e041d1bc43a14e5ab3fe4
|
|
| MD5 |
b0a9c90439ae253ca8f2e530dbd3977a
|
|
| BLAKE2b-256 |
46df79bb6f69731f267e432c989e96fc0b2ac39d96c74c6be0eb5c0fe7d51922
|
Provenance
The following attestation bundles were made for fastproto-0.1.2-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
release.yml on pkozhem/fastproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastproto-0.1.2-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
e2cb07a24a5f1020b486fea794abb855b8a28c5c9c0e041d1bc43a14e5ab3fe4 - Sigstore transparency entry: 2063169358
- Sigstore integration time:
-
Permalink:
pkozhem/fastproto@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pkozhem
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d4ed289aa0fd3a6fe79847316a1b2ccc92d56a -
Trigger Event:
workflow_dispatch
-
Statement type: