1# Protocol Buffers - Google's data interchange format 
    2# Copyright 2008 Google Inc.  All rights reserved. 
    3# 
    4# Use of this source code is governed by a BSD-style 
    5# license that can be found in the LICENSE file or at 
    6# https://developers.google.com/open-source/licenses/bsd 
    7 
    8# TODO: We should just make these methods all "pure-virtual" and move 
    9# all implementation out, into reflection.py for now. 
    10 
    11 
    12"""Contains an abstract base class for protocol messages.""" 
    13 
    14__author__ = 'robinson@google.com (Will Robinson)' 
    15 
    16_INCONSISTENT_MESSAGE_ATTRIBUTES = ('Extensions',) 
    17 
    18 
    19class Error(Exception): 
    20  """Base error type for this module.""" 
    21  pass 
    22 
    23 
    24class DecodeError(Error): 
    25  """Exception raised when deserializing messages.""" 
    26  pass 
    27 
    28 
    29class EncodeError(Error): 
    30  """Exception raised when serializing messages.""" 
    31  pass 
    32 
    33 
    34class Message(object): 
    35 
    36  """Abstract base class for protocol messages. 
    37 
    38  Protocol message classes are almost always generated by the protocol 
    39  compiler.  These generated types subclass Message and implement the methods 
    40  shown below. 
    41  """ 
    42 
    43  # TODO: Link to an HTML document here. 
    44 
    45  # TODO: Document that instances of this class will also 
    46  # have an Extensions attribute with __getitem__ and __setitem__. 
    47  # Again, not sure how to best convey this. 
    48 
    49  # TODO: Document these fields and methods. 
    50 
    51  __slots__ = [] 
    52 
    53  #: The :class:`google.protobuf.Descriptor` 
    54  # for this message type. 
    55  DESCRIPTOR = None 
    56 
    57  def __deepcopy__(self, memo=None): 
    58    clone = type(self)() 
    59    clone.MergeFrom(self) 
    60    return clone 
    61 
    62  def __dir__(self): 
    63    """Provides the list of all accessible Message attributes.""" 
    64    message_attributes = set(super().__dir__()) 
    65 
    66    # TODO: Remove this once the UPB implementation is improved. 
    67    # The UPB proto implementation currently doesn't provide proto fields as 
    68    # attributes and they have to added. 
    69    if self.DESCRIPTOR is not None: 
    70      for field in self.DESCRIPTOR.fields: 
    71        message_attributes.add(field.name) 
    72 
    73    # The Fast C++ proto implementation provides inaccessible attributes that 
    74    # have to be removed. 
    75    for attribute in _INCONSISTENT_MESSAGE_ATTRIBUTES: 
    76      if attribute not in message_attributes: 
    77        continue 
    78      try: 
    79        getattr(self, attribute) 
    80      except AttributeError: 
    81        message_attributes.remove(attribute) 
    82 
    83    return sorted(message_attributes) 
    84 
    85  def __eq__(self, other_msg): 
    86    """Recursively compares two messages by value and structure.""" 
    87    raise NotImplementedError 
    88 
    89  def __ne__(self, other_msg): 
    90    # Can't just say self != other_msg, since that would infinitely recurse. :) 
    91    return not self == other_msg 
    92 
    93  def __hash__(self): 
    94    raise TypeError('unhashable object') 
    95 
    96  def __str__(self): 
    97    """Outputs a human-readable representation of the message.""" 
    98    raise NotImplementedError 
    99 
    100  def __unicode__(self): 
    101    """Outputs a human-readable representation of the message.""" 
    102    raise NotImplementedError 
    103 
    104  def __contains__(self, field_name_or_key): 
    105    """Checks if a certain field is set for the message. 
    106 
    107    Has presence fields return true if the field is set, false if the field is 
    108    not set. Fields without presence do raise `ValueError` (this includes 
    109    repeated fields, map fields, and implicit presence fields). 
    110 
    111    If field_name is not defined in the message descriptor, `ValueError` will 
    112    be raised. 
    113    Note: WKT Struct checks if the key is contained in fields. ListValue checks 
    114    if the item is contained in the list. 
    115 
    116    Args: 
    117      field_name_or_key: For Struct, the key (str) of the fields map. For 
    118        ListValue, any type that may be contained in the list. For other 
    119        messages, name of the field (str) to check for presence. 
    120 
    121    Returns: 
    122      bool: For Struct, whether the item is contained in fields. For ListValue, 
    123            whether the item is contained in the list. For other message, 
    124            whether a value has been set for the named field. 
    125 
    126    Raises: 
    127      ValueError: For normal messages,  if the `field_name_or_key` is not a 
    128                  member of this message or `field_name_or_key` is not a string. 
    129    """ 
    130    raise NotImplementedError 
    131 
    132  def MergeFrom(self, other_msg): 
    133    """Merges the contents of the specified message into current message. 
    134 
    135    This method merges the contents of the specified message into the current 
    136    message. Singular fields that are set in the specified message overwrite 
    137    the corresponding fields in the current message. Repeated fields are 
    138    appended. Singular sub-messages and groups are recursively merged. 
    139 
    140    Args: 
    141      other_msg (Message): A message to merge into the current message. 
    142    """ 
    143    raise NotImplementedError 
    144 
    145  def CopyFrom(self, other_msg): 
    146    """Copies the content of the specified message into the current message. 
    147 
    148    The method clears the current message and then merges the specified 
    149    message using MergeFrom. 
    150 
    151    Args: 
    152      other_msg (Message): A message to copy into the current one. 
    153    """ 
    154    if self is other_msg: 
    155      return 
    156    self.Clear() 
    157    self.MergeFrom(other_msg) 
    158 
    159  def Clear(self): 
    160    """Clears all data that was set in the message.""" 
    161    raise NotImplementedError 
    162 
    163  def SetInParent(self): 
    164    """Mark this as present in the parent. 
    165 
    166    This normally happens automatically when you assign a field of a 
    167    sub-message, but sometimes you want to make the sub-message 
    168    present while keeping it empty.  If you find yourself using this, 
    169    you may want to reconsider your design. 
    170    """ 
    171    raise NotImplementedError 
    172 
    173  def IsInitialized(self): 
    174    """Checks if the message is initialized. 
    175 
    176    Returns: 
    177      bool: The method returns True if the message is initialized (i.e. all of 
    178      its required fields are set). 
    179    """ 
    180    raise NotImplementedError 
    181 
    182  # TODO: MergeFromString() should probably return None and be 
    183  # implemented in terms of a helper that returns the # of bytes read.  Our 
    184  # deserialization routines would use the helper when recursively 
    185  # deserializing, but the end user would almost always just want the no-return 
    186  # MergeFromString(). 
    187 
    188  def MergeFromString(self, serialized): 
    189    """Merges serialized protocol buffer data into this message. 
    190 
    191    When we find a field in `serialized` that is already present 
    192    in this message: 
    193 
    194    -   If it's a "repeated" field, we append to the end of our list. 
    195    -   Else, if it's a scalar, we overwrite our field. 
    196    -   Else, (it's a nonrepeated composite), we recursively merge 
    197        into the existing composite. 
    198 
    199    Args: 
    200      serialized (bytes): Any object that allows us to call 
    201        ``memoryview(serialized)`` to access a string of bytes using the 
    202        buffer interface. 
    203 
    204    Returns: 
    205      int: The number of bytes read from `serialized`. 
    206      For non-group messages, this will always be `len(serialized)`, 
    207      but for messages which are actually groups, this will 
    208      generally be less than `len(serialized)`, since we must 
    209      stop when we reach an ``END_GROUP`` tag.  Note that if 
    210      we *do* stop because of an ``END_GROUP`` tag, the number 
    211      of bytes returned does not include the bytes 
    212      for the ``END_GROUP`` tag information. 
    213 
    214    Raises: 
    215      DecodeError: if the input cannot be parsed. 
    216    """ 
    217    # TODO: Document handling of unknown fields. 
    218    # TODO: When we switch to a helper, this will return None. 
    219    raise NotImplementedError 
    220 
    221  def ParseFromString(self, serialized): 
    222    """Parse serialized protocol buffer data in binary form into this message. 
    223 
    224    Like :func:`MergeFromString()`, except we clear the object first. 
    225 
    226    Raises: 
    227      message.DecodeError if the input cannot be parsed. 
    228    """ 
    229    self.Clear() 
    230    return self.MergeFromString(serialized) 
    231 
    232  def SerializeToString(self, **kwargs): 
    233    """Serializes the protocol message to a binary string. 
    234 
    235    Keyword Args: 
    236      deterministic (bool): If true, requests deterministic serialization 
    237        of the protobuf, with predictable ordering of map keys. 
    238 
    239    Returns: 
    240      A binary string representation of the message if all of the required 
    241      fields in the message are set (i.e. the message is initialized). 
    242 
    243    Raises: 
    244      EncodeError: if the message isn't initialized (see :func:`IsInitialized`). 
    245    """ 
    246    raise NotImplementedError 
    247 
    248  def SerializePartialToString(self, **kwargs): 
    249    """Serializes the protocol message to a binary string. 
    250 
    251    This method is similar to SerializeToString but doesn't check if the 
    252    message is initialized. 
    253 
    254    Keyword Args: 
    255      deterministic (bool): If true, requests deterministic serialization 
    256        of the protobuf, with predictable ordering of map keys. 
    257 
    258    Returns: 
    259      bytes: A serialized representation of the partial message. 
    260    """ 
    261    raise NotImplementedError 
    262 
    263  # TODO: Decide whether we like these better 
    264  # than auto-generated has_foo() and clear_foo() methods 
    265  # on the instances themselves.  This way is less consistent 
    266  # with C++, but it makes reflection-type access easier and 
    267  # reduces the number of magically autogenerated things. 
    268  # 
    269  # TODO: Be sure to document (and test) exactly 
    270  # which field names are accepted here.  Are we case-sensitive? 
    271  # What do we do with fields that share names with Python keywords 
    272  # like 'lambda' and 'yield'? 
    273  # 
    274  # nnorwitz says: 
    275  # """ 
    276  # Typically (in python), an underscore is appended to names that are 
    277  # keywords. So they would become lambda_ or yield_. 
    278  # """ 
    279  def ListFields(self): 
    280    """Returns a list of (FieldDescriptor, value) tuples for present fields. 
    281 
    282    A message field is non-empty if HasField() would return true. A singular 
    283    primitive field is non-empty if HasField() would return true in proto2 or it 
    284    is non zero in proto3. A repeated field is non-empty if it contains at least 
    285    one element. The fields are ordered by field number. 
    286 
    287    Returns: 
    288      list[tuple(FieldDescriptor, value)]: field descriptors and values 
    289      for all fields in the message which are not empty. The values vary by 
    290      field type. 
    291    """ 
    292    raise NotImplementedError 
    293 
    294  def HasField(self, field_name): 
    295    """Checks if a certain field is set for the message. 
    296 
    297    For a oneof group, checks if any field inside is set. Note that if the 
    298    field_name is not defined in the message descriptor, :exc:`ValueError` will 
    299    be raised. 
    300 
    301    Args: 
    302      field_name (str): The name of the field to check for presence. 
    303 
    304    Returns: 
    305      bool: Whether a value has been set for the named field. 
    306 
    307    Raises: 
    308      ValueError: if the `field_name` is not a member of this message. 
    309    """ 
    310    raise NotImplementedError 
    311 
    312  def ClearField(self, field_name): 
    313    """Clears the contents of a given field. 
    314 
    315    Inside a oneof group, clears the field set. If the name neither refers to a 
    316    defined field or oneof group, :exc:`ValueError` is raised. 
    317 
    318    Args: 
    319      field_name (str): The name of the field to check for presence. 
    320 
    321    Raises: 
    322      ValueError: if the `field_name` is not a member of this message. 
    323    """ 
    324    raise NotImplementedError 
    325 
    326  def WhichOneof(self, oneof_group): 
    327    """Returns the name of the field that is set inside a oneof group. 
    328 
    329    If no field is set, returns None. 
    330 
    331    Args: 
    332      oneof_group (str): the name of the oneof group to check. 
    333 
    334    Returns: 
    335      str or None: The name of the group that is set, or None. 
    336 
    337    Raises: 
    338      ValueError: no group with the given name exists 
    339    """ 
    340    raise NotImplementedError 
    341 
    342  def HasExtension(self, field_descriptor): 
    343    """Checks if a certain extension is present for this message. 
    344 
    345    Extensions are retrieved using the :attr:`Extensions` mapping (if present). 
    346 
    347    Args: 
    348      field_descriptor: The field descriptor for the extension to check. 
    349 
    350    Returns: 
    351      bool: Whether the extension is present for this message. 
    352 
    353    Raises: 
    354      KeyError: if the extension is repeated. Similar to repeated fields, 
    355        there is no separate notion of presence: a "not present" repeated 
    356        extension is an empty list. 
    357    """ 
    358    raise NotImplementedError 
    359 
    360  def ClearExtension(self, field_descriptor): 
    361    """Clears the contents of a given extension. 
    362 
    363    Args: 
    364      field_descriptor: The field descriptor for the extension to clear. 
    365    """ 
    366    raise NotImplementedError 
    367 
    368  def UnknownFields(self): 
    369    """Returns the UnknownFieldSet. 
    370 
    371    Returns: 
    372      UnknownFieldSet: The unknown fields stored in this message. 
    373    """ 
    374    raise NotImplementedError 
    375 
    376  def DiscardUnknownFields(self): 
    377    """Clears all fields in the :class:`UnknownFieldSet`. 
    378 
    379    This operation is recursive for nested message. 
    380    """ 
    381    raise NotImplementedError 
    382 
    383  def ByteSize(self): 
    384    """Returns the serialized size of this message. 
    385 
    386    Recursively calls ByteSize() on all contained messages. 
    387 
    388    Returns: 
    389      int: The number of bytes required to serialize this message. 
    390    """ 
    391    raise NotImplementedError 
    392 
    393  @classmethod 
    394  def FromString(cls, s): 
    395    raise NotImplementedError 
    396 
    397  def _SetListener(self, message_listener): 
    398    """Internal method used by the protocol message implementation. 
    399    Clients should not call this directly. 
    400 
    401    Sets a listener that this message will call on certain state transitions. 
    402 
    403    The purpose of this method is to register back-edges from children to 
    404    parents at runtime, for the purpose of setting "has" bits and 
    405    byte-size-dirty bits in the parent and ancestor objects whenever a child or 
    406    descendant object is modified. 
    407 
    408    If the client wants to disconnect this Message from the object tree, she 
    409    explicitly sets callback to None. 
    410 
    411    If message_listener is None, unregisters any existing listener.  Otherwise, 
    412    message_listener must implement the MessageListener interface in 
    413    internal/message_listener.py, and we discard any listener registered 
    414    via a previous _SetListener() call. 
    415    """ 
    416    raise NotImplementedError 
    417 
    418  def __getstate__(self): 
    419    """Support the pickle protocol.""" 
    420    return dict(serialized=self.SerializePartialToString()) 
    421 
    422  def __setstate__(self, state): 
    423    """Support the pickle protocol.""" 
    424    self.__init__() 
    425    serialized = state['serialized'] 
    426    # On Python 3, using encoding='latin1' is required for unpickling 
    427    # protos pickled by Python 2. 
    428    if not isinstance(serialized, bytes): 
    429      serialized = serialized.encode('latin1') 
    430    self.ParseFromString(serialized) 
    431 
    432  def __reduce__(self): 
    433    message_descriptor = self.DESCRIPTOR 
    434    if message_descriptor.containing_type is None: 
    435      return type(self), (), self.__getstate__() 
    436    # the message type must be nested. 
    437    # Python does not pickle nested classes; use the symbol_database on the 
    438    # receiving end. 
    439    container = message_descriptor 
    440    return (_InternalConstructMessage, (container.full_name,), 
    441            self.__getstate__()) 
    442 
    443 
    444def _InternalConstructMessage(full_name): 
    445  """Constructs a nested message.""" 
    446  from google.protobuf import symbol_database  # pylint:disable=g-import-not-at-top 
    447 
    448  return symbol_database.Default().GetSymbol(full_name)()