Import wygenerowanego kodu z protobuf

0

Mam jakiś plik z definicją gRPC:
coś w stylu:

syntax = "proto3";

package me.dotnod.incident_management.v1;

import "google/api/annotations.proto"; // http
import "google/protobuf/timestamp.proto"; // Timestamp
import "dotnod/incident_management/v1/types.proto"; // Detection

option go_package = "me.nod/incident_management/v1";

/*
  Represents collection of [detection]s.

  Detection pose potential security risk. It is usually accompanied by response(s).
*/
service Detections {
  // Get detection.
  rpc GetDetection ( GetDetectionRequest ) returns ( GetDetectionResponse ) {
    option (google.api.http) = {
      // https://cloud.google.com/apis/design/standard_methods#get
      get: "/v1/detections/{detection_uuid}"
    };
  }

  // Return list of all the [detection]s matching criteria.
  rpc ListDetections ( ListDetectionsRequest ) returns ( ListDetectionsResponse ) {
    option (google.api.http) = {
      // https://cloud.google.com/apis/design/standard_methods#list
      get: "/v1/detections"
    };
  }
}

message GetDetectionRequest {
  // [Detection] reference.
  string detection_uuid = 1; // type: Detection
}
message GetDetectionResponse {
  // [Detection] descriptor.
  Detection detection = 1;
}

message ListDetectionsRequest {
  // Include only [detections] occurred on referenced [device].
  string device_uuid = 38; // type: Pablitto.ERA.Device

  /*
    Include only incidents whose detections occurred before `end_time` (excluding).

    `detection.occur_time` < `end_time`

    ```info:
    https://cloud.google.com/apis/design/design_patterns#representing_ranges
    ```
  */
  google.protobuf.Timestamp end_time = 34;

  /*
    Include only incidents whose detections occurred after `start_time` (including).

    `detection.occur_time` >= `start_time`

    ```info:
    https://cloud.google.com/apis/design/design_patterns#representing_ranges
    ```
  */
  google.protobuf.Timestamp start_time = 33;

  ////// Inherited from resource.method.List /////

  /*
    Comma separated list fields (from the request resource).
    
    Allowed formats are:
    - [snake_case version of the field name](https://developers.google.com/protocol-buffers/docs/style#message_and_field_names) as used by protocol buffers.
    - [JSON version of the field name](https://developers.google.com/protocol-buffers/docs/proto3#json)
    
    Syntax is described at: https://cloud.google.com/apis/design/design_patterns#sorting_order
  */
  reserved "order_by";
  reserved 3;

  /*
    Limit for pagination purposes.
    
    ```info:
    For more see [Paginating Requests in APIs](https://medium.com/@ignaciochiazzo/paginating-requests-in-apis-d4883d4c1c4c)
    
    or https://cloud.google.com/apis/design/design_patterns#list_pagination
    ```
  */
  uint32 page_size = 2;

  /*
    Page token of current page.
    
    ```info:
    For more see [Paginating Requests in APIs](https://medium.com/@ignaciochiazzo/paginating-requests-in-apis-d4883d4c1c4c)
    
    or https://cloud.google.com/apis/design/design_patterns#list_pagination
    ```
  */
  string page_token = 1;
}
message ListDetectionsResponse {
  // [Detection]s matching criteria.
  repeated Detection detections = 33;

  ////// Inherited from resource.method.List /////

  /*
    Page token of next page.
    
    ```info:
    For more see [Paginating Requests in APIs](https://medium.com/@ignaciochiazzo/paginating-requests-in-apis-d4883d4c1c4c)
    
    or https://cloud.google.com/apis/design/design_patterns#list_pagination
    ```
  */
  string next_page_token = 1;

  /*
    The total count of items in the list irrespective of pagination.
    
    ```info:
    One of the [standard fields](https://cloud.google.com/apis/design/standard_fields)
    ```
    
    `Page_size` might differ for every call (it is an input parameter) so the calculation of how many pages there is in total is caller's responsibility.
  */
  uint32 total_size = 2;
}

Jest tego troszkę więcej.

Generalnie serwer w C++ wystawia jakies funkcję i potrzebuję napisać testy do tego w python.

Kod python generuję tak na Windows:

py -m grpc_tools.protoc -I Shared\Interface\Proto -I ThirdParty\grpc\third_party\googleapis --python_out=Products\Src\test\generated --grpc_python_out=Products\Src\test\generated Shared\Interface\Proto\dotnod\incident_management\v1\detections.proto  Shared\Interface\Proto\dotnod\incident_management\v1\types.proto

W katalogu 'Products\Src\test\generated` nie dostaję tylko plików, ale strukturę katalogów:

Products\Src\test\generated>tree /f
Folder PATH listing for volume New Volume
Volume serial number is 6027-E95C
F:.
│   README.md
│
└───dotnod
    └───incident_management
        └───v1
                detections_pb2.py
                detections_pb2_grpc.py
                types_pb2.py
                types_pb2_grpc.py

No i teraz jak próbuję zaimportować ten kod w pliku, który jest w katalogu Products\Src\test

from generated.dotnod.incident_management.v1.detections_pb2_grpc import DetectionsStub

Ten import działa, ale import z wnętrze wygenerowanego pliku pada:

Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "F:\.....\Products\Src\test\generated\dotnod\incident_management\v1\detections_pb2_grpc.py", line 5, in <module>
    from dotnod.incident_management.v1 import detections_pb2 as dotnod_dot_incident__management_dot_v1_dot_detections__pb2
ModuleNotFoundError: No module named 'dotnod'
python-BaseException

Ten traceback wskazuje na taką linijkę w wygenerowanym pliku:


from dotnod.incident_management.v1 import detections_pb2 as dotnod_dot_incident__management_dot_v1_dot_detections__pb2


Ten problem przypomina ten wątek na github https://github.com/protocolbuffers/protobuf/issues/1491

Niestety nie ogarniam dobrze pythona, więc nie mogę dojść do ładu i składu jak to naprawić bez dodwania generowanego kodu do repozytorium.

Próbowałem eksperymenty z dodawaniem __init__.py ale to tylko pogarszało sprawę.

0
MarekR22 napisał(a):

Próbowałem eksperymenty z dodawaniem __init__.py ale to tylko pogarszało sprawę.

Czyli?

0

Dobra rozwiązałem problem.
Wystarczyło pozybć się jedneogo levela katalogów. Czyli pozbyć się katalogu generated :/.

1

Jak byś bardzo potrzebował tamtego drzewa, w pythonie można zrobić import sys i "na chama", ręcznie dodawać do
PATH, sys.path.append(<path>), składnia, ".", "../" też wchodzi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1