Reputation: 662
I am trying to setup a larger bazel infrastructure to
.proto
file for gRPC using rules_proto_grpc_python
py_binary
However, I am getting the error
google.protobuf.runtime_version.VersionError: Detected incompatible Protobuf Gencode/Runtime versions
when loading helloworld/hello.proto: gencode 5.29.1 runtime 5.27.2. Runtime version
cannot be older than the linked gencode version. See Protobuf version
guarantees at https://protobuf.dev/support/cross-version-runtime-guarantee.
indicating that the protobuf version that rules_proto_grpc_python
uses to generate the .py files is different from the version used at runtime. I tried to require protobuf>=5.29.1
for the `py_binary`` but that is not possible due to conficts with other packages in the project. In this minimal example, it is possible but issues several warnings about conflicting symlinks which seems concerning as well. Is there a way to either
rules_proto_grpc_python
.py
files from the .proto
in another way?I managed to get this to work by playing around with the requirements in my larger repository. Specifying the minimum protobuf version causes it to work.
The top-level MODULE.bazel:
# MODULE.bazel
bazel_dep(name = "aspect_bazel_lib", version = "2.7.8")
bazel_dep(name = "aspect_rules_py", version = "1.3.2")
bazel_dep(name = "rules_python", version = "1.1.0")
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_proto_grpc_python", version = "5.0.0")
# deps for python projects.
_PY_MINOR_VER = 10
_PY_VERSION = "3.%s" % _PY_MINOR_VER
_PY_VER_ = "python_3_%s" % _PY_MINOR_VER
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
python_version = _PY_VERSION,
is_default = True,
)
# You can use this repo mapping to ensure that your BUILD.bazel files don't need
# to be updated when the python version changes to a different `3.12` version.
use_repo(
python,
"python_3_%s" % _PY_MINOR_VER,
)
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
hub_name = "pypi",
# We need to use the same version here as in the `python.toolchain` call.
python_version = _PY_VERSION,
requirements_lock = "//:requirements_lock.txt",
)
use_repo(pip, "pypi")
Inside a directory /proto_library/proto/hello.proto
# proto_library/proto/hello.proto
syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
The BUILD.bazel alongside the proto file
# proto_library/proto/BUILD.bazel
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_proto_grpc_python//:defs.bzl", "py_proto_library", "py_grpc_library")
proto_library(
name = "hello_proto",
srcs = ["hello.proto"],
# Add these to control Python package structure
strip_import_prefix = "/proto_library/proto",
import_prefix = "helloworld",
visibility = ["//visibility:public"],
)
py_proto_library(
name = "hello_py_proto",
protos = [":hello_proto"],
visibility = ["//visibility:public"],
)
py_grpc_library(
name = "hello_py_grpc",
protos = [":hello_proto"],
visibility = ["//visibility:public"],
deps = [":hello_py_proto"],
)
The python code to implement the server
# proto_library/src/hello_server.py
import logging
import sys
from concurrent import futures
import grpc
from helloworld import hello_pb2, hello_pb2_grpc
class Greeter(hello_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return hello_pb2.HelloReply(message="Hello, %s!" % request.name)
def serve():
port = "50051"
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port("[::]:" + port)
server.start()
print("Server started, listening on " + port)
server.wait_for_termination()
if __name__ == "__main__":
logging.basicConfig()
serve()
And finally, the BUILD file inside proto_library
# proto_library/BUILD.bazel
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_library")
load("@pypi//:requirements.bzl", "requirement")
py_binary(
name = "hello_test",
srcs = ["src/hello_server.py"],
deps = [
"//proto_library/proto:hello_py_proto",
"//proto_library/proto:hello_py_grpc",
requirement("grpcio"),
requirement("protobuf"),
],
# Add these to handle Python packaging
imports = [".."], # Make parent directories importable
visibility = ["//visibility:public"],
package_collisions = "warning",
# Create proper Python package structure
main = "hello_server.py",
)
Upvotes: 0
Views: 38