diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | cf31fe9b4fb650b27e19f5d7ee7297e383660caf (patch) | |
tree | d04ca6a45d579dca5e5469606c48c405aee68f4b /froofle/protobuf/descriptor.py | |
download | git-repo-cf31fe9b4fb650b27e19f5d7ee7297e383660caf.tar.gz |
Initial Contributionv1.0
Diffstat (limited to 'froofle/protobuf/descriptor.py')
-rw-r--r-- | froofle/protobuf/descriptor.py | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/froofle/protobuf/descriptor.py b/froofle/protobuf/descriptor.py new file mode 100644 index 00000000..e74cf25e --- /dev/null +++ b/froofle/protobuf/descriptor.py | |||
@@ -0,0 +1,433 @@ | |||
1 | # Protocol Buffers - Google's data interchange format | ||
2 | # Copyright 2008 Google Inc. All rights reserved. | ||
3 | # http://code.google.com/p/protobuf/ | ||
4 | # | ||
5 | # Redistribution and use in source and binary forms, with or without | ||
6 | # modification, are permitted provided that the following conditions are | ||
7 | # met: | ||
8 | # | ||
9 | # * Redistributions of source code must retain the above copyright | ||
10 | # notice, this list of conditions and the following disclaimer. | ||
11 | # * Redistributions in binary form must reproduce the above | ||
12 | # copyright notice, this list of conditions and the following disclaimer | ||
13 | # in the documentation and/or other materials provided with the | ||
14 | # distribution. | ||
15 | # * Neither the name of Google Inc. nor the names of its | ||
16 | # contributors may be used to endorse or promote products derived from | ||
17 | # this software without specific prior written permission. | ||
18 | # | ||
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
23 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
25 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
26 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
27 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
29 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | |||
31 | # TODO(robinson): We probably need to provide deep-copy methods for | ||
32 | # descriptor types. When a FieldDescriptor is passed into | ||
33 | # Descriptor.__init__(), we should make a deep copy and then set | ||
34 | # containing_type on it. Alternatively, we could just get | ||
35 | # rid of containing_type (iit's not needed for reflection.py, at least). | ||
36 | # | ||
37 | # TODO(robinson): Print method? | ||
38 | # | ||
39 | # TODO(robinson): Useful __repr__? | ||
40 | |||
41 | """Descriptors essentially contain exactly the information found in a .proto | ||
42 | file, in types that make this information accessible in Python. | ||
43 | """ | ||
44 | |||
45 | __author__ = 'robinson@google.com (Will Robinson)' | ||
46 | |||
47 | class DescriptorBase(object): | ||
48 | |||
49 | """Descriptors base class. | ||
50 | |||
51 | This class is the base of all descriptor classes. It provides common options | ||
52 | related functionaility. | ||
53 | """ | ||
54 | |||
55 | def __init__(self, options, options_class_name): | ||
56 | """Initialize the descriptor given its options message and the name of the | ||
57 | class of the options message. The name of the class is required in case | ||
58 | the options message is None and has to be created. | ||
59 | """ | ||
60 | self._options = options | ||
61 | self._options_class_name = options_class_name | ||
62 | |||
63 | def GetOptions(self): | ||
64 | """Retrieves descriptor options. | ||
65 | |||
66 | This method returns the options set or creates the default options for the | ||
67 | descriptor. | ||
68 | """ | ||
69 | if self._options: | ||
70 | return self._options | ||
71 | from froofle.protobuf import descriptor_pb2 | ||
72 | try: | ||
73 | options_class = getattr(descriptor_pb2, self._options_class_name) | ||
74 | except AttributeError: | ||
75 | raise RuntimeError('Unknown options class name %s!' % | ||
76 | (self._options_class_name)) | ||
77 | self._options = options_class() | ||
78 | return self._options | ||
79 | |||
80 | |||
81 | class Descriptor(DescriptorBase): | ||
82 | |||
83 | """Descriptor for a protocol message type. | ||
84 | |||
85 | A Descriptor instance has the following attributes: | ||
86 | |||
87 | name: (str) Name of this protocol message type. | ||
88 | full_name: (str) Fully-qualified name of this protocol message type, | ||
89 | which will include protocol "package" name and the name of any | ||
90 | enclosing types. | ||
91 | |||
92 | filename: (str) Name of the .proto file containing this message. | ||
93 | |||
94 | containing_type: (Descriptor) Reference to the descriptor of the | ||
95 | type containing us, or None if we have no containing type. | ||
96 | |||
97 | fields: (list of FieldDescriptors) Field descriptors for all | ||
98 | fields in this type. | ||
99 | fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor | ||
100 | objects as in |fields|, but indexed by "number" attribute in each | ||
101 | FieldDescriptor. | ||
102 | fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor | ||
103 | objects as in |fields|, but indexed by "name" attribute in each | ||
104 | FieldDescriptor. | ||
105 | |||
106 | nested_types: (list of Descriptors) Descriptor references | ||
107 | for all protocol message types nested within this one. | ||
108 | nested_types_by_name: (dict str -> Descriptor) Same Descriptor | ||
109 | objects as in |nested_types|, but indexed by "name" attribute | ||
110 | in each Descriptor. | ||
111 | |||
112 | enum_types: (list of EnumDescriptors) EnumDescriptor references | ||
113 | for all enums contained within this type. | ||
114 | enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor | ||
115 | objects as in |enum_types|, but indexed by "name" attribute | ||
116 | in each EnumDescriptor. | ||
117 | enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping | ||
118 | from enum value name to EnumValueDescriptor for that value. | ||
119 | |||
120 | extensions: (list of FieldDescriptor) All extensions defined directly | ||
121 | within this message type (NOT within a nested type). | ||
122 | extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor | ||
123 | objects as |extensions|, but indexed by "name" attribute of each | ||
124 | FieldDescriptor. | ||
125 | |||
126 | options: (descriptor_pb2.MessageOptions) Protocol message options or None | ||
127 | to use default message options. | ||
128 | """ | ||
129 | |||
130 | def __init__(self, name, full_name, filename, containing_type, | ||
131 | fields, nested_types, enum_types, extensions, options=None): | ||
132 | """Arguments to __init__() are as described in the description | ||
133 | of Descriptor fields above. | ||
134 | """ | ||
135 | super(Descriptor, self).__init__(options, 'MessageOptions') | ||
136 | self.name = name | ||
137 | self.full_name = full_name | ||
138 | self.filename = filename | ||
139 | self.containing_type = containing_type | ||
140 | |||
141 | # We have fields in addition to fields_by_name and fields_by_number, | ||
142 | # so that: | ||
143 | # 1. Clients can index fields by "order in which they're listed." | ||
144 | # 2. Clients can easily iterate over all fields with the terse | ||
145 | # syntax: for f in descriptor.fields: ... | ||
146 | self.fields = fields | ||
147 | for field in self.fields: | ||
148 | field.containing_type = self | ||
149 | self.fields_by_number = dict((f.number, f) for f in fields) | ||
150 | self.fields_by_name = dict((f.name, f) for f in fields) | ||
151 | |||
152 | self.nested_types = nested_types | ||
153 | self.nested_types_by_name = dict((t.name, t) for t in nested_types) | ||
154 | |||
155 | self.enum_types = enum_types | ||
156 | for enum_type in self.enum_types: | ||
157 | enum_type.containing_type = self | ||
158 | self.enum_types_by_name = dict((t.name, t) for t in enum_types) | ||
159 | self.enum_values_by_name = dict( | ||
160 | (v.name, v) for t in enum_types for v in t.values) | ||
161 | |||
162 | self.extensions = extensions | ||
163 | for extension in self.extensions: | ||
164 | extension.extension_scope = self | ||
165 | self.extensions_by_name = dict((f.name, f) for f in extensions) | ||
166 | |||
167 | |||
168 | # TODO(robinson): We should have aggressive checking here, | ||
169 | # for example: | ||
170 | # * If you specify a repeated field, you should not be allowed | ||
171 | # to specify a default value. | ||
172 | # * [Other examples here as needed]. | ||
173 | # | ||
174 | # TODO(robinson): for this and other *Descriptor classes, we | ||
175 | # might also want to lock things down aggressively (e.g., | ||
176 | # prevent clients from setting the attributes). Having | ||
177 | # stronger invariants here in general will reduce the number | ||
178 | # of runtime checks we must do in reflection.py... | ||
179 | class FieldDescriptor(DescriptorBase): | ||
180 | |||
181 | """Descriptor for a single field in a .proto file. | ||
182 | |||
183 | A FieldDescriptor instance has the following attriubtes: | ||
184 | |||
185 | name: (str) Name of this field, exactly as it appears in .proto. | ||
186 | full_name: (str) Name of this field, including containing scope. This is | ||
187 | particularly relevant for extensions. | ||
188 | index: (int) Dense, 0-indexed index giving the order that this | ||
189 | field textually appears within its message in the .proto file. | ||
190 | number: (int) Tag number declared for this field in the .proto file. | ||
191 | |||
192 | type: (One of the TYPE_* constants below) Declared type. | ||
193 | cpp_type: (One of the CPPTYPE_* constants below) C++ type used to | ||
194 | represent this field. | ||
195 | |||
196 | label: (One of the LABEL_* constants below) Tells whether this | ||
197 | field is optional, required, or repeated. | ||
198 | default_value: (Varies) Default value of this field. Only | ||
199 | meaningful for non-repeated scalar fields. Repeated fields | ||
200 | should always set this to [], and non-repeated composite | ||
201 | fields should always set this to None. | ||
202 | |||
203 | containing_type: (Descriptor) Descriptor of the protocol message | ||
204 | type that contains this field. Set by the Descriptor constructor | ||
205 | if we're passed into one. | ||
206 | Somewhat confusingly, for extension fields, this is the | ||
207 | descriptor of the EXTENDED message, not the descriptor | ||
208 | of the message containing this field. (See is_extension and | ||
209 | extension_scope below). | ||
210 | message_type: (Descriptor) If a composite field, a descriptor | ||
211 | of the message type contained in this field. Otherwise, this is None. | ||
212 | enum_type: (EnumDescriptor) If this field contains an enum, a | ||
213 | descriptor of that enum. Otherwise, this is None. | ||
214 | |||
215 | is_extension: True iff this describes an extension field. | ||
216 | extension_scope: (Descriptor) Only meaningful if is_extension is True. | ||
217 | Gives the message that immediately contains this extension field. | ||
218 | Will be None iff we're a top-level (file-level) extension field. | ||
219 | |||
220 | options: (descriptor_pb2.FieldOptions) Protocol message field options or | ||
221 | None to use default field options. | ||
222 | """ | ||
223 | |||
224 | # Must be consistent with C++ FieldDescriptor::Type enum in | ||
225 | # descriptor.h. | ||
226 | # | ||
227 | # TODO(robinson): Find a way to eliminate this repetition. | ||
228 | TYPE_DOUBLE = 1 | ||
229 | TYPE_FLOAT = 2 | ||
230 | TYPE_INT64 = 3 | ||
231 | TYPE_UINT64 = 4 | ||
232 | TYPE_INT32 = 5 | ||
233 | TYPE_FIXED64 = 6 | ||
234 | TYPE_FIXED32 = 7 | ||
235 | TYPE_BOOL = 8 | ||
236 | TYPE_STRING = 9 | ||
237 | TYPE_GROUP = 10 | ||
238 | TYPE_MESSAGE = 11 | ||
239 | TYPE_BYTES = 12 | ||
240 | TYPE_UINT32 = 13 | ||
241 | TYPE_ENUM = 14 | ||
242 | TYPE_SFIXED32 = 15 | ||
243 | TYPE_SFIXED64 = 16 | ||
244 | TYPE_SINT32 = 17 | ||
245 | TYPE_SINT64 = 18 | ||
246 | MAX_TYPE = 18 | ||
247 | |||
248 | # Must be consistent with C++ FieldDescriptor::CppType enum in | ||
249 | # descriptor.h. | ||
250 | # | ||
251 | # TODO(robinson): Find a way to eliminate this repetition. | ||
252 | CPPTYPE_INT32 = 1 | ||
253 | CPPTYPE_INT64 = 2 | ||
254 | CPPTYPE_UINT32 = 3 | ||
255 | CPPTYPE_UINT64 = 4 | ||
256 | CPPTYPE_DOUBLE = 5 | ||
257 | CPPTYPE_FLOAT = 6 | ||
258 | CPPTYPE_BOOL = 7 | ||
259 | CPPTYPE_ENUM = 8 | ||
260 | CPPTYPE_STRING = 9 | ||
261 | CPPTYPE_MESSAGE = 10 | ||
262 | MAX_CPPTYPE = 10 | ||
263 | |||
264 | # Must be consistent with C++ FieldDescriptor::Label enum in | ||
265 | # descriptor.h. | ||
266 | # | ||
267 | # TODO(robinson): Find a way to eliminate this repetition. | ||
268 | LABEL_OPTIONAL = 1 | ||
269 | LABEL_REQUIRED = 2 | ||
270 | LABEL_REPEATED = 3 | ||
271 | MAX_LABEL = 3 | ||
272 | |||
273 | def __init__(self, name, full_name, index, number, type, cpp_type, label, | ||
274 | default_value, message_type, enum_type, containing_type, | ||
275 | is_extension, extension_scope, options=None): | ||
276 | """The arguments are as described in the description of FieldDescriptor | ||
277 | attributes above. | ||
278 | |||
279 | Note that containing_type may be None, and may be set later if necessary | ||
280 | (to deal with circular references between message types, for example). | ||
281 | Likewise for extension_scope. | ||
282 | """ | ||
283 | super(FieldDescriptor, self).__init__(options, 'FieldOptions') | ||
284 | self.name = name | ||
285 | self.full_name = full_name | ||
286 | self.index = index | ||
287 | self.number = number | ||
288 | self.type = type | ||
289 | self.cpp_type = cpp_type | ||
290 | self.label = label | ||
291 | self.default_value = default_value | ||
292 | self.containing_type = containing_type | ||
293 | self.message_type = message_type | ||
294 | self.enum_type = enum_type | ||
295 | self.is_extension = is_extension | ||
296 | self.extension_scope = extension_scope | ||
297 | |||
298 | |||
299 | class EnumDescriptor(DescriptorBase): | ||
300 | |||
301 | """Descriptor for an enum defined in a .proto file. | ||
302 | |||
303 | An EnumDescriptor instance has the following attributes: | ||
304 | |||
305 | name: (str) Name of the enum type. | ||
306 | full_name: (str) Full name of the type, including package name | ||
307 | and any enclosing type(s). | ||
308 | filename: (str) Name of the .proto file in which this appears. | ||
309 | |||
310 | values: (list of EnumValueDescriptors) List of the values | ||
311 | in this enum. | ||
312 | values_by_name: (dict str -> EnumValueDescriptor) Same as |values|, | ||
313 | but indexed by the "name" field of each EnumValueDescriptor. | ||
314 | values_by_number: (dict int -> EnumValueDescriptor) Same as |values|, | ||
315 | but indexed by the "number" field of each EnumValueDescriptor. | ||
316 | containing_type: (Descriptor) Descriptor of the immediate containing | ||
317 | type of this enum, or None if this is an enum defined at the | ||
318 | top level in a .proto file. Set by Descriptor's constructor | ||
319 | if we're passed into one. | ||
320 | options: (descriptor_pb2.EnumOptions) Enum options message or | ||
321 | None to use default enum options. | ||
322 | """ | ||
323 | |||
324 | def __init__(self, name, full_name, filename, values, | ||
325 | containing_type=None, options=None): | ||
326 | """Arguments are as described in the attribute description above.""" | ||
327 | super(EnumDescriptor, self).__init__(options, 'EnumOptions') | ||
328 | self.name = name | ||
329 | self.full_name = full_name | ||
330 | self.filename = filename | ||
331 | self.values = values | ||
332 | for value in self.values: | ||
333 | value.type = self | ||
334 | self.values_by_name = dict((v.name, v) for v in values) | ||
335 | self.values_by_number = dict((v.number, v) for v in values) | ||
336 | self.containing_type = containing_type | ||
337 | |||
338 | |||
339 | class EnumValueDescriptor(DescriptorBase): | ||
340 | |||
341 | """Descriptor for a single value within an enum. | ||
342 | |||
343 | name: (str) Name of this value. | ||
344 | index: (int) Dense, 0-indexed index giving the order that this | ||
345 | value appears textually within its enum in the .proto file. | ||
346 | number: (int) Actual number assigned to this enum value. | ||
347 | type: (EnumDescriptor) EnumDescriptor to which this value | ||
348 | belongs. Set by EnumDescriptor's constructor if we're | ||
349 | passed into one. | ||
350 | options: (descriptor_pb2.EnumValueOptions) Enum value options message or | ||
351 | None to use default enum value options options. | ||
352 | """ | ||
353 | |||
354 | def __init__(self, name, index, number, type=None, options=None): | ||
355 | """Arguments are as described in the attribute description above.""" | ||
356 | super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions') | ||
357 | self.name = name | ||
358 | self.index = index | ||
359 | self.number = number | ||
360 | self.type = type | ||
361 | |||
362 | |||
363 | class ServiceDescriptor(DescriptorBase): | ||
364 | |||
365 | """Descriptor for a service. | ||
366 | |||
367 | name: (str) Name of the service. | ||
368 | full_name: (str) Full name of the service, including package name. | ||
369 | index: (int) 0-indexed index giving the order that this services | ||
370 | definition appears withing the .proto file. | ||
371 | methods: (list of MethodDescriptor) List of methods provided by this | ||
372 | service. | ||
373 | options: (descriptor_pb2.ServiceOptions) Service options message or | ||
374 | None to use default service options. | ||
375 | """ | ||
376 | |||
377 | def __init__(self, name, full_name, index, methods, options=None): | ||
378 | super(ServiceDescriptor, self).__init__(options, 'ServiceOptions') | ||
379 | self.name = name | ||
380 | self.full_name = full_name | ||
381 | self.index = index | ||
382 | self.methods = methods | ||
383 | # Set the containing service for each method in this service. | ||
384 | for method in self.methods: | ||
385 | method.containing_service = self | ||
386 | |||
387 | def FindMethodByName(self, name): | ||
388 | """Searches for the specified method, and returns its descriptor.""" | ||
389 | for method in self.methods: | ||
390 | if name == method.name: | ||
391 | return method | ||
392 | return None | ||
393 | |||
394 | |||
395 | class MethodDescriptor(DescriptorBase): | ||
396 | |||
397 | """Descriptor for a method in a service. | ||
398 | |||
399 | name: (str) Name of the method within the service. | ||
400 | full_name: (str) Full name of method. | ||
401 | index: (int) 0-indexed index of the method inside the service. | ||
402 | containing_service: (ServiceDescriptor) The service that contains this | ||
403 | method. | ||
404 | input_type: The descriptor of the message that this method accepts. | ||
405 | output_type: The descriptor of the message that this method returns. | ||
406 | options: (descriptor_pb2.MethodOptions) Method options message or | ||
407 | None to use default method options. | ||
408 | """ | ||
409 | |||
410 | def __init__(self, name, full_name, index, containing_service, | ||
411 | input_type, output_type, options=None): | ||
412 | """The arguments are as described in the description of MethodDescriptor | ||
413 | attributes above. | ||
414 | |||
415 | Note that containing_service may be None, and may be set later if necessary. | ||
416 | """ | ||
417 | super(MethodDescriptor, self).__init__(options, 'MethodOptions') | ||
418 | self.name = name | ||
419 | self.full_name = full_name | ||
420 | self.index = index | ||
421 | self.containing_service = containing_service | ||
422 | self.input_type = input_type | ||
423 | self.output_type = output_type | ||
424 | |||
425 | |||
426 | def _ParseOptions(message, string): | ||
427 | """Parses serialized options. | ||
428 | |||
429 | This helper function is used to parse serialized options in generated | ||
430 | proto2 files. It must not be used outside proto2. | ||
431 | """ | ||
432 | message.ParseFromString(string) | ||
433 | return message; | ||