blob: 70ef6cdf35a8f1e26bd9e65d5512d1d24614c4c8 [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):
jadmanski0afbb632008-06-06 21:10:57 +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):
jadmanski0afbb632008-06-06 21:10:57 +000020 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
jadmanski0afbb632008-06-06 21:10:57 +000025 # store all methods from interface modules
26 for module in rpc_interface_modules:
27 self._grab_methods_from(module)
showard7c785282008-05-29 19:45:12 +000028
jadmanski0afbb632008-06-06 21:10:57 +000029 # 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)
showard7c785282008-05-29 19:45:12 +000034
35
jadmanski0afbb632008-06-06 21:10:57 +000036 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)
showard7c785282008-05-29 19:45:12 +000043
jadmanski0afbb632008-06-06 21:10:57 +000044 response['Content-length'] = str(len(response.content))
45 return response
showard7c785282008-05-29 19:45:12 +000046
47
jadmanski0afbb632008-06-06 21:10:57 +000048 @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
showard7c785282008-05-29 19:45:12 +000063
64
jadmanski0afbb632008-06-06 21:10:57 +000065 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)