1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# https://developers.google.com/protocol-buffers/ 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"""A database of Python protocol buffer generated symbols. 32 33SymbolDatabase makes it easy to create new instances of a registered type, given 34only the type's protocol buffer symbol name. Once all symbols are registered, 35they can be accessed using either the MessageFactory interface which 36SymbolDatabase exposes, or the DescriptorPool interface of the underlying 37pool. 38 39Example usage: 40 41 db = symbol_database.SymbolDatabase() 42 43 # Register symbols of interest, from one or multiple files. 44 db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR) 45 db.RegisterMessage(my_proto_pb2.MyMessage) 46 db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR) 47 48 # The database can be used as a MessageFactory, to generate types based on 49 # their name: 50 types = db.GetMessages(['my_proto.proto']) 51 my_message_instance = types['MyMessage']() 52 53 # The database's underlying descriptor pool can be queried, so it's not 54 # necessary to know a type's filename to be able to generate it: 55 filename = db.pool.FindFileContainingSymbol('MyMessage') 56 my_message_instance = db.GetMessages([filename])['MyMessage']() 57 58 # This functionality is also provided directly via a convenience method: 59 my_message_instance = db.GetSymbol('MyMessage')() 60""" 61 62 63from google.protobuf import descriptor_pool 64 65 66class SymbolDatabase(object): 67 """A database of Python generated symbols. 68 69 SymbolDatabase also models message_factory.MessageFactory. 70 71 The symbol database can be used to keep a global registry of all protocol 72 buffer types used within a program. 73 """ 74 75 def __init__(self, pool=None): 76 """Constructor.""" 77 78 self._symbols = {} 79 self._symbols_by_file = {} 80 self.pool = pool or descriptor_pool.Default() 81 82 def RegisterMessage(self, message): 83 """Registers the given message type in the local database. 84 85 Args: 86 message: a message.Message, to be registered. 87 88 Returns: 89 The provided message. 90 """ 91 92 desc = message.DESCRIPTOR 93 self._symbols[desc.full_name] = message 94 if desc.file.name not in self._symbols_by_file: 95 self._symbols_by_file[desc.file.name] = {} 96 self._symbols_by_file[desc.file.name][desc.full_name] = message 97 self.pool.AddDescriptor(desc) 98 return message 99 100 def RegisterEnumDescriptor(self, enum_descriptor): 101 """Registers the given enum descriptor in the local database. 102 103 Args: 104 enum_descriptor: a descriptor.EnumDescriptor. 105 106 Returns: 107 The provided descriptor. 108 """ 109 self.pool.AddEnumDescriptor(enum_descriptor) 110 return enum_descriptor 111 112 def RegisterFileDescriptor(self, file_descriptor): 113 """Registers the given file descriptor in the local database. 114 115 Args: 116 file_descriptor: a descriptor.FileDescriptor. 117 118 Returns: 119 The provided descriptor. 120 """ 121 self.pool.AddFileDescriptor(file_descriptor) 122 123 def GetSymbol(self, symbol): 124 """Tries to find a symbol in the local database. 125 126 Currently, this method only returns message.Message instances, however, if 127 may be extended in future to support other symbol types. 128 129 Args: 130 symbol: A str, a protocol buffer symbol. 131 132 Returns: 133 A Python class corresponding to the symbol. 134 135 Raises: 136 KeyError: if the symbol could not be found. 137 """ 138 139 return self._symbols[symbol] 140 141 def GetPrototype(self, descriptor): 142 """Builds a proto2 message class based on the passed in descriptor. 143 144 Passing a descriptor with a fully qualified name matching a previous 145 invocation will cause the same class to be returned. 146 147 Args: 148 descriptor: The descriptor to build from. 149 150 Returns: 151 A class describing the passed in descriptor. 152 """ 153 154 return self.GetSymbol(descriptor.full_name) 155 156 def GetMessages(self, files): 157 """Gets all the messages from a specified file. 158 159 This will find and resolve dependencies, failing if they are not registered 160 in the symbol database. 161 162 163 Args: 164 files: The file names to extract messages from. 165 166 Returns: 167 A dictionary mapping proto names to the message classes. This will include 168 any dependent messages as well as any messages defined in the same file as 169 a specified message. 170 171 Raises: 172 KeyError: if a file could not be found. 173 """ 174 175 result = {} 176 for f in files: 177 result.update(self._symbols_by_file[f]) 178 return result 179 180_DEFAULT = SymbolDatabase(pool=descriptor_pool.Default()) 181 182 183def Default(): 184 """Returns the default SymbolDatabase.""" 185 return _DEFAULT 186