diff options
Diffstat (limited to 'python/google/protobuf/descriptor_database.py')
-rw-r--r-- | python/google/protobuf/descriptor_database.py | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py index 1333f996..8b7715cd 100644 --- a/python/google/protobuf/descriptor_database.py +++ b/python/google/protobuf/descriptor_database.py @@ -32,6 +32,8 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' +import warnings + class Error(Exception): pass @@ -54,9 +56,9 @@ class DescriptorDatabase(object): Args: file_desc_proto: The FileDescriptorProto to add. Raises: - DescriptorDatabaseException: if an attempt is made to add a proto - with the same name but different definition than an exisiting - proto in the database. + DescriptorDatabaseConflictingDefinitionError: if an attempt is made to + add a proto with the same name but different definition than an + exisiting proto in the database. """ proto_name = file_desc_proto.name if proto_name not in self._file_desc_protos_by_file: @@ -64,18 +66,20 @@ class DescriptorDatabase(object): elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: raise DescriptorDatabaseConflictingDefinitionError( '%s already added, but with different descriptor.' % proto_name) + else: + return - # Add the top-level Message, Enum and Extension descriptors to the index. + # Add all the top-level descriptors to the index. package = file_desc_proto.package for message in file_desc_proto.message_type: - self._file_desc_protos_by_symbol.update( - (name, file_desc_proto) for name in _ExtractSymbols(message, package)) + for name in _ExtractSymbols(message, package): + self._AddSymbol(name, file_desc_proto) for enum in file_desc_proto.enum_type: - self._file_desc_protos_by_symbol[ - '.'.join((package, enum.name))] = file_desc_proto + self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) for extension in file_desc_proto.extension: - self._file_desc_protos_by_symbol[ - '.'.join((package, extension.name))] = file_desc_proto + self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + for service in file_desc_proto.service: + self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) def FindFileByName(self, name): """Finds the file descriptor proto by file name. @@ -104,6 +108,7 @@ class DescriptorDatabase(object): 'some.package.name.Message' 'some.package.name.Message.NestedEnum' + 'some.package.name.Message.some_field' The file descriptor proto containing the specified symbol must be added to this database using the Add method or else an error will be raised. @@ -117,8 +122,25 @@ class DescriptorDatabase(object): Raises: KeyError if no file contains the specified symbol. """ - - return self._file_desc_protos_by_symbol[symbol] + try: + return self._file_desc_protos_by_symbol[symbol] + except KeyError: + # Fields, enum values, and nested extensions are not in + # _file_desc_protos_by_symbol. Try to find the top level + # descriptor. Non-existent nested symbol under a valid top level + # descriptor can also be found. The behavior is the same with + # protobuf C++. + top_level, _, _ = symbol.rpartition('.') + return self._file_desc_protos_by_symbol[top_level] + + def _AddSymbol(self, name, file_desc_proto): + if name in self._file_desc_protos_by_symbol: + warn_msg = ('Conflict register for file "' + file_desc_proto.name + + '": ' + name + + ' is already defined in file "' + + self._file_desc_protos_by_symbol[name].name + '"') + warnings.warn(warn_msg, RuntimeWarning) + self._file_desc_protos_by_symbol[name] = file_desc_proto def _ExtractSymbols(desc_proto, package): @@ -131,8 +153,7 @@ def _ExtractSymbols(desc_proto, package): Yields: The fully qualified name found in the descriptor. """ - - message_name = '.'.join((package, desc_proto.name)) + message_name = package + '.' + desc_proto.name if package else desc_proto.name yield message_name for nested_type in desc_proto.nested_type: for symbol in _ExtractSymbols(nested_type, message_name): |