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.