Imported Upstream version 3.8.0
[platform/upstream/protobuf.git] / python / google / protobuf / descriptor.py
1 # Protocol Buffers - Google's data interchange format
2 # Copyright 2008 Google Inc.  All rights reserved.
3 # https://developers.google.com/protocol-buffers/
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 """Descriptors essentially contain exactly the information found in a .proto
32 file, in types that make this information accessible in Python.
33 """
34
35 __author__ = 'robinson@google.com (Will Robinson)'
36
37 import threading
38 import six
39
40 from google.protobuf.internal import api_implementation
41
42 _USE_C_DESCRIPTORS = False
43 if api_implementation.Type() == 'cpp':
44   # Used by MakeDescriptor in cpp mode
45   import binascii
46   import os
47   from google.protobuf.pyext import _message
48   _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
49
50
51 class Error(Exception):
52   """Base error for this module."""
53
54
55 class TypeTransformationError(Error):
56   """Error transforming between python proto type and corresponding C++ type."""
57
58
59 if _USE_C_DESCRIPTORS:
60   # This metaclass allows to override the behavior of code like
61   #     isinstance(my_descriptor, FieldDescriptor)
62   # and make it return True when the descriptor is an instance of the extension
63   # type written in C++.
64   class DescriptorMetaclass(type):
65     def __instancecheck__(cls, obj):
66       if super(DescriptorMetaclass, cls).__instancecheck__(obj):
67         return True
68       if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
69         return True
70       return False
71 else:
72   # The standard metaclass; nothing changes.
73   DescriptorMetaclass = type
74
75
76 class _Lock(object):
77   """Wrapper class of threading.Lock(), which is allowed by 'with'."""
78
79   def __new__(cls):
80     self = object.__new__(cls)
81     self._lock = threading.Lock()  # pylint: disable=protected-access
82     return self
83
84   def __enter__(self):
85     self._lock.acquire()
86
87   def __exit__(self, exc_type, exc_value, exc_tb):
88     self._lock.release()
89
90
91 _lock = threading.Lock()
92
93
94 class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
95
96   """Descriptors base class.
97
98   This class is the base of all descriptor classes. It provides common options
99   related functionality.
100
101   Attributes:
102     has_options:  True if the descriptor has non-default options.  Usually it
103         is not necessary to read this -- just call GetOptions() which will
104         happily return the default instance.  However, it's sometimes useful
105         for efficiency, and also useful inside the protobuf implementation to
106         avoid some bootstrapping issues.
107   """
108
109   if _USE_C_DESCRIPTORS:
110     # The class, or tuple of classes, that are considered as "virtual
111     # subclasses" of this descriptor class.
112     _C_DESCRIPTOR_CLASS = ()
113
114   def __init__(self, options, serialized_options, options_class_name):
115     """Initialize the descriptor given its options message and the name of the
116     class of the options message. The name of the class is required in case
117     the options message is None and has to be created.
118     """
119     self._options = options
120     self._options_class_name = options_class_name
121     self._serialized_options = serialized_options
122
123     # Does this descriptor have non-default options?
124     self.has_options = (options is not None) or (serialized_options is not None)
125
126   def _SetOptions(self, options, options_class_name):
127     """Sets the descriptor's options
128
129     This function is used in generated proto2 files to update descriptor
130     options. It must not be used outside proto2.
131     """
132     self._options = options
133     self._options_class_name = options_class_name
134
135     # Does this descriptor have non-default options?
136     self.has_options = options is not None
137
138   def GetOptions(self):
139     """Retrieves descriptor options.
140
141     This method returns the options set or creates the default options for the
142     descriptor.
143     """
144     if self._options:
145       return self._options
146
147     from google.protobuf import descriptor_pb2
148     try:
149       options_class = getattr(descriptor_pb2,
150                               self._options_class_name)
151     except AttributeError:
152       raise RuntimeError('Unknown options class name %s!' %
153                          (self._options_class_name))
154
155     with _lock:
156       if self._serialized_options is None:
157         self._options = options_class()
158       else:
159         self._options = _ParseOptions(options_class(),
160                                       self._serialized_options)
161
162       return self._options
163
164
165 class _NestedDescriptorBase(DescriptorBase):
166   """Common class for descriptors that can be nested."""
167
168   def __init__(self, options, options_class_name, name, full_name,
169                file, containing_type, serialized_start=None,
170                serialized_end=None, serialized_options=None):
171     """Constructor.
172
173     Args:
174       options: Protocol message options or None
175         to use default message options.
176       options_class_name: (str) The class name of the above options.
177
178       name: (str) Name of this protocol message type.
179       full_name: (str) Fully-qualified name of this protocol message type,
180         which will include protocol "package" name and the name of any
181         enclosing types.
182       file: (FileDescriptor) Reference to file info.
183       containing_type: if provided, this is a nested descriptor, with this
184         descriptor as parent, otherwise None.
185       serialized_start: The start index (inclusive) in block in the
186         file.serialized_pb that describes this descriptor.
187       serialized_end: The end index (exclusive) in block in the
188         file.serialized_pb that describes this descriptor.
189       serialized_options: Protocol message serilized options or None.
190     """
191     super(_NestedDescriptorBase, self).__init__(
192         options, serialized_options, options_class_name)
193
194     self.name = name
195     # TODO(falk): Add function to calculate full_name instead of having it in
196     #             memory?
197     self.full_name = full_name
198     self.file = file
199     self.containing_type = containing_type
200
201     self._serialized_start = serialized_start
202     self._serialized_end = serialized_end
203
204   def CopyToProto(self, proto):
205     """Copies this to the matching proto in descriptor_pb2.
206
207     Args:
208       proto: An empty proto instance from descriptor_pb2.
209
210     Raises:
211       Error: If self couldnt be serialized, due to to few constructor arguments.
212     """
213     if (self.file is not None and
214         self._serialized_start is not None and
215         self._serialized_end is not None):
216       proto.ParseFromString(self.file.serialized_pb[
217           self._serialized_start:self._serialized_end])
218     else:
219       raise Error('Descriptor does not contain serialization.')
220
221
222 class Descriptor(_NestedDescriptorBase):
223
224   """Descriptor for a protocol message type.
225
226   A Descriptor instance has the following attributes:
227
228     name: (str) Name of this protocol message type.
229     full_name: (str) Fully-qualified name of this protocol message type,
230       which will include protocol "package" name and the name of any
231       enclosing types.
232
233     containing_type: (Descriptor) Reference to the descriptor of the
234       type containing us, or None if this is top-level.
235
236     fields: (list of FieldDescriptors) Field descriptors for all
237       fields in this type.
238     fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor
239       objects as in |fields|, but indexed by "number" attribute in each
240       FieldDescriptor.
241     fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor
242       objects as in |fields|, but indexed by "name" attribute in each
243       FieldDescriptor.
244     fields_by_camelcase_name: (dict str -> FieldDescriptor) Same
245       FieldDescriptor objects as in |fields|, but indexed by
246       "camelcase_name" attribute in each FieldDescriptor.
247
248     nested_types: (list of Descriptors) Descriptor references
249       for all protocol message types nested within this one.
250     nested_types_by_name: (dict str -> Descriptor) Same Descriptor
251       objects as in |nested_types|, but indexed by "name" attribute
252       in each Descriptor.
253
254     enum_types: (list of EnumDescriptors) EnumDescriptor references
255       for all enums contained within this type.
256     enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor
257       objects as in |enum_types|, but indexed by "name" attribute
258       in each EnumDescriptor.
259     enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping
260       from enum value name to EnumValueDescriptor for that value.
261
262     extensions: (list of FieldDescriptor) All extensions defined directly
263       within this message type (NOT within a nested type).
264     extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor
265       objects as |extensions|, but indexed by "name" attribute of each
266       FieldDescriptor.
267
268     is_extendable:  Does this type define any extension ranges?
269
270     oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields
271       in this message.
272     oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|,
273       but indexed by "name" attribute.
274
275     file: (FileDescriptor) Reference to file descriptor.
276   """
277
278   if _USE_C_DESCRIPTORS:
279     _C_DESCRIPTOR_CLASS = _message.Descriptor
280
281     def __new__(cls, name, full_name, filename, containing_type, fields,
282                 nested_types, enum_types, extensions, options=None,
283                 serialized_options=None,
284                 is_extendable=True, extension_ranges=None, oneofs=None,
285                 file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
286                 syntax=None):
287       _message.Message._CheckCalledFromGeneratedFile()
288       return _message.default_pool.FindMessageTypeByName(full_name)
289
290   # NOTE(tmarek): The file argument redefining a builtin is nothing we can
291   # fix right now since we don't know how many clients already rely on the
292   # name of the argument.
293   def __init__(self, name, full_name, filename, containing_type, fields,
294                nested_types, enum_types, extensions, options=None,
295                serialized_options=None,
296                is_extendable=True, extension_ranges=None, oneofs=None,
297                file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
298                syntax=None):
299     """Arguments to __init__() are as described in the description
300     of Descriptor fields above.
301
302     Note that filename is an obsolete argument, that is not used anymore.
303     Please use file.name to access this as an attribute.
304     """
305     super(Descriptor, self).__init__(
306         options, 'MessageOptions', name, full_name, file,
307         containing_type, serialized_start=serialized_start,
308         serialized_end=serialized_end, serialized_options=serialized_options)
309
310     # We have fields in addition to fields_by_name and fields_by_number,
311     # so that:
312     #   1. Clients can index fields by "order in which they're listed."
313     #   2. Clients can easily iterate over all fields with the terse
314     #      syntax: for f in descriptor.fields: ...
315     self.fields = fields
316     for field in self.fields:
317       field.containing_type = self
318     self.fields_by_number = dict((f.number, f) for f in fields)
319     self.fields_by_name = dict((f.name, f) for f in fields)
320     self._fields_by_camelcase_name = None
321
322     self.nested_types = nested_types
323     for nested_type in nested_types:
324       nested_type.containing_type = self
325     self.nested_types_by_name = dict((t.name, t) for t in nested_types)
326
327     self.enum_types = enum_types
328     for enum_type in self.enum_types:
329       enum_type.containing_type = self
330     self.enum_types_by_name = dict((t.name, t) for t in enum_types)
331     self.enum_values_by_name = dict(
332         (v.name, v) for t in enum_types for v in t.values)
333
334     self.extensions = extensions
335     for extension in self.extensions:
336       extension.extension_scope = self
337     self.extensions_by_name = dict((f.name, f) for f in extensions)
338     self.is_extendable = is_extendable
339     self.extension_ranges = extension_ranges
340     self.oneofs = oneofs if oneofs is not None else []
341     self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
342     for oneof in self.oneofs:
343       oneof.containing_type = self
344     self.syntax = syntax or "proto2"
345
346   @property
347   def fields_by_camelcase_name(self):
348     if self._fields_by_camelcase_name is None:
349       self._fields_by_camelcase_name = dict(
350           (f.camelcase_name, f) for f in self.fields)
351     return self._fields_by_camelcase_name
352
353   def EnumValueName(self, enum, value):
354     """Returns the string name of an enum value.
355
356     This is just a small helper method to simplify a common operation.
357
358     Args:
359       enum: string name of the Enum.
360       value: int, value of the enum.
361
362     Returns:
363       string name of the enum value.
364
365     Raises:
366       KeyError if either the Enum doesn't exist or the value is not a valid
367         value for the enum.
368     """
369     return self.enum_types_by_name[enum].values_by_number[value].name
370
371   def CopyToProto(self, proto):
372     """Copies this to a descriptor_pb2.DescriptorProto.
373
374     Args:
375       proto: An empty descriptor_pb2.DescriptorProto.
376     """
377     # This function is overridden to give a better doc comment.
378     super(Descriptor, self).CopyToProto(proto)
379
380
381 # TODO(robinson): We should have aggressive checking here,
382 # for example:
383 #   * If you specify a repeated field, you should not be allowed
384 #     to specify a default value.
385 #   * [Other examples here as needed].
386 #
387 # TODO(robinson): for this and other *Descriptor classes, we
388 # might also want to lock things down aggressively (e.g.,
389 # prevent clients from setting the attributes).  Having
390 # stronger invariants here in general will reduce the number
391 # of runtime checks we must do in reflection.py...
392 class FieldDescriptor(DescriptorBase):
393
394   """Descriptor for a single field in a .proto file.
395
396   A FieldDescriptor instance has the following attributes:
397
398     name: (str) Name of this field, exactly as it appears in .proto.
399     full_name: (str) Name of this field, including containing scope.  This is
400       particularly relevant for extensions.
401     camelcase_name: (str) Camelcase name of this field.
402     index: (int) Dense, 0-indexed index giving the order that this
403       field textually appears within its message in the .proto file.
404     number: (int) Tag number declared for this field in the .proto file.
405
406     type: (One of the TYPE_* constants below) Declared type.
407     cpp_type: (One of the CPPTYPE_* constants below) C++ type used to
408       represent this field.
409
410     label: (One of the LABEL_* constants below) Tells whether this
411       field is optional, required, or repeated.
412     has_default_value: (bool) True if this field has a default value defined,
413       otherwise false.
414     default_value: (Varies) Default value of this field.  Only
415       meaningful for non-repeated scalar fields.  Repeated fields
416       should always set this to [], and non-repeated composite
417       fields should always set this to None.
418
419     containing_type: (Descriptor) Descriptor of the protocol message
420       type that contains this field.  Set by the Descriptor constructor
421       if we're passed into one.
422       Somewhat confusingly, for extension fields, this is the
423       descriptor of the EXTENDED message, not the descriptor
424       of the message containing this field.  (See is_extension and
425       extension_scope below).
426     message_type: (Descriptor) If a composite field, a descriptor
427       of the message type contained in this field.  Otherwise, this is None.
428     enum_type: (EnumDescriptor) If this field contains an enum, a
429       descriptor of that enum.  Otherwise, this is None.
430
431     is_extension: True iff this describes an extension field.
432     extension_scope: (Descriptor) Only meaningful if is_extension is True.
433       Gives the message that immediately contains this extension field.
434       Will be None iff we're a top-level (file-level) extension field.
435
436     options: (descriptor_pb2.FieldOptions) Protocol message field options or
437       None to use default field options.
438
439     containing_oneof: (OneofDescriptor) If the field is a member of a oneof
440       union, contains its descriptor. Otherwise, None.
441
442     file: (FileDescriptor) Reference to file descriptor.
443   """
444
445   # Must be consistent with C++ FieldDescriptor::Type enum in
446   # descriptor.h.
447   #
448   # TODO(robinson): Find a way to eliminate this repetition.
449   TYPE_DOUBLE         = 1
450   TYPE_FLOAT          = 2
451   TYPE_INT64          = 3
452   TYPE_UINT64         = 4
453   TYPE_INT32          = 5
454   TYPE_FIXED64        = 6
455   TYPE_FIXED32        = 7
456   TYPE_BOOL           = 8
457   TYPE_STRING         = 9
458   TYPE_GROUP          = 10
459   TYPE_MESSAGE        = 11
460   TYPE_BYTES          = 12
461   TYPE_UINT32         = 13
462   TYPE_ENUM           = 14
463   TYPE_SFIXED32       = 15
464   TYPE_SFIXED64       = 16
465   TYPE_SINT32         = 17
466   TYPE_SINT64         = 18
467   MAX_TYPE            = 18
468
469   # Must be consistent with C++ FieldDescriptor::CppType enum in
470   # descriptor.h.
471   #
472   # TODO(robinson): Find a way to eliminate this repetition.
473   CPPTYPE_INT32       = 1
474   CPPTYPE_INT64       = 2
475   CPPTYPE_UINT32      = 3
476   CPPTYPE_UINT64      = 4
477   CPPTYPE_DOUBLE      = 5
478   CPPTYPE_FLOAT       = 6
479   CPPTYPE_BOOL        = 7
480   CPPTYPE_ENUM        = 8
481   CPPTYPE_STRING      = 9
482   CPPTYPE_MESSAGE     = 10
483   MAX_CPPTYPE         = 10
484
485   _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
486       TYPE_DOUBLE: CPPTYPE_DOUBLE,
487       TYPE_FLOAT: CPPTYPE_FLOAT,
488       TYPE_ENUM: CPPTYPE_ENUM,
489       TYPE_INT64: CPPTYPE_INT64,
490       TYPE_SINT64: CPPTYPE_INT64,
491       TYPE_SFIXED64: CPPTYPE_INT64,
492       TYPE_UINT64: CPPTYPE_UINT64,
493       TYPE_FIXED64: CPPTYPE_UINT64,
494       TYPE_INT32: CPPTYPE_INT32,
495       TYPE_SFIXED32: CPPTYPE_INT32,
496       TYPE_SINT32: CPPTYPE_INT32,
497       TYPE_UINT32: CPPTYPE_UINT32,
498       TYPE_FIXED32: CPPTYPE_UINT32,
499       TYPE_BYTES: CPPTYPE_STRING,
500       TYPE_STRING: CPPTYPE_STRING,
501       TYPE_BOOL: CPPTYPE_BOOL,
502       TYPE_MESSAGE: CPPTYPE_MESSAGE,
503       TYPE_GROUP: CPPTYPE_MESSAGE
504       }
505
506   # Must be consistent with C++ FieldDescriptor::Label enum in
507   # descriptor.h.
508   #
509   # TODO(robinson): Find a way to eliminate this repetition.
510   LABEL_OPTIONAL      = 1
511   LABEL_REQUIRED      = 2
512   LABEL_REPEATED      = 3
513   MAX_LABEL           = 3
514
515   # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
516   # and kLastReservedNumber in descriptor.h
517   MAX_FIELD_NUMBER = (1 << 29) - 1
518   FIRST_RESERVED_FIELD_NUMBER = 19000
519   LAST_RESERVED_FIELD_NUMBER = 19999
520
521   if _USE_C_DESCRIPTORS:
522     _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
523
524     def __new__(cls, name, full_name, index, number, type, cpp_type, label,
525                 default_value, message_type, enum_type, containing_type,
526                 is_extension, extension_scope, options=None,
527                 serialized_options=None,
528                 has_default_value=True, containing_oneof=None, json_name=None,
529                 file=None):  # pylint: disable=redefined-builtin
530       _message.Message._CheckCalledFromGeneratedFile()
531       if is_extension:
532         return _message.default_pool.FindExtensionByName(full_name)
533       else:
534         return _message.default_pool.FindFieldByName(full_name)
535
536   def __init__(self, name, full_name, index, number, type, cpp_type, label,
537                default_value, message_type, enum_type, containing_type,
538                is_extension, extension_scope, options=None,
539                serialized_options=None,
540                has_default_value=True, containing_oneof=None, json_name=None,
541                file=None):  # pylint: disable=redefined-builtin
542     """The arguments are as described in the description of FieldDescriptor
543     attributes above.
544
545     Note that containing_type may be None, and may be set later if necessary
546     (to deal with circular references between message types, for example).
547     Likewise for extension_scope.
548     """
549     super(FieldDescriptor, self).__init__(
550         options, serialized_options, 'FieldOptions')
551     self.name = name
552     self.full_name = full_name
553     self.file = file
554     self._camelcase_name = None
555     if json_name is None:
556       self.json_name = _ToJsonName(name)
557     else:
558       self.json_name = json_name
559     self.index = index
560     self.number = number
561     self.type = type
562     self.cpp_type = cpp_type
563     self.label = label
564     self.has_default_value = has_default_value
565     self.default_value = default_value
566     self.containing_type = containing_type
567     self.message_type = message_type
568     self.enum_type = enum_type
569     self.is_extension = is_extension
570     self.extension_scope = extension_scope
571     self.containing_oneof = containing_oneof
572     if api_implementation.Type() == 'cpp':
573       if is_extension:
574         self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
575       else:
576         self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
577     else:
578       self._cdescriptor = None
579
580   @property
581   def camelcase_name(self):
582     if self._camelcase_name is None:
583       self._camelcase_name = _ToCamelCase(self.name)
584     return self._camelcase_name
585
586   @staticmethod
587   def ProtoTypeToCppProtoType(proto_type):
588     """Converts from a Python proto type to a C++ Proto Type.
589
590     The Python ProtocolBuffer classes specify both the 'Python' datatype and the
591     'C++' datatype - and they're not the same. This helper method should
592     translate from one to another.
593
594     Args:
595       proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
596     Returns:
597       descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
598     Raises:
599       TypeTransformationError: when the Python proto type isn't known.
600     """
601     try:
602       return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
603     except KeyError:
604       raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
605
606
607 class EnumDescriptor(_NestedDescriptorBase):
608
609   """Descriptor for an enum defined in a .proto file.
610
611   An EnumDescriptor instance has the following attributes:
612
613     name: (str) Name of the enum type.
614     full_name: (str) Full name of the type, including package name
615       and any enclosing type(s).
616
617     values: (list of EnumValueDescriptors) List of the values
618       in this enum.
619     values_by_name: (dict str -> EnumValueDescriptor) Same as |values|,
620       but indexed by the "name" field of each EnumValueDescriptor.
621     values_by_number: (dict int -> EnumValueDescriptor) Same as |values|,
622       but indexed by the "number" field of each EnumValueDescriptor.
623     containing_type: (Descriptor) Descriptor of the immediate containing
624       type of this enum, or None if this is an enum defined at the
625       top level in a .proto file.  Set by Descriptor's constructor
626       if we're passed into one.
627     file: (FileDescriptor) Reference to file descriptor.
628     options: (descriptor_pb2.EnumOptions) Enum options message or
629       None to use default enum options.
630   """
631
632   if _USE_C_DESCRIPTORS:
633     _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
634
635     def __new__(cls, name, full_name, filename, values,
636                 containing_type=None, options=None,
637                 serialized_options=None, file=None,  # pylint: disable=redefined-builtin
638                 serialized_start=None, serialized_end=None):
639       _message.Message._CheckCalledFromGeneratedFile()
640       return _message.default_pool.FindEnumTypeByName(full_name)
641
642   def __init__(self, name, full_name, filename, values,
643                containing_type=None, options=None,
644                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
645                serialized_start=None, serialized_end=None):
646     """Arguments are as described in the attribute description above.
647
648     Note that filename is an obsolete argument, that is not used anymore.
649     Please use file.name to access this as an attribute.
650     """
651     super(EnumDescriptor, self).__init__(
652         options, 'EnumOptions', name, full_name, file,
653         containing_type, serialized_start=serialized_start,
654         serialized_end=serialized_end, serialized_options=serialized_options)
655
656     self.values = values
657     for value in self.values:
658       value.type = self
659     self.values_by_name = dict((v.name, v) for v in values)
660     # Values are reversed to ensure that the first alias is retained.
661     self.values_by_number = dict((v.number, v) for v in reversed(values))
662
663   def CopyToProto(self, proto):
664     """Copies this to a descriptor_pb2.EnumDescriptorProto.
665
666     Args:
667       proto: An empty descriptor_pb2.EnumDescriptorProto.
668     """
669     # This function is overridden to give a better doc comment.
670     super(EnumDescriptor, self).CopyToProto(proto)
671
672
673 class EnumValueDescriptor(DescriptorBase):
674
675   """Descriptor for a single value within an enum.
676
677     name: (str) Name of this value.
678     index: (int) Dense, 0-indexed index giving the order that this
679       value appears textually within its enum in the .proto file.
680     number: (int) Actual number assigned to this enum value.
681     type: (EnumDescriptor) EnumDescriptor to which this value
682       belongs.  Set by EnumDescriptor's constructor if we're
683       passed into one.
684     options: (descriptor_pb2.EnumValueOptions) Enum value options message or
685       None to use default enum value options options.
686   """
687
688   if _USE_C_DESCRIPTORS:
689     _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
690
691     def __new__(cls, name, index, number,
692                 type=None,  # pylint: disable=redefined-builtin
693                 options=None, serialized_options=None):
694       _message.Message._CheckCalledFromGeneratedFile()
695       # There is no way we can build a complete EnumValueDescriptor with the
696       # given parameters (the name of the Enum is not known, for example).
697       # Fortunately generated files just pass it to the EnumDescriptor()
698       # constructor, which will ignore it, so returning None is good enough.
699       return None
700
701   def __init__(self, name, index, number,
702                type=None,  # pylint: disable=redefined-builtin
703                options=None, serialized_options=None):
704     """Arguments are as described in the attribute description above."""
705     super(EnumValueDescriptor, self).__init__(
706         options, serialized_options, 'EnumValueOptions')
707     self.name = name
708     self.index = index
709     self.number = number
710     self.type = type
711
712
713 class OneofDescriptor(DescriptorBase):
714   """Descriptor for a oneof field.
715
716     name: (str) Name of the oneof field.
717     full_name: (str) Full name of the oneof field, including package name.
718     index: (int) 0-based index giving the order of the oneof field inside
719       its containing type.
720     containing_type: (Descriptor) Descriptor of the protocol message
721       type that contains this field.  Set by the Descriptor constructor
722       if we're passed into one.
723     fields: (list of FieldDescriptor) The list of field descriptors this
724       oneof can contain.
725   """
726
727   if _USE_C_DESCRIPTORS:
728     _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
729
730     def __new__(
731         cls, name, full_name, index, containing_type, fields, options=None,
732         serialized_options=None):
733       _message.Message._CheckCalledFromGeneratedFile()
734       return _message.default_pool.FindOneofByName(full_name)
735
736   def __init__(
737       self, name, full_name, index, containing_type, fields, options=None,
738       serialized_options=None):
739     """Arguments are as described in the attribute description above."""
740     super(OneofDescriptor, self).__init__(
741         options, serialized_options, 'OneofOptions')
742     self.name = name
743     self.full_name = full_name
744     self.index = index
745     self.containing_type = containing_type
746     self.fields = fields
747
748
749 class ServiceDescriptor(_NestedDescriptorBase):
750
751   """Descriptor for a service.
752
753     name: (str) Name of the service.
754     full_name: (str) Full name of the service, including package name.
755     index: (int) 0-indexed index giving the order that this services
756       definition appears withing the .proto file.
757     methods: (list of MethodDescriptor) List of methods provided by this
758       service.
759     methods_by_name: (dict str -> MethodDescriptor) Same MethodDescriptor
760       objects as in |methods_by_name|, but indexed by "name" attribute in each
761       MethodDescriptor.
762     options: (descriptor_pb2.ServiceOptions) Service options message or
763       None to use default service options.
764     file: (FileDescriptor) Reference to file info.
765   """
766
767   if _USE_C_DESCRIPTORS:
768     _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
769
770     def __new__(cls, name, full_name, index, methods, options=None,
771                 serialized_options=None, file=None,  # pylint: disable=redefined-builtin
772                 serialized_start=None, serialized_end=None):
773       _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
774       return _message.default_pool.FindServiceByName(full_name)
775
776   def __init__(self, name, full_name, index, methods, options=None,
777                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
778                serialized_start=None, serialized_end=None):
779     super(ServiceDescriptor, self).__init__(
780         options, 'ServiceOptions', name, full_name, file,
781         None, serialized_start=serialized_start,
782         serialized_end=serialized_end, serialized_options=serialized_options)
783     self.index = index
784     self.methods = methods
785     self.methods_by_name = dict((m.name, m) for m in methods)
786     # Set the containing service for each method in this service.
787     for method in self.methods:
788       method.containing_service = self
789
790   def FindMethodByName(self, name):
791     """Searches for the specified method, and returns its descriptor."""
792     return self.methods_by_name.get(name, None)
793
794   def CopyToProto(self, proto):
795     """Copies this to a descriptor_pb2.ServiceDescriptorProto.
796
797     Args:
798       proto: An empty descriptor_pb2.ServiceDescriptorProto.
799     """
800     # This function is overridden to give a better doc comment.
801     super(ServiceDescriptor, self).CopyToProto(proto)
802
803
804 class MethodDescriptor(DescriptorBase):
805
806   """Descriptor for a method in a service.
807
808   name: (str) Name of the method within the service.
809   full_name: (str) Full name of method.
810   index: (int) 0-indexed index of the method inside the service.
811   containing_service: (ServiceDescriptor) The service that contains this
812     method.
813   input_type: The descriptor of the message that this method accepts.
814   output_type: The descriptor of the message that this method returns.
815   options: (descriptor_pb2.MethodOptions) Method options message or
816     None to use default method options.
817   """
818
819   if _USE_C_DESCRIPTORS:
820     _C_DESCRIPTOR_CLASS = _message.MethodDescriptor
821
822     def __new__(cls, name, full_name, index, containing_service,
823                 input_type, output_type, options=None, serialized_options=None):
824       _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
825       return _message.default_pool.FindMethodByName(full_name)
826
827   def __init__(self, name, full_name, index, containing_service,
828                input_type, output_type, options=None, serialized_options=None):
829     """The arguments are as described in the description of MethodDescriptor
830     attributes above.
831
832     Note that containing_service may be None, and may be set later if necessary.
833     """
834     super(MethodDescriptor, self).__init__(
835         options, serialized_options, 'MethodOptions')
836     self.name = name
837     self.full_name = full_name
838     self.index = index
839     self.containing_service = containing_service
840     self.input_type = input_type
841     self.output_type = output_type
842
843
844 class FileDescriptor(DescriptorBase):
845   """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
846
847   Note that enum_types_by_name, extensions_by_name, and dependencies
848   fields are only set by the message_factory module, and not by the
849   generated proto code.
850
851   name: name of file, relative to root of source tree.
852   package: name of the package
853   syntax: string indicating syntax of the file (can be "proto2" or "proto3")
854   serialized_pb: (str) Byte string of serialized
855     descriptor_pb2.FileDescriptorProto.
856   dependencies: List of other FileDescriptors this FileDescriptor depends on.
857   public_dependencies: A list of FileDescriptors, subset of the dependencies
858     above, which were declared as "public".
859   message_types_by_name: Dict of message names and their descriptors.
860   enum_types_by_name: Dict of enum names and their descriptors.
861   extensions_by_name: Dict of extension names and their descriptors.
862   services_by_name: Dict of services names and their descriptors.
863   pool: the DescriptorPool this descriptor belongs to.  When not passed to the
864     constructor, the global default pool is used.
865   """
866
867   if _USE_C_DESCRIPTORS:
868     _C_DESCRIPTOR_CLASS = _message.FileDescriptor
869
870     def __new__(cls, name, package, options=None,
871                 serialized_options=None, serialized_pb=None,
872                 dependencies=None, public_dependencies=None,
873                 syntax=None, pool=None):
874       # FileDescriptor() is called from various places, not only from generated
875       # files, to register dynamic proto files and messages.
876       if serialized_pb:
877         # TODO(amauryfa): use the pool passed as argument. This will work only
878         # for C++-implemented DescriptorPools.
879         return _message.default_pool.AddSerializedFile(serialized_pb)
880       else:
881         return super(FileDescriptor, cls).__new__(cls)
882
883   def __init__(self, name, package, options=None,
884                serialized_options=None, serialized_pb=None,
885                dependencies=None, public_dependencies=None,
886                syntax=None, pool=None):
887     """Constructor."""
888     super(FileDescriptor, self).__init__(
889         options, serialized_options, 'FileOptions')
890
891     if pool is None:
892       from google.protobuf import descriptor_pool
893       pool = descriptor_pool.Default()
894     self.pool = pool
895     self.message_types_by_name = {}
896     self.name = name
897     self.package = package
898     self.syntax = syntax or "proto2"
899     self.serialized_pb = serialized_pb
900
901     self.enum_types_by_name = {}
902     self.extensions_by_name = {}
903     self.services_by_name = {}
904     self.dependencies = (dependencies or [])
905     self.public_dependencies = (public_dependencies or [])
906
907     if (api_implementation.Type() == 'cpp' and
908         self.serialized_pb is not None):
909       _message.default_pool.AddSerializedFile(self.serialized_pb)
910
911   def CopyToProto(self, proto):
912     """Copies this to a descriptor_pb2.FileDescriptorProto.
913
914     Args:
915       proto: An empty descriptor_pb2.FileDescriptorProto.
916     """
917     proto.ParseFromString(self.serialized_pb)
918
919
920 def _ParseOptions(message, string):
921   """Parses serialized options.
922
923   This helper function is used to parse serialized options in generated
924   proto2 files. It must not be used outside proto2.
925   """
926   message.ParseFromString(string)
927   return message
928
929
930 def _ToCamelCase(name):
931   """Converts name to camel-case and returns it."""
932   capitalize_next = False
933   result = []
934
935   for c in name:
936     if c == '_':
937       if result:
938         capitalize_next = True
939     elif capitalize_next:
940       result.append(c.upper())
941       capitalize_next = False
942     else:
943       result += c
944
945   # Lower-case the first letter.
946   if result and result[0].isupper():
947     result[0] = result[0].lower()
948   return ''.join(result)
949
950
951 def _OptionsOrNone(descriptor_proto):
952   """Returns the value of the field `options`, or None if it is not set."""
953   if descriptor_proto.HasField('options'):
954     return descriptor_proto.options
955   else:
956     return None
957
958
959 def _ToJsonName(name):
960   """Converts name to Json name and returns it."""
961   capitalize_next = False
962   result = []
963
964   for c in name:
965     if c == '_':
966       capitalize_next = True
967     elif capitalize_next:
968       result.append(c.upper())
969       capitalize_next = False
970     else:
971       result += c
972
973   return ''.join(result)
974
975
976 def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
977                    syntax=None):
978   """Make a protobuf Descriptor given a DescriptorProto protobuf.
979
980   Handles nested descriptors. Note that this is limited to the scope of defining
981   a message inside of another message. Composite fields can currently only be
982   resolved if the message is defined in the same scope as the field.
983
984   Args:
985     desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
986     package: Optional package name for the new message Descriptor (string).
987     build_file_if_cpp: Update the C++ descriptor pool if api matches.
988                        Set to False on recursion, so no duplicates are created.
989     syntax: The syntax/semantics that should be used.  Set to "proto3" to get
990             proto3 field presence semantics.
991   Returns:
992     A Descriptor for protobuf messages.
993   """
994   if api_implementation.Type() == 'cpp' and build_file_if_cpp:
995     # The C++ implementation requires all descriptors to be backed by the same
996     # definition in the C++ descriptor pool. To do this, we build a
997     # FileDescriptorProto with the same definition as this descriptor and build
998     # it into the pool.
999     from google.protobuf import descriptor_pb2
1000     file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
1001     file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
1002
1003     # Generate a random name for this proto file to prevent conflicts with any
1004     # imported ones. We need to specify a file name so the descriptor pool
1005     # accepts our FileDescriptorProto, but it is not important what that file
1006     # name is actually set to.
1007     proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
1008
1009     if package:
1010       file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
1011                                                 proto_name + '.proto')
1012       file_descriptor_proto.package = package
1013     else:
1014       file_descriptor_proto.name = proto_name + '.proto'
1015
1016     _message.default_pool.Add(file_descriptor_proto)
1017     result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
1018
1019     if _USE_C_DESCRIPTORS:
1020       return result.message_types_by_name[desc_proto.name]
1021
1022   full_message_name = [desc_proto.name]
1023   if package: full_message_name.insert(0, package)
1024
1025   # Create Descriptors for enum types
1026   enum_types = {}
1027   for enum_proto in desc_proto.enum_type:
1028     full_name = '.'.join(full_message_name + [enum_proto.name])
1029     enum_desc = EnumDescriptor(
1030       enum_proto.name, full_name, None, [
1031           EnumValueDescriptor(enum_val.name, ii, enum_val.number)
1032           for ii, enum_val in enumerate(enum_proto.value)])
1033     enum_types[full_name] = enum_desc
1034
1035   # Create Descriptors for nested types
1036   nested_types = {}
1037   for nested_proto in desc_proto.nested_type:
1038     full_name = '.'.join(full_message_name + [nested_proto.name])
1039     # Nested types are just those defined inside of the message, not all types
1040     # used by fields in the message, so no loops are possible here.
1041     nested_desc = MakeDescriptor(nested_proto,
1042                                  package='.'.join(full_message_name),
1043                                  build_file_if_cpp=False,
1044                                  syntax=syntax)
1045     nested_types[full_name] = nested_desc
1046
1047   fields = []
1048   for field_proto in desc_proto.field:
1049     full_name = '.'.join(full_message_name + [field_proto.name])
1050     enum_desc = None
1051     nested_desc = None
1052     if field_proto.json_name:
1053       json_name = field_proto.json_name
1054     else:
1055       json_name = None
1056     if field_proto.HasField('type_name'):
1057       type_name = field_proto.type_name
1058       full_type_name = '.'.join(full_message_name +
1059                                 [type_name[type_name.rfind('.')+1:]])
1060       if full_type_name in nested_types:
1061         nested_desc = nested_types[full_type_name]
1062       elif full_type_name in enum_types:
1063         enum_desc = enum_types[full_type_name]
1064       # Else type_name references a non-local type, which isn't implemented
1065     field = FieldDescriptor(
1066         field_proto.name, full_name, field_proto.number - 1,
1067         field_proto.number, field_proto.type,
1068         FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
1069         field_proto.label, None, nested_desc, enum_desc, None, False, None,
1070         options=_OptionsOrNone(field_proto), has_default_value=False,
1071         json_name=json_name)
1072     fields.append(field)
1073
1074   desc_name = '.'.join(full_message_name)
1075   return Descriptor(desc_proto.name, desc_name, None, None, fields,
1076                     list(nested_types.values()), list(enum_types.values()), [],
1077                     options=_OptionsOrNone(desc_proto))