Open BananaLoaf opened 1 year ago
I stumbled over this problem today and was able to reproduce it in version 2.0.0b6
Given the two proto files below:
dependency.proto
syntax = "proto3";
package report.dependency;
message DependencyMessage {}
main.proto
syntax = "proto3";
import "dependency.proto";
package report.main;
message ReturnMessage {}
service MainService {
rpc SomeCall(report.dependency.DependencyMessage) returns (ReturnMessage);
}
Running python -m grpc_tools.protoc --proto_path . --python_betterproto_out=. main.proto
results in the following, broken python code:
from dataclasses import dataclass
from typing import (
TYPE_CHECKING,
Dict,
Optional,
)
import betterproto
import grpclib
from betterproto.grpc.grpclib_server import ServiceBase
if TYPE_CHECKING:
import grpclib.server
from betterproto.grpc.grpclib_client import MetadataLike
from grpclib.metadata import Deadline
@dataclass(eq=False, repr=False)
class ReturnMessage(betterproto.Message):
pass
class MainServiceStub(betterproto.ServiceStub):
async def some_call(
self,
dependency_dependency_message: "_dependency__.DependencyMessage",
*,
timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None
) -> "ReturnMessage":
return await self._unary_unary(
"/report.main.MainService/SomeCall",
dependency_dependency_message,
ReturnMessage,
timeout=timeout,
deadline=deadline,
metadata=metadata,
)
class MainServiceBase(ServiceBase):
async def some_call(
self, dependency_dependency_message: "_dependency__.DependencyMessage"
) -> "ReturnMessage":
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
async def __rpc_some_call(
self,
stream: "grpclib.server.Stream[_dependency__.DependencyMessage, ReturnMessage]",
) -> None:
request = await stream.recv_message()
response = await self.some_call(request)
await stream.send_message(response)
def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
return {
"/report.main.MainService/SomeCall": grpclib.const.Handler(
self.__rpc_some_call,
grpclib.const.Cardinality.UNARY_UNARY,
_dependency__.DependencyMessage,
ReturnMessage,
),
}
Note the missing import from .. import dependency as _dependency__
which would be needed in lines 32, 50, 56, and 67.
Using the message DependencyMessage
as a output type generates the import as expected, i.e. the following proto file does not show the problem described above
main.proto
syntax = "proto3";
import "dependency.proto";
package report.main;
message ReturnMessage {}
service MainService {
rpc SomeCall(report.dependency.DependencyMessage) returns (report.dependency.DependencyMessage);
}
My unsophisticated fix would be to add this line to the top of plugin.models.ServiceMethodCompiler.__post_init
:
self.py_input_message_type
Simply using the property seems to fix the problem, as the underlying method for building the import statements adds the needed imports to output_file.imports
, which in turn makes them generate properly. This is why using the imported Message type as a return type generates the import properly: we use the property self.py_output_message_type
in the check of line 726
I'm sure there is a better way though :)
@JulianNeuberger I ended up forking it
https://github.com/BananaLoaf/python-bananaproto
I fixed this issue and changed some stuff I needed to change
First of all, I looked at the issue #408 and I am absolutely sure that I have
betterproto[compiler]
of version2.0.0b5
installedI have this file structure:
With
protos/common.proto
:and
protos/devices/rpi.proto
:I then generate betterproto files:
The BUG
In
package_name.grpc.org.company.name.rpi
any mentions ofDeviceId
are presented as_common__.DeviceId
, with_common__
not being imported. Launching that code does not work either, python has no idea what_common__
is.