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"""Contains metaclasses used to create protocol service and service stub 327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclasses from ServiceDescriptor objects at runtime. 337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangThe GeneratedServiceType and GeneratedServiceStubType metaclasses are used to 357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wanginject all useful functionality into the classes output by the protocol 367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangcompiler at compile-time. 377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang""" 387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang__author__ = 'petar@google.com (Petar Petrov)' 407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass GeneratedServiceType(type): 437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Metaclass for service classes created at runtime from ServiceDescriptors. 457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Implementations for all methods described in the Service class are added here 477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang by this class. We also create properties to allow getting/setting all fields 487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang in the protocol message. 497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang The protocol compiler currently uses this metaclass to create protocol service 517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang classes at runtime. Clients can also manually create their own classes at 527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang runtime, as in this example: 537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang mydescriptor = ServiceDescriptor(.....) 557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang class MyProtoService(service.Service): 567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang __metaclass__ = GeneratedServiceType 577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang DESCRIPTOR = mydescriptor 587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang myservice_instance = MyProtoService() 597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang ... 607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang _DESCRIPTOR_KEY = 'DESCRIPTOR' 637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def __init__(cls, name, bases, dictionary): 657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Creates a message service class. 667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang name: Name of the class (ignored, but required by the metaclass 697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang protocol). 707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang bases: Base classes of the class being constructed. 717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang dictionary: The class dictionary of the class being constructed. 727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object 737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang describing this protocol service type. 747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # Don't do anything if this class doesn't have a descriptor. This happens 767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # when a service class is subclassed. 777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary: 787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return 797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY] 807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_builder = _ServiceBuilder(descriptor) 817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_builder.BuildService(cls) 827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass GeneratedServiceStubType(GeneratedServiceType): 857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Metaclass for service stubs created at runtime from ServiceDescriptors. 877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang This class has similar responsibilities as GeneratedServiceType, except that 897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang it creates the service stub classes. 907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang _DESCRIPTOR_KEY = 'DESCRIPTOR' 937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def __init__(cls, name, bases, dictionary): 957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Creates a message service stub class. 967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang name: Name of the class (ignored, here). 997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang bases: Base classes of the class being constructed. 1007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang dictionary: The class dictionary of the class being constructed. 1017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object 1027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang describing this protocol service type. 1037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary) 1057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # Don't do anything if this class doesn't have a descriptor. This happens 1067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # when a service stub is subclassed. 1077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary: 1087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return 1097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] 1107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_stub_builder = _ServiceStubBuilder(descriptor) 1117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_stub_builder.BuildServiceStub(cls) 1127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass _ServiceBuilder(object): 1157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """This class constructs a protocol service class using a service descriptor. 1177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Given a service descriptor, this class constructs a class that represents 1197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang the specified service descriptor. One service builder instance constructs 1207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang exactly one service class. That means all instances of that class share the 1217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang same builder. 1227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def __init__(self, service_descriptor): 1257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Initializes an instance of the service class builder. 1267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 1287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_descriptor: ServiceDescriptor to use when constructing the 1297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service class. 1307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self.descriptor = service_descriptor 1327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def BuildService(self, cls): 1347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Constructs the service class. 1357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 1377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls: The class that will be constructed. 1387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # CallMethod needs to operate with an instance of the Service class. This 1417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # internal wrapper function exists only to be able to pass the service 1427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang # instance to the method that does the real CallMethod work. 1437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _WrapCallMethod(srvc, method_descriptor, 1447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller, request, callback): 1457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return self._CallMethod(srvc, method_descriptor, 1467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller, request, callback) 1477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self.cls = cls 1487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.CallMethod = _WrapCallMethod 1497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.GetDescriptor = staticmethod(lambda: self.descriptor) 1507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.GetDescriptor.__doc__ = "Returns the service descriptor." 1517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.GetRequestClass = self._GetRequestClass 1527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.GetResponseClass = self._GetResponseClass 1537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang for method in self.descriptor.methods: 1547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang setattr(cls, method.name, self._GenerateNonImplementedMethod(method)) 1557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _CallMethod(self, srvc, method_descriptor, 1577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller, request, callback): 1587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Calls the method described by a given method descriptor. 1597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 1617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang srvc: Instance of the service for which this method is called. 1627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor: Descriptor that represent the method to call. 1637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller: RPC controller to use for this method's execution. 1647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang request: Request protocol message. 1657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang callback: A callback to invoke after the method has completed. 1667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang if method_descriptor.containing_service != self.descriptor: 1687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang raise RuntimeError( 1697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 'CallMethod() given method descriptor for wrong service type.') 1707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method = getattr(srvc, method_descriptor.name) 1717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return method(rpc_controller, request, callback) 1727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _GetRequestClass(self, method_descriptor): 1747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Returns the class of the request protocol message. 1757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 1777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor: Descriptor of the method for which to return the 1787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang request protocol message class. 1797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Returns: 1817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang A class that represents the input protocol message of the specified 1827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method. 1837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 1847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang if method_descriptor.containing_service != self.descriptor: 1857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang raise RuntimeError( 1867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 'GetRequestClass() given method descriptor for wrong service type.') 1877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return method_descriptor.input_type._concrete_class 1887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _GetResponseClass(self, method_descriptor): 1907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Returns the class of the response protocol message. 1917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 1937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor: Descriptor of the method for which to return the 1947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang response protocol message class. 1957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 1967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Returns: 1977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang A class that represents the output protocol message of the specified 1987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method. 1997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang if method_descriptor.containing_service != self.descriptor: 2017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang raise RuntimeError( 2027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 'GetResponseClass() given method descriptor for wrong service type.') 2037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return method_descriptor.output_type._concrete_class 2047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _GenerateNonImplementedMethod(self, method): 2067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Generates and returns a method that can be set for a service methods. 2077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 2097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method: Descriptor of the service method for which a method is to be 2107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang generated. 2117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Returns: 2137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang A method that can be added to the service class. 2147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return lambda inst, rpc_controller, request, callback: ( 2167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self._NonImplementedMethod(method.name, rpc_controller, callback)) 2177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _NonImplementedMethod(self, method_name, rpc_controller, callback): 2197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """The body of all methods in the generated service class. 2207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 2227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_name: Name of the method being executed. 2237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller: RPC controller used to execute this method. 2247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang callback: A callback which will be invoked when the method finishes. 2257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller.SetFailed('Method %s not implemented.' % method_name) 2277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang callback(None) 2287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass _ServiceStubBuilder(object): 2317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Constructs a protocol service stub class using a service descriptor. 2337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Given a service descriptor, this class constructs a suitable stub class. 2357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang A stub is just a type-safe wrapper around an RpcChannel which emulates a 2367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang local implementation of the service. 2377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang One service stub builder instance constructs exactly one class. It means all 2397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang instances of that class share the same service stub builder. 2407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def __init__(self, service_descriptor): 2437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Initializes an instance of the service stub class builder. 2447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 2467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang service_descriptor: ServiceDescriptor to use when constructing the 2477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang stub class. 2487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self.descriptor = service_descriptor 2507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def BuildServiceStub(self, cls): 2527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """Constructs the stub class. 2537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 2557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls: The class that will be constructed. 2567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _ServiceStubInit(stub, rpc_channel): 2597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang stub.rpc_channel = rpc_channel 2607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self.cls = cls 2617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang cls.__init__ = _ServiceStubInit 2627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang for method in self.descriptor.methods: 2637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang setattr(cls, method.name, self._GenerateStubMethod(method)) 2647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _GenerateStubMethod(self, method): 2667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return (lambda inst, rpc_controller, request, callback=None: 2677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang self._StubMethod(inst, method, rpc_controller, request, callback)) 2687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang def _StubMethod(self, stub, method_descriptor, 2707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller, request, callback): 2717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """The body of all service methods in the generated stub class. 2727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang 2737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Args: 2747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang stub: Stub instance. 2757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor: Descriptor of the invoked method. 2767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang rpc_controller: Rpc controller to execute the method. 2777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang request: Request protocol message. 2787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang callback: A callback to execute when the method finishes. 2797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Returns: 2807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang Response message (in case of blocking call). 2817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang """ 2827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang return stub.rpc_channel.CallMethod( 2837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor, rpc_controller, request, 2847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang method_descriptor.output_type._concrete_class, callback) 285