Search code examples
pythonarraysprotocol-buffersgrpcpython-3.7

How To Fix: TypeError: No positional arguments allowed' in python List object with gRPC


I have already looked at this post, which doesn't answer my problem

Here is how my proto file looks like

message GetWarehousesRequest {
  CreateAttributes base_wh = 1;
  repeated CreateAttributes partnered_wh = 2;
}

(i am not posting grpc method signatures because they are trivial)

Note how partnered_wh is an array.

In python i have this method

    def get_warehouses(
        self,
        base_wh: create_attributes_pb2,
        partnered_whs: List[create_attributes_pb2],
    ) -> int:
        start_time = utcnow().replace(tzinfo=None)
        request = get_warehouses_request_pb2(
            base_wh=base_wh,
        )

        for partnered_wh in partnered_whs:
            request.partnered_wh.add(partnered_wh)

In the for loop i am getting error that No position arguments are allowed. I need to convert python List to gRPC array. What should be best way to do so? Can i just assign that list to object? or there is better way?


Solution

  • You have 3 options:

    1. c = p.add() -- adds a new child and returns (!) it
    2. `p.append(c) -- appends a child
    3. `p.extend([c1,..cn]) -- appends multiple children

    Assuming create_attributes.proto:

    syntax = "proto3";
    
    message CreateAttributes {}
    
    message GetWarehousesRequest {
      CreateAttributes base_wh = 1;
      repeated CreateAttributes partnered_wh = 2;
    }
    

    And:

    protoc \
    --proto_path=${PWD} \
    --python_out=${PWD} \
    --pyi_out=${PWD} \
    ${PWD}/create_attributes.proto 
    

    Then:

    import create_attributes_pb2
    import datetime
    
    def get_warehouses(
      self,
      base_wh: create_attributes_pb2.CreateAttributes,
      partnered_whs: List[create_attributes_pb2.CreateAttributes],
    ) -> int:
      start_time = datetime.datetime.utcnow().replace(tzinfo=None)
      request =create_attributes_pb2.GetWarehousesRequest(
        base_wh=base_wh,
      )
    
      # You can append the list (!) using `extend`
      request.partnered_wh.extend(partnered_whs)
    
      return(1)
    

    Demonstrating each method (1..3):

    import create_attributes_pb2
    
    
    gwr = create_attributes_pb2.GetWarehousesRequest()
    
    # 1 `add` adds a new and returns a CreateAttributes (ca1)
    ca1 = gwr.partnered_wh.add()
    assert(type(ca1) == create_attributes_pb2.CreateAttributes)
    
    # 2 `append` adds an existing CreateAttributes (ca2)
    ca2 = create_attributes_pb2.CreateAttributes()
    gwr.partnered_wh.append(ca2)
    
    # 3 `extends` adds a list of existing CreateAttributes
    ca3 = create_attributes_pb2.CreateAttributes()
    ca4 = create_attributes_pb2.CreateAttributes()
    gwr.partnered_wh.extend([ca3,ca4])
    
    print(gwr)