Initial import of v2.0.0beta
[protobuf.git] / python / google / protobuf / message.py
blob9b48f889900a3ecf63f69c9d07f7e926e0030c06
1 # Protocol Buffers - Google's data interchange format
2 # Copyright 2008 Google Inc.
3 # http://code.google.com/p/protobuf/
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.
17 # TODO(robinson): We should just make these methods all "pure-virtual" and move
18 # all implementation out, into reflection.py for now.
21 """Contains an abstract base class for protocol messages."""
23 __author__ = 'robinson@google.com (Will Robinson)'
25 from google.protobuf import text_format
27 class Error(Exception): pass
28 class DecodeError(Error): pass
29 class EncodeError(Error): pass
32 class Message(object):
34 """Abstract base class for protocol messages.
36 Protocol message classes are almost always generated by the protocol
37 compiler. These generated types subclass Message and implement the methods
38 shown below.
40 TODO(robinson): Link to an HTML document here.
42 TODO(robinson): 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(robinson): Document that the class must also have a static
47 RegisterExtension(extension_field) method.
48 Not sure how to best express at this point.
49 """
51 # TODO(robinson): Document these fields and methods.
53 __slots__ = []
55 DESCRIPTOR = None
57 def __eq__(self, other_msg):
58 raise NotImplementedError
60 def __ne__(self, other_msg):
61 # Can't just say self != other_msg, since that would infinitely recurse. :)
62 return not self == other_msg
64 def __str__(self):
65 return text_format.MessageToString(self)
67 def MergeFrom(self, other_msg):
68 raise NotImplementedError
70 def CopyFrom(self, other_msg):
71 raise NotImplementedError
73 def Clear(self):
74 raise NotImplementedError
76 def IsInitialized(self):
77 raise NotImplementedError
79 # TODO(robinson): MergeFromString() should probably return None and be
80 # implemented in terms of a helper that returns the # of bytes read. Our
81 # deserialization routines would use the helper when recursively
82 # deserializing, but the end user would almost always just want the no-return
83 # MergeFromString().
85 def MergeFromString(self, serialized):
86 """Merges serialized protocol buffer data into this message.
88 When we find a field in |serialized| that is already present
89 in this message:
90 - If it's a "repeated" field, we append to the end of our list.
91 - Else, if it's a scalar, we overwrite our field.
92 - Else, (it's a nonrepeated composite), we recursively merge
93 into the existing composite.
95 TODO(robinson): Document handling of unknown fields.
97 Args:
98 serialized: Any object that allows us to call buffer(serialized)
99 to access a string of bytes using the buffer interface.
101 TODO(robinson): When we switch to a helper, this will return None.
103 Returns:
104 The number of bytes read from |serialized|.
105 For non-group messages, this will always be len(serialized),
106 but for messages which are actually groups, this will
107 generally be less than len(serialized), since we must
108 stop when we reach an END_GROUP tag. Note that if
109 we *do* stop because of an END_GROUP tag, the number
110 of bytes returned does not include the bytes
111 for the END_GROUP tag information.
113 raise NotImplementedError
115 def ParseFromString(self, serialized):
116 """Like MergeFromString(), except we clear the object first."""
117 self.Clear()
118 self.MergeFromString(serialized)
120 def SerializeToString(self):
121 raise NotImplementedError
123 # TODO(robinson): Decide whether we like these better
124 # than auto-generated has_foo() and clear_foo() methods
125 # on the instances themselves. This way is less consistent
126 # with C++, but it makes reflection-type access easier and
127 # reduces the number of magically autogenerated things.
129 # TODO(robinson): Be sure to document (and test) exactly
130 # which field names are accepted here. Are we case-sensitive?
131 # What do we do with fields that share names with Python keywords
132 # like 'lambda' and 'yield'?
134 # nnorwitz says:
135 # """
136 # Typically (in python), an underscore is appended to names that are
137 # keywords. So they would become lambda_ or yield_.
138 # """
139 def ListFields(self, field_name):
140 """Returns a list of (FieldDescriptor, value) tuples for all
141 fields in the message which are not empty. A singular field is non-empty
142 if HasField() would return true, and a repeated field is non-empty if
143 it contains at least one element. The fields are ordered by field
144 number"""
145 raise NotImplementedError
147 def HasField(self, field_name):
148 raise NotImplementedError
150 def ClearField(self, field_name):
151 raise NotImplementedError
153 def HasExtension(self, extension_handle):
154 raise NotImplementedError
156 def ClearExtension(self, extension_handle):
157 raise NotImplementedError
159 def ByteSize(self):
160 """Returns the serialized size of this message.
161 Recursively calls ByteSize() on all contained messages.
163 raise NotImplementedError
165 def _SetListener(self, message_listener):
166 """Internal method used by the protocol message implementation.
167 Clients should not call this directly.
169 Sets a listener that this message will call on certain state transitions.
171 The purpose of this method is to register back-edges from children to
172 parents at runtime, for the purpose of setting "has" bits and
173 byte-size-dirty bits in the parent and ancestor objects whenever a child or
174 descendant object is modified.
176 If the client wants to disconnect this Message from the object tree, she
177 explicitly sets callback to None.
179 If message_listener is None, unregisters any existing listener. Otherwise,
180 message_listener must implement the MessageListener interface in
181 internal/message_listener.py, and we discard any listener registered
182 via a previous _SetListener() call.
184 raise NotImplementedError