17e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Protocol Buffers - Google's data interchange format
27e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Copyright 2008 Google Inc.  All rights reserved.
37e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# http://code.google.com/p/protobuf/
47e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
57e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Redistribution and use in source and binary forms, with or without
67e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# modification, are permitted provided that the following conditions are
77e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# met:
87e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
97e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions of source code must retain the above copyright
107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# notice, this list of conditions and the following disclaimer.
117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions in binary form must reproduce the above
127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# copyright notice, this list of conditions and the following disclaimer
137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# in the documentation and/or other materials provided with the
147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# distribution.
157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Neither the name of Google Inc. nor the names of its
167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# contributors may be used to endorse or promote products derived from
177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# this software without specific prior written permission.
187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""Provides a container for DescriptorProtos."""
327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang__author__ = 'matthewtoia@google.com (Matt Toia)'
347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass DescriptorDatabase(object):
377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """A container accepting FileDescriptorProtos and maps DescriptorProtos."""
387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __init__(self):
407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._file_desc_protos_by_file = {}
417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._file_desc_protos_by_symbol = {}
427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def Add(self, file_desc_proto):
447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Adds the FileDescriptorProto and its types to this database.
457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      file_desc_proto: The FileDescriptorProto to add.
487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._file_desc_protos_by_file[file_desc_proto.name] = file_desc_proto
517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    package = file_desc_proto.package
527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for message in file_desc_proto.message_type:
537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._file_desc_protos_by_symbol.update(
547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          (name, file_desc_proto) for name in _ExtractSymbols(message, package))
557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for enum in file_desc_proto.enum_type:
567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._file_desc_protos_by_symbol[
577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          '.'.join((package, enum.name))] = file_desc_proto
587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def FindFileByName(self, name):
607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Finds the file descriptor proto by file name.
617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Typically the file name is a relative path ending to a .proto file. The
637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    proto with the given name will have to have been added to this database
647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    using the Add method or else an error will be raised.
657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      name: The file name to find.
687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Returns:
707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      The file descriptor proto matching the name.
717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Raises:
737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      KeyError if no file by the given name was added.
747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._file_desc_protos_by_file[name]
777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def FindFileContainingSymbol(self, symbol):
797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Finds the file descriptor proto containing the specified symbol.
807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    The symbol should be a fully qualified name including the file descriptor's
827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    package and any containing messages. Some examples:
837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    'some.package.name.Message'
857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    'some.package.name.Message.NestedEnum'
867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    The file descriptor proto containing the specified symbol must be added to
887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    this database using the Add method or else an error will be raised.
897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      symbol: The fully qualified symbol name.
927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Returns:
947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      The file descriptor proto containing the symbol.
957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Raises:
977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      KeyError if no file contains the specified symbol.
987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._file_desc_protos_by_symbol[symbol]
1017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef _ExtractSymbols(desc_proto, package):
1047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Pulls out all the symbols from a descriptor proto.
1057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Args:
1077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    desc_proto: The proto to extract symbols from.
1087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    package: The package containing the descriptor type.
1097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Yields:
1117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    The fully qualified name found in the descriptor.
1127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
1137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  message_name = '.'.join((package, desc_proto.name))
1157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  yield message_name
1167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  for nested_type in desc_proto.nested_type:
1177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for symbol in _ExtractSymbols(nested_type, message_name):
1187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      yield symbol
1197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for enum_type in desc_proto.enum_type:
1207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      yield '.'.join((message_name, enum_type.name))
121