]> git.openstreetmap.org Git - osqa.git/blob - forum/modules/decorators.py
11af9e3d1c4c1cd49e60b04db024a9344f7269f9
[osqa.git] / forum / modules / decorators.py
1 import inspect\r
2 \r
3 class DecoratableObject(object):\r
4     MODE_OVERRIDE = 0\r
5     MODE_PARAMS = 1\r
6     MODE_RESULT = 2\r
7 \r
8     def __init__(self, fn, is_method=False):\r
9         self._callable = fn\r
10         self.is_method = is_method\r
11 \r
12         self._params_decoration = None\r
13         self._result_decoration = None\r
14 \r
15     def _decorate(self, fn, mode, **kwargs):\r
16         if mode == self.MODE_OVERRIDE:\r
17             self._decorate_full(fn, **kwargs)\r
18         elif mode == self.MODE_PARAMS:\r
19             self._decorate_params(fn)\r
20         elif mode == self.MODE_RESULT:\r
21             self._decorate_result(fn, **kwargs)\r
22 \r
23     def _decorate_full(self, fn, needs_origin=True):\r
24         origin = self._callable\r
25 \r
26         if needs_origin:\r
27             if self.is_method:\r
28                 self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs)\r
29             else:\r
30                 self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
31         else:\r
32             self._callable = fn\r
33 \r
34     def _decorate_params(self, fn):\r
35         if not self._params_decoration:\r
36             self._params_decoration = []\r
37 \r
38         self._params_decoration.append(fn)\r
39 \r
40     def _decorate_result(self, fn, needs_params=False):\r
41         if not self._result_decoration:\r
42             self._result_decoration = []\r
43 \r
44         fn._needs_params = needs_params\r
45         self._result_decoration.append(fn)\r
46 \r
47     def __call__(self, *args, **kwargs):\r
48         if self._params_decoration:\r
49             for dec in self._params_decoration:\r
50                 try:\r
51                     args, kwargs = dec(*args, **kwargs)\r
52                 except ReturnImediatelyException, e:\r
53                     return e.ret\r
54 \r
55         res = self._callable(*args, **kwargs)\r
56 \r
57         if self._result_decoration:\r
58             for dec in self._result_decoration:\r
59                 if dec._needs_params:\r
60                     res = dec(res, *args, **kwargs)\r
61                 else:\r
62                     res = dec(res)\r
63 \r
64         return res\r
65 \r
66 class ReturnImediatelyException(Exception):\r
67     def __init__(self, ret):\r
68         super(Exception, self).__init__()\r
69         self.ret = ret\r
70 \r
71 def _check_decoratable(origin, install=True):\r
72     if not hasattr(origin, '_decoratable_obj'):\r
73         if inspect.ismethod(origin) and not hasattr(origin, '_decoratable_obj'):\r
74             decoratable = DecoratableObject(origin)\r
75 \r
76             def decoratable_method(self, *args, **kwargs):\r
77                 return decoratable(self, *args, **kwargs)\r
78 \r
79             decoratable_method._decoratable_obj = decoratable\r
80 \r
81             def decoratable_decorate(fn, mode, **kwargs):\r
82                 decoratable._decorate(fn, mode, **kwargs)\r
83 \r
84             decoratable_method._decorate = decoratable_decorate\r
85 \r
86             if install:\r
87                 setattr(origin.im_class, origin.__name__, decoratable_method)\r
88 \r
89             return decoratable_method\r
90                 \r
91         elif inspect.isfunction(origin):\r
92             decoratable = DecoratableObject(origin)\r
93 \r
94             def decorated(*args, **kwargs):\r
95                 return decoratable(*args, **kwargs)\r
96 \r
97             decorated._decoratable_obj = decoratable\r
98 \r
99             if install:\r
100                 setattr(inspect.getmodule(origin), origin.__name__, decorated)\r
101 \r
102             decorated.__name__ = origin.__name__\r
103             decorated.__module__ = origin.__module__\r
104 \r
105             return decorated\r
106 \r
107     return origin\r
108 \r
109 \r
110 def decorate(origin, needs_origin=True):\r
111     origin = _check_decoratable(origin)\r
112 \r
113     def decorator(fn):\r
114         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=needs_origin)\r
115         \r
116     return decorator\r
117 \r
118 \r
119 def _decorate_params(origin):\r
120     origin = _check_decoratable(origin)\r
121 \r
122     def decorator(fn):\r
123         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_PARAMS)\r
124 \r
125     return decorator\r
126 \r
127 decorate.params = _decorate_params\r
128 \r
129 def _decorate_result(origin, needs_params=False):\r
130     origin = _check_decoratable(origin)\r
131 \r
132     def decorator(fn):\r
133         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
134 \r
135     return decorator\r
136 \r
137 decorate.result = _decorate_result\r
138 \r
139 def _decorate_with(fn):\r
140     def decorator(origin):\r
141         origin = _check_decoratable(origin)\r
142         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=True)\r
143         return origin\r
144     return decorator\r
145 \r
146 decorate.withfn = _decorate_with\r
147 \r
148 def _decorate_result_with(fn, needs_params=False):\r
149     def decorator(origin):\r
150         origin = _check_decoratable(origin)\r
151         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
152         return origin\r
153     return decorator\r
154 \r
155 decorate.result.withfn = _decorate_result_with\r
156 \r
157 def _decorate_params_with(fn):\r
158     def decorator(origin):\r
159         origin = _check_decoratable(origin)\r
160         origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_PARAMS)\r
161         return origin\r
162     return decorator\r
163 \r
164 decorate.params.withfn = _decorate_params_with