1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """Provides a container for DescriptorProtos."""
32
33 __author__ = 'matthewtoia@google.com (Matt Toia)'
34
35 import warnings
36
37
40
41
43 """Raised when a proto is added with the same name & different descriptor."""
44
45
47 """A container accepting FileDescriptorProtos and maps DescriptorProtos."""
48
50 self._file_desc_protos_by_file = {}
51 self._file_desc_protos_by_symbol = {}
52
53 - def Add(self, file_desc_proto):
54 """Adds the FileDescriptorProto and its types to this database.
55
56 Args:
57 file_desc_proto: The FileDescriptorProto to add.
58 Raises:
59 DescriptorDatabaseConflictingDefinitionError: if an attempt is made to
60 add a proto with the same name but different definition than an
61 exisiting proto in the database.
62 """
63 proto_name = file_desc_proto.name
64 if proto_name not in self._file_desc_protos_by_file:
65 self._file_desc_protos_by_file[proto_name] = file_desc_proto
66 elif self._file_desc_protos_by_file[proto_name] != file_desc_proto:
67 raise DescriptorDatabaseConflictingDefinitionError(
68 '%s already added, but with different descriptor.' % proto_name)
69 else:
70 return
71
72
73 package = file_desc_proto.package
74 for message in file_desc_proto.message_type:
75 for name in _ExtractSymbols(message, package):
76 self._AddSymbol(name, file_desc_proto)
77 for enum in file_desc_proto.enum_type:
78 self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto)
79 for enum_value in enum.value:
80 self._file_desc_protos_by_symbol[
81 '.'.join((package, enum_value.name))] = file_desc_proto
82 for extension in file_desc_proto.extension:
83 self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto)
84 for service in file_desc_proto.service:
85 self._AddSymbol(('.'.join((package, service.name))), file_desc_proto)
86
88 """Finds the file descriptor proto by file name.
89
90 Typically the file name is a relative path ending to a .proto file. The
91 proto with the given name will have to have been added to this database
92 using the Add method or else an error will be raised.
93
94 Args:
95 name: The file name to find.
96
97 Returns:
98 The file descriptor proto matching the name.
99
100 Raises:
101 KeyError if no file by the given name was added.
102 """
103
104 return self._file_desc_protos_by_file[name]
105
107 """Finds the file descriptor proto containing the specified symbol.
108
109 The symbol should be a fully qualified name including the file descriptor's
110 package and any containing messages. Some examples:
111
112 'some.package.name.Message'
113 'some.package.name.Message.NestedEnum'
114 'some.package.name.Message.some_field'
115
116 The file descriptor proto containing the specified symbol must be added to
117 this database using the Add method or else an error will be raised.
118
119 Args:
120 symbol: The fully qualified symbol name.
121
122 Returns:
123 The file descriptor proto containing the symbol.
124
125 Raises:
126 KeyError if no file contains the specified symbol.
127 """
128 try:
129 return self._file_desc_protos_by_symbol[symbol]
130 except KeyError:
131
132
133
134
135
136 top_level, _, _ = symbol.rpartition('.')
137 try:
138 return self._file_desc_protos_by_symbol[top_level]
139 except KeyError:
140
141 raise KeyError(symbol)
142
146
150
152 if name in self._file_desc_protos_by_symbol:
153 warn_msg = ('Conflict register for file "' + file_desc_proto.name +
154 '": ' + name +
155 ' is already defined in file "' +
156 self._file_desc_protos_by_symbol[name].name + '"')
157 warnings.warn(warn_msg, RuntimeWarning)
158 self._file_desc_protos_by_symbol[name] = file_desc_proto
159
160
162 """Pulls out all the symbols from a descriptor proto.
163
164 Args:
165 desc_proto: The proto to extract symbols from.
166 package: The package containing the descriptor type.
167
168 Yields:
169 The fully qualified name found in the descriptor.
170 """
171 message_name = package + '.' + desc_proto.name if package else desc_proto.name
172 yield message_name
173 for nested_type in desc_proto.nested_type:
174 for symbol in _ExtractSymbols(nested_type, message_name):
175 yield symbol
176 for enum_type in desc_proto.enum_type:
177 yield '.'.join((message_name, enum_type.name))
178