danielgtaylor / python-betterproto

Clean, modern, Python 3.6+ code generator & library for Protobuf 3 and async gRPC
MIT License
1.51k stars 214 forks source link

nested empty types not in to_dict #199

Open kilimnik opened 3 years ago

kilimnik commented 3 years ago

I am not sure if I am wrong here but when executing this:

from dataclasses import dataclass

import betterproto

@dataclass
class Inner(betterproto.Message):
    inner1: str = betterproto.string_field(1)
    inner2: str = betterproto.string_field(2)

@dataclass
class Test(betterproto.Message):
    name: str = betterproto.string_field(1)
    inner: "Inner" = betterproto.message_field(2)

test = Test(name='123', inner=Inner())
print(test.to_json())

I receive the output {"name": "123"}. I would expect the output to be{"name": "123", inner:{}}. Of course there is a similar issue with the to_dict function

Gobot1234 commented 3 years ago

Is this the default behaviour for the google implementation?

kilimnik commented 3 years ago

Yes it is here the example generated with the google implementation

Click to expand! ```python # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: test.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() DESCRIPTOR = _descriptor.FileDescriptor( name='test.proto', package='', syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, serialized_pb=b'\n\ntest.proto\"\'\n\x05Inner\x12\x0e\n\x06inner1\x18\x01 \x01(\t\x12\x0e\n\x06inner2\x18\x02 \x01(\t\"+\n\x04Test\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x15\n\x05inner\x18\x02 \x01(\x0b\x32\x06.Innerb\x06proto3' ) _INNER = _descriptor.Descriptor( name='Inner', full_name='Inner', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( name='inner1', full_name='Inner.inner1', 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='inner2', full_name='Inner.inner2', index=1, number=2, 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), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=14, serialized_end=53, ) _TEST = _descriptor.Descriptor( name='Test', full_name='Test', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( name='name', full_name='Test.name', 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='inner', full_name='Test.inner', index=1, number=2, 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), ], extensions=[ ], nested_types=[], enum_types=[ ], serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=55, serialized_end=98, ) _TEST.fields_by_name['inner'].message_type = _INNER DESCRIPTOR.message_types_by_name['Inner'] = _INNER DESCRIPTOR.message_types_by_name['Test'] = _TEST _sym_db.RegisterFileDescriptor(DESCRIPTOR) Inner = _reflection.GeneratedProtocolMessageType('Inner', (_message.Message,), { 'DESCRIPTOR' : _INNER, '__module__' : 'test_pb2' # @@protoc_insertion_point(class_scope:Inner) }) _sym_db.RegisterMessage(Inner) Test = _reflection.GeneratedProtocolMessageType('Test', (_message.Message,), { 'DESCRIPTOR' : _TEST, '__module__' : 'test_pb2' # @@protoc_insertion_point(class_scope:Test) }) _sym_db.RegisterMessage(Test) # @@protoc_insertion_point(module_scope) from google.protobuf.json_format import MessageToDict test = Test(name='123', inner=Inner()) print(MessageToDict(test)) ```

It produces the output {'name': '123', 'inner': {}}