thirdparty/google_appengine/google/appengine/api/apiproxy_stub_map.py
changeset 828 f5fd65cc3bf3
parent 109 620f9b141567
child 2413 d0b7dac5325c
equal deleted inserted replaced
827:88c186556a80 828:f5fd65cc3bf3
    25 
    25 
    26 
    26 
    27 
    27 
    28 
    28 
    29 
    29 
       
    30 import inspect
    30 import sys
    31 import sys
    31 
    32 
       
    33 def CreateRPC(service):
       
    34   """Creates a RPC instance for the given service.
       
    35 
       
    36   The instance is suitable for talking to remote services.
       
    37   Each RPC instance can be used only once, and should not be reused.
       
    38 
       
    39   Args:
       
    40     service: string representing which service to call.
       
    41 
       
    42   Returns:
       
    43     the rpc object.
       
    44 
       
    45   Raises:
       
    46     AssertionError or RuntimeError if the stub for service doesn't supply a
       
    47     CreateRPC method.
       
    48   """
       
    49   stub = apiproxy.GetStub(service)
       
    50   assert stub, 'No api proxy found for service "%s"' % service
       
    51   assert hasattr(stub, 'CreateRPC'), ('The service "%s" doesn\'t have ' +
       
    52                                       'a CreateRPC method.' % service)
       
    53   return stub.CreateRPC()
       
    54 
       
    55 
    32 def MakeSyncCall(service, call, request, response):
    56 def MakeSyncCall(service, call, request, response):
    33   """The APIProxy entry point.
    57   """The APIProxy entry point for a synchronous API call.
    34 
    58 
    35   Args:
    59   Args:
    36     service: string representing which service to call
    60     service: string representing which service to call
    37     call: string representing which function to call
    61     call: string representing which function to call
    38     request: protocol buffer for the request
    62     request: protocol buffer for the request
    39     response: protocol buffer for the response
    63     response: protocol buffer for the response
    40 
    64 
    41   Raises:
    65   Raises:
    42     apiproxy_errors.Error or a subclass.
    66     apiproxy_errors.Error or a subclass.
    43   """
    67   """
    44   stub = apiproxy.GetStub(service)
    68   apiproxy.MakeSyncCall(service, call, request, response)
    45   assert stub, 'No api proxy found for service "%s"' % service
    69 
    46   stub.MakeSyncCall(service, call, request, response)
    70 
       
    71 class ListOfHooks(object):
       
    72   """An ordered collection of hooks for a particular API call.
       
    73 
       
    74   A hook is a function that has exactly the same signature as
       
    75   a service stub. It will be called before or after an api hook is
       
    76   executed, depending on whether this list is for precall of postcall hooks.
       
    77   Hooks can be used for debugging purposes (check certain
       
    78   pre- or postconditions on api calls) or to apply patches to protocol
       
    79   buffers before/after a call gets submitted.
       
    80   """
       
    81 
       
    82   def __init__(self):
       
    83     """Constructor."""
       
    84 
       
    85     self.__content = []
       
    86 
       
    87     self.__unique_keys = set()
       
    88 
       
    89   def __len__(self):
       
    90     """Returns the amount of elements in the collection."""
       
    91     return self.__content.__len__()
       
    92 
       
    93   def __Insert(self, index, key, function, service=None):
       
    94     """Appends a hook at a certain position in the list.
       
    95 
       
    96     Args:
       
    97       index: the index of where to insert the function
       
    98       key: a unique key (within the module) for this particular function.
       
    99         If something from the same module with the same key is already
       
   100         registered, nothing will be added.
       
   101       function: the hook to be added.
       
   102       service: optional argument that restricts the hook to a particular api
       
   103 
       
   104     Returns:
       
   105       True if the collection was modified.
       
   106     """
       
   107     unique_key = (key, inspect.getmodule(function))
       
   108     if unique_key in self.__unique_keys:
       
   109       return False
       
   110     self.__content.insert(index, (key, function, service))
       
   111     self.__unique_keys.add(unique_key)
       
   112     return True
       
   113 
       
   114   def Append(self, key, function, service=None):
       
   115     """Appends a hook at the end of the list.
       
   116 
       
   117     Args:
       
   118       key: a unique key (within the module) for this particular function.
       
   119         If something from the same module with the same key is already
       
   120         registered, nothing will be added.
       
   121       function: the hook to be added.
       
   122       service: optional argument that restricts the hook to a particular api
       
   123 
       
   124     Returns:
       
   125       True if the collection was modified.
       
   126     """
       
   127     return self.__Insert(len(self), key, function, service)
       
   128 
       
   129   def Push(self, key, function, service=None):
       
   130     """Inserts a hook at the beginning of the list.
       
   131 
       
   132     Args:
       
   133       key: a unique key (within the module) for this particular function.
       
   134         If something from the same module with the same key is already
       
   135         registered, nothing will be added.
       
   136       function: the hook to be added.
       
   137       service: optional argument that restricts the hook to a particular api
       
   138 
       
   139     Returns:
       
   140       True if the collection was modified.
       
   141     """
       
   142     return self.__Insert(0, key, function, service)
       
   143 
       
   144   def Clear(self):
       
   145     """Removes all hooks from the list (useful for unit tests)."""
       
   146     self.__content = []
       
   147     self.__unique_keys = set()
       
   148 
       
   149   def Call(self, service, call, request, response):
       
   150     """Invokes all hooks in this collection.
       
   151 
       
   152     Args:
       
   153       service: string representing which service to call
       
   154       call: string representing which function to call
       
   155       request: protocol buffer for the request
       
   156       response: protocol buffer for the response
       
   157     """
       
   158     for key, function, srv in self.__content:
       
   159       if srv is None or srv == service:
       
   160         function(service, call, request, response)
    47 
   161 
    48 
   162 
    49 class APIProxyStubMap:
   163 class APIProxyStubMap:
    50   """Container of APIProxy stubs for more convenient unittesting.
   164   """Container of APIProxy stubs for more convenient unittesting.
    51 
   165 
    68 
   182 
    69     'default_stub' will be used whenever no specific matching stub is found.
   183     'default_stub' will be used whenever no specific matching stub is found.
    70     """
   184     """
    71     self.__stub_map = {}
   185     self.__stub_map = {}
    72     self.__default_stub = default_stub
   186     self.__default_stub = default_stub
       
   187     self.__precall_hooks = ListOfHooks()
       
   188     self.__postcall_hooks = ListOfHooks()
       
   189 
       
   190   def GetPreCallHooks(self):
       
   191     """Gets a collection for all precall hooks."""
       
   192     return self.__precall_hooks
       
   193 
       
   194   def GetPostCallHooks(self):
       
   195     """Gets a collection for all precall hooks."""
       
   196     return self.__postcall_hooks
    73 
   197 
    74   def RegisterStub(self, service, stub):
   198   def RegisterStub(self, service, stub):
    75     """Register the provided stub for the specified service.
   199     """Register the provided stub for the specified service.
    76 
   200 
    77     Args:
   201     Args:
    95 
   219 
    96     Returns the stub registered for 'service', and returns the default stub
   220     Returns the stub registered for 'service', and returns the default stub
    97     if no such stub is found.
   221     if no such stub is found.
    98     """
   222     """
    99     return self.__stub_map.get(service, self.__default_stub)
   223     return self.__stub_map.get(service, self.__default_stub)
       
   224 
       
   225   def MakeSyncCall(self, service, call, request, response):
       
   226     """The APIProxy entry point.
       
   227 
       
   228     Args:
       
   229       service: string representing which service to call
       
   230       call: string representing which function to call
       
   231       request: protocol buffer for the request
       
   232       response: protocol buffer for the response
       
   233 
       
   234     Raises:
       
   235       apiproxy_errors.Error or a subclass.
       
   236     """
       
   237     stub = self.GetStub(service)
       
   238     assert stub, 'No api proxy found for service "%s"' % service
       
   239     self.__precall_hooks.Call(service, call, request, response)
       
   240     stub.MakeSyncCall(service, call, request, response)
       
   241     self.__postcall_hooks.Call(service, call, request, response)
       
   242 
   100 
   243 
   101 def GetDefaultAPIProxy():
   244 def GetDefaultAPIProxy():
   102   try:
   245   try:
   103     runtime = __import__('google.appengine.runtime', globals(), locals(),
   246     runtime = __import__('google.appengine.runtime', globals(), locals(),
   104                          ['apiproxy'])
   247                          ['apiproxy'])