Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/protobuf/descriptor_database.py: 25%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

61 statements  

1# Protocol Buffers - Google's data interchange format 

2# Copyright 2008 Google Inc. All rights reserved. 

3# 

4# Use of this source code is governed by a BSD-style 

5# license that can be found in the LICENSE file or at 

6# https://developers.google.com/open-source/licenses/bsd 

7 

8"""Provides a container for DescriptorProtos.""" 

9 

10__author__ = 'matthewtoia@google.com (Matt Toia)' 

11 

12import warnings 

13 

14 

15class Error(Exception): 

16 pass 

17 

18 

19class DescriptorDatabaseConflictingDefinitionError(Error): 

20 """Raised when a proto is added with the same name & different descriptor.""" 

21 

22 

23class DescriptorDatabase(object): 

24 """A container accepting FileDescriptorProtos and maps DescriptorProtos.""" 

25 

26 def __init__(self): 

27 self._file_desc_protos_by_file = {} 

28 self._file_desc_protos_by_symbol = {} 

29 

30 def Add(self, file_desc_proto): 

31 """Adds the FileDescriptorProto and its types to this database. 

32 

33 Args: 

34 file_desc_proto: The FileDescriptorProto to add. 

35 Raises: 

36 DescriptorDatabaseConflictingDefinitionError: if an attempt is made to 

37 add a proto with the same name but different definition than an 

38 existing proto in the database. 

39 """ 

40 proto_name = file_desc_proto.name 

41 if proto_name not in self._file_desc_protos_by_file: 

42 self._file_desc_protos_by_file[proto_name] = file_desc_proto 

43 elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: 

44 raise DescriptorDatabaseConflictingDefinitionError( 

45 '%s already added, but with different descriptor.' % proto_name) 

46 else: 

47 return 

48 

49 # Add all the top-level descriptors to the index. 

50 package = file_desc_proto.package 

51 for message in file_desc_proto.message_type: 

52 for name in _ExtractSymbols(message, package): 

53 self._AddSymbol(name, file_desc_proto) 

54 for enum in file_desc_proto.enum_type: 

55 self._AddSymbol( 

56 ('.'.join((package, enum.name)) if package else enum.name), 

57 file_desc_proto, 

58 ) 

59 for enum_value in enum.value: 

60 self._file_desc_protos_by_symbol[ 

61 '.'.join((package, enum_value.name)) if package else enum_value.name 

62 ] = file_desc_proto 

63 for extension in file_desc_proto.extension: 

64 self._AddSymbol( 

65 ('.'.join((package, extension.name)) if package else extension.name), 

66 file_desc_proto, 

67 ) 

68 for service in file_desc_proto.service: 

69 self._AddSymbol( 

70 ('.'.join((package, service.name)) if package else service.name), 

71 file_desc_proto, 

72 ) 

73 

74 def FindFileByName(self, name): 

75 """Finds the file descriptor proto by file name. 

76 

77 Typically the file name is a relative path ending to a .proto file. The 

78 proto with the given name will have to have been added to this database 

79 using the Add method or else an error will be raised. 

80 

81 Args: 

82 name: The file name to find. 

83 

84 Returns: 

85 The file descriptor proto matching the name. 

86 

87 Raises: 

88 KeyError if no file by the given name was added. 

89 """ 

90 

91 return self._file_desc_protos_by_file[name] 

92 

93 def FindFileContainingSymbol(self, symbol): 

94 """Finds the file descriptor proto containing the specified symbol. 

95 

96 The symbol should be a fully qualified name including the file descriptor's 

97 package and any containing messages. Some examples: 

98 

99 'some.package.name.Message' 

100 'some.package.name.Message.NestedEnum' 

101 'some.package.name.Message.some_field' 

102 

103 The file descriptor proto containing the specified symbol must be added to 

104 this database using the Add method or else an error will be raised. 

105 

106 Args: 

107 symbol: The fully qualified symbol name. 

108 

109 Returns: 

110 The file descriptor proto containing the symbol. 

111 

112 Raises: 

113 KeyError if no file contains the specified symbol. 

114 """ 

115 if symbol.count('.') == 1 and symbol[0] == '.': 

116 symbol = symbol.lstrip('.') 

117 warnings.warn( 

118 'Please remove the leading "." when ' 

119 'FindFileContainingSymbol, this will turn to error ' 

120 'in 2026 Jan.', 

121 RuntimeWarning, 

122 ) 

123 try: 

124 return self._file_desc_protos_by_symbol[symbol] 

125 except KeyError: 

126 # Fields, enum values, and nested extensions are not in 

127 # _file_desc_protos_by_symbol. Try to find the top level 

128 # descriptor. Non-existent nested symbol under a valid top level 

129 # descriptor can also be found. The behavior is the same with 

130 # protobuf C++. 

131 top_level, _, _ = symbol.rpartition('.') 

132 try: 

133 return self._file_desc_protos_by_symbol[top_level] 

134 except KeyError: 

135 # Raise the original symbol as a KeyError for better diagnostics. 

136 raise KeyError(symbol) 

137 

138 def FindFileContainingExtension(self, extendee_name, extension_number): 

139 # TODO: implement this API. 

140 return None 

141 

142 def FindAllExtensionNumbers(self, extendee_name): 

143 # TODO: implement this API. 

144 return [] 

145 

146 def _AddSymbol(self, name, file_desc_proto): 

147 if name in self._file_desc_protos_by_symbol: 

148 warn_msg = ('Conflict register for file "' + file_desc_proto.name + 

149 '": ' + name + 

150 ' is already defined in file "' + 

151 self._file_desc_protos_by_symbol[name].name + '"') 

152 warnings.warn(warn_msg, RuntimeWarning) 

153 self._file_desc_protos_by_symbol[name] = file_desc_proto 

154 

155 

156def _ExtractSymbols(desc_proto, package): 

157 """Pulls out all the symbols from a descriptor proto. 

158 

159 Args: 

160 desc_proto: The proto to extract symbols from. 

161 package: The package containing the descriptor type. 

162 

163 Yields: 

164 The fully qualified name found in the descriptor. 

165 """ 

166 message_name = package + '.' + desc_proto.name if package else desc_proto.name 

167 yield message_name 

168 for nested_type in desc_proto.nested_type: 

169 for symbol in _ExtractSymbols(nested_type, message_name): 

170 yield symbol 

171 for enum_type in desc_proto.enum_type: 

172 yield '.'.join((message_name, enum_type.name))