Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/protobuf/message.py: 49%
90 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:40 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:40 +0000
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
8# TODO: We should just make these methods all "pure-virtual" and move
9# all implementation out, into reflection.py for now.
12"""Contains an abstract base class for protocol messages."""
14__author__ = 'robinson@google.com (Will Robinson)'
16class Error(Exception):
17 """Base error type for this module."""
18 pass
21class DecodeError(Error):
22 """Exception raised when deserializing messages."""
23 pass
26class EncodeError(Error):
27 """Exception raised when serializing messages."""
28 pass
31class Message(object):
33 """Abstract base class for protocol messages.
35 Protocol message classes are almost always generated by the protocol
36 compiler. These generated types subclass Message and implement the methods
37 shown below.
38 """
40 # TODO: Link to an HTML document here.
42 # TODO: Document that instances of this class will also
43 # have an Extensions attribute with __getitem__ and __setitem__.
44 # Again, not sure how to best convey this.
46 # TODO: Document these fields and methods.
48 __slots__ = []
50 #: The :class:`google.protobuf.Descriptor`
51 # for this message type.
52 DESCRIPTOR = None
54 def __deepcopy__(self, memo=None):
55 clone = type(self)()
56 clone.MergeFrom(self)
57 return clone
59 def __eq__(self, other_msg):
60 """Recursively compares two messages by value and structure."""
61 raise NotImplementedError
63 def __ne__(self, other_msg):
64 # Can't just say self != other_msg, since that would infinitely recurse. :)
65 return not self == other_msg
67 def __hash__(self):
68 raise TypeError('unhashable object')
70 def __str__(self):
71 """Outputs a human-readable representation of the message."""
72 raise NotImplementedError
74 def __unicode__(self):
75 """Outputs a human-readable representation of the message."""
76 raise NotImplementedError
78 def MergeFrom(self, other_msg):
79 """Merges the contents of the specified message into current message.
81 This method merges the contents of the specified message into the current
82 message. Singular fields that are set in the specified message overwrite
83 the corresponding fields in the current message. Repeated fields are
84 appended. Singular sub-messages and groups are recursively merged.
86 Args:
87 other_msg (Message): A message to merge into the current message.
88 """
89 raise NotImplementedError
91 def CopyFrom(self, other_msg):
92 """Copies the content of the specified message into the current message.
94 The method clears the current message and then merges the specified
95 message using MergeFrom.
97 Args:
98 other_msg (Message): A message to copy into the current one.
99 """
100 if self is other_msg:
101 return
102 self.Clear()
103 self.MergeFrom(other_msg)
105 def Clear(self):
106 """Clears all data that was set in the message."""
107 raise NotImplementedError
109 def SetInParent(self):
110 """Mark this as present in the parent.
112 This normally happens automatically when you assign a field of a
113 sub-message, but sometimes you want to make the sub-message
114 present while keeping it empty. If you find yourself using this,
115 you may want to reconsider your design.
116 """
117 raise NotImplementedError
119 def IsInitialized(self):
120 """Checks if the message is initialized.
122 Returns:
123 bool: The method returns True if the message is initialized (i.e. all of
124 its required fields are set).
125 """
126 raise NotImplementedError
128 # TODO: MergeFromString() should probably return None and be
129 # implemented in terms of a helper that returns the # of bytes read. Our
130 # deserialization routines would use the helper when recursively
131 # deserializing, but the end user would almost always just want the no-return
132 # MergeFromString().
134 def MergeFromString(self, serialized):
135 """Merges serialized protocol buffer data into this message.
137 When we find a field in `serialized` that is already present
138 in this message:
140 - If it's a "repeated" field, we append to the end of our list.
141 - Else, if it's a scalar, we overwrite our field.
142 - Else, (it's a nonrepeated composite), we recursively merge
143 into the existing composite.
145 Args:
146 serialized (bytes): Any object that allows us to call
147 ``memoryview(serialized)`` to access a string of bytes using the
148 buffer interface.
150 Returns:
151 int: The number of bytes read from `serialized`.
152 For non-group messages, this will always be `len(serialized)`,
153 but for messages which are actually groups, this will
154 generally be less than `len(serialized)`, since we must
155 stop when we reach an ``END_GROUP`` tag. Note that if
156 we *do* stop because of an ``END_GROUP`` tag, the number
157 of bytes returned does not include the bytes
158 for the ``END_GROUP`` tag information.
160 Raises:
161 DecodeError: if the input cannot be parsed.
162 """
163 # TODO: Document handling of unknown fields.
164 # TODO: When we switch to a helper, this will return None.
165 raise NotImplementedError
167 def ParseFromString(self, serialized):
168 """Parse serialized protocol buffer data in binary form into this message.
170 Like :func:`MergeFromString()`, except we clear the object first.
172 Raises:
173 message.DecodeError if the input cannot be parsed.
174 """
175 self.Clear()
176 return self.MergeFromString(serialized)
178 def SerializeToString(self, **kwargs):
179 """Serializes the protocol message to a binary string.
181 Keyword Args:
182 deterministic (bool): If true, requests deterministic serialization
183 of the protobuf, with predictable ordering of map keys.
185 Returns:
186 A binary string representation of the message if all of the required
187 fields in the message are set (i.e. the message is initialized).
189 Raises:
190 EncodeError: if the message isn't initialized (see :func:`IsInitialized`).
191 """
192 raise NotImplementedError
194 def SerializePartialToString(self, **kwargs):
195 """Serializes the protocol message to a binary string.
197 This method is similar to SerializeToString but doesn't check if the
198 message is initialized.
200 Keyword Args:
201 deterministic (bool): If true, requests deterministic serialization
202 of the protobuf, with predictable ordering of map keys.
204 Returns:
205 bytes: A serialized representation of the partial message.
206 """
207 raise NotImplementedError
209 # TODO: Decide whether we like these better
210 # than auto-generated has_foo() and clear_foo() methods
211 # on the instances themselves. This way is less consistent
212 # with C++, but it makes reflection-type access easier and
213 # reduces the number of magically autogenerated things.
214 #
215 # TODO: Be sure to document (and test) exactly
216 # which field names are accepted here. Are we case-sensitive?
217 # What do we do with fields that share names with Python keywords
218 # like 'lambda' and 'yield'?
219 #
220 # nnorwitz says:
221 # """
222 # Typically (in python), an underscore is appended to names that are
223 # keywords. So they would become lambda_ or yield_.
224 # """
225 def ListFields(self):
226 """Returns a list of (FieldDescriptor, value) tuples for present fields.
228 A message field is non-empty if HasField() would return true. A singular
229 primitive field is non-empty if HasField() would return true in proto2 or it
230 is non zero in proto3. A repeated field is non-empty if it contains at least
231 one element. The fields are ordered by field number.
233 Returns:
234 list[tuple(FieldDescriptor, value)]: field descriptors and values
235 for all fields in the message which are not empty. The values vary by
236 field type.
237 """
238 raise NotImplementedError
240 def HasField(self, field_name):
241 """Checks if a certain field is set for the message.
243 For a oneof group, checks if any field inside is set. Note that if the
244 field_name is not defined in the message descriptor, :exc:`ValueError` will
245 be raised.
247 Args:
248 field_name (str): The name of the field to check for presence.
250 Returns:
251 bool: Whether a value has been set for the named field.
253 Raises:
254 ValueError: if the `field_name` is not a member of this message.
255 """
256 raise NotImplementedError
258 def ClearField(self, field_name):
259 """Clears the contents of a given field.
261 Inside a oneof group, clears the field set. If the name neither refers to a
262 defined field or oneof group, :exc:`ValueError` is raised.
264 Args:
265 field_name (str): The name of the field to check for presence.
267 Raises:
268 ValueError: if the `field_name` is not a member of this message.
269 """
270 raise NotImplementedError
272 def WhichOneof(self, oneof_group):
273 """Returns the name of the field that is set inside a oneof group.
275 If no field is set, returns None.
277 Args:
278 oneof_group (str): the name of the oneof group to check.
280 Returns:
281 str or None: The name of the group that is set, or None.
283 Raises:
284 ValueError: no group with the given name exists
285 """
286 raise NotImplementedError
288 def HasExtension(self, field_descriptor):
289 """Checks if a certain extension is present for this message.
291 Extensions are retrieved using the :attr:`Extensions` mapping (if present).
293 Args:
294 field_descriptor: The field descriptor for the extension to check.
296 Returns:
297 bool: Whether the extension is present for this message.
299 Raises:
300 KeyError: if the extension is repeated. Similar to repeated fields,
301 there is no separate notion of presence: a "not present" repeated
302 extension is an empty list.
303 """
304 raise NotImplementedError
306 def ClearExtension(self, field_descriptor):
307 """Clears the contents of a given extension.
309 Args:
310 field_descriptor: The field descriptor for the extension to clear.
311 """
312 raise NotImplementedError
314 def UnknownFields(self):
315 """Returns the UnknownFieldSet.
317 Returns:
318 UnknownFieldSet: The unknown fields stored in this message.
319 """
320 raise NotImplementedError
322 def DiscardUnknownFields(self):
323 """Clears all fields in the :class:`UnknownFieldSet`.
325 This operation is recursive for nested message.
326 """
327 raise NotImplementedError
329 def ByteSize(self):
330 """Returns the serialized size of this message.
332 Recursively calls ByteSize() on all contained messages.
334 Returns:
335 int: The number of bytes required to serialize this message.
336 """
337 raise NotImplementedError
339 @classmethod
340 def FromString(cls, s):
341 raise NotImplementedError
343# TODO: Remove it in OSS
344 @staticmethod
345 def RegisterExtension(field_descriptor):
346 raise NotImplementedError
348 def _SetListener(self, message_listener):
349 """Internal method used by the protocol message implementation.
350 Clients should not call this directly.
352 Sets a listener that this message will call on certain state transitions.
354 The purpose of this method is to register back-edges from children to
355 parents at runtime, for the purpose of setting "has" bits and
356 byte-size-dirty bits in the parent and ancestor objects whenever a child or
357 descendant object is modified.
359 If the client wants to disconnect this Message from the object tree, she
360 explicitly sets callback to None.
362 If message_listener is None, unregisters any existing listener. Otherwise,
363 message_listener must implement the MessageListener interface in
364 internal/message_listener.py, and we discard any listener registered
365 via a previous _SetListener() call.
366 """
367 raise NotImplementedError
369 def __getstate__(self):
370 """Support the pickle protocol."""
371 return dict(serialized=self.SerializePartialToString())
373 def __setstate__(self, state):
374 """Support the pickle protocol."""
375 self.__init__()
376 serialized = state['serialized']
377 # On Python 3, using encoding='latin1' is required for unpickling
378 # protos pickled by Python 2.
379 if not isinstance(serialized, bytes):
380 serialized = serialized.encode('latin1')
381 self.ParseFromString(serialized)
383 def __reduce__(self):
384 message_descriptor = self.DESCRIPTOR
385 if message_descriptor.containing_type is None:
386 return type(self), (), self.__getstate__()
387 # the message type must be nested.
388 # Python does not pickle nested classes; use the symbol_database on the
389 # receiving end.
390 container = message_descriptor
391 return (_InternalConstructMessage, (container.full_name,),
392 self.__getstate__())
395def _InternalConstructMessage(full_name):
396 """Constructs a nested message."""
397 from google.protobuf import symbol_database # pylint:disable=g-import-not-at-top
399 return symbol_database.Default().GetSymbol(full_name)()