店播爬取Python脚本

service_reflection.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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. """Contains metaclasses used to create protocol service and service stub
  31. classes from ServiceDescriptor objects at runtime.
  32. The GeneratedServiceType and GeneratedServiceStubType metaclasses are used to
  33. inject all useful functionality into the classes output by the protocol
  34. compiler at compile-time.
  35. """
  36. __author__ = 'petar@google.com (Petar Petrov)'
  37. class GeneratedServiceType(type):
  38. """Metaclass for service classes created at runtime from ServiceDescriptors.
  39. Implementations for all methods described in the Service class are added here
  40. by this class. We also create properties to allow getting/setting all fields
  41. in the protocol message.
  42. The protocol compiler currently uses this metaclass to create protocol service
  43. classes at runtime. Clients can also manually create their own classes at
  44. runtime, as in this example::
  45. mydescriptor = ServiceDescriptor(.....)
  46. class MyProtoService(service.Service):
  47. __metaclass__ = GeneratedServiceType
  48. DESCRIPTOR = mydescriptor
  49. myservice_instance = MyProtoService()
  50. # ...
  51. """
  52. _DESCRIPTOR_KEY = 'DESCRIPTOR'
  53. def __init__(cls, name, bases, dictionary):
  54. """Creates a message service class.
  55. Args:
  56. name: Name of the class (ignored, but required by the metaclass
  57. protocol).
  58. bases: Base classes of the class being constructed.
  59. dictionary: The class dictionary of the class being constructed.
  60. dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
  61. describing this protocol service type.
  62. """
  63. # Don't do anything if this class doesn't have a descriptor. This happens
  64. # when a service class is subclassed.
  65. if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary:
  66. return
  67. descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
  68. service_builder = _ServiceBuilder(descriptor)
  69. service_builder.BuildService(cls)
  70. cls.DESCRIPTOR = descriptor
  71. class GeneratedServiceStubType(GeneratedServiceType):
  72. """Metaclass for service stubs created at runtime from ServiceDescriptors.
  73. This class has similar responsibilities as GeneratedServiceType, except that
  74. it creates the service stub classes.
  75. """
  76. _DESCRIPTOR_KEY = 'DESCRIPTOR'
  77. def __init__(cls, name, bases, dictionary):
  78. """Creates a message service stub class.
  79. Args:
  80. name: Name of the class (ignored, here).
  81. bases: Base classes of the class being constructed.
  82. dictionary: The class dictionary of the class being constructed.
  83. dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
  84. describing this protocol service type.
  85. """
  86. super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
  87. # Don't do anything if this class doesn't have a descriptor. This happens
  88. # when a service stub is subclassed.
  89. if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
  90. return
  91. descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
  92. service_stub_builder = _ServiceStubBuilder(descriptor)
  93. service_stub_builder.BuildServiceStub(cls)
  94. class _ServiceBuilder(object):
  95. """This class constructs a protocol service class using a service descriptor.
  96. Given a service descriptor, this class constructs a class that represents
  97. the specified service descriptor. One service builder instance constructs
  98. exactly one service class. That means all instances of that class share the
  99. same builder.
  100. """
  101. def __init__(self, service_descriptor):
  102. """Initializes an instance of the service class builder.
  103. Args:
  104. service_descriptor: ServiceDescriptor to use when constructing the
  105. service class.
  106. """
  107. self.descriptor = service_descriptor
  108. def BuildService(self, cls):
  109. """Constructs the service class.
  110. Args:
  111. cls: The class that will be constructed.
  112. """
  113. # CallMethod needs to operate with an instance of the Service class. This
  114. # internal wrapper function exists only to be able to pass the service
  115. # instance to the method that does the real CallMethod work.
  116. def _WrapCallMethod(srvc, method_descriptor,
  117. rpc_controller, request, callback):
  118. return self._CallMethod(srvc, method_descriptor,
  119. rpc_controller, request, callback)
  120. self.cls = cls
  121. cls.CallMethod = _WrapCallMethod
  122. cls.GetDescriptor = staticmethod(lambda: self.descriptor)
  123. cls.GetDescriptor.__doc__ = "Returns the service descriptor."
  124. cls.GetRequestClass = self._GetRequestClass
  125. cls.GetResponseClass = self._GetResponseClass
  126. for method in self.descriptor.methods:
  127. setattr(cls, method.name, self._GenerateNonImplementedMethod(method))
  128. def _CallMethod(self, srvc, method_descriptor,
  129. rpc_controller, request, callback):
  130. """Calls the method described by a given method descriptor.
  131. Args:
  132. srvc: Instance of the service for which this method is called.
  133. method_descriptor: Descriptor that represent the method to call.
  134. rpc_controller: RPC controller to use for this method's execution.
  135. request: Request protocol message.
  136. callback: A callback to invoke after the method has completed.
  137. """
  138. if method_descriptor.containing_service != self.descriptor:
  139. raise RuntimeError(
  140. 'CallMethod() given method descriptor for wrong service type.')
  141. method = getattr(srvc, method_descriptor.name)
  142. return method(rpc_controller, request, callback)
  143. def _GetRequestClass(self, method_descriptor):
  144. """Returns the class of the request protocol message.
  145. Args:
  146. method_descriptor: Descriptor of the method for which to return the
  147. request protocol message class.
  148. Returns:
  149. A class that represents the input protocol message of the specified
  150. method.
  151. """
  152. if method_descriptor.containing_service != self.descriptor:
  153. raise RuntimeError(
  154. 'GetRequestClass() given method descriptor for wrong service type.')
  155. return method_descriptor.input_type._concrete_class
  156. def _GetResponseClass(self, method_descriptor):
  157. """Returns the class of the response protocol message.
  158. Args:
  159. method_descriptor: Descriptor of the method for which to return the
  160. response protocol message class.
  161. Returns:
  162. A class that represents the output protocol message of the specified
  163. method.
  164. """
  165. if method_descriptor.containing_service != self.descriptor:
  166. raise RuntimeError(
  167. 'GetResponseClass() given method descriptor for wrong service type.')
  168. return method_descriptor.output_type._concrete_class
  169. def _GenerateNonImplementedMethod(self, method):
  170. """Generates and returns a method that can be set for a service methods.
  171. Args:
  172. method: Descriptor of the service method for which a method is to be
  173. generated.
  174. Returns:
  175. A method that can be added to the service class.
  176. """
  177. return lambda inst, rpc_controller, request, callback: (
  178. self._NonImplementedMethod(method.name, rpc_controller, callback))
  179. def _NonImplementedMethod(self, method_name, rpc_controller, callback):
  180. """The body of all methods in the generated service class.
  181. Args:
  182. method_name: Name of the method being executed.
  183. rpc_controller: RPC controller used to execute this method.
  184. callback: A callback which will be invoked when the method finishes.
  185. """
  186. rpc_controller.SetFailed('Method %s not implemented.' % method_name)
  187. callback(None)
  188. class _ServiceStubBuilder(object):
  189. """Constructs a protocol service stub class using a service descriptor.
  190. Given a service descriptor, this class constructs a suitable stub class.
  191. A stub is just a type-safe wrapper around an RpcChannel which emulates a
  192. local implementation of the service.
  193. One service stub builder instance constructs exactly one class. It means all
  194. instances of that class share the same service stub builder.
  195. """
  196. def __init__(self, service_descriptor):
  197. """Initializes an instance of the service stub class builder.
  198. Args:
  199. service_descriptor: ServiceDescriptor to use when constructing the
  200. stub class.
  201. """
  202. self.descriptor = service_descriptor
  203. def BuildServiceStub(self, cls):
  204. """Constructs the stub class.
  205. Args:
  206. cls: The class that will be constructed.
  207. """
  208. def _ServiceStubInit(stub, rpc_channel):
  209. stub.rpc_channel = rpc_channel
  210. self.cls = cls
  211. cls.__init__ = _ServiceStubInit
  212. for method in self.descriptor.methods:
  213. setattr(cls, method.name, self._GenerateStubMethod(method))
  214. def _GenerateStubMethod(self, method):
  215. return (lambda inst, rpc_controller, request, callback=None:
  216. self._StubMethod(inst, method, rpc_controller, request, callback))
  217. def _StubMethod(self, stub, method_descriptor,
  218. rpc_controller, request, callback):
  219. """The body of all service methods in the generated stub class.
  220. Args:
  221. stub: Stub instance.
  222. method_descriptor: Descriptor of the invoked method.
  223. rpc_controller: Rpc controller to execute the method.
  224. request: Request protocol message.
  225. callback: A callback to execute when the method finishes.
  226. Returns:
  227. Response message (in case of blocking call).
  228. """
  229. return stub.rpc_channel.CallMethod(
  230. method_descriptor, rpc_controller, request,
  231. method_descriptor.output_type._concrete_class, callback)