How to get protobuf FileDescriptor FileOptions in python?

794 views
Skip to first unread message

Karthik Raj

unread,
Nov 18, 2021, 8:51:32 PM11/18/21
to Protocol Buffers

I am trying to use FileOptions defined in a proto file to do some validations on the auto-generated python classes, which will drive some integrations further downstream. 

I couldn't find a way to access the FileOptions, which are serialized and stored under `serialized_options` in the generated python classes. 

sample.proto

```
option (foo.pkg.v1.option1) = option_val1; 
option (foo.pkg.v1.option2) = option_val2; 
option (foo.pkg.v1.option3) = "Sample desc"; 
option (foo.pkg.v1.option4) = option_val4; 
option (foo.pkg.v1.option5) = option_val5; .....
```
 

sample_pb2.py

DESCRIPTOR = _descriptor.FileDescriptor( name='foo/bar/v1/baz.proto', package='foo.bar.v1', syntax='proto3', serialized_options=b'\240\227\"d\220\227\"\364\034\252\227\"nSample desc\210\227\"\350 \230\227\"d', create_key=_descriptor._internal_create_key, serialized_pb=b'\n9foo/bar/v1/baz.proto\x12\x0f\x63hime.bar.v1\x1a*foo/bar/v1/external_source_info.proto\x1a\x1a\x63hime/pii/v1/options.proto\x1a!foo/streaming/v1/metadata.proto\x1a\x17google/type/money.proto\"\xdf\x02\n ExternalDirectDepositAllocations\x12\x1b\n\x13\x65xternal_account_id\x18\x01 \x01(\t\x12\x38\n\x0f\x65xternal_source\x18\x02 \x01(\x0e\x32\x1f.foo.bar.v1.ExternalSource\x12\x1b\n\x13\x61llocation_group_id\x18\x03 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x04 \x01(\t\x12\x38\n\x0f\x61llocation_type\x18\x05 \x01(\x0e\x32\x1f.foo.bar.v1.AllocationType\x12(\n\x06\x61mount\x18\x06 \x01(\x0b\x32\x12.google.type.MoneyB\x04\x88\xb5\x18,\x12\x14\n\x0c\x61\x63\x63ount_name\x18\x07 \x01(\t\x12\x11\n\tbank_name\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\t \x01(\x01\x12\x10\n\x08priority\x18\n \x01(\x03\x42\x84\x01\xa0\x97\"d\x90\x97\"\xf4\x1c\xaa\x97\"nSample desc\x88\x97\"\xe8 \x98\x97\"db\x06proto3' , dependencies=[foo_dot_bar_dot_v1_dot_external__source__info__pb2.DESCRIPTOR,foo_dot_streaming_dot_v1_dot_metadata__pb2.DESCRIPTOR,google_dot_type_dot_money__pb2.DESCRIPTOR,])

How can we access the FileOptions foo.pkg.v1.option1foo.pkg.v1.option2, etc in python?

protobuf_obj.DESCRIPTOR.GetOptions()

does not return anything.

Karthik Raj

unread,
Nov 19, 2021, 2:24:37 PM11/19/21
to Protocol Buffers
Just realized that file/field options are not set in the auto-generated python file

sample.proto
syntax = "proto3";

package foo.bar.v1;

option (foo.qux.v1.option1) = "file_option1";
option (foo.qux.v1.option2) = "file_option2";
option (foo.qux.v1.option3) = "Event description";
option (foo.qux.v1.option4) = "file_option4";
option (foo.qux.v1.option5) = "file_option5";

import "foo/bar/v1/external_enum.proto";
import "foo/baz/v1/options.proto";
import "foo/qux/v1/metadata.proto";
import "google/type/date.proto";
import "google/type/money.proto";


message Sample {
  string field1 = 1;
  ExternalEnum field2 = 2;
  string field3 = 3;
  google.type.Date field4 = 4;
  google.type.Date field5 = 5;
  google.type.Date field6 = 6;
  google.type.Money field7 = 7 [(foo.baz.v1.custom_field_option) = "field_option1"];
  google.type.Money field8 = 8 [(foo.baz.v1.custom_field_option) = "field_option2"];
  google.type.Money field9 = 9 [(foo.baz.v1.custom_field_option) = "field_option3"];
}

sample_pb2.py
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: foo/bar/v1/sample.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()


from foo.bar.v1 import field2_info_pb2 as foo_dot_bar_dot_v1_dot_external__enum__pb2
from foo.baz.v1 import options_pb2 as foo_dot_baz_dot_v1_dot_options__pb2
from foo.qux.v1 import metadata_pb2 as foo_dot_qux_dot_v1_dot_metadata__pb2
from google.type import date_pb2 as google_dot_type_dot_date__pb2
from google.type import money_pb2 as google_dot_type_dot_money__pb2


