aboutsummaryrefslogtreecommitdiffhomepage
path: root/python/google/protobuf/message_factory.py
diff options
context:
space:
mode:
authorGravatar xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
committerGravatar xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
commitb55a20fa2c669b181f47ea9219b8e74d1263da19 (patch)
tree3936a0e7c22196587a6d8397372de41434fe2129 /python/google/protobuf/message_factory.py
parent9ced30caf94bb4e7e9629c199679ff44e8ca7389 (diff)
Down-integrate from internal branch
Diffstat (limited to 'python/google/protobuf/message_factory.py')
-rw-r--r--python/google/protobuf/message_factory.py113
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