1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""Contains metaclasses used to create protocol service and service stub
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclasses from ServiceDescriptor objects at runtime.
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleThe GeneratedServiceType and GeneratedServiceStubType metaclasses are used to
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleinject all useful functionality into the classes output by the protocol
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillecompiler at compile-time.
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville__author__ = 'petar@google.com (Petar Petrov)'
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass GeneratedServiceType(type):
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Metaclass for service classes created at runtime from ServiceDescriptors.
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Implementations for all methods described in the Service class are added here
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  by this class. We also create properties to allow getting/setting all fields
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  in the protocol message.
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  The protocol compiler currently uses this metaclass to create protocol service
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  classes at runtime. Clients can also manually create their own classes at
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  runtime, as in this example:
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  mydescriptor = ServiceDescriptor(.....)
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  class MyProtoService(service.Service):
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    __metaclass__ = GeneratedServiceType
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    DESCRIPTOR = mydescriptor
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  myservice_instance = MyProtoService()
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ...
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _DESCRIPTOR_KEY = 'DESCRIPTOR'
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __init__(cls, name, bases, dictionary):
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Creates a message service class.
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name: Name of the class (ignored, but required by the metaclass
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        protocol).
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bases: Base classes of the class being constructed.
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      dictionary: The class dictionary of the class being constructed.
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        describing this protocol service type.
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # Don't do anything if this class doesn't have a descriptor. This happens
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # when a service class is subclassed.
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary:
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    service_builder = _ServiceBuilder(descriptor)
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    service_builder.BuildService(cls)
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass GeneratedServiceStubType(GeneratedServiceType):
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Metaclass for service stubs created at runtime from ServiceDescriptors.
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  This class has similar responsibilities as GeneratedServiceType, except that
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  it creates the service stub classes.
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _DESCRIPTOR_KEY = 'DESCRIPTOR'
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __init__(cls, name, bases, dictionary):
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Creates a message service stub class.
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name: Name of the class (ignored, here).
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bases: Base classes of the class being constructed.
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      dictionary: The class dictionary of the class being constructed.
101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        describing this protocol service type.
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # Don't do anything if this class doesn't have a descriptor. This happens
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # when a service stub is subclassed.
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    service_stub_builder = _ServiceStubBuilder(descriptor)
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    service_stub_builder.BuildServiceStub(cls)
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass _ServiceBuilder(object):
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """This class constructs a protocol service class using a service descriptor.
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Given a service descriptor, this class constructs a class that represents
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  the specified service descriptor. One service builder instance constructs
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  exactly one service class. That means all instances of that class share the
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  same builder.
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __init__(self, service_descriptor):
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Initializes an instance of the service class builder.
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      service_descriptor: ServiceDescriptor to use when constructing the
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        service class.
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self.descriptor = service_descriptor
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def BuildService(self, cls):
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Constructs the service class.
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      cls: The class that will be constructed.
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # CallMethod needs to operate with an instance of the Service class. This
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # internal wrapper function exists only to be able to pass the service
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # instance to the method that does the real CallMethod work.
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    def _WrapCallMethod(srvc, method_descriptor,
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        rpc_controller, request, callback):
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return self._CallMethod(srvc, method_descriptor,
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                       rpc_controller, request, callback)
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self.cls = cls
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.CallMethod = _WrapCallMethod
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.GetDescriptor = staticmethod(lambda: self.descriptor)
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.GetDescriptor.__doc__ = "Returns the service descriptor."
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.GetRequestClass = self._GetRequestClass
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.GetResponseClass = self._GetResponseClass
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for method in self.descriptor.methods:
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      setattr(cls, method.name, self._GenerateNonImplementedMethod(method))
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _CallMethod(self, srvc, method_descriptor,
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                  rpc_controller, request, callback):
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Calls the method described by a given method descriptor.
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      srvc: Instance of the service for which this method is called.
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method_descriptor: Descriptor that represent the method to call.
163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      rpc_controller: RPC controller to use for this method's execution.
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      request: Request protocol message.
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      callback: A callback to invoke after the method has completed.
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if method_descriptor.containing_service != self.descriptor:
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      raise RuntimeError(
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          'CallMethod() given method descriptor for wrong service type.')
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    method = getattr(srvc, method_descriptor.name)
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return method(rpc_controller, request, callback)
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _GetRequestClass(self, method_descriptor):
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Returns the class of the request protocol message.
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method_descriptor: Descriptor of the method for which to return the
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        request protocol message class.
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      A class that represents the input protocol message of the specified
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method.
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if method_descriptor.containing_service != self.descriptor:
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      raise RuntimeError(
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          'GetRequestClass() given method descriptor for wrong service type.')
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return method_descriptor.input_type._concrete_class
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _GetResponseClass(self, method_descriptor):
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Returns the class of the response protocol message.
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method_descriptor: Descriptor of the method for which to return the
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        response protocol message class.
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      A class that represents the output protocol message of the specified
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method.
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if method_descriptor.containing_service != self.descriptor:
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      raise RuntimeError(
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          'GetResponseClass() given method descriptor for wrong service type.')
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return method_descriptor.output_type._concrete_class
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _GenerateNonImplementedMethod(self, method):
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Generates and returns a method that can be set for a service methods.
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method: Descriptor of the service method for which a method is to be
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        generated.
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      A method that can be added to the service class.
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return lambda inst, rpc_controller, request, callback: (
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        self._NonImplementedMethod(method.name, rpc_controller, callback))
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _NonImplementedMethod(self, method_name, rpc_controller, callback):
219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """The body of all methods in the generated service class.
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method_name: Name of the method being executed.
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      rpc_controller: RPC controller used to execute this method.
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      callback: A callback which will be invoked when the method finishes.
225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    rpc_controller.SetFailed('Method %s not implemented.' % method_name)
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    callback(None)
228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass _ServiceStubBuilder(object):
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Constructs a protocol service stub class using a service descriptor.
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Given a service descriptor, this class constructs a suitable stub class.
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  A stub is just a type-safe wrapper around an RpcChannel which emulates a
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  local implementation of the service.
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  One service stub builder instance constructs exactly one class. It means all
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  instances of that class share the same service stub builder.
240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __init__(self, service_descriptor):
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Initializes an instance of the service stub class builder.
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      service_descriptor: ServiceDescriptor to use when constructing the
247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        stub class.
248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self.descriptor = service_descriptor
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def BuildServiceStub(self, cls):
252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Constructs the stub class.
253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      cls: The class that will be constructed.
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    def _ServiceStubInit(stub, rpc_channel):
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      stub.rpc_channel = rpc_channel
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self.cls = cls
261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls.__init__ = _ServiceStubInit
262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for method in self.descriptor.methods:
263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      setattr(cls, method.name, self._GenerateStubMethod(method))
264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _GenerateStubMethod(self, method):
266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return (lambda inst, rpc_controller, request, callback=None:
267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        self._StubMethod(inst, method, rpc_controller, request, callback))
268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _StubMethod(self, stub, method_descriptor,
270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                  rpc_controller, request, callback):
271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """The body of all service methods in the generated stub class.
272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      stub: Stub instance.
275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      method_descriptor: Descriptor of the invoked method.
276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      rpc_controller: Rpc controller to execute the method.
277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      request: Request protocol message.
278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      callback: A callback to execute when the method finishes.
279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      Response message (in case of blocking call).
281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return stub.rpc_channel.CallMethod(
283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        method_descriptor, rpc_controller, request,
284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        method_descriptor.output_type._concrete_class, callback)
285