Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
message.py449 linesDownload Raw Back to protobuf
1# Protocol Buffers - Google's data interchange format2# Copyright 2008 Google Inc.  All rights reserved.3#4# Use of this source code is governed by a BSD-style5# license that can be found in the LICENSE file or at6# https://developers.google.com/open-source/licenses/bsd7 8# TODO: We should just make these methods all "pure-virtual" and move9# 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  pass22 23 24class DecodeError(Error):25  """Exception raised when deserializing messages."""26  pass27 28 29class EncodeError(Error):30  """Exception raised when serializing messages."""31  pass32 33 34class Message(object):35 36  """Abstract base class for protocol messages.37 38  Protocol message classes are almost always generated by the protocol39  compiler.  These generated types subclass Message and implement the methods40  shown below.41  """42 43  # TODO: Link to an HTML document here.44 45  # TODO: Document that instances of this class will also46  # 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 = None56 57  def __deepcopy__(self, memo=None):58    clone = type(self)()59    clone.MergeFrom(self)60    return clone61 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 as68    # 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 that74    # have to be removed.75    for attribute in _INCONSISTENT_MESSAGE_ATTRIBUTES:76      if attribute not in message_attributes:77        continue78      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 NotImplementedError88 89  def __ne__(self, other_msg):90    # Can't just say self != other_msg, since that would infinitely recurse. :)91    return not self == other_msg92 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 NotImplementedError99 100  def __unicode__(self):101    """Outputs a human-readable representation of the message."""102    raise NotImplementedError103 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 is108    not set. Fields without presence do raise `ValueError` (this includes109    repeated fields, map fields, and implicit presence fields).110 111    If field_name is not defined in the message descriptor, `ValueError` will112    be raised.113    Note: WKT Struct checks if the key is contained in fields. ListValue checks114    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. For118        ListValue, any type that may be contained in the list. For other119        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 a128                  member of this message or `field_name_or_key` is not a string.129    """130    raise NotImplementedError131 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 current136    message. Singular fields that are set in the specified message overwrite137    the corresponding fields in the current message. Repeated fields are138    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 NotImplementedError144 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 specified149    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      return156    self.Clear()157    self.MergeFrom(other_msg)158 159  def Clear(self):160    """Clears all data that was set in the message."""161    raise NotImplementedError162 163  def SetInParent(self):164    """Mark this as present in the parent.165 166    This normally happens automatically when you assign a field of a167    sub-message, but sometimes you want to make the sub-message168    present while keeping it empty.  If you find yourself using this,169    you may want to reconsider your design.170    """171    raise NotImplementedError172 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 of178      its required fields are set).179    """180    raise NotImplementedError181 182  # TODO: MergeFromString() should probably return None and be183  # implemented in terms of a helper that returns the # of bytes read.  Our184  # deserialization routines would use the helper when recursively185  # deserializing, but the end user would almost always just want the no-return186  # 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 present192    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 merge197        into the existing composite.198 199    Args:200      serialized (bytes): Any object that allows us to call201        ``memoryview(serialized)`` to access a string of bytes using the202        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 will208      generally be less than `len(serialized)`, since we must209      stop when we reach an ``END_GROUP`` tag.  Note that if210      we *do* stop because of an ``END_GROUP`` tag, the number211      of bytes returned does not include the bytes212      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 NotImplementedError220 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 serialization237        of the protobuf, with predictable ordering of map keys.238 239    Returns:240      A binary string representation of the message if all of the required241      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 NotImplementedError247 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 the252    message is initialized.253 254    Keyword Args:255      deterministic (bool): If true, requests deterministic serialization256        of the protobuf, with predictable ordering of map keys.257 258    Returns:259      bytes: A serialized representation of the partial message.260    """261    raise NotImplementedError262 263  # TODO: Decide whether we like these better264  # than auto-generated has_foo() and clear_foo() methods265  # on the instances themselves.  This way is less consistent266  # with C++, but it makes reflection-type access easier and267  # reduces the number of magically autogenerated things.268  #269  # TODO: Be sure to document (and test) exactly270  # which field names are accepted here.  Are we case-sensitive?271  # What do we do with fields that share names with Python keywords272  # like 'lambda' and 'yield'?273  #274  # nnorwitz says:275  # """276  # Typically (in python), an underscore is appended to names that are277  # 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 singular283    primitive field is non-empty if HasField() would return true in proto2 or it284    is non zero in proto3. A repeated field is non-empty if it contains at least285    one element. The fields are ordered by field number.286 287    Returns:288      list[tuple(FieldDescriptor, value)]: field descriptors and values289      for all fields in the message which are not empty. The values vary by290      field type.291    """292    raise NotImplementedError293 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 the298    field_name is not defined in the message descriptor, :exc:`ValueError` will299    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 NotImplementedError311 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 a316    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 NotImplementedError325 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 exists339    """340    raise NotImplementedError341 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" repeated356        extension is an empty list.357    """358    raise NotImplementedError359 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 NotImplementedError367 368  def UnknownFields(self):369    """Returns the UnknownFieldSet.370 371    Returns:372      UnknownFieldSet: The unknown fields stored in this message.373    """374    raise NotImplementedError375 376  def DiscardUnknownFields(self):377    """Clears all fields in the :class:`UnknownFieldSet`.378 379    This operation is recursive for nested message.380    """381    raise NotImplementedError382 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 NotImplementedError392 393  @classmethod394  def FromString(cls, s):395    raise NotImplementedError396 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 to404    parents at runtime, for the purpose of setting "has" bits and405    byte-size-dirty bits in the parent and ancestor objects whenever a child or406    descendant object is modified.407 408    If the client wants to disconnect this Message from the object tree, she409    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 in413    internal/message_listener.py, and we discard any listener registered414    via a previous _SetListener() call.415    """416    raise NotImplementedError417 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 unpickling427    # 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.DESCRIPTOR434    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 the438    # receiving end.439    container = message_descriptor440    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-top447 448  return symbol_database.Default().GetSymbol(full_name)()449 
codekingpro/portable-devtools · Team Ai