blob: f9ba2e2e10ee53edd08ade7d63e62991d28782a4 [file] [log] [blame]
mblighe8819cd2008-02-15 16:48:40 +00001"""\
2RPC request handler Django. Exposed RPC interface functions should be
3defined in rpc_interface.py.
4"""
5
6__author__ = 'showard@google.com (Steve Howard)'
7
8import django.http
9import traceback, pydoc
10
11from frontend.afe.json_rpc import serviceHandler
showard7c785282008-05-29 19:45:12 +000012from frontend.afe import rpc_utils
mblighe8819cd2008-02-15 16:48:40 +000013
mblighe8819cd2008-02-15 16:48:40 +000014
15class RpcMethodHolder(object):
showard7c785282008-05-29 19:45:12 +000016 'Dummy class to hold RPC interface methods as attributes.'
mblighe8819cd2008-02-15 16:48:40 +000017
18
showard7c785282008-05-29 19:45:12 +000019class RpcHandler(object):
20 def __init__(self, rpc_interface_modules, document_module=None):
21 self._rpc_methods = RpcMethodHolder()
22 self._dispatcher = serviceHandler.ServiceHandler(
23 self._rpc_methods)
mblighe8819cd2008-02-15 16:48:40 +000024
showard7c785282008-05-29 19:45:12 +000025 # store all methods from interface modules
26 for module in rpc_interface_modules:
27 self._grab_methods_from(module)
28
29 # get documentation for rpc_interface we can send back to the
30 # user
31 if document_module is None:
32 document_module = rpc_interface_modules[0]
33 self.html_doc = pydoc.html.document(document_module)
34
35
36 def handle_rpc_request(self, request):
37 response = django.http.HttpResponse()
38 if len(request.POST):
39 response.write(self._dispatcher.handleRequest(
40 request.raw_post_data))
41 else:
42 response.write(self.html_doc)
43
44 response['Content-length'] = str(len(response.content))
45 return response
46
47
48 @staticmethod
49 def _allow_keyword_args(f):
50 """\
51 Decorator to allow a function to take keyword args even though
52 the RPC layer doesn't support that. The decorated function
53 assumes its last argument is a dictionary of keyword args and
54 passes them to the original function as keyword args.
55 """
56 def new_fn(*args):
57 assert args
58 keyword_args = args[-1]
59 args = args[:-1]
60 return f(*args, **keyword_args)
61 new_fn.func_name = f.func_name
62 return new_fn
63
64
65 def _grab_methods_from(self, module):
66 for name in dir(module):
67 attribute = getattr(module, name)
68 if not callable(attribute):
69 continue
70 decorated_function = (
71 RpcHandler._allow_keyword_args(attribute))
72 setattr(self._rpc_methods, name, decorated_function)