From d929956bb69d7a88ed54d634c555679c13e803e2 Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Wed, 18 Jun 2025 18:36:50 -0400 Subject: [PATCH 1/6] support ServerReflection with a custom DescriptorPool --- grpclib/reflection/_deprecated.py | 10 ++++--- grpclib/reflection/service.py | 20 +++++++++----- tests/test_reflection.py | 44 +++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/grpclib/reflection/_deprecated.py b/grpclib/reflection/_deprecated.py index 5408ec5..95fe4ac 100644 --- a/grpclib/reflection/_deprecated.py +++ b/grpclib/reflection/_deprecated.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import Collection +from typing import Any, Collection from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto @@ -35,10 +35,14 @@ class ServerReflection(ServerReflectionBase): """ Implements server reflection protocol. """ - def __init__(self, *, _service_names: Collection[str]): + def __init__( + self, *, + _service_names: Collection[str], + _pool: Any | None = None # type: ignore + ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings - self._pool = Default() # type: ignore + self._pool = _pool or Default() # type: ignore def _not_found_response(self) -> ServerReflectionResponse: return ServerReflectionResponse( diff --git a/grpclib/reflection/service.py b/grpclib/reflection/service.py index 02544b5..275e4ed 100644 --- a/grpclib/reflection/service.py +++ b/grpclib/reflection/service.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import TYPE_CHECKING, Collection, List +from typing import TYPE_CHECKING, Any, Collection, List from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto @@ -41,10 +41,14 @@ class ServerReflection(ServerReflectionBase): """ Implements server reflection protocol. """ - def __init__(self, *, _service_names: Collection[str]): + def __init__( + self, *, + _service_names: Collection[str], + _pool: Any | None = None # type: ignore + ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings - self._pool = Default() # type: ignore + self._pool = _pool or Default() # type: ignore def _not_found_response(self) -> ServerReflectionResponse: return ServerReflectionResponse( @@ -161,7 +165,10 @@ async def ServerReflectionInfo( await stream.send_message(response) @classmethod - def extend(cls, services: 'Collection[IServable]') -> 'List[IServable]': + def extend( + cls, services: 'Collection[IServable]', + pool: Any | None = None # type: ignore + ) -> 'List[IServable]': """ Extends services list with reflection service: @@ -181,6 +188,7 @@ def extend(cls, services: 'Collection[IServable]') -> 'List[IServable]': for service in services: service_names.append(_service_name(service)) services = list(services) - services.append(cls(_service_names=service_names)) - services.append(_ServerReflectionV1Alpha(_service_names=service_names)) + services.append(cls(_service_names=service_names, _pool=pool)) + services.append( + _ServerReflectionV1Alpha(_service_names=service_names, _pool=pool)) return services diff --git a/tests/test_reflection.py b/tests/test_reflection.py index 73a02be..0955490 100644 --- a/tests/test_reflection.py +++ b/tests/test_reflection.py @@ -1,5 +1,7 @@ import socket +from google.protobuf.descriptor_pool import DescriptorPool + import pytest import pytest_asyncio @@ -108,3 +110,45 @@ async def test_list_services_response(channel): service, = r1.list_services_response.service assert service.name == DESCRIPTOR.services_by_name['DummyService'].full_name + + +@pytest.mark.asyncio +async def test_file_containing_symbol_response_custom_pool(port): + my_pool = DescriptorPool() + services = [DummyService()] + services = ServerReflection.extend(services, pool=my_pool) + + server = Server(services) + await server.start(port=port) + + channel = Channel(port=port) + try: + # because we use our own pool (my_pool), there's no descriptors to find. + req = ServerReflectionRequest( + file_containing_symbol=( + DESCRIPTOR.message_types_by_name['DummyRequest'].full_name + ), + ) + resp, = await ServerReflectionStub(channel).ServerReflectionInfo([req]) + + assert resp == ServerReflectionResponse( + error_response=ErrorResponse( + error_code=5, + error_message='not found', + ), + ) + + # once we update the pool, we should find the descriptor. + my_pool.AddSerializedFile(DESCRIPTOR.serialized_pb) + + resp, = await ServerReflectionStub(channel).ServerReflectionInfo([req]) + + proto_bytes, = resp.file_descriptor_response.file_descriptor_proto + dummy_proto = FileDescriptorProto() + dummy_proto.ParseFromString(proto_bytes) + assert dummy_proto.name == DESCRIPTOR.name + assert dummy_proto.package == DESCRIPTOR.package + finally: + channel.close() + server.close() + await server.wait_closed() From ec30fc02a3a56061b6d2aad14877330de867e10b Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Sat, 28 Jun 2025 20:51:36 -0400 Subject: [PATCH 2/6] use union instead of pipe --- grpclib/reflection/_deprecated.py | 4 ++-- grpclib/reflection/service.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grpclib/reflection/_deprecated.py b/grpclib/reflection/_deprecated.py index 95fe4ac..8b53450 100644 --- a/grpclib/reflection/_deprecated.py +++ b/grpclib/reflection/_deprecated.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import Any, Collection +from typing import Any, Collection, Union from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto @@ -38,7 +38,7 @@ class ServerReflection(ServerReflectionBase): def __init__( self, *, _service_names: Collection[str], - _pool: Any | None = None # type: ignore + _pool: Union[Any, None] = None ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings diff --git a/grpclib/reflection/service.py b/grpclib/reflection/service.py index 275e4ed..44442dc 100644 --- a/grpclib/reflection/service.py +++ b/grpclib/reflection/service.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import TYPE_CHECKING, Any, Collection, List +from typing import TYPE_CHECKING, Any, Collection, List, Union from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto @@ -44,7 +44,7 @@ class ServerReflection(ServerReflectionBase): def __init__( self, *, _service_names: Collection[str], - _pool: Any | None = None # type: ignore + _pool: Union[Any, None] = None ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings @@ -167,7 +167,7 @@ async def ServerReflectionInfo( @classmethod def extend( cls, services: 'Collection[IServable]', - pool: Any | None = None # type: ignore + pool: Union[Any, None] = None ) -> 'List[IServable]': """ Extends services list with reflection service: From 8693474c0f0c3e7f533d4810326cfe74eac7b447 Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Tue, 8 Jul 2025 10:16:20 -0400 Subject: [PATCH 3/6] pr changes --- grpclib/reflection/service.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grpclib/reflection/service.py b/grpclib/reflection/service.py index 44442dc..c75bbeb 100644 --- a/grpclib/reflection/service.py +++ b/grpclib/reflection/service.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import TYPE_CHECKING, Any, Collection, List, Union +from typing import TYPE_CHECKING, Any, Collection, List, Optional, Union from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto @@ -44,7 +44,7 @@ class ServerReflection(ServerReflectionBase): def __init__( self, *, _service_names: Collection[str], - _pool: Union[Any, None] = None + _pool: Optional[Any] = None ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings @@ -167,7 +167,8 @@ async def ServerReflectionInfo( @classmethod def extend( cls, services: 'Collection[IServable]', - pool: Union[Any, None] = None + *, + pool: Optional[Any] = None ) -> 'List[IServable]': """ Extends services list with reflection service: From c1e9691898018815afd05d0c9d6067a146e6a400 Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Tue, 8 Jul 2025 10:19:40 -0400 Subject: [PATCH 4/6] pr changes --- grpclib/reflection/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grpclib/reflection/service.py b/grpclib/reflection/service.py index c75bbeb..fff06f6 100644 --- a/grpclib/reflection/service.py +++ b/grpclib/reflection/service.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import TYPE_CHECKING, Any, Collection, List, Optional, Union +from typing import TYPE_CHECKING, Any, Collection, List, Optional from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto From 3063d394e419deb42ea61e01f33914137ca3961a Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Tue, 8 Jul 2025 14:10:20 -0400 Subject: [PATCH 5/6] Update grpclib/reflection/_deprecated.py Co-authored-by: Volodymyr Magamedov --- grpclib/reflection/_deprecated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grpclib/reflection/_deprecated.py b/grpclib/reflection/_deprecated.py index 8b53450..43294a1 100644 --- a/grpclib/reflection/_deprecated.py +++ b/grpclib/reflection/_deprecated.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from typing import Any, Collection, Union +from typing import Any, Collection, Optional from google.protobuf.descriptor import FileDescriptor from google.protobuf.descriptor_pb2 import FileDescriptorProto From 7ba008dd43189a9083ac67c58c52be8c9f7f6cb7 Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Tue, 8 Jul 2025 14:10:24 -0400 Subject: [PATCH 6/6] Update grpclib/reflection/_deprecated.py Co-authored-by: Volodymyr Magamedov --- grpclib/reflection/_deprecated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grpclib/reflection/_deprecated.py b/grpclib/reflection/_deprecated.py index 43294a1..78a93a9 100644 --- a/grpclib/reflection/_deprecated.py +++ b/grpclib/reflection/_deprecated.py @@ -38,7 +38,7 @@ class ServerReflection(ServerReflectionBase): def __init__( self, *, _service_names: Collection[str], - _pool: Union[Any, None] = None + _pool: Optional[Any] = None ): self._service_names = _service_names # FIXME: DescriptorPool has incomplete typings