0

metadata3.proto

syntax = "proto3";

import "google/protobuf/descriptor.proto";

package metas3;

message MessageOptionsMetadata3 {
  optional string message_options_field1 = 1;
  optional string message_options_field2 = 2;
  optional string message_options_field3 = 3;
}

extend google.protobuf.MessageOptions {
  MessageOptionsMetadata3 message_options_metadata3 = 50000;
}

message FileOptionsMetadata3 {
  optional string file_options_field1 = 1;
  optional string file_options_field2 = 2;
  optional string file_options_field3 = 3;
  optional string file_options_field4 = 4;
}

extend google.protobuf.FileOptions {
  FileOptionsMetadata3 file_options_metadata3 = 60000;
}

extend google.protobuf.FieldOptions {
  repeated string event_type = 70000;
}

my_proto_file.proto

syntax = "proto3";

import "metadata3.proto";
import "google/protobuf/descriptor.proto";

package events;

extend google.protobuf.MessageOptions {
  optional string my_option = 51234;
}

message MyMessage {
  option (my_option) = "Hello world!";
  option (metas3.message_options_metadata3).message_options_field1 = "Message option";
}

Generated metadata3_pb2.py and used that in protoc plugin as follows,

protoc -I=./protos --python_out=./protos_generated --plugin=./protos_generated/metadata3_pb2.py ./protos/*.proto

my_proto_file_pb2.py

# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: my_proto_file.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()


import metadata3_pb2 as metadata3__pb2
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2


DESCRIPTOR = _descriptor.FileDescriptor(
  name='my_proto_file.proto',
  package='events',
  syntax='proto3',
  serialized_options=None,
  create_key=_descriptor._internal_create_key,
  serialized_pb=b'\n\x13my_proto_file.proto\x12\x06\x65vents\x1a\x0fmetadata3.proto\x1a google/protobuf/descriptor.proto\"1\n\tMyMessage:$\x92\x82\x19\x0cHello world!\x82\xb5\x18\x10\n\x0eMessage option:7\n\tmy_option\x12\x1f.google.protobuf.MessageOptions\x18\xa2\x90\x03 \x01(\t\x88\x01\x01\x62\x06proto3'
  ,
  dependencies=[metadata3__pb2.DESCRIPTOR,google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,])


MY_OPTION_FIELD_NUMBER = 51234
my_option = _descriptor.FieldDescriptor(
  name='my_option', full_name='events.my_option', index=0,
  number=51234, 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=True, extension_scope=None,
  serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key)


_MYMESSAGE = _descriptor.Descriptor(
  name='MyMessage',
  full_name='events.MyMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  create_key=_descriptor._internal_create_key,
  fields=[
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=b'\222\202\031\014Hello world!\202\265\030\020\n\016Message option',
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=82,
  serialized_end=131,
)

DESCRIPTOR.message_types_by_name['MyMessage'] = _MYMESSAGE
DESCRIPTOR.extensions_by_name['my_option'] = my_option
_sym_db.RegisterFileDescriptor(DESCRIPTOR)

MyMessage = _reflection.GeneratedProtocolMessageType('MyMessage', (_message.Message,), {
  'DESCRIPTOR' : _MYMESSAGE,
  '__module__' : 'my_proto_file_pb2'
  # @@protoc_insertion_point(class_scope:events.MyMessage)
  })
_sym_db.RegisterMessage(MyMessage)

google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(my_option)

_MYMESSAGE._options = None
# @@protoc_insertion_point(module_scope)

Accessing options defined in the file works as the option in set in generated code

value = my_proto_file_pb2.MyMessage.DESCRIPTOR.GetOptions().Extensions[my_proto_file_pb2.my_option]

But options imported from external proto files doesn't seem to be set and hence isn't accessible

value = my_proto_file_pb2.MyMessage.DESCRIPTOR.GetOptions().Extensions[my_proto_file_pb2.message_options_field1]
maverickz
  • 143
  • 1
  • 7

1 Answers1

0
--plugin=./protos_generated/metadata3_pb2.py

This looks weird to me. What do you expect it should do?

serialized_options=b'\222\202\031\014Hello world!\202\265\030\020\n\016Message option',

It looks like your Message option is included also. So the problem is only in accessing it.

value = my_proto_file_pb2.MyMessage.DESCRIPTOR.GetOptions()
           .Extensions[my_proto_file_pb2.message_options_field1]

As far as I can tell there is no my_proto_file_pb2.message_options_field1 defined in my_proto_file.proto. Instead it should be metadata3_pb2.message_options_metadata3.

jpa
  • 10,351
  • 1
  • 28
  • 45
  • plugin options was suggested as a solution to have external options be populated [here](https://github.com/protocolbuffers/protobuf/issues/7363#issuecomment-610106385) `metadata3_pb2.message_options_metadata3` doesn't work either. Though message options are set in serialized options, options imported from external proto files aren't set in generated code, options defined in the same proto file are set in generated code. For example: `DESCRIPTOR.extensions_by_name['my_option'] = my_option` – maverickz Dec 03 '21 at 04:26