Mypy Protobuf Stubs Generator
mypy-protobuf is a Python library and `protoc` plugin that generates mypy stub files (.pyi files) from Protocol Buffer (.proto) specifications. It ensures type safety for Python code interacting with protobuf messages and gRPC services, providing more accurate and detailed type information than the standard `protoc --pyi_out` option. Currently at version 5.0.0, it maintains an active release cadence with frequent updates.
Warnings
- breaking mypy-protobuf versions have historically updated their minimum required `protobuf` major version without a corresponding major version bump in `mypy-protobuf` itself. For example, `mypy-protobuf 3.4.0` implicitly required `protobuf 4.x.x`, breaking compatibility with existing `protobuf 3.x.x` installations. Always check the PyPI project page for the latest compatible `protoc` and `python-protobuf` versions for your `mypy-protobuf` release.
- breaking Python version support has been dropped in several major releases. `mypy-protobuf 2.10` was the last version to support targeting Python 2.7. `mypy-protobuf 3.5.0` dropped support for Python 3.7. Python 3.8 testing was dropped in `mypy-protobuf 3.7.0` due to incompatibilities with newer `protobuf` versions.
- gotcha The `readable_stubs` option (if enabled) can generate stubs that are easier to read but might not pass `mypy`, particularly in cases of name collisions between global identifiers and field names. By default, `mypy-protobuf` uses fully qualified imports and mangled global identifiers to prevent such collisions.
- gotcha To run `protoc` with the `mypy-protobuf` plugin, the `protoc-gen-mypy` executable (installed by `pip install mypy-protobuf`) must be discoverable by `protoc`. This typically means it needs to be in your system's `PATH` environment variable. If it's not, `protoc` will report an error like 'plugin not found'.
Install
-
pip install mypy-protobuf
Quickstart
mkdir -p project/proto project/output
cat <<EOF > project/proto/example.proto
syntax = "proto3";
package example;
message MyMessage {
string name = 1;
int32 id = 2;
bool is_active = 3;
}
EOF
# Ensure protoc and protoc-gen-mypy are in PATH or specify full paths
# protoc --plugin=protoc-gen-mypy=/path/to/protoc-gen-mypy ...
protoc --python_out=project/output --mypy_out=project/output project/proto/example.proto
# Expected output will include example_pb2.py and example_pb2.pyi in project/output
cat <<EOF > project/main.py
from project.output import example_pb2
def process_message(msg: example_pb2.MyMessage) -> None:
print(f"Processing: {msg.name} (ID: {msg.id}, Active: {msg.is_active})")
# Correct usage
my_msg = example_pb2.MyMessage(name="Test", id=123, is_active=True)
process_message(my_msg)
# Incorrect usage (mypy would catch this)
# invalid_msg = example_pb2.MyMessage(name=123, id="abc")
# process_message(invalid_msg)
EOF
# Run mypy to type-check the project
mypy project