]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/modules/decorators.py
Makes tags and users lists use the new paginators, completelly remove the old cnprog...
[osqa.git] / forum / modules / decorators.py
index 17d248b1559b378f950da64f53e87404afe2f1a8..c7c564030adafdb8263ca922e6eb85144625cda4 100644 (file)
 import inspect\r
 \r
 class DecoratableObject(object):\r
+    MODE_OVERRIDE = 0\r
+    MODE_PARAMS = 1\r
+    MODE_RESULT = 2\r
+\r
     def __init__(self, fn):\r
+        a = inspect.getargspec(fn)\r
         self._callable = fn\r
+        self._params_decoration = None\r
+        self._result_decoration = None\r
 \r
-    def decorate(self, fn, needs_origin):\r
+    def _decorate(self, fn, needs_origin, method=False):\r
         origin = self._callable\r
 \r
         if needs_origin:\r
-            self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
+            if method:\r
+                self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs)\r
+            else:\r
+                self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
         else:\r
-            self._callable = lambda *args, **kwargs: fn(*args, **kwargs)\r
+            self._callable = fn\r
+\r
+    def _decorate_params(self, fn):\r
+        if not self._params_decoration:\r
+            self._params_decoration = []\r
+\r
+        self._params_decoration.append(fn)\r
+\r
+    def _decorate_result(self, fn):\r
+        if not self._result_decoration:\r
+            self._result_decoration = []\r
+\r
+        self._result_decoration.append(fn)\r
 \r
     def __call__(self, *args, **kwargs):\r
-        return self._callable(*args, **kwargs)\r
+        if self._params_decoration:\r
+            for dec in self._params_decoration:\r
+                args, kwargs = dec(*args, **kwargs)\r
+\r
+        res = self._callable(*args, **kwargs)\r
 \r
+        if self._result_decoration:\r
+            for dec in self._result_decoration:\r
+                res = dec(res)\r
 \r
-def decoratable(fn):\r
-    return DecoratableObject(fn)\r
+        return res\r
+\r
+\r
+def _create_decorator(origin, needs_origin, mode, method=False):\r
+    def decorator(fn):\r
+        if mode == DecoratableObject.MODE_OVERRIDE:\r
+            origin._decorate(fn, needs_origin, method=method)\r
+        elif mode == DecoratableObject.MODE_PARAMS:\r
+            origin._decorate_params(fn)\r
+        elif mode == DecoratableObject.MODE_RESULT:\r
+            origin._decorate_result(fn)\r
+\r
+        return fn\r
+\r
+    return decorator\r
 \r
-def decoratable_method(fn):\r
-    obj = DecoratableObject(fn)\r
-    def decorated(self, *args, **kwargs):\r
-        return obj(self, *args, **kwargs)\r
 \r
-    decorated.__obj = obj\r
-    return decorated\r
+def _decorate_method(origin, needs_origin, mode):\r
+    if not hasattr(origin, '_decoratable_obj'):\r
+        name = origin.__name__\r
+        cls = origin.im_class\r
 \r
-decoratable.method = decoratable_method\r
+        decoratable = DecoratableObject(origin)\r
 \r
-def decorate(origin, needs_origin=True):\r
+        def decoratable_method(self, *args, **kwargs):\r
+            return decoratable(self, *args, **kwargs)\r
+\r
+        decoratable_method._decoratable_obj = decoratable\r
+        setattr(cls, name, decoratable_method)\r
+    else:\r
+        decoratable = origin._decoratable_obj\r
+\r
+    return _create_decorator(decoratable, needs_origin, mode, method=True)\r
+\r
+def _decorate_function(origin, needs_origin, mode):\r
     if not isinstance(origin, DecoratableObject):\r
-        if hasattr(origin, '__obj'):\r
-            def decorator(fn):\r
-                origin.__obj.decorate(fn, needs_origin)\r
-                return origin\r
-            return decorator\r
+        mod = inspect.getmodule(origin)\r
+\r
+        name = origin.__name__\r
+        origin = DecoratableObject(origin)\r
+        setattr(mod, name, origin)\r
+\r
+    return _create_decorator(origin, needs_origin, mode)\r
+\r
 \r
-        raise Exception('Not an decoratable function: %s' % origin.name)\r
+def decorate(origin, needs_origin=True, mode=DecoratableObject.MODE_OVERRIDE):\r
+    if inspect.ismethod(origin):\r
+        return _decorate_method(origin, needs_origin, mode)\r
+\r
+    if inspect.isfunction(origin) or isinstance(origin, DecoratableObject):\r
+        return _decorate_function(origin, needs_origin, mode)\r
 \r
     def decorator(fn):\r
-        origin.decorate(fn, needs_origin)\r
-        return origin\r
+        return fn\r
 \r
     return decorator\r
 \r
 \r
+def _decorate_params(origin):\r
+    return decorate(origin, mode=DecoratableObject.MODE_PARAMS)\r
+\r
+decorate.params = _decorate_params\r
 \r
+def _decorate_result(origin):\r
+    return decorate(origin, mode=DecoratableObject.MODE_RESULT)\r
 \r
+decorate.result = _decorate_result\r
 \r
+def _decorate_with(fn):\r
+    def decorator(origin):\r
+        if not isinstance(origin, DecoratableObject):\r
+            decoratable = DecoratableObject(origin)\r
+        else:\r
+            decoratable = origin\r
+\r
+        decoratable._decorate(fn, True, False)\r
+        return decoratable\r
+    return decorator\r
 \r
 \r
+decorate.withfn = _decorate_with
\ No newline at end of file