]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/modules/decorators.py
Use the islatest field on the apps feed to get the latest version of an app.
[osqa.git] / forum / modules / decorators.py
index 90109a99d0fc916867f6997fce4f46d39844c45f..11af9e3d1c4c1cd49e60b04db024a9344f7269f9 100644 (file)
 import inspect\r
 \r
 class DecoratableObject(object):\r
-    def __init__(self, fn):\r
+    MODE_OVERRIDE = 0\r
+    MODE_PARAMS = 1\r
+    MODE_RESULT = 2\r
+\r
+    def __init__(self, fn, is_method=False):\r
         self._callable = fn\r
+        self.is_method = is_method\r
 \r
-    def _decorate(self, fn, needs_origin):\r
-        origin = self._callable\r
+        self._params_decoration = None\r
+        self._result_decoration = None\r
 \r
-        if needs_origin:\r
-            self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
-        else:\r
-            self._callable = lambda *args, **kwargs: fn(*args, **kwargs)\r
+    def _decorate(self, fn, mode, **kwargs):\r
+        if mode == self.MODE_OVERRIDE:\r
+            self._decorate_full(fn, **kwargs)\r
+        elif mode == self.MODE_PARAMS:\r
+            self._decorate_params(fn)\r
+        elif mode == self.MODE_RESULT:\r
+            self._decorate_result(fn, **kwargs)\r
 \r
-    def _decorate_method(self, fn, needs_origin):\r
+    def _decorate_full(self, fn, needs_origin=True):\r
         origin = self._callable\r
 \r
         if needs_origin:\r
-            self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs)\r
+            if self.is_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 inst, *args, **kwargs: fn(inst, *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
-    def __call__(self, *args, **kwargs):\r
-        return self._callable(*args, **kwargs)\r
+        self._params_decoration.append(fn)\r
+\r
+    def _decorate_result(self, fn, needs_params=False):\r
+        if not self._result_decoration:\r
+            self._result_decoration = []\r
 \r
+        fn._needs_params = needs_params\r
+        self._result_decoration.append(fn)\r
 \r
-def _decorate_method(origin, needs_origin):\r
+    def __call__(self, *args, **kwargs):\r
+        if self._params_decoration:\r
+            for dec in self._params_decoration:\r
+                try:\r
+                    args, kwargs = dec(*args, **kwargs)\r
+                except ReturnImediatelyException, e:\r
+                    return e.ret\r
+\r
+        res = self._callable(*args, **kwargs)\r
+\r
+        if self._result_decoration:\r
+            for dec in self._result_decoration:\r
+                if dec._needs_params:\r
+                    res = dec(res, *args, **kwargs)\r
+                else:\r
+                    res = dec(res)\r
+\r
+        return res\r
+\r
+class ReturnImediatelyException(Exception):\r
+    def __init__(self, ret):\r
+        super(Exception, self).__init__()\r
+        self.ret = ret\r
+\r
+def _check_decoratable(origin, install=True):\r
     if not hasattr(origin, '_decoratable_obj'):\r
-        name = origin.__name__\r
-        cls = origin.im_class\r
+        if inspect.ismethod(origin) and not hasattr(origin, '_decoratable_obj'):\r
+            decoratable = DecoratableObject(origin)\r
+\r
+            def decoratable_method(self, *args, **kwargs):\r
+                return decoratable(self, *args, **kwargs)\r
+\r
+            decoratable_method._decoratable_obj = decoratable\r
+\r
+            def decoratable_decorate(fn, mode, **kwargs):\r
+                decoratable._decorate(fn, mode, **kwargs)\r
+\r
+            decoratable_method._decorate = decoratable_decorate\r
+\r
+            if install:\r
+                setattr(origin.im_class, origin.__name__, decoratable_method)\r
+\r
+            return decoratable_method\r
+                \r
+        elif inspect.isfunction(origin):\r
+            decoratable = DecoratableObject(origin)\r
+\r
+            def decorated(*args, **kwargs):\r
+                return decoratable(*args, **kwargs)\r
+\r
+            decorated._decoratable_obj = decoratable\r
+\r
+            if install:\r
+                setattr(inspect.getmodule(origin), origin.__name__, decorated)\r
 \r
-        decoratable = DecoratableObject(origin)\r
+            decorated.__name__ = origin.__name__\r
+            decorated.__module__ = origin.__module__\r
 \r
-        def decoratable_method(self, *args, **kwargs):\r
-            return decoratable(self, *args, **kwargs)\r
+            return decorated\r
 \r
-        decoratable_method._decoratable_obj = decoratable\r
-        setattr(cls, name, decoratable_method)\r
-    else:\r
-        decoratable = origin._decoratable_obj\r
+    return origin\r
+\r
+\r
+def decorate(origin, needs_origin=True):\r
+    origin = _check_decoratable(origin)\r
+\r
+    def decorator(fn):\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=needs_origin)\r
+        \r
+    return decorator\r
+\r
+\r
+def _decorate_params(origin):\r
+    origin = _check_decoratable(origin)\r
 \r
     def decorator(fn):\r
-        decoratable._decorate_method(fn, needs_origin)\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_PARAMS)\r
 \r
     return decorator\r
 \r
-def _decorate_function(origin, needs_origin):\r
-    if not isinstance(origin, DecoratableObject):\r
-        mod = inspect.getmodule(origin)\r
+decorate.params = _decorate_params\r
 \r
-        name = origin.__name__\r
-        origin = DecoratableObject(origin)\r
-        setattr(mod, name, DecoratableObject(origin))\r
+def _decorate_result(origin, needs_params=False):\r
+    origin = _check_decoratable(origin)\r
 \r
     def decorator(fn):\r
-        origin._decorate(fn, needs_origin)\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
 \r
     return decorator\r
 \r
+decorate.result = _decorate_result\r
 \r
-def decorate(origin, needs_origin=True):\r
-    if inspect.ismethod(origin):\r
-        return _decorate_method(origin, needs_origin)\r
+def _decorate_with(fn):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=True)\r
+        return origin\r
+    return decorator\r
+\r
+decorate.withfn = _decorate_with\r
+\r
+def _decorate_result_with(fn, needs_params=False):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
+        return origin\r
+    return decorator\r
+\r
+decorate.result.withfn = _decorate_result_with\r
+\r
+def _decorate_params_with(fn):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decoratable_obj._decorate(fn, DecoratableObject.MODE_PARAMS)\r
+        return origin\r
+    return decorator\r
 \r
-    if inspect.isfunction(origin):\r
-        return _decorate_function(origin, needs_origin)
\ No newline at end of file
+decorate.params.withfn = _decorate_params_with
\ No newline at end of file