Python – How do I assign a field on the protobuf message if the child message doesn’t have a field?

How do I assign a field on the protobuf message if the child message doesn’t have a field?… here is a solution to the problem.

How do I assign a field on the protobuf message if the child message doesn’t have a field?

I want to create a BigTable DeleteFromRow mutation. The prototypes for Mutation and DeleteFromRow are as follows:

oneof mutation {
     Set a cell's value.
    SetCell set_cell = 1;

 Deletes cells from a column.
    DeleteFromColumn delete_from_column = 2;

 Deletes cells from a column family.
    DeleteFromFamily delete_from_family = 3;

 Deletes cells from the entire row.
    DeleteFromRow delete_from_row = 4;
  }
}

message DeleteFromRow {

}

In Python, you cannot directly instantiate a DeleteFromRow object and set the delete_from_row field of Mutation to that object.

So this doesn’t work :

request = bigtable_pb2. MutateRowRequest(table_name='tablename', row_key=row_key)
mutation = request.mutations.add()
mutation.delete_from_row = data_pb2. Mutation.DeleteFromRow()

As other SO users have suggested (see this question, which led to

AttributeError: Assignment not allowed to composite field "delete_from_row" in protocol message object.

According to protobuf docs, You should set up a field by setting one of the subfields. Therefore, the DeleteFromFamily mutation should be created in this way:

mutation.delete_from_family.family_name = 'some_family'

But how do you do this for a DeleteFromRow message that has no fields?

Solution

You can use Message.SetInParent :

Mark this as present in the parent.

This normally happens automatically when you assign a field of a sub-message, but sometimes you want to make the sub-message present while keeping it empty. If you find yourself using this, you may want to reconsider your design.

Example:

message Msg {
  oneof kind {
    int64 int_field = 1;
    EmptyMsg msg_field = 1;
  }
}

message EmptyMsg {}
msg = Msg()
print(msg. WhichOneof('kind'))  # None

msg.msg_field  # No-op (return EmptyMsg but don't set oneof field)
print(msg. WhichOneof('kind'))  # None

msg.msg_field. SetInParent()
print(v.WhichOneof('kind'))  # msg_field

Related Problems and Solutions