thirdparty/google_appengine/google/appengine/api/apiproxy_rpc.py
changeset 828 f5fd65cc3bf3
child 1278 a7766286a7be
equal deleted inserted replaced
827:88c186556a80 828:f5fd65cc3bf3
       
     1 #!/usr/bin/env python
       
     2 #
       
     3 # Copyright 2007 Google Inc.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #     http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 #
       
    17 
       
    18 """Base class for implementing RPC of API proxy stubs."""
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 import sys
       
    25 
       
    26 
       
    27 class RPC(object):
       
    28   """Base class for implementing RPC of API proxy stubs.
       
    29 
       
    30   To implement a RPC to make real asynchronous API call:
       
    31     - Extend this class.
       
    32     - Override _MakeCallImpl and/or _WaitImpl to do a real asynchronous call.
       
    33   """
       
    34 
       
    35   IDLE = 0
       
    36   RUNNING = 1
       
    37   FINISHING = 2
       
    38 
       
    39   def __init__(self, package=None, call=None, request=None, response=None,
       
    40                callback=None, stub=None):
       
    41     """Constructor for the RPC object.
       
    42 
       
    43     All arguments are optional, and simply set members on the class.
       
    44     These data members will be overriden by values passed to MakeCall.
       
    45 
       
    46     Args:
       
    47       package: string, the package for the call
       
    48       call: string, the call within the package
       
    49       request: ProtocolMessage instance, appropriate for the arguments
       
    50       response: ProtocolMessage instance, appropriate for the response
       
    51       callback: callable, called when call is complete
       
    52       stub: APIProxyStub instance, used in default _WaitImpl to do real call
       
    53     """
       
    54     self.__exception = None
       
    55     self.__state = RPC.IDLE
       
    56     self.__traceback = None
       
    57 
       
    58     self.package = package
       
    59     self.call = call
       
    60     self.request = request
       
    61     self.response = response
       
    62     self.callback = callback
       
    63     self.stub = stub
       
    64 
       
    65   def MakeCall(self, package=None, call=None, request=None, response=None,
       
    66                callback=None):
       
    67     """Makes an asynchronous (i.e. non-blocking) API call within the
       
    68     specified package for the specified call method.
       
    69 
       
    70     It will call the _MakeRealCall to do the real job.
       
    71 
       
    72     Args:
       
    73       Same as constructor; see __init__.
       
    74 
       
    75     Raises:
       
    76       TypeError or AssertionError if an argument is of an invalid type.
       
    77       AssertionError or RuntimeError is an RPC is already in use.
       
    78     """
       
    79     self.callback = callback or self.callback
       
    80     self.package = package or self.package
       
    81     self.call = call or self.call
       
    82     self.request = request or self.request
       
    83     self.response = response or self.response
       
    84 
       
    85     assert self.__state is RPC.IDLE, ('RPC for %s.%s has already been started' %
       
    86                                       (self.package, self.call))
       
    87     assert self.callback is None or callable(self.callback)
       
    88 
       
    89     self._MakeCallImpl()
       
    90 
       
    91   def Wait(self):
       
    92     """Waits on the API call associated with this RPC."""
       
    93     rpc_completed = self._WaitImpl()
       
    94 
       
    95     assert rpc_completed, ('RPC for %s.%s was not completed, and no other ' +
       
    96                            'exception was raised ' % (self.package, self.call))
       
    97 
       
    98   def CheckSuccess(self):
       
    99     """If there was an exception, raise it now.
       
   100 
       
   101     Raises:
       
   102       Exception of the API call or the callback, if any.
       
   103     """
       
   104     if self.exception and self.__traceback:
       
   105       raise self.exception.__class__, self.exception, self.__traceback
       
   106     elif self.exception:
       
   107       raise self.exception
       
   108 
       
   109   @property
       
   110   def exception(self):
       
   111     return self.__exception
       
   112 
       
   113   @property
       
   114   def state(self):
       
   115     return self.__state
       
   116 
       
   117   def _MakeCallImpl(self):
       
   118     """Override this method to implement a real asynchronous call rpc."""
       
   119     self.__state = RPC.RUNNING
       
   120 
       
   121   def _WaitImpl(self):
       
   122     """Override this method to implement a real asynchronous call rpc.
       
   123 
       
   124     Returns:
       
   125       True if the async call was completed successfully.
       
   126     """
       
   127     try:
       
   128       try:
       
   129         self.stub.MakeSyncCall(self.package, self.call,
       
   130                                self.request, self.response)
       
   131       except Exception, e:
       
   132         self.__exception = e
       
   133     finally:
       
   134       self.__state = RPC.FINISHING
       
   135       self.__Callback()
       
   136 
       
   137     return True
       
   138 
       
   139   def __Callback(self):
       
   140     if self.callback:
       
   141       try:
       
   142         self.callback()
       
   143       except:
       
   144         exc_class, self.__exception, self.__traceback = sys.exc_info()
       
   145         self.__exception._appengine_apiproxy_rpc = self
       
   146         raise