protovalidate-python
protovalidate-python copied to clipboard
Protocol Buffer Validation for Python.
protovalidate-python
protovalidate-python is the Python implementation of protovalidate,
designed to validate Protobuf messages at runtime based on user-defined validation constraints. Powered by Google's
Common Expression Language (CEL), it provides a flexible and efficient foundation
for defining and evaluating custom validation rules. The primary goal of protovalidate is to help developers ensure
data consistency and integrity across the network without requiring generated code.
The protovalidate project
Head over to the core protovalidate repository for:
- The API definition: used to describe validation constraints
- Documentation: how to apply
protovalidateeffectively - Migration tooling: incrementally migrate
from
protoc-gen-validate - Conformance testing utilities: for
acceptance testing of
protovalidateimplementations
Other protovalidate runtime implementations include:
- Go:
protovalidate-go - C++:
protovalidate-cc - Java:
protovalidate-java
And others coming soon:
- TypeScript:
protovalidate-ts
Installation
To install the package, use pip:
pip install protovalidate
Make sure you have the latest version of protovalidate-python by checking the
project's PyPI page.
Usage
Implementing validation constraints
Validation constraints are defined directly within .proto files. Documentation for adding constraints can be found in
the protovalidate project README and
its comprehensive docs.
syntax = "proto3";
package my.package;
import "google/protobuf/timestamp.proto";
import "buf/validate/validate.proto";
message Transaction {
uint64 id = 1 [(buf.validate.field).uint64.gt = 999];
google.protobuf.Timestamp purchase_date = 2;
google.protobuf.Timestamp delivery_date = 3;
string price = 4 [(buf.validate.field).cel = {
id: "transaction.price",
message: "price must be positive and include a valid currency symbol ($ or £)",
expression: "(this.startswith('$') or this.startswith('£')) and float(this[1:]) > 0"
}];
option (buf.validate.message).cel = {
id: "transaction.delivery_date",
message: "delivery date must be after purchase date",
expression: "this.delivery_date > this.purchase_date"
};
}
Generating Code with buf
When using the runtime library after installing it with pip, it's necessary to generate the Python code for the core buf.protovalidate Protobuf package. buf provides an efficient method for this:
-
Initialize a New Configuration File:
buf mod initThis initializes the
buf.yamlconfiguration file at the root of the Protobuf source files. -
Module Configuration and Dependencies:
# buf.yaml version: v1 deps: - buf.build/bufbuild/protovalidateEnsure your dependencies are up-to-date with:
buf mod update -
Setup Code Generation:
# buf.gen.yaml version: v1 plugins: - plugin: buf.build/protocolbuffers/python:v23.4 out: gen -
Generate Code: To generate the required Python code:
buf generate --include-imports
If your goal is to generate code specifically for the buf.protovalidate Protobuf package, run:
buf generate buf.build/bufbuild/protovalidate
Note: For users familiar with
protoc, while it's an alternative tobuf, it is recommended to use tooling or frameworks like Bazel for direct code generation, as it provides an encapsulated environment for such tasks.
Example
import protovalidate
from google.protobuf.timestamp_pb2 import Timestamp
from my.package import Transaction
transaction = Transaction()
transaction.id = 1234
transaction.price = "$5.67"
transaction.purchase_date.CopyFrom(Timestamp())
transaction.delivery_date.CopyFrom(Timestamp())
try:
protovalidate.validate(transaction)
except protovalidate.ValidationError as e:
# Report the violations
Ecosystem
protovalidatecore repository- Buf
- CEL Spec
Legal
Offered under the Apache 2 license.