Phrogz Phrogz - 1 month ago 15
Python Question

Test if ProtoBuf value is using default

I have a ProtoBuf object. I'd like to detect when a particular field is using the default, versus explicitly supplied.

message vector_measurement
{
measurement x = 1;
measurement y = 2;
measurement z = 3;
}
...
message measurement
{
...
float value = 2;
...
}


When I use
HasField
it returns
True
, yet this is clearly not the case:

c = my_vector

print(c)
# x {
# value: 60.3813476562
# }
# y {
# value: 0.444311201572
# }
# z {
# }

print(c.x)
# value: 60.3813476562

print(c.z)
#

print(c.z==None)
# False

print(c.z.value)
# 0

print( c.HasField('x'), c.HasField('z') )
# (True, True )

print (c.z.HasField('value') )
# ValueError: Protocol message has no non-repeated submessage field "value"


The string representation seems to know that
z
is using a default value; how can I detect this myself?

Answer

You can check if a message is the default by calling ByteSize() on the message:

print(c.x.ByteSize())
# 5

print(c.z.ByteSize())
# 0

However, note that this is true for every default value, not just those not sent with the message. In other words, if each component value is explicitly set to exactly match the default, it will then report ByteSize()==0:

print(c.x, c.x.ByteSize())
#myBool: true
#stdDev: 1.06
#value: 14.32
# 12

c.x.myBool = False
print(c.x, c.x.ByteSize())
#stdDev: 1.06
#value: 14.32
# 10

c.x.value = 0
print(c.x, c.x.ByteSize())
#stdDev: 1.06
# 5

c.x.stdDev = 0
print(c.x, c.x.ByteSize())
# 0