Releases: bufbuild/protobuf-py
Release list
v0.5.0
This release includes a breaking change to codegen options - the recently introduced rewrite_imports option was removed in favor of an easier to use map_imports.
rewrite_imports accepted a path glob to match against import statements to rewrite to an external dependency. While enabling the use of external packages such as on the BSR, the syntax was difficult to use, especially since there was no way to set a prefix. We have replaced it with a map_imports option, following the same pattern as released in protobuf-es which instead matches on the path of the proto file being imported, i.e. the string next to import in a proto file. Prefixes are also supported, either with a trailing / or **, so for example, mapping all of protovalidate becomes much simpler.
Before:
plugins:
- local: protoc-gen-py
out: src/gen
opt: rewrite_imports=./buf/validate/**/*_pb.py:After:
plugins:
- local: protoc-gen-py
out: src/gen
opt: map_imports=buf/validate/:📈 Enhancements
- Add depth limit to serialization by @anuraaga in #87
- Replace rewrite_imports with map_imports by @anuraaga in #98
Full Changelog: v0.4.0...v0.5.0
v0.4.0
This release improves performance for JSON, adds support for the new protobuf edition 2026, and adds an option to allow depending on protobuf-py generated code published as a package, such as a BSR generated SDK, along with other miscellaneous enhancements.
JSON parse accepts duplicate fields
Most JSON parsers accept objects which include duplicate keys, with the last key winning, and the spec for ProtoJSON has also documented this behavior as recommended for some time. However, conformance tests did not allow this behavior and would fail, so per our policy of full conformance, we had to implement rejection of duplicate fields, which can be unintuitive and have poor performance. We have worked with the protobuf team to update conformance tests to match the spec, so they pass for implementations accepting duplicate keys. With that, we have also updated our implementation to accept duplicate fields, with last-in-wins semantics.
The most obvious benefit of this is improved performance for all JSON objects as we do not have to track keys anymore to find duplicates. With this, our benchmarks show consistently higher performance than Pydantic across. The gap is not large, generally less than 10% - performance is not a reason to pick Protobuf over Pydantic but we hope that users can enjoy the benefits of the Protobuf ecosystem without worrying about regressions.
Edition 2026 support
protobuf-py now supports the latest Protobuf Edition 2026. The notable new feature is the ability to customize the JSON string for enum values, not just field names as before. This should allow even more existing JSON schemas to be mappable to proto, for example when migrating to Connect.
edition = "2026";
import "google/protobuf/json_enumvalue_options.proto";
enum Season {
SEASON_UNSPECIFIED = 0;
SEASON_SPRING = 1 [(pb.enumvalue.json).string = "primavera"];
SEASON_SUMMER = 2 [(pb.enumvalue.json).string = "estate"];
SEASON_FALL = 3;
}
message JsonEnumNames {
Season season_field = 1;
}rewrite_imports option for protoc plugins
protoc-gen-py and other plugins based on protobuf-py by default use relative imports for proto dependencies. This conveniently allows outputting code to any location, for example a package called gen. But it prevented being able to reference proto dependencies you may not be generating, for example those in a BSR generated SDK dependency. The workaround for this has to always generate for proto dependencies using include_imports, accepting potential duplication of gencode.
This release adds a flexible rewrite_imports option that can be used to map default relative imports to absolute imports for referencing other packages. For example, if using protovalidate, you can replace rewrite_imports with a dependency on the bufbuild-protovalidate-bufbuild-py generated SDK and point imports at it.
plugins:
- local: protoc-gen-py
out: src/gen
opt: rewrite_imports=./buf/validate/**/*_pb.py:We will continue to explore options to allow this to be more automatic without glob expressions but hope this enables more convenient usage of protobuf-py by enabling the use of published packages.
📈 Enhancements
- Implement eq in native by @anuraaga in #62
- Remove handling of duplicates in JSON parsing by @anuraaga in #56
- Add DescFile dependencies to registry automatically by @anuraaga in #64
- Wire in typing_extensions and set Message generic parameter default by @anuraaga in #79
- Add edition 2026 support and pure-python depth limit to JSON parse by @anuraaga in #73
- Accept any buffer for from_binary by @anuraaga in #85
- Add rewrite_imports option by @anuraaga in #70
Full Changelog: v0.3.0...v0.4.0
v0.3.0
This release is primarily about JSON - we have implemented JSON marshaling in the native extension bringing significant performance improvements, usually 10-20x. As a reminder, connect-py makes it easy to build services using binary or JSON encoding, and with this you should feel comfortable using JSON in production if your use case needs it as the performance difference with binary tends to be 4-5x, not 20x. And new Pydantic integration means you can even use it with normal FastAPI endpoints.
Pydantic integration
Protobuf Message now implement a hook allowing them to be used in most cases a Pydantic model can be - see how it can be used in the docs. Notably, because FastAPI natively supports Pydantic types in API handlers, you can now use messages in place of custom defined models.
from typing import Annotated
from fastapi import Body, FastAPI
from gen.user_pb import User
app = FastAPI()
@app.post("/users")
async def create_user(user: Annotated[User, Body()]) -> User:
user.active = True
return userThe messages will be fully documented and debuggable in the /docs endpoint as well.
📈 Enhancements
- Allow passing in CLI parameters to plugin run by @anuraaga in #20
- Add optional pydantic integration by @anuraaga in #26
- Use fastpath attribute access on free-threaded Python by @anuraaga in #41
- Encode into a bytearray for pure Python by @anuraaga in #42
- Add native JSON marshaler by @anuraaga in #28
- Use a Python-backed global allocator in Rust by @anuraaga in #46
- Add public helpers for codegen plugins by @anuraaga in #53
Full Changelog: v0.2.0...v0.3.0
v0.2.0
This is a relatively small release with some bugfixes and addition of txtpb marshaling for debugging. Thanks for all the great feedback.
🛠️ Bug fixes
- Allow passing int values to float fields by @anuraaga in #4
- Tighten Any.unpack definition with overloads by @anuraaga in #8
- Fix timestamp validation range by @AdrienVannson in #18
📈 Enhancements
- Encode compact JSON by @anuraaga in #16
- Add Registry.extensions_for by @anuraaga in #14
- Add protobuf text format support by @stefanvanburen in #13
New Contributors
Thanks for the help!
- @KoljaFrahm made their first contribution in #7
- @pkwarren made their first contribution in #11
- @stefanvanburen made their first contribution in #13
- @AdrienVannson made their first contribution in #18
Full Changelog: https://github.com/bufbuild/protobuf-py/commits/v0.2.0