diff options
Diffstat (limited to 'python/google/protobuf/message_factory.py')
-rw-r--r-- | python/google/protobuf/message_factory.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py new file mode 100644 index 00000000..36e2fef0 --- /dev/null +++ b/python/google/protobuf/message_factory.py @@ -0,0 +1,113 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides a factory class for generating dynamic messages.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message +from google.protobuf import reflection + + +class MessageFactory(object): + """Factory for creating Proto2 messages from descriptors in a pool.""" + + def __init__(self): + """Initializes a new factory.""" + self._classes = {} + + def GetPrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + + if descriptor.full_name not in self._classes: + result_class = reflection.GeneratedProtocolMessageType( + descriptor.name.encode('ascii', 'ignore'), + (message.Message,), + {'DESCRIPTOR': descriptor}) + self._classes[descriptor.full_name] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + return self._classes[descriptor.full_name] + + +_DB = descriptor_database.DescriptorDatabase() +_POOL = descriptor_pool.DescriptorPool(_DB) +_FACTORY = MessageFactory() + + +def GetMessages(file_protos): + """Builds a dictionary of all the messages available in a set of files. + + Args: + file_protos: A sequence of file protos to build messages out of. + + Returns: + A dictionary containing all the message types in the files mapping the + fully qualified name to a Message subclass for the descriptor. + """ + + result = {} + for file_proto in file_protos: + _DB.Add(file_proto) + for file_proto in file_protos: + for desc in _GetAllDescriptors(file_proto.message_type, file_proto.package): + result[desc.full_name] = _FACTORY.GetPrototype(desc) + return result + + +def _GetAllDescriptors(desc_protos, package): + """Gets all levels of nested message types as a flattened list of descriptors. + + Args: + desc_protos: The descriptor protos to process. + package: The package where the protos are defined. + + Yields: + Each message descriptor for each nested type. + """ + + for desc_proto in desc_protos: + name = '.'.join((package, desc_proto.name)) + yield _POOL.FindMessageTypeByName(name) + for nested_desc in _GetAllDescriptors(desc_proto.nested_type, name): + yield nested_desc |