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

Fix typing and datetime imports not being present for service method type annotations #183

Merged
merged 1 commit into from
Mar 12, 2021
Merged

Fix typing and datetime imports not being present for service method type annotations #183

merged 1 commit into from
Mar 12, 2021

Conversation

leenr
Copy link
Contributor

@leenr leenr commented Dec 13, 2020

Example messages.proto:

syntax = "proto3";

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

package things.messages;

message DoThingRequest {
  string name = 1;
  repeated string comments = 2;
  google.protobuf.Timestamp when = 3;
  google.protobuf.Duration duration = 4;
}

message DoThingResponse {
  repeated string names = 1;
}

Example service.proto:

syntax = "proto3";

import "messages.proto";

package things.service;

service Test {
  rpc DoThing (things.messages.DoThingRequest) returns (things.messages.DoThingResponse);
}

Using current master (1d54ef8):

$ protoc --python_betterproto_out=.local/servicemethod_imports_issue/output_master_1d54ef8 --proto_path=.local/servicemethod_imports_issue/proto .local/servicemethod_imports_issue/proto/*.proto
Writing __init__.py
Writing things/__init__.py
Writing things/messages/__init__.py
Writing things/service/__init__.py

$ head -n20 .local/servicemethod_imports_issue/output_master_1d54ef8/things/service/__init__.py
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: service.proto
# plugin: python-betterproto
from dataclasses import dataclass
from typing import Dict, Optional

import betterproto
from betterproto.grpc.grpclib_server import ServiceBase
import grpclib


class TestStub(betterproto.ServiceStub):
    async def do_thing(
        self,
        *,
        name: str = "",
        comments: Optional[List[str]] = None,
        when: datetime = None,
        duration: timedelta = None,
    ) -> "_messages__.DoThingResponse":

Notice List, datetime and timedelta being used in type annotation, but not listed in imports.


Using version from this PR:

$ protoc --python_betterproto_out=.local/servicemethod_imports_issue/output_fix_b854d38 --proto_path=.local/servicemethod_imports_issue/proto .local/servicemethod_imports_issue/proto/*.proto
Writing __init__.py
Writing things/__init__.py
Writing things/messages/__init__.py
Writing things/service/__init__.py

$ head -n21 .local/servicemethod_imports_issue/output_fix_b854d38/things/service/__init__.py
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: service.proto
# plugin: python-betterproto
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Dict, List, Optional

import betterproto
from betterproto.grpc.grpclib_server import ServiceBase
import grpclib


class TestStub(betterproto.ServiceStub):
    async def do_thing(
        self,
        *,
        name: str = "",
        comments: Optional[List[str]] = None,
        when: datetime = None,
        duration: timedelta = None,
    ) -> "_messages__.DoThingResponse":

I've also implemented a copy of test's "things service" (service), separated in two protobuf packages: one with messages, other with service definition, and added Duration and Timestamp fields to DoThingRequest message.
It fails on current master (1d54ef8), but succeeds with the changes from this PR.

…hod type annotations

It can happen, for example, when repeated field is used in the
request message for the service method and request message is in
different package than the service definition.
Copy link
Collaborator

@nat-n nat-n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix :)

if self.py_input_message:
for f in self.py_input_message.fields:
if f.default_value_string == "None":
self.output_file.typing_imports.add("Optional")
f.add_imports_to(self.output_file)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that this line is the actual fix?

Copy link
Contributor Author

@leenr leenr Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, along with the other changes.

I've deleted adding "Optional" import two lines above because there already is the code to add it in the FieldCompiler class:

if "Optional[" in annotation:
    imports.add("Optional")

@huan
Copy link

huan commented Feb 27, 2021

Looking forward to having this PR merged!

It will fix my wechaty/grpc#120

@nat-n nat-n merged commit 2f62189 into danielgtaylor:master Mar 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants