Amir
Amir

Reputation: 541

How can I check if a protobuf message has a field defined

I'm working with a protobuf message that has some of the fields marked for deprecation with [deprecated = true]. To my understanding the field can still be used by some part of the code (maybe with a warning). I want to make sure that my code is still supporting this field with the possibility of handling the case when it actually gets deprecated. Was thinking HasField gives me that tool but sounds like HasField only check if an existing field in a message has been set or not. In my case my proto message looks roughly like this:

message Message1 {
    map<string, Message2> message_collection = 1;
}

message Message2 {
    bool some_var = 1 [deprecated = true];
}

I was hoping for a piece of code like this:

my_message = Message1()

for mystr, mymessage2 in my_message.message_collection.items():
    if mymessage2.HasField("some_var"):
        mymessage2.some_var = True

How can I check if some_var in Message2 is still a defined field or not?

Upvotes: 6

Views: 10407

Answers (1)

Yaakov Bressler
Yaakov Bressler

Reputation: 12128

Deprecated fields have no impact on code, as per the docs. In your case, it looks like you are trying to evaluate if the class Message2 has a field defined or not?

Before going forward, you need add optional as an option in your proto to allow for HasField() to work:

my_message.proto

syntax = "proto3";

message Message1 {
    map<string, Message2> message_collection = 1;
}

message Message2 {
    optional bool some_var = 1 [deprecated = true];
}

Your python code should look like the following:
main.py

from sample_message_pb2 import Message1, Message2

# Create your object
my_message = Message1(
    message_collection={
        'key_1': Message2(some_var=True),
        'key_2': Message2(some_var=False),
        'key_3': Message2()
    }
)

# Iterate over your object
for mystr, mymessage2 in my_message.message_collection.items():

    # If the value is assigned or not
    if mymessage2.HasField(field_name):
        print(f'{mystr}: {field_name} = {getattr(mymessage2, field_name)}')
    
        # Reassign the value
        mymessage2.some_var = True
    
    # If the field exists or not
    field_names = mymessage2.ListFields()
    if 'pickles' in field_names:
        print('Uh oh, here comes Mr. Pickles')

I dug around and could not find if it's possible to surface the deprecation warning to your python code. Looks like it's a limitation presently.

Upvotes: 3

Related Questions