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 """Mark functions as deprecated."""
74 def NewFunc(*args, **kwargs):
76 'Call to deprecated function %s(). Note: Do add unlinked descriptors '
77 'to descriptor_pool is wrong. Use Add() or AddSerializedFile() '
78 'instead.' % func.__name__,
79 category=DeprecationWarning)
80 return func(*args, **kwargs)
81 NewFunc.__name__ = func.__name__
82 NewFunc.__doc__ = func.__doc__
83 NewFunc.__dict__.update(func.__dict__)
88 """Remove leading period from fully-qualified type name.
90 Due to b/13860351 in descriptor_database.py, types in the root namespace are
91 generated with a leading period. This function removes that prefix.
94 name (str): The fully-qualified symbol name.
97 str: The normalized fully-qualified symbol name.
99 return name.lstrip(
'.')
103 """Returns the value of the field `options`, or None if it is not set."""
104 if descriptor_proto.HasField(
'options'):
105 return descriptor_proto.options
111 return (field.is_extension
and
112 field.containing_type.has_options
and
113 field.containing_type.GetOptions().message_set_wire_format
and
114 field.type == descriptor.FieldDescriptor.TYPE_MESSAGE
and
115 field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL)
119 """A collection of protobufs dynamically constructed by descriptor protos."""
121 if _USE_C_DESCRIPTORS:
125 return descriptor._message.DescriptorPool(descriptor_db)
128 """Initializes a Pool of proto buffs.
130 The descriptor_db argument to the constructor is provided to allow
131 specialized file descriptor proto lookup code to be triggered on demand. An
132 example would be an implementation which will read and compile a file
133 specified in a call to FindFileByName() and not require the call to Add()
134 at all. Results from this database will be cached internally here as well.
137 descriptor_db: A secondary source of file descriptors.
158 """Check if the descriptor name conflicts with another of the same name.
161 desc: Descriptor of a message, enum, service, extension or enum value.
162 desc_name (str): the full name of desc.
163 file_name (str): The file name of descriptor.
165 for register, descriptor_type
in [
171 if desc_name
in register:
172 old_desc = register[desc_name]
174 old_file = old_desc.type.file.name
176 old_file = old_desc.file.name
178 if not isinstance(desc, descriptor_type)
or (
179 old_file != file_name):
180 error_msg = (
'Conflict register for file "' + file_name +
182 ' is already defined in file "' +
183 old_file +
'". Please fix the conflict by adding '
184 'package name on the proto file, or use different '
185 'name for the duplication.')
187 error_msg += (
'\nNote: enum values appear as '
188 'siblings of the enum type instead of '
191 raise TypeError(error_msg)
195 def Add(self, file_desc_proto):
196 """Adds the FileDescriptorProto and its types to this pool.
199 file_desc_proto (FileDescriptorProto): The file descriptor to add.
205 """Adds the FileDescriptorProto and its types to this pool.
208 serialized_file_desc_proto (bytes): A bytes string, serialization of the
209 :class:`FileDescriptorProto` to add.
212 FileDescriptor: Descriptor for the added file.
217 file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
218 serialized_file_desc_proto)
220 file_desc.serialized_pb = serialized_file_desc_proto
231 """Adds a Descriptor to the pool, non-recursively.
233 If the Descriptor contains nested messages or enums, the caller must
234 explicitly register them. This method also registers the FileDescriptor
235 associated with the message.
241 raise TypeError(
'Expected instance of descriptor.Descriptor.')
256 """Adds an EnumDescriptor to the pool.
258 This method also registers the FileDescriptor associated with the enum.
261 enum_desc: An EnumDescriptor.
265 raise TypeError(
'Expected instance of descriptor.EnumDescriptor.')
267 file_name = enum_desc.file.name
274 if enum_desc.file.package:
275 top_level = (enum_desc.full_name.count(
'.')
276 - enum_desc.file.package.count(
'.') == 1)
278 top_level = enum_desc.full_name.count(
'.') == 0
280 file_name = enum_desc.file.name
281 package = enum_desc.file.package
282 for enum_value
in enum_desc.values:
284 '.'.join((package, enum_value.name)))
297 """Adds a ServiceDescriptor to the pool.
300 service_desc: A ServiceDescriptor.
304 raise TypeError(
'Expected instance of descriptor.ServiceDescriptor.')
307 service_desc.file.name)
318 """Adds a FieldDescriptor describing an extension to the pool.
321 extension: A FieldDescriptor.
324 AssertionError: when another extension with the same number extends the
326 TypeError: when the specified extension is not a
327 descriptor.FieldDescriptor.
330 extension.is_extension):
331 raise TypeError(
'Expected an extension descriptor.')
333 if extension.extension_scope
is None:
338 extension.containing_type][extension.number]
342 if extension
is not existing_desc:
343 raise AssertionError(
344 'Extensions "%s" and "%s" both try to extend message type "%s" '
345 'with field number %d.' %
346 (extension.full_name, existing_desc.full_name,
347 extension.containing_type.full_name, extension.number))
350 extension.number] = extension
352 extension.full_name] = extension
357 extension.message_type.full_name] = extension
365 """Adds a FileDescriptor to the pool, non-recursively.
367 If the FileDescriptor contains messages or enums, the caller must explicitly
371 file_desc: A FileDescriptor.
378 for extension
in file_desc.extensions_by_name.values():
380 extension.full_name] = file_desc
383 """Adds a FileDescriptor to the pool, non-recursively.
385 If the FileDescriptor contains messages or enums, the caller must explicitly
389 file_desc: A FileDescriptor.
393 raise TypeError(
'Expected instance of descriptor.FileDescriptor.')
397 """Gets a FileDescriptor by file name.
400 file_name (str): The path to the file to get a descriptor for.
403 FileDescriptor: The descriptor for the named file.
406 KeyError: if the file cannot be found in the pool.
416 except KeyError
as error:
422 raise KeyError(
'Cannot find a file named %s' % file_name)
426 """Gets the FileDescriptor for the file containing the specified symbol.
429 symbol (str): The name of the symbol to search for.
432 FileDescriptor: Descriptor for the file that contains the specified
436 KeyError: if the file cannot be found in the pool.
450 raise KeyError(
'Cannot find a file containing %s' % symbol)
453 """Gets the already built FileDescriptor containing the specified symbol.
456 symbol (str): The name of the symbol to search for.
459 FileDescriptor: Descriptor for the file that contains the specified
463 KeyError: if the file cannot be found in the pool.
491 top_name, _, sub_name = symbol.rpartition(
'.')
494 assert (sub_name
in message.extensions_by_name
or
495 sub_name
in message.fields_by_name
or
496 sub_name
in message.enum_values_by_name)
498 except (KeyError, AssertionError):
499 raise KeyError(
'Cannot find a file containing %s' % symbol)
502 """Loads the named descriptor from the pool.
505 full_name (str): The full name of the descriptor to load.
508 Descriptor: The descriptor for the named type.
511 KeyError: if the message cannot be found in the pool.
520 """Loads the named enum descriptor from the pool.
523 full_name (str): The full name of the enum descriptor to load.
526 EnumDescriptor: The enum descriptor for the named type.
529 KeyError: if the enum cannot be found in the pool.
538 """Loads the named field descriptor from the pool.
541 full_name (str): The full name of the field descriptor to load.
544 FieldDescriptor: The field descriptor for the named field.
547 KeyError: if the field cannot be found in the pool.
550 message_name, _, field_name = full_name.rpartition(
'.')
552 return message_descriptor.fields_by_name[field_name]
555 """Loads the named oneof descriptor from the pool.
558 full_name (str): The full name of the oneof descriptor to load.
561 OneofDescriptor: The oneof descriptor for the named oneof.
564 KeyError: if the oneof cannot be found in the pool.
567 message_name, _, oneof_name = full_name.rpartition(
'.')
569 return message_descriptor.oneofs_by_name[oneof_name]
572 """Loads the named extension descriptor from the pool.
575 full_name (str): The full name of the extension descriptor to load.
578 FieldDescriptor: The field descriptor for the named extension.
581 KeyError: if the extension cannot be found in the pool.
592 message_name, _, extension_name = full_name.rpartition(
'.')
599 return scope.extensions_by_name[extension_name]
602 """Gets the extension of the specified message with the specified number.
604 Extensions have to be registered to this pool by calling :func:`Add` or
605 :func:`AddExtensionDescriptor`.
608 message_descriptor (Descriptor): descriptor of the extended message.
609 number (int): Number of the extension field.
612 FieldDescriptor: The descriptor for the extension.
615 KeyError: when no extension with the given number is known for the
625 """Gets all the known extensions of a given message.
627 Extensions have to be registered to this pool by build related
628 :func:`Add` or :func:`AddExtensionDescriptor`.
631 message_descriptor (Descriptor): Descriptor of the extended message.
634 list[FieldDescriptor]: Field descriptors describing the extensions.
639 full_name = message_descriptor.full_name
640 all_numbers = self.
_descriptor_db.FindAllExtensionNumbers(full_name)
641 for number
in all_numbers:
649 """Try to Load extensions from descriptor db.
652 message_descriptor: descriptor of the extended message.
653 number: the extension number that needs to be loaded.
662 full_name = message_descriptor.full_name
666 if file_proto
is None:
672 warn_msg = (
'Unable to load proto file %s for extension number %d.' %
673 (file_proto.name, number))
674 warnings.warn(warn_msg, RuntimeWarning)
677 """Loads the named service descriptor from the pool.
680 full_name (str): The full name of the service descriptor to load.
683 ServiceDescriptor: The service descriptor for the named service.
686 KeyError: if the service cannot be found in the pool.
694 """Loads the named service method descriptor from the pool.
697 full_name (str): The full name of the method descriptor to load.
700 MethodDescriptor: The method descriptor for the service method.
703 KeyError: if the method cannot be found in the pool.
706 service_name, _, method_name = full_name.rpartition(
'.')
708 return service_descriptor.methods_by_name[method_name]
711 """Finds the file in descriptor DB containing the specified symbol.
714 symbol (str): The name of the symbol to search for.
717 FileDescriptor: The file that contains the specified symbol.
720 KeyError: if the file cannot be found in the descriptor database.
724 except KeyError
as error:
730 raise KeyError(
'Cannot find a file containing %s' % symbol)
734 """Creates a FileDescriptor from a proto or returns a cached copy.
736 This method also has the side effect of loading all the symbols found in
737 the file into the appropriate dictionaries in the pool.
740 file_proto: The proto to convert.
743 A FileDescriptor matching the passed in proto.
746 built_deps = list(self.
_GetDeps(file_proto.dependency))
747 direct_deps = [self.
FindFileByName(n)
for n
in file_proto.dependency]
748 public_deps = [direct_deps[i]
for i
in file_proto.public_dependency]
752 name=file_proto.name,
753 package=file_proto.package,
754 syntax=file_proto.syntax,
756 serialized_pb=file_proto.SerializeToString(),
757 dependencies=direct_deps,
758 public_dependencies=public_deps,
760 create_key=descriptor._internal_create_key)
767 for dependency
in built_deps:
769 dependency.message_types_by_name.values()))
771 for enum
in dependency.enum_types_by_name.values())
773 for message_type
in file_proto.message_type:
775 message_type, file_proto.package, file_descriptor, scope,
777 file_descriptor.message_types_by_name[message_desc.name] = (
780 for enum_type
in file_proto.enum_type:
781 file_descriptor.enum_types_by_name[enum_type.name] = (
783 file_descriptor,
None, scope,
True))
785 for index, extension_proto
in enumerate(file_proto.extension):
787 extension_proto, file_proto.package, index, file_descriptor,
790 file_descriptor.package, extension_proto.extendee, scope)
792 file_descriptor.package, scope)
793 file_descriptor.extensions_by_name[extension_desc.name] = (
798 for desc_proto
in file_proto.message_type:
801 if file_proto.package:
804 desc_proto_prefix =
''
806 for desc_proto
in file_proto.message_type:
808 desc_proto_prefix, desc_proto.name, scope)
809 file_descriptor.message_types_by_name[desc_proto.name] = desc
811 for index, service_proto
in enumerate(file_proto.service):
812 file_descriptor.services_by_name[service_proto.name] = (
814 file_proto.package, file_descriptor))
820 for extension
in file_desc.extensions_by_name.values():
822 for message_type
in file_desc.message_types_by_name.values():
823 for extension
in message_type.extensions:
829 scope=None, syntax=None):
830 """Adds the proto to the pool in the specified package.
833 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
834 package: The package the proto should be located in.
835 file_desc: The file containing this message.
836 scope: Dict mapping short and full symbols to message and enum types.
837 syntax: string indicating syntax of the file ("proto2" or "proto3")
840 The added descriptor.
844 desc_name =
'.'.join((package, desc_proto.name))
846 desc_name = desc_proto.name
848 if file_desc
is None:
851 file_name = file_desc.name
858 nested, desc_name, file_desc, scope, syntax)
859 for nested
in desc_proto.nested_type]
863 for enum
in desc_proto.enum_type]
865 for index, field
in enumerate(desc_proto.field)]
869 for index, extension
in enumerate(desc_proto.extension)]
874 '.'.join((desc_name, desc.name)),
880 create_key=descriptor._internal_create_key)
881 for index, desc
in enumerate(desc_proto.oneof_decl)
883 extension_ranges = [(r.start, r.end)
for r
in desc_proto.extension_range]
887 is_extendable =
False
889 name=desc_proto.name,
892 containing_type=
None,
897 extensions=extensions,
899 is_extendable=is_extendable,
900 extension_ranges=extension_ranges,
902 serialized_start=
None,
906 create_key=descriptor._internal_create_key)
907 for nested
in desc.nested_types:
908 nested.containing_type = desc
909 for enum
in desc.enum_types:
910 enum.containing_type = desc
911 for field_index, field_desc
in enumerate(desc_proto.field):
912 if field_desc.HasField(
'oneof_index'):
913 oneof_index = field_desc.oneof_index
914 oneofs[oneof_index].fields.append(fields[field_index])
915 fields[field_index].containing_oneof = oneofs[oneof_index]
923 containing_type=None, scope=None, top_level=False):
924 """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
927 enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
928 package: Optional package name for the new message EnumDescriptor.
929 file_desc: The file containing the enum descriptor.
930 containing_type: The type containing this enum.
931 scope: Scope containing available types.
932 top_level: If True, the enum is a top level symbol. If False, the enum
933 is defined inside a message.
940 enum_name =
'.'.join((package, enum_proto.name))
942 enum_name = enum_proto.name
944 if file_desc
is None:
947 file_name = file_desc.name
950 for index, value
in enumerate(enum_proto.value)]
956 containing_type=containing_type,
959 create_key=descriptor._internal_create_key)
960 scope[
'.%s' % enum_name] = desc
968 '.'.join((package, value.name)))
975 file_desc, is_extension=False):
976 """Creates a field descriptor from a FieldDescriptorProto.
978 For message and enum type fields, this method will do a look up
979 in the pool for the appropriate descriptor for that type. If it
980 is unavailable, it will fall back to the _source function to
981 create it. If this type is still unavailable, construction will
985 field_proto: The proto describing the field.
986 message_name: The name of the containing message.
987 index: Index of the field
988 file_desc: The file containing the field descriptor.
989 is_extension: Indication that this field is for an extension.
992 An initialized FieldDescriptor object
996 full_name =
'.'.join((message_name, field_proto.name))
998 full_name = field_proto.name
1000 if field_proto.json_name:
1001 json_name = field_proto.json_name
1006 name=field_proto.name,
1007 full_name=full_name,
1009 number=field_proto.number,
1010 type=field_proto.type,
1014 containing_type=
None,
1015 label=field_proto.label,
1016 has_default_value=
False,
1018 is_extension=is_extension,
1019 extension_scope=
None,
1021 json_name=json_name,
1024 create_key=descriptor._internal_create_key)
1027 """Sets all the descriptor's fields's types.
1029 This method also sets the containing types on any extensions.
1032 package: The current package of desc_proto.
1033 desc_proto: The message descriptor to update.
1034 scope: Enclosing scope of available types.
1044 nested_package =
'.'.join([package, desc_proto.name])
1046 for field_proto, field_desc
in zip(desc_proto.field, main_desc.fields):
1047 self.
_SetFieldType(field_proto, field_desc, nested_package, scope)
1049 for extension_proto, extension_desc
in (
1050 zip(desc_proto.extension, main_desc.extensions)):
1052 nested_package, extension_proto.extendee, scope)
1053 self.
_SetFieldType(extension_proto, extension_desc, nested_package, scope)
1055 for nested_type
in desc_proto.nested_type:
1059 """Sets the field's type, cpp_type, message_type and enum_type.
1062 field_proto: Data about the field in proto format.
1063 field_desc: The descriptor to modify.
1064 package: The package the field's container is in.
1065 scope: Enclosing scope of available types.
1067 if field_proto.type_name:
1072 if not field_proto.HasField(
'type'):
1074 field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
1076 field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
1078 field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
1081 if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
1082 or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
1083 field_desc.message_type = desc
1085 if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1086 field_desc.enum_type = desc
1088 if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
1089 field_desc.has_default_value =
False
1090 field_desc.default_value = []
1091 elif field_proto.HasField(
'default_value'):
1092 field_desc.has_default_value =
True
1093 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE
or
1094 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
1095 field_desc.default_value = float(field_proto.default_value)
1096 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
1097 field_desc.default_value = field_proto.default_value
1098 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
1099 field_desc.default_value = field_proto.default_value.lower() ==
'true'
1100 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1101 field_desc.default_value = field_desc.enum_type.values_by_name[
1102 field_proto.default_value].number
1103 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
1104 field_desc.default_value = text_encoding.CUnescape(
1105 field_proto.default_value)
1106 elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE:
1107 field_desc.default_value =
None
1110 field_desc.default_value =
int(field_proto.default_value)
1112 field_desc.has_default_value =
False
1113 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE
or
1114 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
1115 field_desc.default_value = 0.0
1116 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
1117 field_desc.default_value =
u''
1118 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
1119 field_desc.default_value =
False
1120 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
1121 field_desc.default_value = field_desc.enum_type.values[0].number
1122 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
1123 field_desc.default_value = b
''
1124 elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE:
1125 field_desc.default_value =
None
1126 elif field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP:
1127 field_desc.default_value =
None
1130 field_desc.default_value = 0
1132 field_desc.type = field_proto.type
1135 """Creates a enum value descriptor object from a enum value proto.
1138 value_proto: The proto describing the enum value.
1139 index: The index of the enum value.
1142 An initialized EnumValueDescriptor object.
1146 name=value_proto.name,
1148 number=value_proto.number,
1152 create_key=descriptor._internal_create_key)
1155 package, file_desc):
1156 """Make a protobuf ServiceDescriptor given a ServiceDescriptorProto.
1159 service_proto: The descriptor_pb2.ServiceDescriptorProto protobuf message.
1160 service_index: The index of the service in the File.
1161 scope: Dict mapping short and full symbols to message and enum types.
1162 package: Optional package name for the new message EnumDescriptor.
1163 file_desc: The file containing the service descriptor.
1166 The added descriptor.
1170 service_name =
'.'.join((package, service_proto.name))
1172 service_name = service_proto.name
1176 for index, method_proto
in enumerate(service_proto.method)]
1178 name=service_proto.name,
1179 full_name=service_name,
1180 index=service_index,
1185 create_key=descriptor._internal_create_key)
1192 """Creates a method descriptor from a MethodDescriptorProto.
1195 method_proto: The proto describing the method.
1196 service_name: The name of the containing service.
1197 package: Optional package name to look up for types.
1198 scope: Scope containing available types.
1199 index: Index of the method in the service.
1202 An initialized MethodDescriptor object.
1204 full_name =
'.'.join((service_name, method_proto.name))
1206 package, method_proto.input_type, scope)
1208 package, method_proto.output_type, scope)
1210 name=method_proto.name,
1211 full_name=full_name,
1213 containing_service=
None,
1214 input_type=input_type,
1215 output_type=output_type,
1218 create_key=descriptor._internal_create_key)
1221 """Pulls out all the symbols from descriptor protos.
1224 descriptors: The messages to extract descriptors from.
1226 A two element tuple of the type name and descriptor object.
1229 for desc
in descriptors:
1233 for enum
in desc.enum_types:
1237 """Recursively finds dependencies for file protos.
1240 dependencies: The names of the files being depended on.
1243 Each direct and indirect dependency.
1246 for dependency
in dependencies:
1249 for parent_dep
in dep_desc.dependencies:
1253 """Finds a given type name in the current scope.
1256 package: The package the proto should be located in.
1257 type_name: The name of the type to be found in the scope.
1258 scope: Dict mapping short and full symbols to message and enum types.
1261 The descriptor for the requested type.
1263 if type_name
not in scope:
1266 possible_match =
'.'.join(components + [type_name])
1267 if possible_match
in scope:
1268 type_name = possible_match
1272 return scope[type_name]
1276 return name
if name.startswith(
'.')
else '.%s' % name
1279 if _USE_C_DESCRIPTORS:
1283 _DEFAULT = descriptor._message.default_pool