| # 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 |