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