31 """Provides DescriptorPool to use as a container for proto2 descriptors.
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.
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.
41 Below is a straightforward example on how to use this class:
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')
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
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.
58 __author__ =
'matthewtoia@google.com (Matt Toia)'
68 _USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS
72 """Remove leading period from fully-qualified type name.
74 Due to b/13860351 in descriptor_database.py, types in the root namespace are
75 generated with a leading period. This function removes that prefix.
78 name: A str, the fully-qualified symbol name.
81 A str, the normalized fully-qualified symbol name.
83 return name.lstrip(
'.')
87 """Returns the value of the field `options`, or None if it is not set."""
88 if descriptor_proto.HasField(
'options'):
89 return descriptor_proto.options
95 return (field.is_extension
and
96 field.containing_type.has_options
and
97 field.containing_type.GetOptions().message_set_wire_format
and
98 field.type == descriptor.FieldDescriptor.TYPE_MESSAGE
and
99 field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL)
103 """A collection of protobufs dynamically constructed by descriptor protos."""
105 if _USE_C_DESCRIPTORS:
109 return descriptor._message.DescriptorPool(descriptor_db)
112 """Initializes a Pool of proto buffs.
114 The descriptor_db argument to the constructor is provided to allow
115 specialized file descriptor proto lookup code to be triggered on demand. An
116 example would be an implementation which will read and compile a file
117 specified in a call to FindFileByName() and not require the call to Add()
118 at all. Results from this database will be cached internally here as well.
121 descriptor_db: A secondary source of file descriptors.
142 """Check if the descriptor name conflicts with another of the same name.
145 desc: Descriptor of a message, enum, service, extension or enum value.
146 desc_name: the full name of desc.
147 file_name: The file name of descriptor.
149 for register, descriptor_type
in [
155 if desc_name
in register:
156 old_desc = register[desc_name]
158 old_file = old_desc.type.file.name
160 old_file = old_desc.file.name
162 if not isinstance(desc, descriptor_type)
or (
163 old_file != file_name):
164 error_msg = (
'Conflict register for file "' + file_name +
166 ' is already defined in file "' +
167 old_file +
'". Please fix the conflict by adding '
168 'package name on the proto file, or use different '
169 'name for the duplication.')
171 error_msg += (
'\nNote: enum values appear as '
172 'siblings of the enum type instead of '
175 raise TypeError(error_msg)
179 def Add(self, file_desc_proto):
180 """Adds the FileDescriptorProto and its types to this pool.
183 file_desc_proto: The FileDescriptorProto to add.
189 """Adds the FileDescriptorProto and its types to this pool.
192 serialized_file_desc_proto: A bytes string, serialization of the
193 FileDescriptorProto to add.
198 file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
199 serialized_file_desc_proto)
200 self.
Add(file_desc_proto)
203 """Adds a Descriptor to the pool, non-recursively.
205 If the Descriptor contains nested messages or enums, the caller must
206 explicitly register them. This method also registers the FileDescriptor
207 associated with the message.
213 raise TypeError(
'Expected instance of descriptor.Descriptor.')
221 """Adds an EnumDescriptor to the pool.
223 This method also registers the FileDescriptor associated with the enum.
226 enum_desc: An EnumDescriptor.
230 raise TypeError(
'Expected instance of descriptor.EnumDescriptor.')
232 file_name = enum_desc.file.name
239 if enum_desc.file.package:
240 top_level = (enum_desc.full_name.count(
'.')
241 - enum_desc.file.package.count(
'.') == 1)
243 top_level = enum_desc.full_name.count(
'.') == 0
245 file_name = enum_desc.file.name
246 package = enum_desc.file.package
247 for enum_value
in enum_desc.values:
249 '.'.join((package, enum_value.name)))
255 """Adds a ServiceDescriptor to the pool.
258 service_desc: A ServiceDescriptor.
262 raise TypeError(
'Expected instance of descriptor.ServiceDescriptor.')
265 service_desc.file.name)
269 """Adds a FieldDescriptor describing an extension to the pool.
272 extension: A FieldDescriptor.
275 AssertionError: when another extension with the same number extends the
277 TypeError: when the specified extension is not a
278 descriptor.FieldDescriptor.
281 extension.is_extension):
282 raise TypeError(
'Expected an extension descriptor.')
284 if extension.extension_scope
is None:
289 extension.containing_type][extension.number]
293 if extension
is not existing_desc:
294 raise AssertionError(
295 'Extensions "%s" and "%s" both try to extend message type "%s" '
296 'with field number %d.' %
297 (extension.full_name, existing_desc.full_name,
298 extension.containing_type.full_name, extension.number))
301 extension.number] = extension
303 extension.full_name] = extension
308 extension.message_type.full_name] = extension
311 """Adds a FileDescriptor to the pool, non-recursively.
313 If the FileDescriptor contains messages or enums, the caller must explicitly
317 file_desc: A FileDescriptor.
324 for extension
in file_desc.extensions_by_name.values():
326 extension.full_name] = file_desc
329 """Adds a FileDescriptor to the pool, non-recursively.
331 If the FileDescriptor contains messages or enums, the caller must explicitly
335 file_desc: A FileDescriptor.
339 raise TypeError(
'Expected instance of descriptor.FileDescriptor.')
343 """Gets a FileDescriptor by file name.
346 file_name: The path to the file to get a descriptor for.
349 A FileDescriptor for the named file.
352 KeyError: if the file cannot be found in the pool.
362 except KeyError
as error:
368 raise KeyError(
'Cannot find a file named %s' % file_name)
372 """Gets the FileDescriptor for the file containing the specified symbol.
375 symbol: The name of the symbol to search for.
378 A FileDescriptor that contains the specified symbol.
381 KeyError: if the file cannot be found in the pool.
395 raise KeyError(
'Cannot find a file containing %s' % symbol)
398 """Gets the already built FileDescriptor containing the specified symbol.
401 symbol: The name of the symbol to search for.
404 A FileDescriptor that contains the specified symbol.
407 KeyError: if the file cannot be found in the pool.
435 top_name, _, sub_name = symbol.rpartition(
'.')
438 assert (sub_name
in message.extensions_by_name
or
439 sub_name
in message.fields_by_name
or
440 sub_name
in message.enum_values_by_name)
442 except (KeyError, AssertionError):
443 raise KeyError(
'Cannot find a file containing %s' % symbol)
446 """Loads the named descriptor from the pool.
449 full_name: The full name of the descriptor to load.
452 The descriptor for the named type.
455 KeyError: if the message cannot be found in the pool.
464 """Loads the named enum descriptor from the pool.
467 full_name: The full name of the enum descriptor to load.
470 The enum descriptor for the named type.
473 KeyError: if the enum cannot be found in the pool.
482 """Loads the named field descriptor from the pool.
485 full_name: The full name of the field descriptor to load.
488 The field descriptor for the named field.
491 KeyError: if the field cannot be found in the pool.
494 message_name, _, field_name = full_name.rpartition(
'.')
496 return message_descriptor.fields_by_name[field_name]
499 """Loads the named oneof descriptor from the pool.
502 full_name: The full name of the oneof descriptor to load.
505 The oneof descriptor for the named oneof.
508 KeyError: if the oneof cannot be found in the pool.
511 message_name, _, oneof_name = full_name.rpartition(
'.')
513 return message_descriptor.oneofs_by_name[oneof_name]
516 """Loads the named extension descriptor from the pool.
519 full_name: The full name of the extension descriptor to load.
522 A FieldDescriptor, describing the named extension.
525 KeyError: if the extension cannot be found in the pool.
536 message_name, _, extension_name = full_name.rpartition(
'.')
543 return scope.extensions_by_name[extension_name]
546 """Gets the extension of the specified message with the specified number.
548 Extensions have to be registered to this pool by calling
549 AddExtensionDescriptor.
552 message_descriptor: descriptor of the extended message.
553 number: integer, number of the extension field.
556 A FieldDescriptor describing the extension.
559 KeyError: when no extension with the given number is known for the
569 """Gets all the known extension of a given message.
571 Extensions have to be registered to this pool by calling
572 AddExtensionDescriptor.
575 message_descriptor: descriptor of the extended message.
578 A list of FieldDescriptor describing the extensions.
583 full_name = message_descriptor.full_name
584 all_numbers = self.
_descriptor_db.FindAllExtensionNumbers(full_name)
585 for number
in all_numbers:
593 """Try to Load extensions from decriptor db.
596 message_descriptor: descriptor of the extended message.
597 number: the extension number that needs to be loaded.
606 full_name = message_descriptor.full_name
610 if file_proto
is None:
615 for extension
in file_desc.extensions_by_name.values():
617 extension.number] = extension
619 extension.full_name] = extension
620 for message_type
in file_desc.message_types_by_name.values():
621 for extension
in message_type.extensions:
623 extension.number] = extension
625 extension.full_name] = extension
627 warn_msg = (
'Unable to load proto file %s for extension number %d.' %
628 (file_proto.name, number))
629 warnings.warn(warn_msg, RuntimeWarning)
632 """Loads the named service descriptor from the pool.
635 full_name: The full name of the service descriptor to load.
638 The service descriptor for the named service.
641 KeyError: if the service cannot be found in the pool.
649 """Loads the named service method descriptor from the pool.
652 full_name: The full name of the method descriptor to load.
655 The method descriptor for the service method.
658 KeyError: if the method cannot be found in the pool.
661 service_name, _, method_name = full_name.rpartition(
'.')
663 return service_descriptor.methods_by_name[method_name]
666 """Finds the file in descriptor DB containing the specified symbol.
669 symbol: The name of the symbol to search for.
672 A FileDescriptor that contains the specified symbol.
675 KeyError: if the file cannot be found in the descriptor database.
679 except KeyError
as error:
685 raise KeyError(
'Cannot find a file containing %s' % symbol)
689 """Creates a FileDescriptor from a proto or returns a cached copy.
691 This method also has the side effect of loading all the symbols found in
692 the file into the appropriate dictionaries in the pool.
695 file_proto: The proto to convert.
698 A FileDescriptor matching the passed in proto.
701 built_deps = list(self.
_GetDeps(file_proto.dependency))
702 direct_deps = [self.
FindFileByName(n)
for n
in file_proto.dependency]
703 public_deps = [direct_deps[i]
for i
in file_proto.public_dependency]
707 name=file_proto.name,
708 package=file_proto.package,
709 syntax=file_proto.syntax,
711 serialized_pb=file_proto.SerializeToString(),
712 dependencies=direct_deps,
713 public_dependencies=public_deps)
720 for dependency
in built_deps:
722 dependency.message_types_by_name.values()))
724 for enum
in dependency.enum_types_by_name.values())
726 for message_type
in file_proto.message_type:
728 message_type, file_proto.package, file_descriptor, scope,
730 file_descriptor.message_types_by_name[message_desc.name] = (
733 for enum_type
in file_proto.enum_type:
734 file_descriptor.enum_types_by_name[enum_type.name] = (
736 file_descriptor,
None, scope,
True))
738 for index, extension_proto
in enumerate(file_proto.extension):
740 extension_proto, file_proto.package, index, file_descriptor,
743 file_descriptor.package, extension_proto.extendee, scope)
745 file_descriptor.package, scope)
746 file_descriptor.extensions_by_name[extension_desc.name] = (
751 for desc_proto
in file_proto.message_type:
754 if file_proto.package:
757 desc_proto_prefix =
''
759 for desc_proto
in file_proto.message_type:
761 desc_proto_prefix, desc_proto.name, scope)
762 file_descriptor.message_types_by_name[desc_proto.name] = desc
764 for index, service_proto
in enumerate(file_proto.service):
765 file_descriptor.services_by_name[service_proto.name] = (
767 file_proto.package, file_descriptor))
775 scope=None, syntax=None):
776 """Adds the proto to the pool in the specified package.
779 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
780 package: The package the proto should be located in.
781 file_desc: The file containing this message.
782 scope: Dict mapping short and full symbols to message and enum types.
783 syntax: string indicating syntax of the file ("proto2" or "proto3")
786 The added descriptor.
790 desc_name =
'.'.join((package, desc_proto.name))
792 desc_name = desc_proto.name
794 if file_desc
is None:
797 file_name = file_desc.name
804 nested, desc_name, file_desc, scope, syntax)
805 for nested
in desc_proto.nested_type]
809 for enum
in desc_proto.enum_type]
811 for index, field
in enumerate(desc_proto.field)]
815 for index, extension
in enumerate(desc_proto.extension)]
818 index,
None, [], desc.options)
819 for index, desc
in enumerate(desc_proto.oneof_decl)]
820 extension_ranges = [(r.start, r.end)
for r
in desc_proto.extension_range]
824 is_extendable =
False
826 name=desc_proto.name,
829 containing_type=
None,
834 extensions=extensions,
836 is_extendable=is_extendable,
837 extension_ranges=extension_ranges,
839 serialized_start=
None,
842 for nested
in desc.nested_types:
843 nested.containing_type = desc
844 for enum
in desc.enum_types:
845 enum.containing_type = desc
846 for field_index, field_desc
in enumerate(desc_proto.field):
847 if field_desc.HasField(
'oneof_index'):
848 oneof_index = field_desc.oneof_index
849 oneofs[oneof_index].fields.append(fields[field_index])
850 fields[field_index].containing_oneof = oneofs[oneof_index]
858 containing_type=None, scope=None, top_level=False):
859 """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
862 enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
863 package: Optional package name for the new message EnumDescriptor.
864 file_desc: The file containing the enum descriptor.
865 containing_type: The type containing this enum.
866 scope: Scope containing available types.
867 top_level: If True, the enum is a top level symbol. If False, the enum
868 is defined inside a message.
875 enum_name =
'.'.join((package, enum_proto.name))
877 enum_name = enum_proto.name
879 if file_desc
is None:
882 file_name = file_desc.name
885 for index, value
in enumerate(enum_proto.value)]
891 containing_type=containing_type,
893 scope[
'.%s' % enum_name] = desc
901 '.'.join((package, value.name)))
908 file_desc, is_extension=False):
909 """Creates a field descriptor from a FieldDescriptorProto.
911 For message and enum type fields, this method will do a look up
912 in the pool for the appropriate descriptor for that type. If it
913 is unavailable, it will fall back to the _source function to
914 create it. If this type is still unavailable, construction will
918 field_proto: The proto describing the field.
919 message_name: The name of the containing message.
920 index: Index of the field
921 file_desc: The file containing the field descriptor.
922 is_extension: Indication that this field is for an extension.
925 An initialized FieldDescriptor object
929 full_name =
'.'.join((message_name, field_proto.name))
931 full_name = field_proto.name
934 name=field_proto.name,
937 number=field_proto.number,
938 type=field_proto.type,
942 containing_type=
None,
943 label=field_proto.label,
944 has_default_value=
False,
946 is_extension=is_extension,
947 extension_scope=
None,
952 """Sets all the descriptor's fields's types.
954 This method also sets the containing types on any extensions.
957 package: The current package of desc_proto.
958 desc_proto: The message descriptor to update.
959 scope: Enclosing scope of available types.
969 nested_package =
'.'.join([package, desc_proto.name])
971 for field_proto, field_desc
in zip(desc_proto.field, main_desc.fields):
972 self.
_SetFieldType(field_proto, field_desc, nested_package, scope)
974 for extension_proto, extension_desc
in (
975 zip(desc_proto.extension, main_desc.extensions)):
977 nested_package, extension_proto.extendee, scope)
978 self.
_SetFieldType(extension_proto, extension_desc, nested_package, scope)
980 for nested_type
in desc_proto.nested_type:
984 """Sets the field's type, cpp_type, message_type and enum_type.
987 field_proto: Data about the field in proto format.
988 field_desc: The descriptor to modiy.
989 package: The package the field's container is in.
990 scope: Enclosing scope of available types.
992 if field_proto.type_name:
997 if not field_proto.HasField(
'type'):
999 field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
1001 field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
1003 field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
1006 if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
1007 or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
1008 field_desc.message_type = desc
1010 if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1011 field_desc.enum_type = desc
1013 if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
1014 field_desc.has_default_value =
False
1015 field_desc.default_value = []
1016 elif field_proto.HasField(
'default_value'):
1017 field_desc.has_default_value =
True
1018 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE
or
1019 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
1020 field_desc.default_value = float(field_proto.default_value)
1021 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
1022 field_desc.default_value = field_proto.default_value
1023 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
1024 field_desc.default_value = field_proto.default_value.lower() ==
'true'
1025 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1026 field_desc.default_value = field_desc.enum_type.values_by_name[
1027 field_proto.default_value].number
1028 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
1029 field_desc.default_value = text_encoding.CUnescape(
1030 field_proto.default_value)
1031 elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE:
1032 field_desc.default_value =
None
1035 field_desc.default_value = int(field_proto.default_value)
1037 field_desc.has_default_value =
False
1038 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE
or
1039 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
1040 field_desc.default_value = 0.0
1041 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
1042 field_desc.default_value =
u''
1043 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
1044 field_desc.default_value =
False
1045 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1046 field_desc.default_value = field_desc.enum_type.values[0].number
1047 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
1048 field_desc.default_value = b
''
1049 elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE:
1050 field_desc.default_value =
None
1053 field_desc.default_value = 0
1055 field_desc.type = field_proto.type
1058 """Creates a enum value descriptor object from a enum value proto.
1061 value_proto: The proto describing the enum value.
1062 index: The index of the enum value.
1065 An initialized EnumValueDescriptor object.
1069 name=value_proto.name,
1071 number=value_proto.number,
1076 package, file_desc):
1077 """Make a protobuf ServiceDescriptor given a ServiceDescriptorProto.
1080 service_proto: The descriptor_pb2.ServiceDescriptorProto protobuf message.
1081 service_index: The index of the service in the File.
1082 scope: Dict mapping short and full symbols to message and enum types.
1083 package: Optional package name for the new message EnumDescriptor.
1084 file_desc: The file containing the service descriptor.
1087 The added descriptor.
1091 service_name =
'.'.join((package, service_proto.name))
1093 service_name = service_proto.name
1097 for index, method_proto
in enumerate(service_proto.method)]
1099 full_name=service_name,
1100 index=service_index,
1110 """Creates a method descriptor from a MethodDescriptorProto.
1113 method_proto: The proto describing the method.
1114 service_name: The name of the containing service.
1115 package: Optional package name to look up for types.
1116 scope: Scope containing available types.
1117 index: Index of the method in the service.
1120 An initialized MethodDescriptor object.
1122 full_name =
'.'.join((service_name, method_proto.name))
1124 package, method_proto.input_type, scope)
1126 package, method_proto.output_type, scope)
1128 full_name=full_name,
1130 containing_service=
None,
1131 input_type=input_type,
1132 output_type=output_type,
1136 """Pulls out all the symbols from descriptor protos.
1139 descriptors: The messages to extract descriptors from.
1141 A two element tuple of the type name and descriptor object.
1144 for desc
in descriptors:
1148 for enum
in desc.enum_types:
1152 """Recursively finds dependencies for file protos.
1155 dependencies: The names of the files being depended on.
1158 Each direct and indirect dependency.
1161 for dependency
in dependencies:
1164 for parent_dep
in dep_desc.dependencies:
1168 """Finds a given type name in the current scope.
1171 package: The package the proto should be located in.
1172 type_name: The name of the type to be found in the scope.
1173 scope: Dict mapping short and full symbols to message and enum types.
1176 The descriptor for the requested type.
1178 if type_name
not in scope:
1181 possible_match =
'.'.join(components + [type_name])
1182 if possible_match
in scope:
1183 type_name = possible_match
1187 return scope[type_name]
1191 return name
if name.startswith(
'.')
else '.%s' % name
1194 if _USE_C_DESCRIPTORS:
1198 _DEFAULT = descriptor._message.default_pool