]> git.openstreetmap.org Git - osqa.git/blob - forum/modules/decorators.py
Shows user diamonds in some missing spots, and adds some improvements to module decor...
[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):\r
9         a = inspect.getargspec(fn)\r
10         self._callable = fn\r
11         self._params_decoration = None\r
12         self._result_decoration = None\r
13 \r
14     def _decorate(self, fn, needs_origin, method=False):\r
15         origin = self._callable\r
16 \r
17         if needs_origin:\r
18             if method:\r
19                 self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs)\r
20             else:\r
21                 self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
22         else:\r
23             self._callable = fn\r
24 \r
25     def _decorate_params(self, fn):\r
26         if not self._params_decoration:\r
27             self._params_decoration = []\r
28 \r
29         self._params_decoration.append(fn)\r
30 \r
31     def _decorate_result(self, fn):\r
32         if not self._result_decoration:\r
33             self._result_decoration = []\r
34 \r
35         self._result_decoration.append(fn)\r
36 \r
37     def __call__(self, *args, **kwargs):\r
38         if self._params_decoration:\r
39             for dec in self._params_decoration:\r
40                 args, kwargs = dec(*args, **kwargs)\r
41 \r
42         res = self._callable(*args, **kwargs)\r
43 \r
44         if self._result_decoration:\r
45             for dec in self._result_decoration:\r
46                 res = dec(res)\r
47 \r
48         return res\r
49 \r
50 \r
51 def _create_decorator(origin, needs_origin, mode, method=False):\r
52     def decorator(fn):\r
53         if mode == DecoratableObject.MODE_OVERRIDE:\r
54             origin._decorate(fn, needs_origin, method=method)\r
55         elif mode == DecoratableObject.MODE_PARAMS:\r
56             origin._decorate_params(fn)\r
57         elif mode == DecoratableObject.MODE_RESULT:\r
58             origin._decorate_result(fn)\r
59 \r
60         return fn\r
61 \r
62     return decorator\r
63 \r
64 \r
65 def _decorate_method(origin, needs_origin, mode):\r
66     if not hasattr(origin, '_decoratable_obj'):\r
67         name = origin.__name__\r
68         cls = origin.im_class\r
69 \r
70         decoratable = DecoratableObject(origin)\r
71 \r
72         def decoratable_method(self, *args, **kwargs):\r
73             return decoratable(self, *args, **kwargs)\r
74 \r
75         decoratable_method._decoratable_obj = decoratable\r
76         setattr(cls, name, decoratable_method)\r
77     else:\r
78         decoratable = origin._decoratable_obj\r
79 \r
80     return _create_decorator(decoratable, needs_origin, mode, method=True)\r
81 \r
82 def _decorate_function(origin, needs_origin, mode):\r
83     if not isinstance(origin, DecoratableObject):\r
84         mod = inspect.getmodule(origin)\r
85 \r
86         name = origin.__name__\r
87         origin = DecoratableObject(origin)\r
88         setattr(mod, name, origin)\r
89 \r
90     return _create_decorator(origin, needs_origin, mode)\r
91 \r
92 \r
93 def decorate(origin, needs_origin=True, mode=DecoratableObject.MODE_OVERRIDE):\r
94     if inspect.ismethod(origin):\r
95         return _decorate_method(origin, needs_origin, mode)\r
96 \r
97     if inspect.isfunction(origin) or isinstance(origin, DecoratableObject):\r
98         return _decorate_function(origin, needs_origin, mode)\r
99 \r
100     def decorator(fn):\r
101         return fn\r
102 \r
103     return decorator\r
104 \r
105 \r
106 def _decorate_params(origin):\r
107     return decorate(origin, mode=DecoratableObject.MODE_PARAMS)\r
108 \r
109 decorate.params = _decorate_params\r
110 \r
111 def _decorate_result(origin):\r
112     return decorate(origin, mode=DecoratableObject.MODE_RESULT)\r
113 \r
114 decorate.result = _decorate_result\r
115 \r
116 def _decorate_with(fn):\r
117     def decorator(origin):\r
118         if not isinstance(origin, DecoratableObject):\r
119             mod = inspect.getmodule(origin)\r
120 \r
121             name = origin.__name__\r
122             origin = DecoratableObject(origin)\r
123 \r
124         origin._decorate(fn, True, False)\r
125         return origin\r
126     return decorator\r
127 \r
128 \r
129 decorate.withfn = _decorate_with