I'm using protoc version 28.3 on macos:
> protoc --version
libprotoc 28.3
This version can generate gRPC for typescript and go and C++, with the appropriate plugins. It can also generate plain protobuf:
> protoc --experimental_editions -I src/proto3 --python_out=./src/generated/python/revepb src/proto3/*.proto
>
However, when I try to generate grpc, it fails:
> uv run python3 -m grpc_tools.protoc --experimental_editions -I src/proto3 --python_out=./src/generated/python/revepb src/proto3/*.proto
basetypes.generated.proto: is an editions file, but code generator --python_out hasn't been updated to support editions yet. Please ask the owner of this code generator to add support or switch back to proto2/proto3.
This makes no sense because --python_out works well in isolation.
The closest I can think of would be that grpc_tools might include its own flavor of protoc, AND that tool hasn't been updated for two years or something.
These are the versions:
+ grpcio==1.67.1
+ grpcio-tools==1.67.1
+ protobuf==5.28.3
+ setuptools==75.5.0
1.67.1 is the latest released version, from October 28 2024.
What else can I check, version-wise?
I assume, perhaps wrongly, that "use grpc with editions in python" is a mainstream thing that I should expect to work, given that python is a core language inside google -- is this assumption wrong?
What else can I do to make this work?
I'm unable to repro your issue (on Linux), I tried:
Yes, grpc_tools
bundles a (current) protoc
binary:
python3 -m grpc_tools.protoc --version
libprotoc 27.2
You're missing the --grpc_python_out
directive to generate service
and rpc
bindings:
# Includes:
# 1. `--pyi_out` for Python type-checking (not gRPC :-()
# 2. `--grpc_python_out` for Python gRPC service|rpc stubs
python3 \
-m grpc_tools.protoc \
--experimental_editions \
--proto_path=${PWD} \
--python_out=${PWD} \
--pyi_out=${PWD} \
--grpc_python_out=${PWD} \
${PWD}/foo.proto
And, using a gRPC-enabled variant of Player
:
foo.proto
:
// Edition version of proto2 file
edition = "2023";
package com.example;
message Player {
// fields have explicit presence, so no explicit setting needed
string name = 1;
// to match the proto2 behavior, LEGACY_REQUIRED is set at the field level
int32 id = 2 [features.field_presence = LEGACY_REQUIRED];
// to match the proto2 behavior, EXPANDED is set at the field level
repeated int32 scores = 3 [features.repeated_field_encoding = EXPANDED];
enum Handed {
// this overrides the default edition 2023 behavior, which is OPEN
option features.enum_type = CLOSED;
HANDED_UNSPECIFIED = 0;
HANDED_LEFT = 1;
HANDED_RIGHT = 2;
HANDED_AMBIDEXTROUS = 3;
}
Handed handed = 4;
reserved gender;
}
// Some gRPC service
service Foo {
// Some gRPC method
rpc Fooey (Player) returns (Player) {}
}
Yields:
.
├── foo_pb2_grpc.py
├── foo_pb2.py
├── foo_pb2.pyi
└── foo.proto
From:
python3 -m venv venv && \
source venv/bin/activate && \
python3 -m pip install grpcio && \
python3 -m pip install grpcio-tools && \
python3 -m pip freeze
grpcio==1.67.1
grpcio-tools==1.67.1
protobuf==5.28.3