[reflection] python: reflection response returns dependencies (#32909)

Fix #32899 - include all dependency-descriptors in the
ServerReflectionResponse

Using the C# Server-code as blue print:

6bf44820a2/src/Grpc.Reflection/ReflectionServiceImpl.cs (L148)

see also:
   - The cpp-server implementation of this:

d299f5ecce/src/cpp/ext/proto_server_reflection.cc (L208)
  - The go-server implementation of this:

2cd95c7514/reflection/serverreflection.go (L184)
`return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors)`

---------

Co-authored-by: Xuan Wang <xuanwn@google.com>
pull/33086/head
Thomas Zeugner 2 years ago committed by GitHub
parent 1b01336504
commit 74d00f2c9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      src/python/grpcio_reflection/grpc_reflection/v1alpha/_base.py
  2. 9
      src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
  3. 9
      src/python/grpcio_tests/tests_aio/reflection/reflection_servicer_test.py

@ -30,13 +30,29 @@ def _not_found_error():
))
def _collect_transitive_dependencies(descriptor, seen_files):
seen_files.update({descriptor.name: descriptor})
for dependency in descriptor.dependencies:
if not dependency.name in seen_files:
# descriptors cannot have circular dependencies
_collect_transitive_dependencies(dependency, seen_files)
def _file_descriptor_response(descriptor):
proto = descriptor_pb2.FileDescriptorProto()
descriptor.CopyToProto(proto)
serialized_proto = proto.SerializeToString()
# collect all dependencies
descriptors = {}
_collect_transitive_dependencies(descriptor, descriptors)
# serialize all descriptors
serialized_proto_list = []
for d_key in descriptors:
proto = descriptor_pb2.FileDescriptorProto()
descriptors[d_key].CopyToProto(proto)
serialized_proto_list.append(proto.SerializeToString())
return _reflection_pb2.ServerReflectionResponse(
file_descriptor_response=_reflection_pb2.FileDescriptorResponse(
file_descriptor_proto=(serialized_proto,)),)
file_descriptor_proto=(serialized_proto_list)),)
class BaseReflectionServicer(_reflection_pb2_grpc.ServerReflectionServicer):

@ -25,6 +25,7 @@ from grpc_reflection.v1alpha import reflection_pb2_grpc
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing.proto2 import empty2_extensions_pb2
from src.proto.grpc.testing.proto2 import empty2_pb2
from tests.unit import test_common
_EMPTY_PROTO_FILE_NAME = 'src/proto/grpc/testing/empty.proto'
@ -128,9 +129,11 @@ class ReflectionServicerTest(unittest.TestCase):
expected_responses = (
reflection_pb2.ServerReflectionResponse(
valid_host='',
file_descriptor_response=reflection_pb2.FileDescriptorResponse(
file_descriptor_proto=(_file_descriptor_to_proto(
empty2_extensions_pb2.DESCRIPTOR),))),
file_descriptor_response=reflection_pb2.
FileDescriptorResponse(file_descriptor_proto=(
_file_descriptor_to_proto(empty2_extensions_pb2.DESCRIPTOR),
_file_descriptor_to_proto(empty2_pb2.DESCRIPTOR),
))),
reflection_pb2.ServerReflectionResponse(
valid_host='',
error_response=reflection_pb2.ErrorResponse(

@ -25,6 +25,7 @@ from grpc_reflection.v1alpha import reflection_pb2_grpc
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing.proto2 import empty2_extensions_pb2
from src.proto.grpc.testing.proto2 import empty2_pb2
from tests_aio.unit._test_base import AioTestBase
_EMPTY_PROTO_FILE_NAME = 'src/proto/grpc/testing/empty.proto'
@ -132,9 +133,11 @@ class ReflectionServicerTest(AioTestBase):
expected_responses = (
reflection_pb2.ServerReflectionResponse(
valid_host='',
file_descriptor_response=reflection_pb2.FileDescriptorResponse(
file_descriptor_proto=(_file_descriptor_to_proto(
empty2_extensions_pb2.DESCRIPTOR),))),
file_descriptor_response=reflection_pb2.
FileDescriptorResponse(file_descriptor_proto=(
_file_descriptor_to_proto(empty2_extensions_pb2.DESCRIPTOR),
_file_descriptor_to_proto(empty2_pb2.DESCRIPTOR),
))),
reflection_pb2.ServerReflectionResponse(
valid_host='',
error_response=reflection_pb2.ErrorResponse(

Loading…
Cancel
Save