15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Contains helper functions used to create protocol message classes from
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Descriptor objects at runtime backed by the protocol buffer C++ API.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__author__ = 'petar@google.com (Petar Petrov)'
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochimport copy_reg
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import operator
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from google.protobuf.internal import _net_proto2___python
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochfrom google.protobuf.internal import enum_type_wrapper
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from google.protobuf import message
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_LABEL_REPEATED = _net_proto2___python.LABEL_REPEATED
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_LABEL_OPTIONAL = _net_proto2___python.LABEL_OPTIONAL
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_CPPTYPE_MESSAGE = _net_proto2___python.CPPTYPE_MESSAGE
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_TYPE_MESSAGE = _net_proto2___python.TYPE_MESSAGE
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetDescriptorPool():
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates a new DescriptorPool C++ object."""
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _net_proto2___python.NewCDescriptorPool()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_pool = GetDescriptorPool()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetFieldDescriptor(full_field_name):
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Searches for a field descriptor given a full field name."""
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _pool.FindFieldByName(full_field_name)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def BuildFile(content):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Registers a new proto file in the underlying C++ descriptor pool."""
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _net_proto2___python.BuildFile(content)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetExtensionDescriptor(full_extension_name):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Searches for extension descriptor given a full field name."""
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _pool.FindExtensionByName(full_extension_name)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def NewCMessage(full_message_name):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates a new C++ protocol message by its name."""
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _net_proto2___python.NewCMessage(full_message_name)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ScalarProperty(cdescriptor):
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a scalar property for the given descriptor."""
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Getter(self):
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.GetScalar(cdescriptor)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Setter(self, value):
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.SetScalar(cdescriptor, value)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return property(Getter, Setter)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CompositeProperty(cdescriptor, message_type):
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a Python property the given composite field."""
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Getter(self):
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sub_message = self._composite_fields.get(cdescriptor.name, None)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if sub_message is None:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmessage = self._cmsg.NewSubMessage(cdescriptor)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sub_message = message_type._concrete_class(__cmessage=cmessage)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._composite_fields[cdescriptor.name] = sub_message
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sub_message
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return property(Getter)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RepeatedScalarContainer(object):
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Container for repeated scalar fields."""
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __slots__ = ['_message', '_cfield_descriptor', '_cmsg']
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, msg, cfield_descriptor):
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._message = msg
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg = msg._cmsg
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cfield_descriptor = cfield_descriptor
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def append(self, value):
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.AddRepeatedScalar(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._cfield_descriptor, value)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def extend(self, sequence):
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for element in sequence:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.append(element)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def insert(self, key, value):
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values = self[slice(None, None, None)]
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values.insert(key, value)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def remove(self, value):
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values = self[slice(None, None, None)]
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values.remove(value)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __setitem__(self, key, value):
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values = self[slice(None, None, None)]
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values[key] = value
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __getitem__(self, key):
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.GetRepeatedScalar(self._cfield_descriptor, key)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __delitem__(self, key):
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.DeleteRepeatedField(self._cfield_descriptor, key)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __len__(self):
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return len(self[slice(None, None, None)])
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other):
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self is other:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not operator.isSequenceType(other):
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise TypeError(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          'Can only compare repeated scalar fields against sequences.')
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We are presumably comparing against some other sequence type.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return other == self[slice(None, None, None)]
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __ne__(self, other):
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not self == other
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __hash__(self):
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise TypeError('unhashable object')
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  def sort(self, *args, **kwargs):
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # Maintain compatibility with the previous interface.
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if 'sort_function' in kwargs:
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      kwargs['cmp'] = kwargs.pop('sort_function')
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor,
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                    sorted(self, *args, **kwargs))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RepeatedScalarProperty(cdescriptor):
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a Python property the given repeated scalar field."""
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Getter(self):
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    container = self._composite_fields.get(cdescriptor.name, None)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if container is None:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container = RepeatedScalarContainer(self, cdescriptor)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._composite_fields[cdescriptor.name] = container
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return container
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Setter(self, new_value):
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise AttributeError('Assignment not allowed to repeated field '
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         '"%s" in protocol message object.' % cdescriptor.name)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return property(Getter, Setter, doc=doc)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RepeatedCompositeContainer(object):
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Container for repeated composite fields."""
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __slots__ = ['_message', '_subclass', '_cfield_descriptor', '_cmsg']
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, msg, cfield_descriptor, subclass):
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._message = msg
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg = msg._cmsg
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._subclass = subclass
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cfield_descriptor = cfield_descriptor
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def add(self, **kwargs):
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmessage = self._cmsg.AddMessage(self._cfield_descriptor)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._subclass(__cmessage=cmessage, __owner=self._message, **kwargs)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def extend(self, elem_seq):
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Extends by appending the given sequence of elements of the same type
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    as this one, copying each individual message.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for message in elem_seq:
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.add().MergeFrom(message)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  def remove(self, value):
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # TODO(protocol-devel): This is inefficient as it needs to generate a
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # message pointer for each message only to do index().  Move this to a C++
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # extension function.
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    self.__delitem__(self[slice(None, None, None)].index(value))
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MergeFrom(self, other):
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for message in other[:]:
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.add().MergeFrom(message)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __getitem__(self, key):
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmessages = self._cmsg.GetRepeatedMessage(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._cfield_descriptor, key)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subclass = self._subclass
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(cmessages, list):
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return subclass(__cmessage=cmessages, __owner=self._message)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return [subclass(__cmessage=m, __owner=self._message) for m in cmessages]
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __delitem__(self, key):
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.DeleteRepeatedField(
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._cfield_descriptor, key)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __len__(self):
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.FieldLength(self._cfield_descriptor)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other):
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Compares the current instance with another one."""
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self is other:
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(other, self.__class__):
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise TypeError('Can only compare repeated composite fields against '
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      'other repeated composite fields.')
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    messages = self[slice(None, None, None)]
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other_messages = other[slice(None, None, None)]
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return messages == other_messages
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __hash__(self):
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise TypeError('unhashable object')
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  def sort(self, cmp=None, key=None, reverse=False, **kwargs):
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # Maintain compatibility with the old interface.
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if cmp is None and 'sort_function' in kwargs:
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      cmp = kwargs.pop('sort_function')
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # The cmp function, if provided, is passed the results of the key function,
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # so we only need to wrap one of them.
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if key is None:
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      index_key = self.__getitem__
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else:
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      index_key = lambda i: key(self[i])
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # Sort the list of current indexes by the underlying object.
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    indexes = range(len(self))
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    indexes.sort(cmp=cmp, key=index_key, reverse=reverse)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Apply the transposition.
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for dest, src in enumerate(indexes):
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if dest == src:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self._cmsg.SwapRepeatedFieldElements(self._cfield_descriptor, dest, src)
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # Don't swap the same value twice.
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      indexes[src] = src
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RepeatedCompositeProperty(cdescriptor, message_type):
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a Python property for the given repeated composite field."""
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Getter(self):
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    container = self._composite_fields.get(cdescriptor.name, None)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if container is None:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container = RepeatedCompositeContainer(
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          self, cdescriptor, message_type._concrete_class)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._composite_fields[cdescriptor.name] = container
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return container
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Setter(self, new_value):
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise AttributeError('Assignment not allowed to repeated field '
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         '"%s" in protocol message object.' % cdescriptor.name)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return property(Getter, Setter, doc=doc)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionDict(object):
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Extension dictionary added to each protocol message."""
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, msg):
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._message = msg
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg = msg._cmsg
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._values = {}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __setitem__(self, extension, value):
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    from google.protobuf import descriptor
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(extension, descriptor.FieldDescriptor):
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise KeyError('Bad extension %r.' % (extension,))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cdescriptor = extension._cdescriptor
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cdescriptor.label != _LABEL_OPTIONAL or
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise TypeError('Extension %r is repeated and/or a composite type.' % (
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension.full_name,))
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.SetScalar(cdescriptor, value)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._values[extension] = value
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __getitem__(self, extension):
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    from google.protobuf import descriptor
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(extension, descriptor.FieldDescriptor):
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise KeyError('Bad extension %r.' % (extension,))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cdescriptor = extension._cdescriptor
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cdescriptor.label != _LABEL_REPEATED and
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cdescriptor.cpp_type != _CPPTYPE_MESSAGE):
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return self._cmsg.GetScalar(cdescriptor)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext = self._values.get(extension, None)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ext is not None:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ext
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext = self._CreateNewHandle(extension)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._values[extension] = ext
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ext
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ClearExtension(self, extension):
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    from google.protobuf import descriptor
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(extension, descriptor.FieldDescriptor):
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise KeyError('Bad extension %r.' % (extension,))
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.ClearFieldByDescriptor(extension._cdescriptor)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if extension in self._values:
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      del self._values[extension]
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def HasExtension(self, extension):
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    from google.protobuf import descriptor
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(extension, descriptor.FieldDescriptor):
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise KeyError('Bad extension %r.' % (extension,))
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.HasFieldByDescriptor(extension._cdescriptor)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _FindExtensionByName(self, name):
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Tries to find a known extension with the specified name.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name: Extension full name.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Extension field descriptor.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._message._extensions_by_name.get(name, None)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _CreateNewHandle(self, extension):
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cdescriptor = extension._cdescriptor
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cdescriptor.label != _LABEL_REPEATED and
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmessage = self._cmsg.NewSubMessage(cdescriptor)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return extension.message_type._concrete_class(__cmessage=cmessage)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if cdescriptor.label == _LABEL_REPEATED:
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return RepeatedCompositeContainer(
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self._message, cdescriptor, extension.message_type._concrete_class)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return RepeatedScalarContainer(self._message, cdescriptor)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # This shouldn't happen!
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert False
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochdef NewMessage(bases, message_descriptor, dictionary):
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates a new protocol message *class*."""
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddClassAttributesForNestedExtensions(message_descriptor, dictionary)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddEnumValues(message_descriptor, dictionary)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddDescriptors(message_descriptor, dictionary)
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return bases
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def InitMessage(message_descriptor, cls):
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Constructs a new message instance (called before instance's __init__)."""
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cls._extensions_by_name = {}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddInitMethod(message_descriptor, cls)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddMessageMethods(message_descriptor, cls)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _AddPropertiesForExtensions(message_descriptor, cls)
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddDescriptors(message_descriptor, dictionary):
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Sets up a new protocol message class dictionary.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_descriptor: A Descriptor instance describing this message type.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary: Class dictionary to which we'll add a '__slots__' entry.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary['__descriptors'] = {}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for field in message_descriptor.fields:
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary['__descriptors'][field.name] = GetFieldDescriptor(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field.full_name)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary['__slots__'] = list(dictionary['__descriptors'].iterkeys()) + [
404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      '_cmsg', '_owner', '_composite_fields', 'Extensions', '_HACK_REFCOUNTS']
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddEnumValues(message_descriptor, dictionary):
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Sets class-level attributes for all enum fields defined in this message.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_descriptor: Descriptor object for this message type.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary: Class dictionary that should be populated.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for enum_type in message_descriptor.enum_types:
415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    dictionary[enum_type.name] = enum_type_wrapper.EnumTypeWrapper(enum_type)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for enum_value in enum_type.values:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dictionary[enum_value.name] = enum_value.number
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddClassAttributesForNestedExtensions(message_descriptor, dictionary):
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Adds class attributes for the nested extensions."""
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_dict = message_descriptor.extensions_by_name
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for extension_name, extension_field in extension_dict.iteritems():
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert extension_name not in dictionary
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary[extension_name] = extension_field
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddInitMethod(message_descriptor, cls):
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Adds an __init__ method to cls."""
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Create and attach message field properties to the message class.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # This can be done just once per message class, since property setters and
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # getters are passed the message instance.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # This makes message instantiation extremely fast, and at the same time it
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # doesn't require the creation of property objects for each message instance,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # which saves a lot of memory.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for field in message_descriptor.fields:
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_cdescriptor = cls.__descriptors[field.name]
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if field.label == _LABEL_REPEATED:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if field.cpp_type == _CPPTYPE_MESSAGE:
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = RepeatedCompositeProperty(field_cdescriptor, field.message_type)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value = RepeatedScalarProperty(field_cdescriptor)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif field.cpp_type == _CPPTYPE_MESSAGE:
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value = CompositeProperty(field_cdescriptor, field.message_type)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value = ScalarProperty(field_cdescriptor)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setattr(cls, field.name, value)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Attach a constant with the field number.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    constant_name = field.name.upper() + '_FIELD_NUMBER'
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setattr(cls, constant_name, field.number)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Init(self, **kwargs):
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Message constructor."""
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmessage = kwargs.pop('__cmessage', None)
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if cmessage:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._cmsg = cmessage
459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else:
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self._cmsg = NewCMessage(message_descriptor.full_name)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Keep a reference to the owner, as the owner keeps a reference to the
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # underlying protocol buffer message.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owner = kwargs.pop('__owner', None)
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if owner:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._owner = owner
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if message_descriptor.is_extendable:
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self.Extensions = ExtensionDict(self)
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else:
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # Reference counting in the C++ code is broken and depends on
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # the Extensions reference to keep this object alive during unit
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # tests (see b/4856052).  Remove this once b/4945904 is fixed.
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self._HACK_REFCOUNTS = self
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._composite_fields = {}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for field_name, field_value in kwargs.iteritems():
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_cdescriptor = self.__descriptors.get(field_name, None)
479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if not field_cdescriptor:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise ValueError('Protocol message has no "%s" field.' % field_name)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if field_cdescriptor.label == _LABEL_REPEATED:
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          field_name = getattr(self, field_name)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          for val in field_value:
485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            field_name.add().MergeFrom(val)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          getattr(self, field_name).extend(field_value)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        getattr(self, field_name).MergeFrom(field_value)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setattr(self, field_name, field_value)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init.__module__ = None
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init.__doc__ = None
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cls.__init__ = Init
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _IsMessageSetExtension(field):
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Checks if a field is a message set extension."""
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (field.is_extension and
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field.containing_type.has_options and
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field.containing_type.GetOptions().message_set_wire_format and
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field.type == _TYPE_MESSAGE and
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field.message_type == field.extension_scope and
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field.label == _LABEL_OPTIONAL)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddMessageMethods(message_descriptor, cls):
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Adds the methods to a protocol message class."""
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if message_descriptor.is_extendable:
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ClearExtension(self, extension):
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.Extensions.ClearExtension(extension)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def HasExtension(self, extension):
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return self.Extensions.HasExtension(extension)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def HasField(self, field_name):
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.HasField(field_name)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ClearField(self, field_name):
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    child_cmessage = None
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if field_name in self._composite_fields:
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      child_field = self._composite_fields[field_name]
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      del self._composite_fields[field_name]
526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      child_cdescriptor = self.__descriptors[field_name]
528ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # TODO(anuraag): Support clearing repeated message fields as well.
529ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (child_cdescriptor.label != _LABEL_REPEATED and
530ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        child_field._owner = None
532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        child_cmessage = child_field._cmsg
533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if child_cmessage is not None:
535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self._cmsg.ClearField(field_name, child_cmessage)
536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else:
537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      self._cmsg.ClearField(field_name)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Clear(self):
540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    cmessages_to_release = []
541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for field_name, child_field in self._composite_fields.iteritems():
542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      child_cdescriptor = self.__descriptors[field_name]
543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      # TODO(anuraag): Support clearing repeated message fields as well.
544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (child_cdescriptor.label != _LABEL_REPEATED and
545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        child_field._owner = None
547ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        cmessages_to_release.append((child_cdescriptor, child_field._cmsg))
548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    self._composite_fields.clear()
549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    self._cmsg.Clear(cmessages_to_release)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def IsInitialized(self, errors=None):
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._cmsg.IsInitialized():
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if errors is not None:
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors.extend(self.FindInitializationErrors());
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return False
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SerializeToString(self):
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not self.IsInitialized():
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise message.EncodeError(
561ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          'Message %s is missing required fields: %s' % (
562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          self._cmsg.full_name, ','.join(self.FindInitializationErrors())))
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.SerializeToString()
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SerializePartialToString(self):
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.SerializePartialToString()
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ParseFromString(self, serialized):
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Clear()
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.MergeFromString(serialized)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MergeFromString(self, serialized):
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    byte_size = self._cmsg.MergeFromString(serialized)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if byte_size < 0:
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise message.DecodeError('Unable to merge from string.')
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return byte_size
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MergeFrom(self, msg):
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(msg, cls):
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise TypeError(
581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          "Parameter to MergeFrom() must be instance of same class: "
582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          "expected %s got %s." % (cls.__name__, type(msg).__name__))
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.MergeFrom(msg._cmsg)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def CopyFrom(self, msg):
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._cmsg.CopyFrom(msg._cmsg)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ByteSize(self):
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.ByteSize()
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetInParent(self):
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.SetInParent()
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ListFields(self):
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    all_fields = []
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_list = self._cmsg.ListFields()
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields_by_name = cls.DESCRIPTOR.fields_by_name
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for is_extension, field_name in field_list:
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if is_extension:
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension = cls._extensions_by_name[field_name]
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all_fields.append((extension, self.Extensions[extension]))
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_descriptor = fields_by_name[field_name]
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all_fields.append(
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (field_descriptor, getattr(self, field_name)))
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    all_fields.sort(key=lambda item: item[0].number)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return all_fields
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def FindInitializationErrors(self):
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.FindInitializationErrors()
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._cmsg.DebugString()
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other):
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self is other:
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not isinstance(other, self.__class__):
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return False
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.ListFields() == other.ListFields()
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __ne__(self, other):
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not self == other
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __hash__(self):
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise TypeError('unhashable object')
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __unicode__(self):
629ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    # Lazy import to prevent circular import when text_format imports this file.
630ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    from google.protobuf import text_format
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Attach the local methods to the message class.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for key, value in locals().copy().iteritems():
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if key not in ('key', 'value', '__builtins__', '__name__', '__doc__'):
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setattr(cls, key, value)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Static methods:
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def RegisterExtension(extension_handle):
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_handle.containing_type = cls.DESCRIPTOR
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cls._extensions_by_name[extension_handle.full_name] = extension_handle
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if _IsMessageSetExtension(extension_handle):
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # MessageSet extension.  Also register under type name.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cls._extensions_by_name[
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_handle.message_type.full_name] = extension_handle
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cls.RegisterExtension = staticmethod(RegisterExtension)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def FromString(string):
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg = cls()
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg.MergeFromString(string)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return msg
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cls.FromString = staticmethod(FromString)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _AddPropertiesForExtensions(message_descriptor, cls):
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Adds properties for all fields in this protocol message type."""
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_dict = message_descriptor.extensions_by_name
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for extension_name, extension_field in extension_dict.iteritems():
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    constant_name = extension_name.upper() + '_FIELD_NUMBER'
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setattr(cls, constant_name, extension_field.number)
664