Skip to content

Commit

Permalink
Pretty printers working
Browse files Browse the repository at this point in the history
  • Loading branch information
ViridianForge committed Nov 23, 2023
1 parent 662936f commit 055784c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 21 deletions.
9 changes: 6 additions & 3 deletions src/grpc_requests/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,15 @@ def get_service_descriptor(self, service):
return self._desc_pool.FindServiceByName(service)

def describe_method_request(self, service, method):
warnings.warn("This function is deprecated, and will be removed in a future release. Use describe_request() instead.", DeprecationWarning)
warnings.warn(
"This function is deprecated, and will be removed in a future release. Use describe_request() instead.",
DeprecationWarning
)
return describe_request(self.get_method_descriptor(service, method))

def describe_request(self, service, method):
return describe_descriptor(self.get_method_descriptor(service, method).input_type)

def describe_response(self, service, method):
return describe_descriptor(self.get_method_descriptor(service, method).output_type)

Expand Down
55 changes: 39 additions & 16 deletions src/grpc_requests/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from google.protobuf.descriptor import Descriptor, MethodDescriptor
from google.protobuf.descriptor import Descriptor, EnumDescriptor, MethodDescriptor, OneofDescriptor

import warnings

Expand Down Expand Up @@ -37,38 +37,61 @@ def describe_request(method_descriptor: MethodDescriptor) -> dict:
:param method_descriptor: MethodDescriptor
:return: dict - a mapping of field names to their types
"""
warnings.warn("This function is deprecated, and will be removed in a future release. Use describe_descriptor() instead.", DeprecationWarning)
warnings.warn(
"This function is deprecated, and will be removed in a future release. Use describe_descriptor() instead.",
DeprecationWarning
)
description = {}
for field in method_descriptor.input_type.fields:
description[field.name] = FIELD_TYPES[field.type-1]
return description

def describe_descriptor(descriptor: Descriptor) -> str:
def describe_descriptor(descriptor: Descriptor, indent: int = 0) -> str:
"""
Prints a human readable description of a protobuf descriptor.
:param descriptor: Descriptor - a protobuf descriptor
:return: str - a human readable description of the descriptor
"""
description = descriptor.full_name
description = descriptor.name
padding = "\t" * indent

if descriptor.enum_types:
description += "\nEnums:"
description += f"\n{padding}Enums:"
for enum in descriptor.enum_types:
description += f"\n{enum.name}: {enum.values}"
description += describe_enum_descriptor(enum, indent+1)

if descriptor.fields:
description += "\nFields:"
description += f"\n{padding}Fields:"
for field in descriptor.fields:
description += f"\n{field.name}: {FIELD_TYPES[field.type-1]}"

if descriptor.nested_types:
description += "\nNested Types:"
for nested_type in descriptor.nested_types:
description += f"\n{nested_type.name}"
description += f"\n\t{padding}{field.name}: {FIELD_TYPES[field.type-1]}"

if descriptor.oneofs:
description += "\nOneofs:"
description += f"\n{padding}Oneofs:"
for oneof in descriptor.oneofs:
description += f"\n{oneof.name}"
description += describe_oneof_descriptor(oneof, indent+1)

return description

def describe_enum_descriptor(enum_descriptor: EnumDescriptor, indent: int = 0) -> str:
"""
Prints a human readable description of a protobuf enum descriptor.
:param enum_descriptor: EnumDescriptor - a protobuf enum descriptor
:return: str - a human readable description of the enum descriptor
"""
padding = "\t" * indent
description = f"\n{padding}{enum_descriptor.name}:"
for value in enum_descriptor.values:
description += f"\n{padding}{value.name} = {value.number}"
return description

return description
def describe_oneof_descriptor(oneof_descriptor: OneofDescriptor, indent: int = 0) -> str:
"""
Prints a human readable description of a protobuf oneof descriptor.
:param oneof_descriptor: OneofDescriptor - a protobuf oneof descriptor
:return: str - a human readable description of the oneof descriptor
"""
padding = "\t" * indent
description = f"\n{padding}{oneof_descriptor.name}:"
for field in oneof_descriptor.fields:
description += f"\n{padding}{field.name}: {FIELD_TYPES[field.type-1]}"
return description
16 changes: 14 additions & 2 deletions src/tests/reflection_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,24 @@ def test_describe_method_request(client_tester_reflection_client):
def test_describe_request(client_tester_reflection_client):
request_description = \
client_tester_reflection_client.describe_request('client_tester.ClientTester', 'TestUnaryUnary')
assert request_description == 'client_tester.ClientTester.TestUnaryUnaryRequest'
expected_request_description = """TestRequest
Fields:
\tfactor: INT32
\treadings: FLOAT
\tuuid: UINT64
\tsample_flag: BOOL
\trequest_name: STRING
\textra_data: BYTES"""
assert request_description == expected_request_description

def test_describe_response(client_tester_reflection_client):
request_description = \
client_tester_reflection_client.describe_response('client_tester.ClientTester', 'TestUnaryUnary')
assert request_description == 'client_tester.ClientTester.TestUnaryUnaryResponse'
expected_response_description = """TestResponse
Fields:
\taverage: DOUBLE
\tfeedback: STRING"""
assert request_description == expected_response_description

def test_empty_body_request(helloworld_reflection_client):
response = helloworld_reflection_client.request('helloworld.Greeter', 'SayHello', {})
Expand Down

0 comments on commit 055784c

Please sign in to comment.