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 """Provides DescriptorPool to use as a container for proto2 descriptors.
     32 
     33 The DescriptorPool is used in conjection with a DescriptorDatabase to maintain
     34 a collection of protocol buffer descriptors for use when dynamically creating
     35 message types at runtime.
     36 
     37 For most applications protocol buffers should be used via modules generated by
     38 the protocol buffer compiler tool. This should only be used when the type of
     39 protocol buffers used in an application or library cannot be predetermined.
     40 
     41 Below is a straightforward example on how to use this class:
     42 
     43   pool = DescriptorPool()
     44   file_descriptor_protos = [ ... ]
     45   for file_descriptor_proto in file_descriptor_protos:
     46     pool.Add(file_descriptor_proto)
     47   my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType')
     48 
     49 The message descriptor can be used in conjunction with the message_factory
     50 module in order to create a protocol buffer class that can be encoded and
     51 decoded.
     52 
     53 If you want to get a Python class for the specified proto, use the
     54 helper functions inside google.protobuf.message_factory
     55 directly instead of this class.
     56 """
     57 
     58 __author__ = 'matthewtoia (at] google.com (Matt Toia)'
     59 
     60 from google.protobuf import descriptor
     61 from google.protobuf import descriptor_database
     62 from google.protobuf import text_encoding
     63 
     64 
     65 _USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS
     66 
     67 
     68 def _NormalizeFullyQualifiedName(name):
     69   """Remove leading period from fully-qualified type name.
     70 
     71   Due to b/13860351 in descriptor_database.py, types in the root namespace are
     72   generated with a leading period. This function removes that prefix.
     73 
     74   Args:
     75     name: A str, the fully-qualified symbol name.
     76 
     77   Returns:
     78     A str, the normalized fully-qualified symbol name.
     79   """
     80   return name.lstrip('.')
     81 
     82 
     83 class DescriptorPool(object):
     84   """A collection of protobufs dynamically constructed by descriptor protos."""
     85 
     86   if _USE_C_DESCRIPTORS:
     87 
     88     def __new__(cls, descriptor_db=None):
     89       # pylint: disable=protected-access
     90       return descriptor._message.DescriptorPool(descriptor_db)
     91 
     92   def __init__(self, descriptor_db=None):
     93     """Initializes a Pool of proto buffs.
     94 
     95     The descriptor_db argument to the constructor is provided to allow
     96     specialized file descriptor proto lookup code to be triggered on demand. An
     97     example would be an implementation which will read and compile a file
     98     specified in a call to FindFileByName() and not require the call to Add()
     99     at all. Results from this database will be cached internally here as well.
    100 
    101     Args:
    102       descriptor_db: A secondary source of file descriptors.
    103     """
    104 
    105     self._internal_db = descriptor_database.DescriptorDatabase()
    106     self._descriptor_db = descriptor_db
    107     self._descriptors = {}
    108     self._enum_descriptors = {}
    109     self._file_descriptors = {}
    110 
    111   def Add(self, file_desc_proto):
    112     """Adds the FileDescriptorProto and its types to this pool.
    113 
    114     Args:
    115       file_desc_proto: The FileDescriptorProto to add.
    116     """
    117 
    118     self._internal_db.Add(file_desc_proto)
    119 
    120   def AddSerializedFile(self, serialized_file_desc_proto):
    121     """Adds the FileDescriptorProto and its types to this pool.
    122 
    123     Args:
    124       serialized_file_desc_proto: A bytes string, serialization of the
    125         FileDescriptorProto to add.
    126     """
    127 
    128     # pylint: disable=g-import-not-at-top
    129     from google.protobuf import descriptor_pb2
    130     file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
    131         serialized_file_desc_proto)
    132     self.Add(file_desc_proto)
    133 
    134   def AddDescriptor(self, desc):
    135     """Adds a Descriptor to the pool, non-recursively.
    136 
    137     If the Descriptor contains nested messages or enums, the caller must
    138     explicitly register them. This method also registers the FileDescriptor
    139     associated with the message.
    140 
    141     Args:
    142       desc: A Descriptor.
    143     """
    144     if not isinstance(desc, descriptor.Descriptor):
    145       raise TypeError('Expected instance of descriptor.Descriptor.')
    146 
    147     self._descriptors[desc.full_name] = desc
    148     self.AddFileDescriptor(desc.file)
    149 
    150   def AddEnumDescriptor(self, enum_desc):
    151     """Adds an EnumDescriptor to the pool.
    152 
    153     This method also registers the FileDescriptor associated with the message.
    154 
    155     Args:
    156       enum_desc: An EnumDescriptor.
    157     """
    158 
    159     if not isinstance(enum_desc, descriptor.EnumDescriptor):
    160       raise TypeError('Expected instance of descriptor.EnumDescriptor.')
    161 
    162     self._enum_descriptors[enum_desc.full_name] = enum_desc
    163     self.AddFileDescriptor(enum_desc.file)
    164 
    165   def AddFileDescriptor(self, file_desc):
    166     """Adds a FileDescriptor to the pool, non-recursively.
    167 
    168     If the FileDescriptor contains messages or enums, the caller must explicitly
    169     register them.
    170 
    171     Args:
    172       file_desc: A FileDescriptor.
    173     """
    174 
    175     if not isinstance(file_desc, descriptor.FileDescriptor):
    176       raise TypeError('Expected instance of descriptor.FileDescriptor.')
    177     self._file_descriptors[file_desc.name] = file_desc
    178 
    179   def FindFileByName(self, file_name):
    180     """Gets a FileDescriptor by file name.
    181 
    182     Args:
    183       file_name: The path to the file to get a descriptor for.
    184 
    185     Returns:
    186       A FileDescriptor for the named file.
    187 
    188     Raises:
    189       KeyError: if the file can not be found in the pool.
    190     """
    191 
    192     try:
    193       return self._file_descriptors[file_name]
    194     except KeyError:
    195       pass
    196 
    197     try:
    198       file_proto = self._internal_db.FindFileByName(file_name)
    199     except KeyError as error:
    200       if self._descriptor_db:
    201         file_proto = self._descriptor_db.FindFileByName(file_name)
    202       else:
    203         raise error
    204     if not file_proto:
    205       raise KeyError('Cannot find a file named %s' % file_name)
    206     return self._ConvertFileProtoToFileDescriptor(file_proto)
    207 
    208   def FindFileContainingSymbol(self, symbol):
    209     """Gets the FileDescriptor for the file containing the specified symbol.
    210 
    211     Args:
    212       symbol: The name of the symbol to search for.
    213 
    214     Returns:
    215       A FileDescriptor that contains the specified symbol.
    216 
    217     Raises:
    218       KeyError: if the file can not be found in the pool.
    219     """
    220 
    221     symbol = _NormalizeFullyQualifiedName(symbol)
    222     try:
    223       return self._descriptors[symbol].file
    224     except KeyError:
    225       pass
    226 
    227     try:
    228       return self._enum_descriptors[symbol].file
    229     except KeyError:
    230       pass
    231 
    232     try:
    233       file_proto = self._internal_db.FindFileContainingSymbol(symbol)
    234     except KeyError as error:
    235       if self._descriptor_db:
    236         file_proto = self._descriptor_db.FindFileContainingSymbol(symbol)
    237       else:
    238         raise error
    239     if not file_proto:
    240       raise KeyError('Cannot find a file containing %s' % symbol)
    241     return self._ConvertFileProtoToFileDescriptor(file_proto)
    242 
    243   def FindMessageTypeByName(self, full_name):
    244     """Loads the named descriptor from the pool.
    245 
    246     Args:
    247       full_name: The full name of the descriptor to load.
    248 
    249     Returns:
    250       The descriptor for the named type.
    251     """
    252 
    253     full_name = _NormalizeFullyQualifiedName(full_name)
    254     if full_name not in self._descriptors:
    255       self.FindFileContainingSymbol(full_name)
    256     return self._descriptors[full_name]
    257 
    258   def FindEnumTypeByName(self, full_name):
    259     """Loads the named enum descriptor from the pool.
    260 
    261     Args:
    262       full_name: The full name of the enum descriptor to load.
    263 
    264     Returns:
    265       The enum descriptor for the named type.
    266     """
    267 
    268     full_name = _NormalizeFullyQualifiedName(full_name)
    269     if full_name not in self._enum_descriptors:
    270       self.FindFileContainingSymbol(full_name)
    271     return self._enum_descriptors[full_name]
    272 
    273   def FindFieldByName(self, full_name):
    274     """Loads the named field descriptor from the pool.
    275 
    276     Args:
    277       full_name: The full name of the field descriptor to load.
    278 
    279     Returns:
    280       The field descriptor for the named field.
    281     """
    282     full_name = _NormalizeFullyQualifiedName(full_name)
    283     message_name, _, field_name = full_name.rpartition('.')
    284     message_descriptor = self.FindMessageTypeByName(message_name)
    285     return message_descriptor.fields_by_name[field_name]
    286 
    287   def FindExtensionByName(self, full_name):
    288     """Loads the named extension descriptor from the pool.
    289 
    290     Args:
    291       full_name: The full name of the extension descriptor to load.
    292 
    293     Returns:
    294       A FieldDescriptor, describing the named extension.
    295     """
    296     full_name = _NormalizeFullyQualifiedName(full_name)
    297     message_name, _, extension_name = full_name.rpartition('.')
    298     try:
    299       # Most extensions are nested inside a message.
    300       scope = self.FindMessageTypeByName(message_name)
    301     except KeyError:
    302       # Some extensions are defined at file scope.
    303       scope = self.FindFileContainingSymbol(full_name)
    304     return scope.extensions_by_name[extension_name]
    305 
    306   def _ConvertFileProtoToFileDescriptor(self, file_proto):
    307     """Creates a FileDescriptor from a proto or returns a cached copy.
    308 
    309     This method also has the side effect of loading all the symbols found in
    310     the file into the appropriate dictionaries in the pool.
    311 
    312     Args:
    313       file_proto: The proto to convert.
    314 
    315     Returns:
    316       A FileDescriptor matching the passed in proto.
    317     """
    318 
    319     if file_proto.name not in self._file_descriptors:
    320       built_deps = list(self._GetDeps(file_proto.dependency))
    321       direct_deps = [self.FindFileByName(n) for n in file_proto.dependency]
    322       public_deps = [direct_deps[i] for i in file_proto.public_dependency]
    323 
    324       file_descriptor = descriptor.FileDescriptor(
    325           pool=self,
    326           name=file_proto.name,
    327           package=file_proto.package,
    328           syntax=file_proto.syntax,
    329           options=file_proto.options,
    330           serialized_pb=file_proto.SerializeToString(),
    331           dependencies=direct_deps,
    332           public_dependencies=public_deps)
    333       if _USE_C_DESCRIPTORS:
    334         # When using C++ descriptors, all objects defined in the file were added
    335         # to the C++ database when the FileDescriptor was built above.
    336         # Just add them to this descriptor pool.
    337         def _AddMessageDescriptor(message_desc):
    338           self._descriptors[message_desc.full_name] = message_desc
    339           for nested in message_desc.nested_types:
    340             _AddMessageDescriptor(nested)
    341           for enum_type in message_desc.enum_types:
    342             _AddEnumDescriptor(enum_type)
    343         def _AddEnumDescriptor(enum_desc):
    344           self._enum_descriptors[enum_desc.full_name] = enum_desc
    345         for message_type in file_descriptor.message_types_by_name.values():
    346           _AddMessageDescriptor(message_type)
    347         for enum_type in file_descriptor.enum_types_by_name.values():
    348           _AddEnumDescriptor(enum_type)
    349       else:
    350         scope = {}
    351 
    352         # This loop extracts all the message and enum types from all the
    353         # dependencies of the file_proto. This is necessary to create the
    354         # scope of available message types when defining the passed in
    355         # file proto.
    356         for dependency in built_deps:
    357           scope.update(self._ExtractSymbols(
    358               dependency.message_types_by_name.values()))
    359           scope.update((_PrefixWithDot(enum.full_name), enum)
    360                        for enum in dependency.enum_types_by_name.values())
    361 
    362         for message_type in file_proto.message_type:
    363           message_desc = self._ConvertMessageDescriptor(
    364               message_type, file_proto.package, file_descriptor, scope,
    365               file_proto.syntax)
    366           file_descriptor.message_types_by_name[message_desc.name] = (
    367               message_desc)
    368 
    369         for enum_type in file_proto.enum_type:
    370           file_descriptor.enum_types_by_name[enum_type.name] = (
    371               self._ConvertEnumDescriptor(enum_type, file_proto.package,
    372                                           file_descriptor, None, scope))
    373 
    374         for index, extension_proto in enumerate(file_proto.extension):
    375           extension_desc = self._MakeFieldDescriptor(
    376               extension_proto, file_proto.package, index, is_extension=True)
    377           extension_desc.containing_type = self._GetTypeFromScope(
    378               file_descriptor.package, extension_proto.extendee, scope)
    379           self._SetFieldType(extension_proto, extension_desc,
    380                             file_descriptor.package, scope)
    381           file_descriptor.extensions_by_name[extension_desc.name] = (
    382               extension_desc)
    383 
    384         for desc_proto in file_proto.message_type:
    385           self._SetAllFieldTypes(file_proto.package, desc_proto, scope)
    386 
    387         if file_proto.package:
    388           desc_proto_prefix = _PrefixWithDot(file_proto.package)
    389         else:
    390           desc_proto_prefix = ''
    391 
    392         for desc_proto in file_proto.message_type:
    393           desc = self._GetTypeFromScope(
    394               desc_proto_prefix, desc_proto.name, scope)
    395           file_descriptor.message_types_by_name[desc_proto.name] = desc
    396 
    397       self.Add(file_proto)
    398       self._file_descriptors[file_proto.name] = file_descriptor
    399 
    400     return self._file_descriptors[file_proto.name]
    401 
    402   def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
    403                                 scope=None, syntax=None):
    404     """Adds the proto to the pool in the specified package.
    405 
    406     Args:
    407       desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
    408       package: The package the proto should be located in.
    409       file_desc: The file containing this message.
    410       scope: Dict mapping short and full symbols to message and enum types.
    411 
    412     Returns:
    413       The added descriptor.
    414     """
    415 
    416     if package:
    417       desc_name = '.'.join((package, desc_proto.name))
    418     else:
    419       desc_name = desc_proto.name
    420 
    421     if file_desc is None:
    422       file_name = None
    423     else:
    424       file_name = file_desc.name
    425 
    426     if scope is None:
    427       scope = {}
    428 
    429     nested = [
    430         self._ConvertMessageDescriptor(
    431             nested, desc_name, file_desc, scope, syntax)
    432         for nested in desc_proto.nested_type]
    433     enums = [
    434         self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
    435         for enum in desc_proto.enum_type]
    436     fields = [self._MakeFieldDescriptor(field, desc_name, index)
    437               for index, field in enumerate(desc_proto.field)]
    438     extensions = [
    439         self._MakeFieldDescriptor(extension, desc_name, index,
    440                                   is_extension=True)
    441         for index, extension in enumerate(desc_proto.extension)]
    442     oneofs = [
    443         descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)),
    444                                    index, None, [])
    445         for index, desc in enumerate(desc_proto.oneof_decl)]
    446     extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
    447     if extension_ranges:
    448       is_extendable = True
    449     else:
    450       is_extendable = False
    451     desc = descriptor.Descriptor(
    452         name=desc_proto.name,
    453         full_name=desc_name,
    454         filename=file_name,
    455         containing_type=None,
    456         fields=fields,
    457         oneofs=oneofs,
    458         nested_types=nested,
    459         enum_types=enums,
    460         extensions=extensions,
    461         options=desc_proto.options,
    462         is_extendable=is_extendable,
    463         extension_ranges=extension_ranges,
    464         file=file_desc,
    465         serialized_start=None,
    466         serialized_end=None,
    467         syntax=syntax)
    468     for nested in desc.nested_types:
    469       nested.containing_type = desc
    470     for enum in desc.enum_types:
    471       enum.containing_type = desc
    472     for field_index, field_desc in enumerate(desc_proto.field):
    473       if field_desc.HasField('oneof_index'):
    474         oneof_index = field_desc.oneof_index
    475         oneofs[oneof_index].fields.append(fields[field_index])
    476         fields[field_index].containing_oneof = oneofs[oneof_index]
    477 
    478     scope[_PrefixWithDot(desc_name)] = desc
    479     self._descriptors[desc_name] = desc
    480     return desc
    481 
    482   def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None,
    483                              containing_type=None, scope=None):
    484     """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
    485 
    486     Args:
    487       enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
    488       package: Optional package name for the new message EnumDescriptor.
    489       file_desc: The file containing the enum descriptor.
    490       containing_type: The type containing this enum.
    491       scope: Scope containing available types.
    492 
    493     Returns:
    494       The added descriptor
    495     """
    496 
    497     if package:
    498       enum_name = '.'.join((package, enum_proto.name))
    499     else:
    500       enum_name = enum_proto.name
    501 
    502     if file_desc is None:
    503       file_name = None
    504     else:
    505       file_name = file_desc.name
    506 
    507     values = [self._MakeEnumValueDescriptor(value, index)
    508               for index, value in enumerate(enum_proto.value)]
    509     desc = descriptor.EnumDescriptor(name=enum_proto.name,
    510                                      full_name=enum_name,
    511                                      filename=file_name,
    512                                      file=file_desc,
    513                                      values=values,
    514                                      containing_type=containing_type,
    515                                      options=enum_proto.options)
    516     scope['.%s' % enum_name] = desc
    517     self._enum_descriptors[enum_name] = desc
    518     return desc
    519 
    520   def _MakeFieldDescriptor(self, field_proto, message_name, index,
    521                            is_extension=False):
    522     """Creates a field descriptor from a FieldDescriptorProto.
    523 
    524     For message and enum type fields, this method will do a look up
    525     in the pool for the appropriate descriptor for that type. If it
    526     is unavailable, it will fall back to the _source function to
    527     create it. If this type is still unavailable, construction will
    528     fail.
    529 
    530     Args:
    531       field_proto: The proto describing the field.
    532       message_name: The name of the containing message.
    533       index: Index of the field
    534       is_extension: Indication that this field is for an extension.
    535 
    536     Returns:
    537       An initialized FieldDescriptor object
    538     """
    539 
    540     if message_name:
    541       full_name = '.'.join((message_name, field_proto.name))
    542     else:
    543       full_name = field_proto.name
    544 
    545     return descriptor.FieldDescriptor(
    546         name=field_proto.name,
    547         full_name=full_name,
    548         index=index,
    549         number=field_proto.number,
    550         type=field_proto.type,
    551         cpp_type=None,
    552         message_type=None,
    553         enum_type=None,
    554         containing_type=None,
    555         label=field_proto.label,
    556         has_default_value=False,
    557         default_value=None,
    558         is_extension=is_extension,
    559         extension_scope=None,
    560         options=field_proto.options)
    561 
    562   def _SetAllFieldTypes(self, package, desc_proto, scope):
    563     """Sets all the descriptor's fields's types.
    564 
    565     This method also sets the containing types on any extensions.
    566 
    567     Args:
    568       package: The current package of desc_proto.
    569       desc_proto: The message descriptor to update.
    570       scope: Enclosing scope of available types.
    571     """
    572 
    573     package = _PrefixWithDot(package)
    574 
    575     main_desc = self._GetTypeFromScope(package, desc_proto.name, scope)
    576 
    577     if package == '.':
    578       nested_package = _PrefixWithDot(desc_proto.name)
    579     else:
    580       nested_package = '.'.join([package, desc_proto.name])
    581 
    582     for field_proto, field_desc in zip(desc_proto.field, main_desc.fields):
    583       self._SetFieldType(field_proto, field_desc, nested_package, scope)
    584 
    585     for extension_proto, extension_desc in (
    586         zip(desc_proto.extension, main_desc.extensions)):
    587       extension_desc.containing_type = self._GetTypeFromScope(
    588           nested_package, extension_proto.extendee, scope)
    589       self._SetFieldType(extension_proto, extension_desc, nested_package, scope)
    590 
    591     for nested_type in desc_proto.nested_type:
    592       self._SetAllFieldTypes(nested_package, nested_type, scope)
    593 
    594   def _SetFieldType(self, field_proto, field_desc, package, scope):
    595     """Sets the field's type, cpp_type, message_type and enum_type.
    596 
    597     Args:
    598       field_proto: Data about the field in proto format.
    599       field_desc: The descriptor to modiy.
    600       package: The package the field's container is in.
    601       scope: Enclosing scope of available types.
    602     """
    603     if field_proto.type_name:
    604       desc = self._GetTypeFromScope(package, field_proto.type_name, scope)
    605     else:
    606       desc = None
    607 
    608     if not field_proto.HasField('type'):
    609       if isinstance(desc, descriptor.Descriptor):
    610         field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
    611       else:
    612         field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
    613 
    614     field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
    615         field_proto.type)
    616 
    617     if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
    618         or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
    619       field_desc.message_type = desc
    620 
    621     if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
    622       field_desc.enum_type = desc
    623 
    624     if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
    625       field_desc.has_default_value = False
    626       field_desc.default_value = []
    627     elif field_proto.HasField('default_value'):
    628       field_desc.has_default_value = True
    629       if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
    630           field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
    631         field_desc.default_value = float(field_proto.default_value)
    632       elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
    633         field_desc.default_value = field_proto.default_value
    634       elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
    635         field_desc.default_value = field_proto.default_value.lower() == 'true'
    636       elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
    637         field_desc.default_value = field_desc.enum_type.values_by_name[
    638             field_proto.default_value].number
    639       elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
    640         field_desc.default_value = text_encoding.CUnescape(
    641             field_proto.default_value)
    642       else:
    643         # All other types are of the "int" type.
    644         field_desc.default_value = int(field_proto.default_value)
    645     else:
    646       field_desc.has_default_value = False
    647       if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
    648           field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
    649         field_desc.default_value = 0.0
    650       elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
    651         field_desc.default_value = u''
    652       elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
    653         field_desc.default_value = False
    654       elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
    655         field_desc.default_value = field_desc.enum_type.values[0].number
    656       elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
    657         field_desc.default_value = b''
    658       else:
    659         # All other types are of the "int" type.
    660         field_desc.default_value = 0
    661 
    662     field_desc.type = field_proto.type
    663 
    664   def _MakeEnumValueDescriptor(self, value_proto, index):
    665     """Creates a enum value descriptor object from a enum value proto.
    666 
    667     Args:
    668       value_proto: The proto describing the enum value.
    669       index: The index of the enum value.
    670 
    671     Returns:
    672       An initialized EnumValueDescriptor object.
    673     """
    674 
    675     return descriptor.EnumValueDescriptor(
    676         name=value_proto.name,
    677         index=index,
    678         number=value_proto.number,
    679         options=value_proto.options,
    680         type=None)
    681 
    682   def _ExtractSymbols(self, descriptors):
    683     """Pulls out all the symbols from descriptor protos.
    684 
    685     Args:
    686       descriptors: The messages to extract descriptors from.
    687     Yields:
    688       A two element tuple of the type name and descriptor object.
    689     """
    690 
    691     for desc in descriptors:
    692       yield (_PrefixWithDot(desc.full_name), desc)
    693       for symbol in self._ExtractSymbols(desc.nested_types):
    694         yield symbol
    695       for enum in desc.enum_types:
    696         yield (_PrefixWithDot(enum.full_name), enum)
    697 
    698   def _GetDeps(self, dependencies):
    699     """Recursively finds dependencies for file protos.
    700 
    701     Args:
    702       dependencies: The names of the files being depended on.
    703 
    704     Yields:
    705       Each direct and indirect dependency.
    706     """
    707 
    708     for dependency in dependencies:
    709       dep_desc = self.FindFileByName(dependency)
    710       yield dep_desc
    711       for parent_dep in dep_desc.dependencies:
    712         yield parent_dep
    713 
    714   def _GetTypeFromScope(self, package, type_name, scope):
    715     """Finds a given type name in the current scope.
    716 
    717     Args:
    718       package: The package the proto should be located in.
    719       type_name: The name of the type to be found in the scope.
    720       scope: Dict mapping short and full symbols to message and enum types.
    721 
    722     Returns:
    723       The descriptor for the requested type.
    724     """
    725     if type_name not in scope:
    726       components = _PrefixWithDot(package).split('.')
    727       while components:
    728         possible_match = '.'.join(components + [type_name])
    729         if possible_match in scope:
    730           type_name = possible_match
    731           break
    732         else:
    733           components.pop(-1)
    734     return scope[type_name]
    735 
    736 
    737 def _PrefixWithDot(name):
    738   return name if name.startswith('.') else '.%s' % name
    739 
    740 
    741 if _USE_C_DESCRIPTORS:
    742   # TODO(amauryfa): This pool could be constructed from Python code, when we
    743   # support a flag like 'use_cpp_generated_pool=True'.
    744   # pylint: disable=protected-access
    745   _DEFAULT = descriptor._message.default_pool
    746 else:
    747   _DEFAULT = DescriptorPool()
    748 
    749 
    750 def Default():
    751   return _DEFAULT
    752