Hi there,

So I've spent a good deal of time honing in on the crux of my issue, and 
I've written this quick script to demonstrate. The premise is that I need 
to send a protobuf descriptor to the server, which then uses it to 
serialize/deserialize messages containing nested types.

test.proto:

message A {
  message B {
    required string data = 1;
  }
  repeated B bs = 1;
}


test.py:

from descriptor_pb2 import DescriptorProto

from google.protobuf import descriptor,reflection,message

from test_pb2 import *

a = A()

b = a.bs.add()

b.data = "stuff"

d1 = a.DESCRIPTOR

dp1 = DescriptorProto()

d1.CopyToProto(dp1)

# dp1 serialized, sent over network, deserialized

d2 = descriptor.MakeDescriptor(dp1)


## Un-commenting this block fixes the problem

#

#for desc in dp1.nested_type:

#    d2.nested_types.append( descriptor.MakeDescriptor(desc) )

#d2.nested_types_by_name = dict((t.name, t) for t in d2.nested_types)

#    

#for f in dp1.field:

#    d2.fields_by_number[f.number].message_type = 
d2.nested_types_by_name[f.type_name.split('.')[-1]]

#

# This cannot be duplicated across the net

#d2.fields[0].message_type._concrete_class = 
d1.fields[0].message_type._concrete_class 

 

reflection.ParseMessage(d1, a.SerializeToString()) # succeeds

reflection.ParseMessage(d2, a.SerializeToString()) # fails

 

When I run this code, I get an error on the last line:


Traceback (most recent call last):

  File "C:/state-update-service/bug_POC.py", line 29, in <module>

    reflection.ParseMessage(d2, a.SerializeToString())

  File "build\bdist.win32\egg\google\protobuf\reflection.py", line 168, in 
ParseMessage

    new_msg.ParseFromString(byte_str)

  File "build\bdist.win32\egg\google\protobuf\message.py", line 182, in 
ParseFromString

    self.MergeFromString(serialized)

  File "build\bdist.win32\egg\google\protobuf\internal\python_message.py", line 
795, in MergeFromString

    if self._InternalParse(serialized, 0, length) != length:

  File "build\bdist.win32\egg\google\protobuf\internal\python_message.py", line 
827, in InternalParse

    pos = field_decoder(buffer, new_pos, end, self, field_dict)

  File "build\bdist.win32\egg\google\protobuf\internal\decoder.py", line 523, 
in DecodeRepeatedField

    if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:

  File "build\bdist.win32\egg\google\protobuf\internal\containers.py", line 
216, in add

    new_element = self._message_descriptor._concrete_class(**kwargs)

AttributeError: 'NoneType' object has no attribute '_concrete_class'


I determined that the problem was that descriptor.MakeDescriptor() doesn't 
copy the nested_types from the deserialized DescriptorProto, so I wrote the 
code in the comment block to compensate for this. Everything runs fine 
then, however, the last line creates a reference to the original 
descriptor, so I can't do that if I'm deserializing on a different machine.

Can anyone come up with a work-around for this problem? I've spent hours 
and hours trying to figure it out to no avail.

Thanks in advance,
-Eric

   

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to