mbligh | e8819cd | 2008-02-15 16:48:40 +0000 | [diff] [blame] | 1 | """\ |
| 2 | RPC request handler Django. Exposed RPC interface functions should be |
| 3 | defined in rpc_interface.py. |
| 4 | """ |
| 5 | |
| 6 | __author__ = 'showard@google.com (Steve Howard)' |
| 7 | |
| 8 | import django.http |
| 9 | import traceback, pydoc |
| 10 | |
| 11 | from frontend.afe.json_rpc import serviceHandler |
| 12 | from frontend.afe import rpc_interface, rpc_utils, site_rpc_interface |
| 13 | |
| 14 | # since site_rpc_interface is later in the list, its methods will override those |
| 15 | # of rpc_interface |
| 16 | RPC_INTERFACE_MODULES = (rpc_interface, site_rpc_interface) |
| 17 | |
| 18 | class RpcMethodHolder(object): |
| 19 | 'Dummy class to hold RPC interface methods as attributes.' |
| 20 | |
| 21 | rpc_methods = RpcMethodHolder() |
| 22 | |
| 23 | dispatcher = serviceHandler.ServiceHandler(rpc_methods) |
| 24 | |
| 25 | # get documentation for rpc_interface we can send back to the user |
| 26 | html_doc = pydoc.html.document(rpc_interface) |
| 27 | |
| 28 | def rpc_handler(request): |
| 29 | rpc_utils.set_user(request.afe_user) |
| 30 | response = django.http.HttpResponse() |
| 31 | if len(request.POST): |
| 32 | response.write(dispatcher.handleRequest(request.raw_post_data)) |
| 33 | else: |
| 34 | response.write(html_doc) |
| 35 | |
| 36 | response['Content-length'] = str(len(response.content)) |
| 37 | return response |
| 38 | |
| 39 | |
| 40 | def allow_keyword_args(f): |
| 41 | """\ |
| 42 | Decorator to allow a function to take keyword args even though the RPC |
| 43 | layer doesn't support that. The decorated function assumes its last |
| 44 | argument is a dictionary of keyword args and passes them to the original |
| 45 | function as keyword args. |
| 46 | """ |
| 47 | def new_fn(*args): |
| 48 | assert args |
| 49 | keyword_args = args[-1] |
| 50 | args = args[:-1] |
| 51 | return f(*args, **keyword_args) |
| 52 | new_fn.func_name = f.func_name |
| 53 | return new_fn |
| 54 | |
| 55 | # decorate all functions in rpc_interface to take keyword args |
| 56 | function_type = type(rpc_handler) # could be any function |
| 57 | for module in RPC_INTERFACE_MODULES: |
| 58 | for name in dir(module): |
| 59 | thing = getattr(module, name) |
| 60 | if type(thing) is function_type: |
| 61 | decorated_function = allow_keyword_args(thing) |
| 62 | setattr(rpc_methods, name, decorated_function) |