--- a/thirdparty/google_appengine/google/appengine/api/apiproxy_stub_map.py Tue Jan 20 01:12:43 2009 +0000
+++ b/thirdparty/google_appengine/google/appengine/api/apiproxy_stub_map.py Tue Jan 20 13:19:45 2009 +0000
@@ -27,10 +27,34 @@
+import inspect
import sys
+def CreateRPC(service):
+ """Creates a RPC instance for the given service.
+
+ The instance is suitable for talking to remote services.
+ Each RPC instance can be used only once, and should not be reused.
+
+ Args:
+ service: string representing which service to call.
+
+ Returns:
+ the rpc object.
+
+ Raises:
+ AssertionError or RuntimeError if the stub for service doesn't supply a
+ CreateRPC method.
+ """
+ stub = apiproxy.GetStub(service)
+ assert stub, 'No api proxy found for service "%s"' % service
+ assert hasattr(stub, 'CreateRPC'), ('The service "%s" doesn\'t have ' +
+ 'a CreateRPC method.' % service)
+ return stub.CreateRPC()
+
+
def MakeSyncCall(service, call, request, response):
- """The APIProxy entry point.
+ """The APIProxy entry point for a synchronous API call.
Args:
service: string representing which service to call
@@ -41,9 +65,99 @@
Raises:
apiproxy_errors.Error or a subclass.
"""
- stub = apiproxy.GetStub(service)
- assert stub, 'No api proxy found for service "%s"' % service
- stub.MakeSyncCall(service, call, request, response)
+ apiproxy.MakeSyncCall(service, call, request, response)
+
+
+class ListOfHooks(object):
+ """An ordered collection of hooks for a particular API call.
+
+ A hook is a function that has exactly the same signature as
+ a service stub. It will be called before or after an api hook is
+ executed, depending on whether this list is for precall of postcall hooks.
+ Hooks can be used for debugging purposes (check certain
+ pre- or postconditions on api calls) or to apply patches to protocol
+ buffers before/after a call gets submitted.
+ """
+
+ def __init__(self):
+ """Constructor."""
+
+ self.__content = []
+
+ self.__unique_keys = set()
+
+ def __len__(self):
+ """Returns the amount of elements in the collection."""
+ return self.__content.__len__()
+
+ def __Insert(self, index, key, function, service=None):
+ """Appends a hook at a certain position in the list.
+
+ Args:
+ index: the index of where to insert the function
+ key: a unique key (within the module) for this particular function.
+ If something from the same module with the same key is already
+ registered, nothing will be added.
+ function: the hook to be added.
+ service: optional argument that restricts the hook to a particular api
+
+ Returns:
+ True if the collection was modified.
+ """
+ unique_key = (key, inspect.getmodule(function))
+ if unique_key in self.__unique_keys:
+ return False
+ self.__content.insert(index, (key, function, service))
+ self.__unique_keys.add(unique_key)
+ return True
+
+ def Append(self, key, function, service=None):
+ """Appends a hook at the end of the list.
+
+ Args:
+ key: a unique key (within the module) for this particular function.
+ If something from the same module with the same key is already
+ registered, nothing will be added.
+ function: the hook to be added.
+ service: optional argument that restricts the hook to a particular api
+
+ Returns:
+ True if the collection was modified.
+ """
+ return self.__Insert(len(self), key, function, service)
+
+ def Push(self, key, function, service=None):
+ """Inserts a hook at the beginning of the list.
+
+ Args:
+ key: a unique key (within the module) for this particular function.
+ If something from the same module with the same key is already
+ registered, nothing will be added.
+ function: the hook to be added.
+ service: optional argument that restricts the hook to a particular api
+
+ Returns:
+ True if the collection was modified.
+ """
+ return self.__Insert(0, key, function, service)
+
+ def Clear(self):
+ """Removes all hooks from the list (useful for unit tests)."""
+ self.__content = []
+ self.__unique_keys = set()
+
+ def Call(self, service, call, request, response):
+ """Invokes all hooks in this collection.
+
+ Args:
+ service: string representing which service to call
+ call: string representing which function to call
+ request: protocol buffer for the request
+ response: protocol buffer for the response
+ """
+ for key, function, srv in self.__content:
+ if srv is None or srv == service:
+ function(service, call, request, response)
class APIProxyStubMap:
@@ -70,6 +184,16 @@
"""
self.__stub_map = {}
self.__default_stub = default_stub
+ self.__precall_hooks = ListOfHooks()
+ self.__postcall_hooks = ListOfHooks()
+
+ def GetPreCallHooks(self):
+ """Gets a collection for all precall hooks."""
+ return self.__precall_hooks
+
+ def GetPostCallHooks(self):
+ """Gets a collection for all precall hooks."""
+ return self.__postcall_hooks
def RegisterStub(self, service, stub):
"""Register the provided stub for the specified service.
@@ -98,6 +222,25 @@
"""
return self.__stub_map.get(service, self.__default_stub)
+ def MakeSyncCall(self, service, call, request, response):
+ """The APIProxy entry point.
+
+ Args:
+ service: string representing which service to call
+ call: string representing which function to call
+ request: protocol buffer for the request
+ response: protocol buffer for the response
+
+ Raises:
+ apiproxy_errors.Error or a subclass.
+ """
+ stub = self.GetStub(service)
+ assert stub, 'No api proxy found for service "%s"' % service
+ self.__precall_hooks.Call(service, call, request, response)
+ stub.MakeSyncCall(service, call, request, response)
+ self.__postcall_hooks.Call(service, call, request, response)
+
+
def GetDefaultAPIProxy():
try:
runtime = __import__('google.appengine.runtime', globals(), locals(),