]> git.openstreetmap.org Git - osqa.git/blob - forum/modules/decorators.py
OSQA-266
[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                 args, kwargs = dec(*args, **kwargs)\r
51 \r
52         res = self._callable(*args, **kwargs)\r
53 \r
54         if self._result_decoration:\r
55             for dec in self._result_decoration:\r
56                 if dec._needs_params:\r
57                     res = dec(res, *args, **kwargs)\r
58                 else:\r
59                     res = dec(res)\r
60 \r
61         return res\r
62 \r
63 def _check_decoratable(origin, install=True):\r
64     if not isinstance(origin, DecoratableObject):\r
65         if inspect.ismethod(origin) and not hasattr(origin, '_decoratable_obj'):\r
66             decoratable = DecoratableObject(origin)\r
67 \r
68             def decoratable_method(self, *args, **kwargs):\r
69                 return decoratable(self, *args, **kwargs)\r
70 \r
71             decoratable_method._decoratable_obj = decoratable\r
72 \r
73             def decoratable_decorate(fn, mode, **kwargs):\r
74                 decoratable._decorate(fn, mode, **kwargs)\r
75 \r
76             decoratable_method._decorate = decoratable_decorate\r
77 \r
78             if install:\r
79                 setattr(origin.im_class, origin.__name__, decoratable_method)\r
80 \r
81             return decoratable_method\r
82                 \r
83         elif inspect.isfunction(origin):\r
84             decoratable = DecoratableObject(origin)\r
85 \r
86             if install:\r
87                 setattr(inspect.getmodule(origin), origin.__name__, decoratable)\r
88 \r
89             return decoratable\r
90 \r
91     return origin\r
92 \r
93 \r
94 def decorate(origin, needs_origin=True):\r
95     origin = _check_decoratable(origin)\r
96 \r
97     def decorator(fn):\r
98         origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=needs_origin)\r
99         \r
100     return decorator\r
101 \r
102 \r
103 def _decorate_params(origin):\r
104     origin = _check_decoratable(origin)\r
105 \r
106     def decorator(fn):\r
107         origin._decorate(fn, DecoratableObject.MODE_PARAMS)\r
108 \r
109     return decorator\r
110 \r
111 decorate.params = _decorate_params\r
112 \r
113 def _decorate_result(origin, needs_params=False):\r
114     origin = _check_decoratable(origin)\r
115 \r
116     def decorator(fn):\r
117         origin._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
118 \r
119     return decorator\r
120 \r
121 decorate.result = _decorate_result\r
122 \r
123 def _decorate_with(fn):\r
124     def decorator(origin):\r
125         origin = _check_decoratable(origin)\r
126         origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=True)\r
127         return origin\r
128     return decorator\r
129 \r
130 decorate.withfn = _decorate_with\r
131 \r
132 def _decorate_result_with(fn, needs_params=False):\r
133     def decorator(origin):\r
134         origin = _check_decoratable(origin)\r
135         origin._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
136         return origin\r
137     return decorator\r
138 \r
139 decorate.result.withfn = _decorate_result_with\r
140 \r
141 def _decorate_params_with(fn):\r
142     def decorator(origin):\r
143         origin = _check_decoratable(origin)\r
144         origin._decorate(fn, DecoratableObject.MODE_PARAMS)\r
145         return origin\r
146     return decorator\r
147 \r
148 decorate.params.withfn = _decorate_params_with