]>
Commit | Line | Data |
---|---|---|
a4b75251 TL |
1 | from functools import wraps |
2 | ||
3 | import cherrypy | |
4 | ||
5 | from ..tools import TaskManager | |
6 | from ._helpers import _get_function_params | |
7 | ||
8 | ||
9 | class Task: | |
10 | def __init__(self, name, metadata, wait_for=5.0, exception_handler=None): | |
11 | self.name = name | |
12 | if isinstance(metadata, list): | |
13 | self.metadata = {e[1:-1]: e for e in metadata} | |
14 | else: | |
15 | self.metadata = metadata | |
16 | self.wait_for = wait_for | |
17 | self.exception_handler = exception_handler | |
18 | ||
19 | def _gen_arg_map(self, func, args, kwargs): | |
20 | arg_map = {} | |
21 | params = _get_function_params(func) | |
22 | ||
23 | args = args[1:] # exclude self | |
24 | for idx, param in enumerate(params): | |
25 | if idx < len(args): | |
26 | arg_map[param['name']] = args[idx] | |
27 | else: | |
28 | if param['name'] in kwargs: | |
29 | arg_map[param['name']] = kwargs[param['name']] | |
30 | else: | |
31 | assert not param['required'], "{0} is required".format(param['name']) | |
32 | arg_map[param['name']] = param['default'] | |
33 | ||
34 | if param['name'] in arg_map: | |
35 | # This is not a type error. We are using the index here. | |
36 | arg_map[idx+1] = arg_map[param['name']] | |
37 | ||
38 | return arg_map | |
39 | ||
1e59de90 TL |
40 | def _get_metadata(self, arg_map): |
41 | metadata = {} | |
42 | for k, v in self.metadata.items(): | |
43 | if isinstance(v, str) and v and v[0] == '{' and v[-1] == '}': | |
44 | param = v[1:-1] | |
45 | try: | |
46 | pos = int(param) | |
47 | metadata[k] = arg_map[pos] | |
48 | except ValueError: | |
49 | if param.find('.') == -1: | |
50 | metadata[k] = arg_map[param] | |
51 | else: | |
52 | path = param.split('.') | |
53 | metadata[k] = arg_map[path[0]] | |
54 | for i in range(1, len(path)): | |
55 | metadata[k] = metadata[k][path[i]] | |
56 | else: | |
57 | metadata[k] = v | |
58 | return metadata | |
59 | ||
a4b75251 TL |
60 | def __call__(self, func): |
61 | @wraps(func) | |
62 | def wrapper(*args, **kwargs): | |
63 | arg_map = self._gen_arg_map(func, args, kwargs) | |
1e59de90 TL |
64 | metadata = self._get_metadata(arg_map) |
65 | ||
a4b75251 TL |
66 | task = TaskManager.run(self.name, metadata, func, args, kwargs, |
67 | exception_handler=self.exception_handler) | |
68 | try: | |
69 | status, value = task.wait(self.wait_for) | |
70 | except Exception as ex: | |
71 | if task.ret_value: | |
72 | # exception was handled by task.exception_handler | |
73 | if 'status' in task.ret_value: | |
74 | status = task.ret_value['status'] | |
75 | else: | |
76 | status = getattr(ex, 'status', 500) | |
77 | cherrypy.response.status = status | |
78 | return task.ret_value | |
79 | raise ex | |
80 | if status == TaskManager.VALUE_EXECUTING: | |
81 | cherrypy.response.status = 202 | |
82 | return {'name': self.name, 'metadata': metadata} | |
83 | return value | |
84 | return wrapper |