DESCRIPTOR = _descriptor.FileDescriptor(
  name='foo/bar/v1/sample.proto',
  package='foo.bar.v1',
  syntax='proto3',
  serialized_options=b'\240\227\"d\220\227\"\364\034\252\227\"Event description\210\227\"\350 \230\227\"d',
  create_key=_descriptor._internal_create_key,
  serialized_pb=b'\n\'foo/bar/v1/sample.proto\x12\x0f\x63hime.bar.v1\x1a*foo/bar/v1/field2_info.proto\x1a\x1a\x63hime/baz/v1/options.proto\x1a!foo/qux/v1/metadata.proto\x1a\x16google/type/date.proto\x1a\x17google/type/money.proto\"\x96\x03\n\x10\x45xternalPaystubs\x12\x1b\n\x13\x65xternal_account_id\x18\x01 \x01(\t\x12\x38\n\x0f\x65xternal_source\x18\x02 \x01(\x0e\x32\x1f.foo.bar.v1.ExternalSource\x12\x18\n\x10field3\x18\x03 \x01(\t\x12+\n\x10field4\x18\x04 \x01(\x0b\x32\x11.google.type.Date\x12)\n\x0efield5\x18\x05 \x01(\x0b\x32\x11.google.type.Date\x12#\n\x08field6\x18\x06 \x01(\x0b\x32\x11.google.type.Date\x12\x30\n\x0efield7\x18\x07 \x01(\x0b\x32\x12.google.type.MoneyB\x04\x88\xb5\x18,\x12\x32\n\x10field8\x18\x08 \x01(\x0b\x32\x12.google.type.MoneyB\x04\x88\xb5\x18-\x12.\n\x0c\x63heck_amount\x18\t \x01(\x0b\x32\x12.google.type.MoneyB\x04\x88\xb5\x18-BW\xa0\x97\"d\x90\x97\"\xf4\x1c\xaa\x97\"Event description\x88\x97\"\xe8 \x98\x97\"db\x06proto3'
  ,
  dependencies=[foo_dot_bar_dot_v1_dot_external__enum__pb2.DESCRIPTOR,foo_dot_baz_dot_v1_dot_options__pb2.DESCRIPTOR,foo_dot_qux_dot_v1_dot_metadata__pb2.DESCRIPTOR,google_dot_type_dot_date__pb2.DESCRIPTOR,google_dot_type_dot_money__pb2.DESCRIPTOR,])




_Sample = _descriptor.Descriptor(
  name='Sample',
  full_name='foo.bar.v1.Sample',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  create_key=_descriptor._internal_create_key,
  fields=[
    _descriptor.FieldDescriptor(
      name='field1', full_name='foo.bar.v1.Sample.field1', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field2', full_name='foo.bar.v1.Sample.field2', index=1,
      number=2, type=14, cpp_type=8, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field3', full_name='foo.bar.v1.Sample.field3', index=2,
      number=3, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field4', full_name='foo.bar.v1.Sample.field4', index=3,
      number=4, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field5', full_name='foo.bar.v1.Sample.field5', index=4,
      number=5, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field6', full_name='foo.bar.v1.Sample.field6', index=5,
      number=6, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field7', full_name='foo.bar.v1.Sample.field7', index=6,
      number=7, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=b'\210\265\030,', file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field8', full_name='foo.bar.v1.Sample.field8', index=7,
      number=8, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=b'\210\265\030-', file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='field9', full_name='foo.bar.v1.Sample.field9', index=8,
      number=9, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=b'\210\265\030-', file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=217,
  serialized_end=623,
)

_Sample.fields_by_name['field2'].enum_type = foo_dot_bar_dot_v1_dot_external__enum__pb2._EXTERNALENUM
_Sample.fields_by_name['field4'].message_type = google_dot_type_dot_date__pb2._DATE
_Sample.fields_by_name['field5'].message_type = google_dot_type_dot_date__pb2._DATE
_Sample.fields_by_name['field6'].message_type = google_dot_type_dot_date__pb2._DATE
_Sample.fields_by_name['field7'].message_type = google_dot_type_dot_money__pb2._MONEY
_Sample.fields_by_name['field8'].message_type = google_dot_type_dot_money__pb2._MONEY
_Sample.fields_by_name['field9'].message_type = google_dot_type_dot_money__pb2._MONEY
DESCRIPTOR.message_types_by_name['Sample'] = _Sample
_sym_db.RegisterFileDescriptor(DESCRIPTOR)

Sample = _reflection.GeneratedProtocolMessageType('Sample', (_message.Message,), {
  'DESCRIPTOR' : _Sample,
  '__module__' : 'foo.bar.v1.sample_pb2'
  # @@protoc_insertion_point(class_scope:foo.bar.v1.Sample)
  })
_sym_db.RegisterMessage(Sample)


DESCRIPTOR._options = None
_Sample.fields_by_name['field7']._options = None
_Sample.fields_by_name['field8']._options = None
_Sample.fields_by_name['field9']._options = None
# @@protoc_insertion_point(module_scope)

Any reason why these aren't set? 


Reply all
Reply to author
Forward
0 new messages