diff -r 88c186556a80 -r f5fd65cc3bf3 thirdparty/google_appengine/google/appengine/api/apiproxy_rpc.py --- /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