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