blob: 9b48f889900a3ecf63f69c9d07f7e926e0030c06 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc.
3# http://code.google.com/p/protobuf/
4#
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
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
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.
16
17# TODO(robinson): We should just make these methods all "pure-virtual" and move
18# all implementation out, into reflection.py for now.
19
20
21"""Contains an abstract base class for protocol messages."""
22
23__author__ = 'robinson@google.com (Will Robinson)'
24
25from google.protobuf import text_format
26
27class Error(Exception): pass
28class DecodeError(Error): pass
29class EncodeError(Error): pass
30
31
32class Message(object):
33
34 """Abstract base class for protocol messages.
35
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.
39
40 TODO(robinson): Link to an HTML document here.
41
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.
45
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 """
50
51 # TODO(robinson): Document these fields and methods.
52
53 __slots__ = []
54
55 DESCRIPTOR = None
56
57 def __eq__(self, other_msg):
58 raise NotImplementedError
59
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
63
64 def __str__(self):
65 return text_format.MessageToString(self)
66
67 def MergeFrom(self, other_msg):
68 raise NotImplementedError
69
70 def CopyFrom(self, other_msg):
71 raise NotImplementedError
72
73 def Clear(self):
74 raise NotImplementedError
75
76 def IsInitialized(self):
77 raise NotImplementedError
78
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().
84
85 def MergeFromString(self, serialized):
86 """Merges serialized protocol buffer data into this message.
87
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.
94
95 TODO(robinson): Document handling of unknown fields.
96
97 Args:
98 serialized: Any object that allows us to call buffer(serialized)
99 to access a string of bytes using the buffer interface.
100
101 TODO(robinson): When we switch to a helper, this will return None.
102
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.
112 """
113 raise NotImplementedError
114
115 def ParseFromString(self, serialized):
116 """Like MergeFromString(), except we clear the object first."""
117 self.Clear()
118 self.MergeFromString(serialized)
119
120 def SerializeToString(self):
121 raise NotImplementedError
122
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.
128 #
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'?
133 #
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
146
147 def HasField(self, field_name):
148 raise NotImplementedError
149
150 def ClearField(self, field_name):
151 raise NotImplementedError
152
153 def HasExtension(self, extension_handle):
154 raise NotImplementedError
155
156 def ClearExtension(self, extension_handle):
157 raise NotImplementedError
158
159 def ByteSize(self):
160 """Returns the serialized size of this message.
161 Recursively calls ByteSize() on all contained messages.
162 """
163 raise NotImplementedError
164
165 def _SetListener(self, message_listener):
166 """Internal method used by the protocol message implementation.
167 Clients should not call this directly.
168
169 Sets a listener that this message will call on certain state transitions.
170
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.
175
176 If the client wants to disconnect this Message from the object tree, she
177 explicitly sets callback to None.
178
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.
183 """
184 raise NotImplementedError