pythondictionaryprotocol-buffersprotobuf-python

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?


Solution

  • 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.