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@google.com (Matt Toia)' 34 35from google.protobuf import descriptor_database 36from google.protobuf import descriptor_pool 37from google.protobuf import message 38from google.protobuf import reflection 39 40 41class 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 78def 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 98def _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