36 """Contains a metaclass and helper functions used to create
37 protocol message classes from Descriptor objects at runtime.
39 Recall that a metaclass is the "type" of a class.
40 (A class is to a metaclass what an instance is to a class.)
42 In this case, we use the GeneratedProtocolMessageType metaclass
43 to inject all the useful functionality into the classes
44 output by the protocol compiler at compile-time.
46 The upshot of all this is that the real implementation
47 details for ALL pure-Python protocol buffers are *here in
51 __author__ =
'robinson@google.com (Will Robinson)'
53 from io
import BytesIO
59 from six.moves
import range
76 _FieldDescriptor = descriptor_mod.FieldDescriptor
77 _AnyFullTypeName =
'google.protobuf.Any'
82 """Metaclass for protocol message classes created at runtime from Descriptors.
84 We add implementations for all methods described in the Message class. We
85 also create properties to allow getting/setting all fields in the protocol
86 message. Finally, we create slots to prevent users from accidentally
87 "setting" nonexistent fields in the protocol message, which then wouldn't get
88 serialized / deserialized properly.
90 The protocol compiler currently uses this metaclass to create protocol
91 message classes at runtime. Clients can also manually create their own
92 classes at runtime, as in this example:
94 mydescriptor = Descriptor(.....)
95 factory = symbol_database.Default()
96 factory.pool.AddDescriptor(mydescriptor)
97 MyProtoClass = factory.GetPrototype(mydescriptor)
98 myproto_instance = MyProtoClass()
99 myproto.foo_field = 23
105 _DESCRIPTOR_KEY =
'DESCRIPTOR'
108 """Custom allocation for runtime-generated class types.
110 We override __new__ because this is apparently the only place
111 where we can meaningfully set __slots__ on the class we're creating(?).
112 (The interplay between metaclasses and slots is not very well-documented).
115 name: Name of the class (ignored, but required by the
117 bases: Base classes of the class we're constructing.
118 (Should be message.Message). We ignore this field, but
119 it's required by the metaclass protocol
120 dictionary: The class dictionary of the class we're
121 constructing. dictionary[_DESCRIPTOR_KEY] must contain
122 a Descriptor object describing this protocol message
126 Newly-allocated class.
128 descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
140 new_class =
getattr(descriptor,
'_concrete_class',
None)
144 if descriptor.full_name
in well_known_types.WKTBASES:
145 bases += (well_known_types.WKTBASES[descriptor.full_name],)
149 superclass = super(GeneratedProtocolMessageType, cls)
150 new_class = superclass.__new__(cls, name, bases, dictionary)
154 """Here we perform the majority of our work on the class.
155 We add enum getters, an __init__ method, implementations
156 of all Message methods, and properties for all fields
157 in the protocol type.
160 name: Name of the class (ignored, but required by the
162 bases: Base classes of the class we're constructing.
163 (Should be message.Message). We ignore this field, but
164 it's required by the metaclass protocol
165 dictionary: The class dictionary of the class we're
166 constructing. dictionary[_DESCRIPTOR_KEY] must contain
167 a Descriptor object describing this protocol message
170 descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
174 existing_class =
getattr(descriptor,
'_concrete_class',
None)
176 assert existing_class
is cls, (
177 'Duplicate `GeneratedProtocolMessageType` created for descriptor %r'
178 % (descriptor.full_name))
182 if (descriptor.has_options
and
183 descriptor.GetOptions().message_set_wire_format):
185 decoder.MessageSetItemDecoder(descriptor),
None)
188 for field
in descriptor.fields:
191 descriptor._concrete_class = cls
200 superclass = super(GeneratedProtocolMessageType, cls)
201 superclass.__init__(name, bases, dictionary)
213 """Returns the name of the public property attribute which
214 clients can use to get and (in some cases) set the value
215 of a protocol message field.
218 proto_field_name: The protocol message field name, exactly
219 as it appears (or would appear) in a .proto file.
238 return proto_field_name
242 """Adds a __slots__ entry to dictionary, containing the names of all valid
243 attributes for this message type.
246 message_descriptor: A Descriptor instance describing this message type.
247 dictionary: Class dictionary to which we'll add a '__slots__' entry.
249 dictionary[
'__slots__'] = [
'_cached_byte_size',
250 '_cached_byte_size_dirty',
253 '_unknown_field_set',
254 '_is_present_in_parent',
256 '_listener_for_children',
262 return (field.is_extension
and
263 field.containing_type.has_options
and
264 field.containing_type.GetOptions().message_set_wire_format
and
265 field.type == _FieldDescriptor.TYPE_MESSAGE
and
266 field.label == _FieldDescriptor.LABEL_OPTIONAL)
270 return (field.type == _FieldDescriptor.TYPE_MESSAGE
and
271 field.message_type.has_options
and
272 field.message_type.GetOptions().map_entry)
276 value_type = field.message_type.fields_by_name[
'value']
277 return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
281 if field.containing_type.syntax !=
'proto3':
288 is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
289 is_packable = (is_repeated
and
290 wire_format.IsTypePackable(field_descriptor.type))
293 elif field_descriptor.containing_type.syntax ==
'proto2':
294 is_packed = (field_descriptor.has_options
and
295 field_descriptor.GetOptions().packed)
297 has_packed_false = (field_descriptor.has_options
and
298 field_descriptor.GetOptions().
HasField(
'packed')
and
299 field_descriptor.GetOptions().packed ==
False)
300 is_packed =
not has_packed_false
304 field_encoder = encoder.MapEncoder(field_descriptor)
305 sizer = encoder.MapSizer(field_descriptor,
308 field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
309 sizer = encoder.MessageSetItemSizer(field_descriptor.number)
311 field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
312 field_descriptor.number, is_repeated, is_packed)
313 sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
314 field_descriptor.number, is_repeated, is_packed)
316 field_descriptor._encoder = field_encoder
317 field_descriptor._sizer = sizer
321 def AddDecoder(wiretype, is_packed):
322 tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
323 decode_type = field_descriptor.type
324 if (decode_type == _FieldDescriptor.TYPE_ENUM
and
325 type_checkers.SupportsOpenEnums(field_descriptor)):
326 decode_type = _FieldDescriptor.TYPE_INT32
328 oneof_descriptor =
None
329 if field_descriptor.containing_oneof
is not None:
330 oneof_descriptor = field_descriptor
335 field_decoder = decoder.MapDecoder(
338 elif decode_type == _FieldDescriptor.TYPE_STRING:
340 field_decoder = decoder.StringDecoder(
341 field_descriptor.number, is_repeated, is_packed,
342 field_descriptor, field_descriptor._default_constructor,
343 is_strict_utf8_check)
345 field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
346 field_descriptor.number, is_repeated, is_packed,
347 field_descriptor, field_descriptor._default_constructor)
349 cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
351 AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
354 if is_repeated
and wire_format.IsTypePackable(field_descriptor.type):
357 AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED,
True)
361 extensions = descriptor.extensions_by_name
362 for extension_name, extension_field
in extensions.items():
363 assert extension_name
not in dictionary
364 dictionary[extension_name] = extension_field
368 """Sets class-level attributes for all enum fields defined in this message.
370 Also exporting a class-level object that can name enum values.
373 descriptor: Descriptor object for this message type.
374 cls: Class we're constructing for this message type.
376 for enum_type
in descriptor.enum_types:
378 for enum_value
in enum_type.values:
379 setattr(cls, enum_value.name, enum_value.number)
383 if field.label != _FieldDescriptor.LABEL_REPEATED:
384 raise ValueError(
'map_entry set on non-repeated field %s' % (
386 fields_by_name = field.message_type.fields_by_name
387 key_checker = type_checkers.GetTypeChecker(fields_by_name[
'key'])
389 value_field = fields_by_name[
'value']
391 def MakeMessageMapDefault(message):
393 message._listener_for_children, value_field.message_type, key_checker,
395 return MakeMessageMapDefault
397 value_checker = type_checkers.GetTypeChecker(value_field)
398 def MakePrimitiveMapDefault(message):
400 message._listener_for_children, key_checker, value_checker,
402 return MakePrimitiveMapDefault
405 """Returns a function which returns a default value for a field.
408 field: FieldDescriptor object for this field.
410 The returned function has one argument:
411 message: Message instance containing this field, or a weakref proxy
414 That function in turn returns a default value for this field. The default
415 value may refer back to |message| via a weak reference.
421 if field.label == _FieldDescriptor.LABEL_REPEATED:
422 if field.has_default_value
and field.default_value != []:
423 raise ValueError(
'Repeated field default value not empty list: %s' % (
424 field.default_value))
425 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
428 message_type = field.message_type
429 def MakeRepeatedMessageDefault(message):
431 message._listener_for_children, field.message_type)
432 return MakeRepeatedMessageDefault
434 type_checker = type_checkers.GetTypeChecker(field)
435 def MakeRepeatedScalarDefault(message):
437 message._listener_for_children, type_checker)
438 return MakeRepeatedScalarDefault
440 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
442 message_type = field.message_type
443 def MakeSubMessageDefault(message):
444 assert getattr(message_type,
'_concrete_class',
None), (
445 'Uninitialized concrete class found for field %r (message type %r)'
446 % (field.full_name, message_type.full_name))
447 result = message_type._concrete_class()
450 if field.containing_oneof
is not None
451 else message._listener_for_children)
453 return MakeSubMessageDefault
455 def MakeScalarDefault(message):
458 return field.default_value
459 return MakeScalarDefault
463 """Re-raise the currently-handled TypeError with the field name added."""
464 exc = sys.exc_info()[1]
465 if len(exc.args) == 1
and type(exc)
is TypeError:
467 exc = TypeError(
'%s for field %s.%s' % (
str(exc), message_name, field_name))
470 six.reraise(type(exc), exc, sys.exc_info()[2])
474 """Adds an __init__ method to cls."""
476 def _GetIntegerEnumValue(enum_type, value):
477 """Convert a string or integer enum value to an integer.
479 If the value is a string, it is converted to the enum value in
480 enum_type with the same name. If the value is not a string, it's
481 returned as-is. (No conversion or bounds-checking is done.)
483 if isinstance(value, six.string_types):
485 return enum_type.values_by_name[value].number
487 raise ValueError(
'Enum type %s: unknown label "%s"' % (
488 enum_type.full_name, value))
491 def init(self, **kwargs):
492 self._cached_byte_size = 0
493 self._cached_byte_size_dirty =
len(kwargs) > 0
501 self._unknown_fields = ()
504 self._unknown_field_set =
None
505 self._is_present_in_parent =
False
506 self._listener = message_listener_mod.NullMessageListener()
508 for field_name, field_value
in kwargs.items():
511 raise TypeError(
'%s() got an unexpected keyword argument "%s"' %
512 (message_descriptor.name, field_name))
513 if field_value
is None:
516 if field.label == _FieldDescriptor.LABEL_REPEATED:
517 copy = field._default_constructor(self)
518 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
521 for key
in field_value:
524 copy.update(field_value)
526 for val
in field_value:
527 if isinstance(val, dict):
532 if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
533 field_value = [_GetIntegerEnumValue(field.enum_type, val)
534 for val
in field_value]
535 copy.extend(field_value)
536 self._fields[field] = copy
537 elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
538 copy = field._default_constructor(self)
539 new_val = field_value
540 if isinstance(field_value, dict):
541 new_val = field.message_type._concrete_class(**field_value)
543 copy.MergeFrom(new_val)
546 self._fields[field] = copy
548 if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
549 field_value = _GetIntegerEnumValue(field.enum_type, field_value)
551 setattr(self, field_name, field_value)
555 init.__module__ =
None
561 """Returns a field descriptor by field name.
564 message_descriptor: A Descriptor describing all fields in message.
565 field_name: The name of the field to retrieve.
567 The field descriptor associated with the field name.
570 return message_descriptor.fields_by_name[field_name]
572 raise ValueError(
'Protocol message %s has no "%s" field.' %
573 (message_descriptor.name, field_name))
577 """Adds properties for all fields in this protocol message type."""
578 for field
in descriptor.fields:
581 if descriptor.is_extendable:
588 """Adds a public property for a protocol message field.
589 Clients can use this property to get and (in the case
590 of non-repeated scalar fields) directly set the value
591 of a protocol message field.
594 field: A FieldDescriptor for this field.
595 cls: The class we're constructing.
599 assert _FieldDescriptor.MAX_CPPTYPE == 10
601 constant_name = field.name.upper() +
'_FIELD_NUMBER'
602 setattr(cls, constant_name, field.number)
604 if field.label == _FieldDescriptor.LABEL_REPEATED:
606 elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
613 __slots__ = (
'DESCRIPTOR',)
615 def __init__(self, descriptor, getter, setter, doc):
616 property.__init__(self, getter, setter, doc=doc)
621 """Adds a public property for a "repeated" protocol message field. Clients
622 can use this property to get the value of the field, which will be either a
623 _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
626 Note that when clients add values to these containers, we perform
627 type-checking in the case of repeated scalar fields, and we also set any
628 necessary "has" bits as a side-effect.
631 field: A FieldDescriptor for this field.
632 cls: The class we're constructing.
634 proto_field_name = field.name
638 field_value = self._fields.get(field)
639 if field_value
is None:
641 field_value = field._default_constructor(self)
649 field_value = self._fields.setdefault(field, field_value)
651 getter.__module__ =
None
652 getter.__doc__ =
'Getter for %s.' % proto_field_name
656 def setter(self, new_value):
657 raise AttributeError(
'Assignment not allowed to repeated field '
658 '"%s" in protocol message object.' % proto_field_name)
660 doc =
'Magic attribute generated for "%s" proto field.' % proto_field_name
665 """Adds a public property for a nonrepeated, scalar protocol message field.
666 Clients can use this property to get and directly set the value of the field.
667 Note that when the client sets the value of a field by using this property,
668 all necessary "has" bits are set as a side-effect, and we also perform
672 field: A FieldDescriptor for this field.
673 cls: The class we're constructing.
675 proto_field_name = field.name
677 type_checker = type_checkers.GetTypeChecker(field)
678 default_value = field.default_value
680 is_proto3 = field.containing_type.syntax ==
'proto3'
685 return self._fields.get(field, default_value)
686 getter.__module__ =
None
687 getter.__doc__ =
'Getter for %s.' % proto_field_name
689 clear_when_set_to_default = is_proto3
and not field.containing_oneof
691 def field_setter(self, new_value):
696 new_value = type_checker.CheckValue(new_value)
697 except TypeError
as e:
699 'Cannot set %s to %.1024r: %s' % (field.full_name, new_value, e))
700 if clear_when_set_to_default
and not new_value:
701 self._fields.
pop(field,
None)
703 self._fields[field] = new_value
706 if not self._cached_byte_size_dirty:
709 if field.containing_oneof:
710 def setter(self, new_value):
711 field_setter(self, new_value)
712 self._UpdateOneofState(field)
714 setter = field_setter
716 setter.__module__ =
None
717 setter.__doc__ =
'Setter for %s.' % proto_field_name
720 doc =
'Magic attribute generated for "%s" proto field.' % proto_field_name
725 """Adds a public property for a nonrepeated, composite protocol message field.
726 A composite field is a "group" or "message" field.
728 Clients can use this property to get the value of the field, but cannot
729 assign to the property directly.
732 field: A FieldDescriptor for this field.
733 cls: The class we're constructing.
737 proto_field_name = field.name
741 field_value = self._fields.get(field)
742 if field_value
is None:
744 field_value = field._default_constructor(self)
752 field_value = self._fields.setdefault(field, field_value)
754 getter.__module__ =
None
755 getter.__doc__ =
'Getter for %s.' % proto_field_name
759 def setter(self, new_value):
760 raise AttributeError(
'Assignment not allowed to composite field '
761 '"%s" in protocol message object.' % proto_field_name)
764 doc =
'Magic attribute generated for "%s" proto field.' % proto_field_name
769 """Adds properties for all fields in this protocol message type."""
770 extensions = descriptor.extensions_by_name
771 for extension_name, extension_field
in extensions.items():
772 constant_name = extension_name.upper() +
'_FIELD_NUMBER'
773 setattr(cls, constant_name, extension_field.number)
777 if descriptor.file
is not None:
779 pool = descriptor.file.pool
780 cls._extensions_by_number = pool._extensions_by_number[descriptor]
781 cls._extensions_by_name = pool._extensions_by_name[descriptor]
786 extension_handle.containing_type = cls.DESCRIPTOR
788 cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle)
790 cls.RegisterExtension = staticmethod(RegisterExtension)
794 message.MergeFromString(s)
796 cls.FromString = staticmethod(FromString)
800 """Given a (FieldDescriptor, value) tuple from _fields, return true if the
801 value should be included in the list returned by ListFields()."""
803 if item[0].label == _FieldDescriptor.LABEL_REPEATED:
805 elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
806 return item[1]._is_present_in_parent
812 """Helper for _AddMessageMethods()."""
815 all_fields = [item
for item
in self._fields.items()
if _IsPresent(item)]
816 all_fields.sort(key =
lambda item: item[0].number)
819 cls.ListFields = ListFields
821 _PROTO3_ERROR_TEMPLATE = \
822 'Protocol message %s has no non-repeated submessage field "%s"'
823 _PROTO2_ERROR_TEMPLATE =
'Protocol message %s has no non-repeated field "%s"'
826 """Helper for _AddMessageMethods()."""
828 is_proto3 = (message_descriptor.syntax ==
"proto3")
829 error_msg = _PROTO3_ERROR_TEMPLATE
if is_proto3
else _PROTO2_ERROR_TEMPLATE
832 for field
in message_descriptor.fields:
833 if field.label == _FieldDescriptor.LABEL_REPEATED:
836 if (is_proto3
and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE
and
837 not field.containing_oneof):
839 hassable_fields[field.name] = field
843 for oneof
in message_descriptor.oneofs:
844 hassable_fields[oneof.name] = oneof
848 field = hassable_fields[field_name]
850 raise ValueError(error_msg % (message_descriptor.full_name, field_name))
852 if isinstance(field, descriptor_mod.OneofDescriptor):
854 return HasField(self, self._oneofs[field].name)
858 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
859 value = self._fields.get(field)
860 return value
is not None and value._is_present_in_parent
862 return field
in self._fields
864 cls.HasField = HasField
868 """Helper for _AddMessageMethods()."""
871 field = message_descriptor.fields_by_name[field_name]
874 field = message_descriptor.oneofs_by_name[field_name]
875 if field
in self._oneofs:
876 field = self._oneofs[field]
880 raise ValueError(
'Protocol message %s has no "%s" field.' %
881 (message_descriptor.name, field_name))
883 if field
in self._fields:
886 if hasattr(self._fields[field],
'InvalidateIterators'):
887 self._fields[field].InvalidateIterators()
892 del self._fields[field]
894 if self._oneofs.get(field.containing_oneof,
None)
is field:
895 del self._oneofs[field.containing_oneof]
902 cls.ClearField = ClearField
906 """Helper for _AddMessageMethods()."""
908 extension_dict._VerifyExtensionHandle(self, extension_handle)
911 if extension_handle
in self._fields:
912 del self._fields[extension_handle]
914 cls.ClearExtension = ClearExtension
918 """Helper for _AddMessageMethods()."""
920 extension_dict._VerifyExtensionHandle(self, extension_handle)
921 if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
922 raise KeyError(
'"%s" is repeated.' % extension_handle.full_name)
924 if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
925 value = self._fields.get(extension_handle)
926 return value
is not None and value._is_present_in_parent
928 return extension_handle
in self._fields
929 cls.HasExtension = HasExtension
932 """Unpacks Any message and returns the unpacked message.
934 This internal method is different from public Any Unpack method which takes
935 the target message as argument. _InternalUnpackAny method does not have
936 target message type and need to find the message type in descriptor pool.
939 msg: An Any message to be unpacked.
942 The unpacked message.
949 factory = symbol_database.Default()
951 type_url = msg.type_url
958 type_name = type_url.split(
'/')[-1]
959 descriptor = factory.pool.FindMessageTypeByName(type_name)
961 if descriptor
is None:
964 message_class = factory.GetPrototype(descriptor)
965 message = message_class()
967 message.ParseFromString(msg.value)
972 """Helper for _AddMessageMethods()."""
974 if (
not isinstance(other, message_mod.Message)
or
975 other.DESCRIPTOR != self.DESCRIPTOR):
981 if self.DESCRIPTOR.full_name == _AnyFullTypeName:
985 return any_a == any_b
987 if not self.ListFields() == other.ListFields():
992 unknown_fields = list(self._unknown_fields)
993 unknown_fields.sort()
994 other_unknown_fields = list(other._unknown_fields)
995 other_unknown_fields.sort()
996 return unknown_fields == other_unknown_fields
1002 """Helper for _AddMessageMethods()."""
1004 return text_format.MessageToString(self)
1005 cls.__str__ = __str__
1009 """Helper for _AddMessageMethods()."""
1011 return text_format.MessageToString(self)
1012 cls.__repr__ = __repr__
1016 """Helper for _AddMessageMethods()."""
1019 return text_format.MessageToString(self, as_utf8=
True).decode(
'utf-8')
1020 cls.__unicode__ = __unicode__
1024 """Returns the number of bytes needed to serialize a non-repeated element.
1025 The returned byte count includes space for tag information and any
1026 other additional space associated with serializing value.
1029 value: Value we're serializing.
1030 field_number: Field number of this value. (Since the field number
1031 is stored as part of a varint-encoded tag, this has an impact
1032 on the total bytes required to serialize the value).
1033 field_type: The type of the field. One of the TYPE_* constants
1034 within FieldDescriptor.
1037 fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
1038 return fn(field_number, value)
1040 raise message_mod.EncodeError(
'Unrecognized field type: %d' % field_type)
1044 """Helper for _AddMessageMethods()."""
1047 if not self._cached_byte_size_dirty:
1048 return self._cached_byte_size
1051 descriptor = self.DESCRIPTOR
1052 if descriptor.GetOptions().map_entry:
1054 size = descriptor.fields_by_name[
'key']._sizer(self.key)
1055 size += descriptor.fields_by_name[
'value']._sizer(self.value)
1057 for field_descriptor, field_value
in self.ListFields():
1058 size += field_descriptor._sizer(field_value)
1059 for tag_bytes, value_bytes
in self._unknown_fields:
1060 size +=
len(tag_bytes) +
len(value_bytes)
1062 self._cached_byte_size = size
1063 self._cached_byte_size_dirty =
False
1064 self._listener_for_children.dirty =
False
1067 cls.ByteSize = ByteSize
1071 """Helper for _AddMessageMethods()."""
1076 if not self.IsInitialized():
1077 raise message_mod.EncodeError(
1078 'Message %s is missing required fields: %s' % (
1079 self.DESCRIPTOR.full_name,
','.join(self.FindInitializationErrors())))
1080 return self.SerializePartialToString(**kwargs)
1081 cls.SerializeToString = SerializeToString
1085 """Helper for _AddMessageMethods()."""
1089 self._InternalSerialize(out.write, **kwargs)
1090 return out.getvalue()
1091 cls.SerializePartialToString = SerializePartialToString
1093 def InternalSerialize(self, write_bytes, deterministic=None):
1094 if deterministic
is None:
1096 api_implementation.IsPythonDefaultSerializationDeterministic())
1098 deterministic = bool(deterministic)
1100 descriptor = self.DESCRIPTOR
1101 if descriptor.GetOptions().map_entry:
1103 descriptor.fields_by_name[
'key']._encoder(
1104 write_bytes, self.key, deterministic)
1105 descriptor.fields_by_name[
'value']._encoder(
1106 write_bytes, self.value, deterministic)
1108 for field_descriptor, field_value
in self.ListFields():
1109 field_descriptor._encoder(write_bytes, field_value, deterministic)
1110 for tag_bytes, value_bytes
in self._unknown_fields:
1111 write_bytes(tag_bytes)
1112 write_bytes(value_bytes)
1113 cls._InternalSerialize = InternalSerialize
1117 """Helper for _AddMessageMethods()."""
1119 if isinstance(serialized, memoryview)
and six.PY2:
1121 'memoryview not supported in Python 2 with the pure Python proto '
1122 'implementation: this is to maintain compatibility with the C++ '
1125 serialized = memoryview(serialized)
1126 length =
len(serialized)
1128 if self._InternalParse(serialized, 0, length) != length:
1131 raise message_mod.DecodeError(
'Unexpected end-group tag.')
1132 except (IndexError, TypeError):
1134 raise message_mod.DecodeError(
'Truncated message.')
1135 except struct.error
as e:
1136 raise message_mod.DecodeError(e)
1138 cls.MergeFromString = MergeFromString
1140 local_ReadTag = decoder.ReadTag
1141 local_SkipField = decoder.SkipField
1142 decoders_by_tag = cls._decoders_by_tag
1144 def InternalParse(self, buffer, pos, end):
1145 """Create a message from serialized bytes.
1148 self: Message, instance of the proto message object.
1149 buffer: memoryview of the serialized data.
1150 pos: int, position to start in the serialized data.
1151 end: int, end position of the serialized data.
1158 assert isinstance(buffer, memoryview)
1160 field_dict = self._fields
1162 unknown_field_set = self._unknown_field_set
1164 (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
1165 field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (
None,
None))
1166 if field_decoder
is None:
1167 if not self._unknown_fields:
1168 self._unknown_fields = []
1169 if unknown_field_set
is None:
1173 unknown_field_set = self._unknown_field_set
1175 (tag, _) = decoder._DecodeVarint(tag_bytes, 0)
1176 field_number, wire_type = wire_format.UnpackTag(tag)
1179 (data, new_pos) = decoder._DecodeUnknownField(
1180 buffer, new_pos, wire_type)
1184 unknown_field_set._add(field_number, wire_type, data)
1186 new_pos = local_SkipField(buffer, old_pos, end, tag_bytes)
1189 self._unknown_fields.append(
1190 (tag_bytes, buffer[old_pos:new_pos].tobytes()))
1193 pos = field_decoder(buffer, new_pos, end, self, field_dict)
1195 self._UpdateOneofState(field_desc)
1197 cls._InternalParse = InternalParse
1201 """Adds the IsInitialized and FindInitializationError methods to the
1202 protocol message class."""
1204 required_fields = [field
for field
in message_descriptor.fields
1205 if field.label == _FieldDescriptor.LABEL_REQUIRED]
1208 """Checks if all required fields of a message are set.
1211 errors: A list which, if provided, will be populated with the field
1212 paths of all missing required fields.
1215 True iff the specified message has all required fields set.
1220 for field
in required_fields:
1221 if (field
not in self._fields
or
1222 (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
and
1223 not self._fields[field]._is_present_in_parent)):
1224 if errors
is not None:
1225 errors.extend(self.FindInitializationErrors())
1228 for field, value
in list(self._fields.items()):
1229 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
1230 if field.label == _FieldDescriptor.LABEL_REPEATED:
1231 if (field.message_type.has_options
and
1232 field.message_type.GetOptions().map_entry):
1234 for element
in value:
1235 if not element.IsInitialized():
1236 if errors
is not None:
1237 errors.extend(self.FindInitializationErrors())
1239 elif value._is_present_in_parent
and not value.IsInitialized():
1240 if errors
is not None:
1241 errors.extend(self.FindInitializationErrors())
1246 cls.IsInitialized = IsInitialized
1249 """Finds required fields which are not initialized.
1252 A list of strings. Each string is a path to an uninitialized field from
1253 the top-level message, e.g. "foo.bar[5].baz".
1258 for field
in required_fields:
1259 if not self.HasField(field.name):
1260 errors.append(field.name)
1262 for field, value
in self.ListFields():
1263 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
1264 if field.is_extension:
1265 name =
'(%s)' % field.full_name
1272 element = value[key]
1273 prefix =
'%s[%s].' % (name, key)
1274 sub_errors = element.FindInitializationErrors()
1275 errors += [prefix + error
for error
in sub_errors]
1279 elif field.label == _FieldDescriptor.LABEL_REPEATED:
1282 prefix =
'%s[%d].' % (name, i)
1283 sub_errors = element.FindInitializationErrors()
1284 errors += [prefix + error
for error
in sub_errors]
1287 sub_errors = value.FindInitializationErrors()
1288 errors += [prefix + error
for error
in sub_errors]
1292 cls.FindInitializationErrors = FindInitializationErrors
1296 LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
1297 CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
1300 if not isinstance(msg, cls):
1302 'Parameter to MergeFrom() must be instance of same class: '
1303 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__))
1305 assert msg
is not self
1308 fields = self._fields
1310 for field, value
in msg._fields.items():
1311 if field.label == LABEL_REPEATED:
1312 field_value = fields.get(field)
1313 if field_value
is None:
1315 field_value = field._default_constructor(self)
1316 fields[field] = field_value
1317 field_value.MergeFrom(value)
1318 elif field.cpp_type == CPPTYPE_MESSAGE:
1319 if value._is_present_in_parent:
1320 field_value = fields.get(field)
1321 if field_value
is None:
1323 field_value = field._default_constructor(self)
1324 fields[field] = field_value
1325 field_value.MergeFrom(value)
1327 self._fields[field] = value
1328 if field.containing_oneof:
1329 self._UpdateOneofState(field)
1331 if msg._unknown_fields:
1332 if not self._unknown_fields:
1333 self._unknown_fields = []
1334 self._unknown_fields.extend(msg._unknown_fields)
1336 if self._unknown_field_set
is None:
1338 self._unknown_field_set._extend(msg._unknown_field_set)
1340 cls.MergeFrom = MergeFrom
1345 """Returns the name of the currently set field inside a oneof, or None."""
1347 field = message_descriptor.oneofs_by_name[oneof_name]
1350 'Protocol message has no oneof "%s" field.' % oneof_name)
1352 nested_field = self._oneofs.get(field,
None)
1353 if nested_field
is not None and self.HasField(nested_field.name):
1354 return nested_field.name
1358 cls.WhichOneof = WhichOneof
1363 return (type(self), (), self.__getstate__())
1364 cls.__reduce__ = __reduce__
1370 self._unknown_fields = ()
1372 if self._unknown_field_set
is not None:
1373 self._unknown_field_set._clear()
1374 self._unknown_field_set =
None
1381 if self._unknown_field_set
is None:
1384 return self._unknown_field_set
1388 self._unknown_fields = []
1389 self._unknown_field_set =
None
1390 for field, value
in self.ListFields():
1391 if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
1396 elif field.label == _FieldDescriptor.LABEL_REPEATED:
1397 for sub_message
in value:
1398 sub_message.DiscardUnknownFields()
1400 value.DiscardUnknownFields()
1404 if listener
is None:
1405 self._listener = message_listener_mod.NullMessageListener()
1407 self._listener = listener
1411 """Adds implementations of all Message methods to cls."""
1415 if message_descriptor.is_extendable:
1432 cls.UnknownFields = _UnknownFields
1433 cls.DiscardUnknownFields = _DiscardUnknownFields
1434 cls._SetListener = _SetListener
1438 """Adds implementation of private helper methods to cls."""
1441 """Sets the _cached_byte_size_dirty bit to true,
1442 and propagates this to our listener iff this was a state change.
1449 if not self._cached_byte_size_dirty:
1450 self._cached_byte_size_dirty =
True
1451 self._listener_for_children.dirty =
True
1452 self._is_present_in_parent =
True
1453 self._listener.Modified()
1456 """Sets field as the active field in its containing oneof.
1458 Will also delete currently active field in the oneof, if it is different
1459 from the argument. Does not mark the message as modified.
1461 other_field = self._oneofs.setdefault(field.containing_oneof, field)
1462 if other_field
is not field:
1463 del self._fields[other_field]
1464 self._oneofs[field.containing_oneof] = field
1466 cls._Modified = Modified
1467 cls.SetInParent = Modified
1468 cls._UpdateOneofState = _UpdateOneofState
1473 """MessageListener implementation that a parent message registers with its
1476 In order to support semantics like:
1478 foo.bar.baz.qux = 23
1479 assert foo.HasField('bar')
1481 ...child objects must have back references to their parents.
1482 This helper class is at the heart of this support.
1487 parent_message: The message whose _Modified() method we should call when
1488 we receive Modified() messages.
1494 if isinstance(parent_message, weakref.ProxyType):
1510 except ReferenceError:
1518 """Special listener implementation for setting composite oneof fields."""
1522 parent_message: The message whose _Modified() method we should call when
1523 we receive Modified() messages.
1524 field: The descriptor of the field being set in the parent message.
1526 super(_OneofListener, self).
__init__(parent_message)
1530 """Also updates the state of the containing oneof in the parent message."""
1533 super(_OneofListener, self).
Modified()
1534 except ReferenceError: