Protocol Buffer Validation for Python
protovalidate is a Python library that provides Protocol Buffer validation based on Buf's Protovalidate specification. It allows defining validation rules directly in `.proto` files using custom options and then enforcing these rules at runtime within Python applications. The current version is 1.1.2, and it follows a frequent release cadence, often aligning with the core Protovalidate specification releases and `protobuf` runtime updates.
Warnings
- breaking The `protovalidate.Config` class was removed and the `into` argument for `collect_validations` was removed.
- breaking The `regex_matches_func` configuration option was removed. RE2 regular expression syntax now requires the `google-re2` dependency.
- breaking The `IGNORE_IF_UNPOPULATED` rule option in `.proto` files was renamed to `IGNORE_IF_ZERO_VALUE`.
- gotcha Python 3.9 support was dropped.
- gotcha Compatibility issues with `protobuf==7` existed in versions prior to `1.1.2`.
Install
-
pip install protovalidate -
pip install protovalidate[re2]
Imports
- validate
from protovalidate import validate
Quickstart
import os
import sys
from pathlib import Path
# This quickstart assumes you have a proto file 'example.proto'
# that has been compiled to 'example_pb2.py' using protoc.
# For example, if example.proto contains:
#
# syntax = "proto3";
# package example;
# import buf/validate/validate.proto;
#
# message User {
# string name = 1 [(buf.validate.field).string.min_len = 1];
# int32 age = 2 [(buf.validate.field).int32.gt = 0];
# }
#
# You would compile it with:
# protoc --python_out=. --proto_path=. --proto_path=$(go env GOPATH)/src/github.com/bufbuild/protovalidate example.proto
# (or similar, ensuring validate.proto is in the proto path)
# For demonstration, we'll create a dummy 'example_pb2' module if not found
# In a real app, this module would be generated by protoc.
try:
# In a real application, this would be generated by protoc
# and imported normally. We include this workaround for a runnable quickstart.
if 'example_pb2' not in sys.modules:
# Mock a minimal pb2 module for demonstration if not generated
class User:
def __init__(self, name=None, age=None):
self.name = name
self.age = age
def SerializeToString(self):
# In real scenario, this would serialize the actual proto
return b''
def __str__(self):
return f"User(name='{self.name}', age={self.age})"
sys.modules['example_pb2'] = type('module', (object,), {'User': User})
from example_pb2 import User # This will now resolve to our mock User or actual generated one
from protovalidate import validate
# Valid user
valid_user = User(name="Alice", age=30)
violations_valid = validate(valid_user)
print(f"Valid User: {valid_user}")
if violations_valid:
for violation in violations_valid:
print(f" Violation: {violation.field_path} - {violation.message}")
else:
print(" No violations.")
print("\n---")
# Invalid user (empty name, negative age)
invalid_user = User(name="", age=-5)
violations_invalid = validate(invalid_user)
print(f"Invalid User: {invalid_user}")
if violations_invalid:
for violation in violations_invalid:
print(f" Violation: {violation.field_path} - {violation.message}")
else:
print(" No violations.")
except ImportError as e:
print(f"Error: Could not import protobuf-generated modules. Please ensure 'example.proto' is compiled to 'example_pb2.py'.\nDetails: {e}")
print("For a full setup, refer to the protovalidate-python documentation on generating protobuf files with validation rules.")