App Engine Python SDK version 1.9.12
[gae.git] / python / google / net / proto2 / python / public / message.py
blob10c679a64d656d0b421854175e41937dd8dd6bf4
1 #!/usr/bin/env python
3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
25 """Contains an abstract base class for protocol messages."""
29 class Error(Exception): pass
30 class DecodeError(Error): pass
31 class EncodeError(Error): pass
34 class Message(object):
36 """Abstract base class for protocol messages.
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.
42 TODO: Link to an HTML document here.
44 TODO: Document that instances of this class will also
45 have an Extensions attribute with __getitem__ and __setitem__.
46 Again, not sure how to best convey this.
48 TODO: Document that the class must also have a static
49 RegisterExtension(extension_field) method.
50 Not sure how to best express at this point.
51 """
55 __slots__ = []
57 DESCRIPTOR = None
59 def __deepcopy__(self, memo=None):
60 clone = type(self)()
61 clone.MergeFrom(self)
62 return clone
64 def __eq__(self, other_msg):
65 """Recursively compares two messages by value and structure."""
66 raise NotImplementedError
68 def __ne__(self, other_msg):
70 return not self == other_msg
72 def __hash__(self):
73 raise TypeError('unhashable object')
75 def __str__(self):
76 """Outputs a human-readable representation of the message."""
77 raise NotImplementedError
79 def __unicode__(self):
80 """Outputs a human-readable representation of the message."""
81 raise NotImplementedError
83 def MergeFrom(self, other_msg):
84 """Merges the contents of the specified message into current message.
86 This method merges the contents of the specified message into the current
87 message. Singular fields that are set in the specified message overwrite
88 the corresponding fields in the current message. Repeated fields are
89 appended. Singular sub-messages and groups are recursively merged.
91 Args:
92 other_msg: Message to merge into the current message.
93 """
94 raise NotImplementedError
96 def CopyFrom(self, other_msg):
97 """Copies the content of the specified message into the current message.
99 The method clears the current message and then merges the specified
100 message using MergeFrom.
102 Args:
103 other_msg: Message to copy into the current one.
105 if self is other_msg:
106 return
107 self.Clear()
108 self.MergeFrom(other_msg)
110 def Clear(self):
111 """Clears all data that was set in the message."""
112 raise NotImplementedError
114 def SetInParent(self):
115 """Mark this as present in the parent.
117 This normally happens automatically when you assign a field of a
118 sub-message, but sometimes you want to make the sub-message
119 present while keeping it empty. If you find yourself using this,
120 you may want to reconsider your design."""
121 raise NotImplementedError
123 def IsInitialized(self):
124 """Checks if the message is initialized.
126 Returns:
127 The method returns True if the message is initialized (i.e. all of its
128 required fields are set).
130 raise NotImplementedError
138 def MergeFromString(self, serialized):
139 """Merges serialized protocol buffer data into this message.
141 When we find a field in |serialized| that is already present
142 in this message:
143 - If it's a "repeated" field, we append to the end of our list.
144 - Else, if it's a scalar, we overwrite our field.
145 - Else, (it's a nonrepeated composite), we recursively merge
146 into the existing composite.
148 TODO: Document handling of unknown fields.
150 Args:
151 serialized: Any object that allows us to call buffer(serialized)
152 to access a string of bytes using the buffer interface.
154 TODO: When we switch to a helper, this will return None.
156 Returns:
157 The number of bytes read from |serialized|.
158 For non-group messages, this will always be len(serialized),
159 but for messages which are actually groups, this will
160 generally be less than len(serialized), since we must
161 stop when we reach an END_GROUP tag. Note that if
162 we *do* stop because of an END_GROUP tag, the number
163 of bytes returned does not include the bytes
164 for the END_GROUP tag information.
166 raise NotImplementedError
168 def ParseFromString(self, serialized):
169 """Parse serialized protocol buffer data into this message.
171 Like MergeFromString(), except we clear the object first and
172 do not return the value that MergeFromString returns.
174 self.Clear()
175 self.MergeFromString(serialized)
177 def SerializeToString(self):
178 """Serializes the protocol message to a binary string.
180 Returns:
181 A binary string representation of the message if all of the required
182 fields in the message are set (i.e. the message is initialized).
184 Raises:
185 message.EncodeError if the message isn't initialized.
187 raise NotImplementedError
189 def SerializePartialToString(self):
190 """Serializes the protocol message to a binary string.
192 This method is similar to SerializeToString but doesn't check if the
193 message is initialized.
195 Returns:
196 A string representation of the partial message.
198 raise NotImplementedError
216 def ListFields(self):
217 """Returns a list of (FieldDescriptor, value) tuples for all
218 fields in the message which are not empty. A singular field is non-empty
219 if HasField() would return true, and a repeated field is non-empty if
220 it contains at least one element. The fields are ordered by field
221 number"""
222 raise NotImplementedError
224 def HasField(self, field_name):
225 """Checks if a certain field is set for the message, or if any field inside
226 a oneof group is set. Note that if the field_name is not defined in the
227 message descriptor, ValueError will be raised."""
228 raise NotImplementedError
230 def ClearField(self, field_name):
231 """Clears the contents of a given field, or the field set inside a oneof
232 group. If the name neither refers to a defined field or oneof group,
233 ValueError is raised."""
234 raise NotImplementedError
236 def WhichOneof(self, oneof_group):
237 """Returns the name of the field that is set inside a oneof group, or
238 None if no field is set. If no group with the given name exists, ValueError
239 will be raised."""
240 raise NotImplementedError
242 def HasExtension(self, extension_handle):
243 raise NotImplementedError
245 def ClearExtension(self, extension_handle):
246 raise NotImplementedError
248 def ByteSize(self):
249 """Returns the serialized size of this message.
250 Recursively calls ByteSize() on all contained messages.
252 raise NotImplementedError
254 def _SetListener(self, message_listener):
255 """Internal method used by the protocol message implementation.
256 Clients should not call this directly.
258 Sets a listener that this message will call on certain state transitions.
260 The purpose of this method is to register back-edges from children to
261 parents at runtime, for the purpose of setting "has" bits and
262 byte-size-dirty bits in the parent and ancestor objects whenever a child or
263 descendant object is modified.
265 If the client wants to disconnect this Message from the object tree, she
266 explicitly sets callback to None.
268 If message_listener is None, unregisters any existing listener. Otherwise,
269 message_listener must implement the MessageListener interface in
270 internal/message_listener.py, and we discard any listener registered
271 via a previous _SetListener() call.
273 raise NotImplementedError
275 def __getstate__(self):
276 """Support the pickle protocol."""
277 return dict(serialized=self.SerializePartialToString())
279 def __setstate__(self, state):
280 """Support the pickle protocol."""
281 self.__init__()
282 self.ParseFromString(state['serialized'])