thirdparty/google_appengine/google/appengine/api/apiproxy_rpc.py
changeset 828 f5fd65cc3bf3
child 1278 a7766286a7be
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thirdparty/google_appengine/google/appengine/api/apiproxy_rpc.py	Tue Jan 20 13:19:45 2009 +0000
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""Base class for implementing RPC of API proxy stubs."""
+
+
+
+
+
+import sys
+
+
+class RPC(object):
+  """Base class for implementing RPC of API proxy stubs.
+
+  To implement a RPC to make real asynchronous API call:
+    - Extend this class.
+    - Override _MakeCallImpl and/or _WaitImpl to do a real asynchronous call.
+  """
+
+  IDLE = 0
+  RUNNING = 1
+  FINISHING = 2
+
+  def __init__(self, package=None, call=None, request=None, response=None,
+               callback=None, stub=None):
+    """Constructor for the RPC object.
+
+    All arguments are optional, and simply set members on the class.
+    These data members will be overriden by values passed to MakeCall.
+
+    Args:
+      package: string, the package for the call
+      call: string, the call within the package
+      request: ProtocolMessage instance, appropriate for the arguments
+      response: ProtocolMessage instance, appropriate for the response
+      callback: callable, called when call is complete
+      stub: APIProxyStub instance, used in default _WaitImpl to do real call
+    """
+    self.__exception = None
+    self.__state = RPC.IDLE
+    self.__traceback = None
+
+    self.package = package
+    self.call = call
+    self.request = request
+    self.response = response
+    self.callback = callback
+    self.stub = stub
+
+  def MakeCall(self, package=None, call=None, request=None, response=None,
+               callback=None):
+    """Makes an asynchronous (i.e. non-blocking) API call within the
+    specified package for the specified call method.
+
+    It will call the _MakeRealCall to do the real job.
+
+    Args:
+      Same as constructor; see __init__.
+
+    Raises:
+      TypeError or AssertionError if an argument is of an invalid type.
+      AssertionError or RuntimeError is an RPC is already in use.
+    """
+    self.callback = callback or self.callback
+    self.package = package or self.package
+    self.call = call or self.call
+    self.request = request or self.request
+    self.response = response or self.response
+
+    assert self.__state is RPC.IDLE, ('RPC for %s.%s has already been started' %
+                                      (self.package, self.call))
+    assert self.callback is None or callable(self.callback)
+
+    self._MakeCallImpl()
+
+  def Wait(self):
+    """Waits on the API call associated with this RPC."""
+    rpc_completed = self._WaitImpl()
+
+    assert rpc_completed, ('RPC for %s.%s was not completed, and no other ' +
+                           'exception was raised ' % (self.package, self.call))
+
+  def CheckSuccess(self):
+    """If there was an exception, raise it now.
+
+    Raises:
+      Exception of the API call or the callback, if any.
+    """
+    if self.exception and self.__traceback:
+      raise self.exception.__class__, self.exception, self.__traceback
+    elif self.exception:
+      raise self.exception
+
+  @property
+  def exception(self):
+    return self.__exception
+
+  @property
+  def state(self):
+    return self.__state
+
+  def _MakeCallImpl(self):
+    """Override this method to implement a real asynchronous call rpc."""
+    self.__state = RPC.RUNNING
+
+  def _WaitImpl(self):
+    """Override this method to implement a real asynchronous call rpc.
+
+    Returns:
+      True if the async call was completed successfully.
+    """
+    try:
+      try:
+        self.stub.MakeSyncCall(self.package, self.call,
+                               self.request, self.response)
+      except Exception, e:
+        self.__exception = e
+    finally:
+      self.__state = RPC.FINISHING
+      self.__Callback()
+
+    return True
+
+  def __Callback(self):
+    if self.callback:
+      try:
+        self.callback()
+      except:
+        exc_class, self.__exception, self.__traceback = sys.exc_info()
+        self.__exception._appengine_apiproxy_rpc = self
+        raise