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)# TODO(robinson): We should just make these methods all "pure-virtual" and move
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# all implementation out, into reflection.py for now.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Contains an abstract base class for protocol messages."""
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__author__ = 'robinson@google.com (Will Robinson)'
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Error(Exception): pass
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DecodeError(Error): pass
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EncodeError(Error): pass
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Message(object):
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Abstract base class for protocol messages.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Protocol message classes are almost always generated by the protocol
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  compiler.  These generated types subclass Message and implement the methods
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shown below.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TODO(robinson): Link to an HTML document here.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TODO(robinson): Document that instances of this class will also
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  have an Extensions attribute with __getitem__ and __setitem__.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Again, not sure how to best convey this.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TODO(robinson): Document that the class must also have a static
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegisterExtension(extension_field) method.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Not sure how to best express at this point.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(robinson): Document these fields and methods.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __slots__ = []
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DESCRIPTOR = None
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __deepcopy__(self, memo=None):
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clone = type(self)()
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clone.MergeFrom(self)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return clone
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other_msg):
763d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    """Recursively compares two messages by value and structure."""
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __ne__(self, other_msg):
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Can't just say self != other_msg, since that would infinitely recurse. :)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not self == other_msg
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __hash__(self):
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise TypeError('unhashable object')
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
873d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    """Outputs a human-readable representation of the message."""
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __unicode__(self):
913d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    """Outputs a human-readable representation of the message."""
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MergeFrom(self, other_msg):
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Merges the contents of the specified message into current message.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This method merges the contents of the specified message into the current
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message. Singular fields that are set in the specified message overwrite
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    the corresponding fields in the current message. Repeated fields are
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    appended. Singular sub-messages and groups are recursively merged.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_msg: Message to merge into the current message.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def CopyFrom(self, other_msg):
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Copies the content of the specified message into the current message.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The method clears the current message and then merges the specified
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message using MergeFrom.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_msg: Message to copy into the current one.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self is other_msg:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Clear()
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.MergeFrom(other_msg)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Clear(self):
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Clears all data that was set in the message."""
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetInParent(self):
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Mark this as present in the parent.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This normally happens automatically when you assign a field of a
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sub-message, but sometimes you want to make the sub-message
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    present while keeping it empty.  If you find yourself using this,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    you may want to reconsider your design."""
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def IsInitialized(self):
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks if the message is initialized.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The method returns True if the message is initialized (i.e. all of its
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      required fields are set).
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(robinson): MergeFromString() should probably return None and be
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # implemented in terms of a helper that returns the # of bytes read.  Our
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # deserialization routines would use the helper when recursively
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # deserializing, but the end user would almost always just want the no-return
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # MergeFromString().
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MergeFromString(self, serialized):
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Merges serialized protocol buffer data into this message.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    When we find a field in |serialized| that is already present
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in this message:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      - If it's a "repeated" field, we append to the end of our list.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      - Else, if it's a scalar, we overwrite our field.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      - Else, (it's a nonrepeated composite), we recursively merge
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        into the existing composite.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TODO(robinson): Document handling of unknown fields.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      serialized: Any object that allows us to call buffer(serialized)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to access a string of bytes using the buffer interface.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TODO(robinson): When we switch to a helper, this will return None.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The number of bytes read from |serialized|.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      For non-group messages, this will always be len(serialized),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      but for messages which are actually groups, this will
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generally be less than len(serialized), since we must
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stop when we reach an END_GROUP tag.  Note that if
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      we *do* stop because of an END_GROUP tag, the number
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      of bytes returned does not include the bytes
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for the END_GROUP tag information.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ParseFromString(self, serialized):
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Like MergeFromString(), except we clear the object first."""
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Clear()
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.MergeFromString(serialized)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SerializeToString(self):
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Serializes the protocol message to a binary string.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      A binary string representation of the message if all of the required
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fields in the message are set (i.e. the message is initialized).
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Raises:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message.EncodeError if the message isn't initialized.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SerializePartialToString(self):
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Serializes the protocol message to a binary string.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This method is similar to SerializeToString but doesn't check if the
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message is initialized.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      A string representation of the partial message.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(robinson): Decide whether we like these better
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # than auto-generated has_foo() and clear_foo() methods
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # on the instances themselves.  This way is less consistent
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # with C++, but it makes reflection-type access easier and
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # reduces the number of magically autogenerated things.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(robinson): Be sure to document (and test) exactly
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # which field names are accepted here.  Are we case-sensitive?
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # What do we do with fields that share names with Python keywords
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # like 'lambda' and 'yield'?
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # nnorwitz says:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # """
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Typically (in python), an underscore is appended to names that are
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # keywords. So they would become lambda_ or yield_.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # """
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ListFields(self):
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns a list of (FieldDescriptor, value) tuples for all
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields in the message which are not empty.  A singular field is non-empty
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if HasField() would return true, and a repeated field is non-empty if
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it contains at least one element.  The fields are ordered by field
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    number"""
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def HasField(self, field_name):
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks if a certain field is set for the message. Note if the
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_name is not defined in the message descriptor, ValueError will be
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raised."""
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ClearField(self, field_name):
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def HasExtension(self, extension_handle):
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ClearExtension(self, extension_handle):
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ByteSize(self):
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns the serialized size of this message.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Recursively calls ByteSize() on all contained messages.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _SetListener(self, message_listener):
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Internal method used by the protocol message implementation.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Clients should not call this directly.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Sets a listener that this message will call on certain state transitions.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The purpose of this method is to register back-edges from children to
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parents at runtime, for the purpose of setting "has" bits and
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    byte-size-dirty bits in the parent and ancestor objects whenever a child or
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    descendant object is modified.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    If the client wants to disconnect this Message from the object tree, she
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicitly sets callback to None.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    If message_listener is None, unregisters any existing listener.  Otherwise,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_listener must implement the MessageListener interface in
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal/message_listener.py, and we discard any listener registered
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    via a previous _SetListener() call.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise NotImplementedError
2723d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
2733d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  def __getstate__(self):
2743d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    """Support the pickle protocol."""
2753d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    return dict(serialized=self.SerializePartialToString())
2763d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
2773d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  def __setstate__(self, state):
2783d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    """Support the pickle protocol."""
2793d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    self.__init__()
2803d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    self.ParseFromString(state['serialized'])
281