blob: e74cf25e5067bdfc65711588e14c93ffb4167536 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001# 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
42file, in types that make this information accessible in Python.
43"""
44
45__author__ = 'robinson@google.com (Will Robinson)'
46
47class 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
81class 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...
179class 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
299class 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
339class 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
363class 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
395class 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
426def _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;