Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python] Cannot use reflection to find a service by name if service does not have package #18943

Open
inikolaev opened this issue Oct 22, 2024 · 2 comments
Assignees
Labels

Comments

@inikolaev
Copy link

What version of protobuf and what language are you using?
Version: main
Language: Python

What operating system (Linux, Windows, ...) and version?
All

What runtime / compiler are you using (e.g., python version or gcc version)
Not applicable

What did you do?
Steps to reproduce the behavior:

  1. Deploy gRPC service that does not have a package
  2. Use reflection and DescriptorPool to find service by name
  3. KeyError is being raised

What did you expect to see
It should be possible to find a service even though it does not have a pckage

I have debugged through the code and the culprit is this code that assumes that package name is not empty. I happened to have an example where this was not the case.

The fix I think is trivial - just check if package is empty or not before concatenating it with an object name.

@inikolaev inikolaev added the untriaged auto added to all issues by default when created. label Oct 22, 2024
@anandolee anandolee added python and removed untriaged auto added to all issues by default when created. labels Oct 23, 2024
@anandolee anandolee self-assigned this Oct 23, 2024
@anandolee
Copy link
Contributor

anandolee commented Oct 23, 2024

Can you help to provide a reproduce example code and .proto definition?

@inikolaev
Copy link
Author

Sure!

Here's the minimal protobuf that I created to reproduce it:

syntax = "proto3";

option go_package = "proto/gen;servicepb";

service Service {
  rpc Method(Request) returns (Response);
}

message Request {
  string data = 1;
}

message Response {
  string data = 1;
}

and the following Python code:

import grpc
from google.protobuf.descriptor_pool import DescriptorPool
from grpc_reflection.v1alpha.proto_reflection_descriptor_database import ProtoReflectionDescriptorDatabase

with grpc.insecure_channel('localhost:50051', ) as channel:
    reflection_db = ProtoReflectionDescriptorDatabase(channel)
    desc_pool = DescriptorPool(reflection_db)
    service_desc = desc_pool.FindServiceByName("Service")
    method_desc = service_desc.FindMethodByName("Method")
    print(method_desc)

With current implementation it raises the following error:

Traceback (most recent call last):
  File "client.py", line 45, in <module>
    service_desc = desc_pool.FindServiceByName("Service")
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: "Couldn't find service Service"

And if I debug an look at the DescriptorDatabase._file_desc_protos_by_symbol it looks like this:

{
  '.Service': <value>, 
  'Request': <value>,
  'Response': <value>
}

Please note the dot in the .Service which is caused by missing package, while other symbols from the same package don't have it - it's taken care of by _ExtractSymbols which handles empty package already.

I have submitted a PR if you want to take a look and help me get it through.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants