1 # Protocol Buffers - Google's data interchange format 2 # Copyright 2008 Google Inc. All rights reserved. 3 # http://code.google.com/p/protobuf/ 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions are 7 # met: 8 # 9 # * Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # * Redistributions in binary form must reproduce the above 12 # copyright notice, this list of conditions and the following disclaimer 13 # in the documentation and/or other materials provided with the 14 # distribution. 15 # * Neither the name of Google Inc. nor the names of its 16 # contributors may be used to endorse or promote products derived from 17 # this software without specific prior written permission. 18 # 19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 """Provides a factory class for generating dynamic messages.""" 32 33 __author__ = 'matthewtoia (at] google.com (Matt Toia)' 34 35 from google.protobuf import descriptor_database 36 from google.protobuf import descriptor_pool 37 from google.protobuf import message 38 from google.protobuf import reflection 39 40 41 class MessageFactory(object): 42 """Factory for creating Proto2 messages from descriptors in a pool.""" 43 44 def __init__(self): 45 """Initializes a new factory.""" 46 self._classes = {} 47 48 def GetPrototype(self, descriptor): 49 """Builds a proto2 message class based on the passed in descriptor. 50 51 Passing a descriptor with a fully qualified name matching a previous 52 invocation will cause the same class to be returned. 53 54 Args: 55 descriptor: The descriptor to build from. 56 57 Returns: 58 A class describing the passed in descriptor. 59 """ 60 61 if descriptor.full_name not in self._classes: 62 result_class = reflection.GeneratedProtocolMessageType( 63 descriptor.name.encode('ascii', 'ignore'), 64 (message.Message,), 65 {'DESCRIPTOR': descriptor}) 66 self._classes[descriptor.full_name] = result_class 67 for field in descriptor.fields: 68 if field.message_type: 69 self.GetPrototype(field.message_type) 70 return self._classes[descriptor.full_name] 71 72 73 _DB = descriptor_database.DescriptorDatabase() 74 _POOL = descriptor_pool.DescriptorPool(_DB) 75 _FACTORY = MessageFactory() 76 77 78 def GetMessages(file_protos): 79 """Builds a dictionary of all the messages available in a set of files. 80 81 Args: 82 file_protos: A sequence of file protos to build messages out of. 83 84 Returns: 85 A dictionary containing all the message types in the files mapping the 86 fully qualified name to a Message subclass for the descriptor. 87 """ 88 89 result = {} 90 for file_proto in file_protos: 91 _DB.Add(file_proto) 92 for file_proto in file_protos: 93 for desc in _GetAllDescriptors(file_proto.message_type, file_proto.package): 94 result[desc.full_name] = _FACTORY.GetPrototype(desc) 95 return result 96 97 98 def _GetAllDescriptors(desc_protos, package): 99 """Gets all levels of nested message types as a flattened list of descriptors. 100 101 Args: 102 desc_protos: The descriptor protos to process. 103 package: The package where the protos are defined. 104 105 Yields: 106 Each message descriptor for each nested type. 107 """ 108 109 for desc_proto in desc_protos: 110 name = '.'.join((package, desc_proto.name)) 111 yield _POOL.FindMessageTypeByName(name) 112 for nested_desc in _GetAllDescriptors(desc_proto.nested_type, name): 113 yield nested_desc 114