|
|
|
@ -35,6 +35,7 @@ from google.protobuf import descriptor_pb2 |
|
|
|
|
from google.protobuf import descriptor_pool |
|
|
|
|
|
|
|
|
|
from grpc_reflection.v1alpha import reflection_pb2 |
|
|
|
|
from grpc_reflection.v1alpha import reflection_pb2_grpc |
|
|
|
|
|
|
|
|
|
_POOL = descriptor_pool.Default() |
|
|
|
|
|
|
|
|
@ -64,7 +65,7 @@ class ReflectionServicer(reflection_pb2.ServerReflectionServicer): |
|
|
|
|
Args: |
|
|
|
|
service_names: Iterable of fully-qualified service names available. |
|
|
|
|
""" |
|
|
|
|
self._service_names = list(service_names) |
|
|
|
|
self._service_names = tuple(sorted(service_names)) |
|
|
|
|
self._pool = _POOL if pool is None else pool |
|
|
|
|
|
|
|
|
|
def _file_by_filename(self, filename): |
|
|
|
@ -84,23 +85,32 @@ class ReflectionServicer(reflection_pb2.ServerReflectionServicer): |
|
|
|
|
else: |
|
|
|
|
return _file_descriptor_response(descriptor) |
|
|
|
|
|
|
|
|
|
def _file_containing_extension(containing_type, extension_number): |
|
|
|
|
# TODO(atash) Python protobuf currently doesn't support querying extensions. |
|
|
|
|
# https://github.com/google/protobuf/issues/2248 |
|
|
|
|
return reflection_pb2.ServerReflectionResponse( |
|
|
|
|
error_response=reflection_pb2.ErrorResponse( |
|
|
|
|
error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], |
|
|
|
|
error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(),)) |
|
|
|
|
|
|
|
|
|
def _extension_numbers_of_type(fully_qualified_name): |
|
|
|
|
# TODO(atash) We're allowed to leave this unsupported according to the |
|
|
|
|
# protocol, but we should still eventually implement it. Hits the same issue |
|
|
|
|
# as `_file_containing_extension`, however. |
|
|
|
|
# https://github.com/google/protobuf/issues/2248 |
|
|
|
|
return reflection_pb2.ServerReflectionResponse( |
|
|
|
|
error_response=reflection_pb2.ErrorResponse( |
|
|
|
|
error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], |
|
|
|
|
error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(),)) |
|
|
|
|
def _file_containing_extension(self, containing_type, extension_number): |
|
|
|
|
try: |
|
|
|
|
message_descriptor = self._pool.FindMessageTypeByName(containing_type) |
|
|
|
|
extension_descriptor = self._pool.FindExtensionByNumber( |
|
|
|
|
message_descriptor, extension_number) |
|
|
|
|
descriptor = self._pool.FindFileContainingSymbol( |
|
|
|
|
extension_descriptor.full_name) |
|
|
|
|
except KeyError: |
|
|
|
|
return _not_found_error() |
|
|
|
|
else: |
|
|
|
|
return _file_descriptor_response(descriptor) |
|
|
|
|
|
|
|
|
|
def _all_extension_numbers_of_type(self, containing_type): |
|
|
|
|
try: |
|
|
|
|
message_descriptor = self._pool.FindMessageTypeByName(containing_type) |
|
|
|
|
extension_numbers = tuple(sorted( |
|
|
|
|
extension.number |
|
|
|
|
for extension in self._pool.FindAllExtensions(message_descriptor))) |
|
|
|
|
except KeyError: |
|
|
|
|
return _not_found_error() |
|
|
|
|
else: |
|
|
|
|
return reflection_pb2.ServerReflectionResponse( |
|
|
|
|
all_extension_numbers_response=reflection_pb2. |
|
|
|
|
ExtensionNumberResponse( |
|
|
|
|
base_type_name=message_descriptor.full_name, |
|
|
|
|
extension_number=extension_numbers)) |
|
|
|
|
|
|
|
|
|
def _list_services(self): |
|
|
|
|
return reflection_pb2.ServerReflectionResponse( |
|
|
|
@ -121,7 +131,7 @@ class ReflectionServicer(reflection_pb2.ServerReflectionServicer): |
|
|
|
|
request.file_containing_extension.containing_type, |
|
|
|
|
request.file_containing_extension.extension_number) |
|
|
|
|
elif request.HasField('all_extension_numbers_of_type'): |
|
|
|
|
yield _all_extension_numbers_of_type( |
|
|
|
|
yield self._all_extension_numbers_of_type( |
|
|
|
|
request.all_extension_numbers_of_type) |
|
|
|
|
elif request.HasField('list_services'): |
|
|
|
|
yield self._list_services() |
|
|
|
@ -131,3 +141,14 @@ class ReflectionServicer(reflection_pb2.ServerReflectionServicer): |
|
|
|
|
error_code=grpc.StatusCode.INVALID_ARGUMENT.value[0], |
|
|
|
|
error_message=grpc.StatusCode.INVALID_ARGUMENT.value[1] |
|
|
|
|
.encode(),)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def enable_server_reflection(service_names, server): |
|
|
|
|
"""Enables server reflection on a server. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
service_names: Iterable of fully-qualified service names available. |
|
|
|
|
server: grpc.Server to which reflection service will be added. |
|
|
|
|
""" |
|
|
|
|
reflection_pb2_grpc.add_ServerReflectionServicer_to_server( |
|
|
|
|
ReflectionServicer(service_names), server) |
|
|
|
|