14 """Reference implementation for reflection client in gRPC Python.
16 For usage instructions, see the Python Reflection documentation at
17 ``doc/python/server_reflection.md``.
21 from typing
import Any, Dict, Iterable, List, Set
26 from grpc_reflection.v1alpha.reflection_pb2
import ExtensionNumberResponse
27 from grpc_reflection.v1alpha.reflection_pb2
import ExtensionRequest
28 from grpc_reflection.v1alpha.reflection_pb2
import FileDescriptorResponse
29 from grpc_reflection.v1alpha.reflection_pb2
import ListServiceResponse
30 from grpc_reflection.v1alpha.reflection_pb2
import ServerReflectionRequest
31 from grpc_reflection.v1alpha.reflection_pb2
import ServerReflectionResponse
32 from grpc_reflection.v1alpha.reflection_pb2
import ServiceResponse
33 from grpc_reflection.v1alpha.reflection_pb2_grpc
import ServerReflectionStub
38 A container and interface for receiving descriptors from a server's
41 ProtoReflectionDescriptorDatabase takes a channel to a server with
42 Reflection service, and provides an interface to retrieve the Reflection
43 information. It implements the DescriptorDatabase interface.
45 It is typically used to feed a DescriptorPool instance.
54 DescriptorDatabase.__init__(self)
55 self.
_logger = logging.getLogger(__name__)
56 self.
_stub = ServerReflectionStub(channel)
57 self._known_files: Set[str] =
set()
58 self._cached_extension_numbers: Dict[str, List[int]] = dict()
62 Get list of full names of the registered services.
65 A list of strings corresponding to the names of the services.
68 request = ServerReflectionRequest(list_services=
"")
70 list_services: ListServiceResponse = response.list_services_response
71 services: List[ServiceResponse] = list_services.service
72 return [service.name
for service
in services]
76 Find a file descriptor by file name.
78 This function implements a DescriptorDatabase interface, and is
79 typically not called directly; prefer using a DescriptorPool instead.
82 name: The name of the file. Typically this is a relative path ending in ".proto".
85 A FileDescriptorProto for the file.
88 KeyError: the file was not found.
95 assert name
not in self._known_files
96 request = ServerReflectionRequest(file_by_filename=name)
103 Find the file containing the symbol, and return its file descriptor.
105 The symbol should be a fully qualified name including the file
106 descriptor's package and any containing messages. Some examples:
108 * "some.package.name.Message"
109 * "some.package.name.Message.NestedEnum"
110 * "some.package.name.Message.some_field"
112 This function implements a DescriptorDatabase interface, and is
113 typically not called directly; prefer using a DescriptorPool instead.
116 symbol: The fully-qualified name of the symbol.
119 FileDescriptorProto for the file containing the symbol.
122 KeyError: the symbol was not found.
130 request = ServerReflectionRequest(file_containing_symbol=symbol)
137 Find the field numbers used by all known extensions of `extendee_name`.
139 This function implements a DescriptorDatabase interface, and is
140 typically not called directly; prefer using a DescriptorPool instead.
143 extendee_name: fully-qualified name of the extended message type.
146 A list of field numbers used by all known extensions.
149 KeyError: The message type `extendee_name` was not found.
152 if extendee_name
in self._cached_extension_numbers:
153 return self._cached_extension_numbers[extendee_name]
154 request = ServerReflectionRequest(
155 all_extension_numbers_of_type=extendee_name)
157 all_extension_numbers: ExtensionNumberResponse = (
158 response.all_extension_numbers_response)
159 numbers = list(all_extension_numbers.extension_number)
160 self._cached_extension_numbers[extendee_name] = numbers
164 self, extendee_name: str,
165 extension_number: int) -> FileDescriptorProto:
167 Find the file which defines an extension for the given message type
170 This function implements a DescriptorDatabase interface, and is
171 typically not called directly; prefer using a DescriptorPool instead.
174 extendee_name: fully-qualified name of the extended message type.
175 extension_number: the number of the extension field.
178 FileDescriptorProto for the file containing the extension.
181 KeyError: The message or the extension number were not found.
189 request = ServerReflectionRequest(
190 file_containing_extension=ExtensionRequest(
191 containing_type=extendee_name,
192 extension_number=extension_number))
194 key=(extendee_name, extension_number))
195 file_desc = response.file_descriptor_response
201 key: Any) -> ServerReflectionResponse:
202 response = self.
_stub.ServerReflectionInfo(
iter([request]))
204 if res.WhichOneof(
"message_response") ==
"error_response":
206 error_code = res.error_response.error_code
207 assert (error_code == grpc.StatusCode.NOT_FOUND.value[0]
208 ),
"unexpected error response: " + repr(res.error_response)
213 self, file_descriptor: FileDescriptorResponse) ->
None:
214 protos: List[bytes] = file_descriptor.file_descriptor_proto
217 desc.ParseFromString(proto)
218 if desc.name
not in self._known_files:
219 self.
_logger.info(
"Loading descriptors from file: %s",
221 self._known_files.
add(desc.name)