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 factory class for generating dynamic messages.
32
33 The easiest way to use this class is if you have access to the FileDescriptor
34 protos containing the messages you want to create you can just do the following:
35
36 message_classes = message_factory.GetMessages(iterable_of_file_descriptors)
37 my_proto_instance = message_classes['some.proto.package.MessageName']()
38 """
39
40 __author__ = 'matthewtoia@google.com (Matt Toia)'
41
42 from google.protobuf.internal import api_implementation
43 from google.protobuf import descriptor_pool
44 from google.protobuf import message
45
46 if api_implementation.Type() == 'cpp':
47 from google.protobuf.pyext import cpp_message as message_impl
48 else:
49 from google.protobuf.internal import python_message as message_impl
50
51
52
53 _GENERATED_PROTOCOL_MESSAGE_TYPE = message_impl.GeneratedProtocolMessageType
54
55
57 """Factory for creating Proto2 messages from descriptors in a pool."""
58
65
67 """Builds a proto2 message class based on the passed in descriptor.
68
69 Passing a descriptor with a fully qualified name matching a previous
70 invocation will cause the same class to be returned.
71
72 Args:
73 descriptor: The descriptor to build from.
74
75 Returns:
76 A class describing the passed in descriptor.
77 """
78 if descriptor not in self._classes:
79 descriptor_name = descriptor.name
80 if str is bytes:
81 descriptor_name = descriptor.name.encode('ascii', 'ignore')
82 result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
83 descriptor_name,
84 (message.Message,),
85 {'DESCRIPTOR': descriptor, '__module__': None})
86
87 self._classes[descriptor] = result_class
88 for field in descriptor.fields:
89 if field.message_type:
90 self.GetPrototype(field.message_type)
91 for extension in result_class.DESCRIPTOR.extensions:
92 if extension.containing_type not in self._classes:
93 self.GetPrototype(extension.containing_type)
94 extended_class = self._classes[extension.containing_type]
95 extended_class.RegisterExtension(extension)
96 return self._classes[descriptor]
97
99 """Gets all the messages from a specified file.
100
101 This will find and resolve dependencies, failing if the descriptor
102 pool cannot satisfy them.
103
104 Args:
105 files: The file names to extract messages from.
106
107 Returns:
108 A dictionary mapping proto names to the message classes. This will include
109 any dependent messages as well as any messages defined in the same file as
110 a specified message.
111 """
112 result = {}
113 for file_name in files:
114 file_desc = self.pool.FindFileByName(file_name)
115 for desc in file_desc.message_types_by_name.values():
116 result[desc.full_name] = self.GetPrototype(desc)
117
118
119
120
121
122
123
124
125
126
127 for extension in file_desc.extensions_by_name.values():
128 if extension.containing_type not in self._classes:
129 self.GetPrototype(extension.containing_type)
130 extended_class = self._classes[extension.containing_type]
131 extended_class.RegisterExtension(extension)
132 return result
133
134
135 _FACTORY = MessageFactory()
136
137
139 """Builds a dictionary of all the messages available in a set of files.
140
141 Args:
142 file_protos: Iterable of FileDescriptorProto to build messages out of.
143
144 Returns:
145 A dictionary mapping proto names to the message classes. This will include
146 any dependent messages as well as any messages defined in the same file as
147 a specified message.
148 """
149
150
151 file_by_name = {file_proto.name: file_proto for file_proto in file_protos}
152 def _AddFile(file_proto):
153 for dependency in file_proto.dependency:
154 if dependency in file_by_name:
155
156 _AddFile(file_by_name.pop(dependency))
157 _FACTORY.pool.Add(file_proto)
158 while file_by_name:
159 _AddFile(file_by_name.popitem()[1])
160 return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos])
161