]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/modules/decorators.py
Applies some of the Justin Grant's patches.
[osqa.git] / forum / modules / decorators.py
index 48bee43ce5994032d3454e79090eafbc939ac039..3c53412dc0505c4c92bbe183a6709ca007dc5a34 100644 (file)
@@ -5,17 +5,26 @@ class DecoratableObject(object):
     MODE_PARAMS = 1\r
     MODE_RESULT = 2\r
 \r
-    def __init__(self, fn):\r
-        a = inspect.getargspec(fn)\r
+    def __init__(self, fn, is_method=False):\r
         self._callable = fn\r
+        self.is_method = is_method\r
+\r
         self._params_decoration = None\r
         self._result_decoration = None\r
 \r
-    def _decorate(self, fn, needs_origin, method=False):\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_full(self, fn, needs_origin=True):\r
         origin = self._callable\r
 \r
         if needs_origin:\r
-            if method:\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
@@ -28,102 +37,120 @@ class DecoratableObject(object):
 \r
         self._params_decoration.append(fn)\r
 \r
-    def _decorate_result(self, fn):\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 __call__(self, *args, **kwargs):\r
         if self._params_decoration:\r
             for dec in self._params_decoration:\r
-                args, kwargs = dec(*args, **kwargs)\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
-                res = dec(res)\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 _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
+def _check_decoratable(origin, install=True):\r
+    if not isinstance(origin, DecoratableObject):\r
+        if inspect.ismethod(origin) and not hasattr(origin, '_decoratable_obj'):\r
+            decoratable = DecoratableObject(origin)\r
 \r
-        return fn\r
+            def decoratable_method(self, *args, **kwargs):\r
+                return decoratable(self, *args, **kwargs)\r
 \r
-    return decorator\r
+            decoratable_method._decoratable_obj = decoratable\r
 \r
+            def decoratable_decorate(fn, mode, **kwargs):\r
+                decoratable._decorate(fn, mode, **kwargs)\r
 \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
+            decoratable_method._decorate = decoratable_decorate\r
 \r
-        decoratable = DecoratableObject(origin)\r
+            if install:\r
+                setattr(origin.im_class, origin.__name__, decoratable_method)\r
 \r
-        def decoratable_method(self, *args, **kwargs):\r
-            return decoratable(self, *args, **kwargs)\r
+            return decoratable_method\r
+                \r
+        elif inspect.isfunction(origin):\r
+            decoratable = DecoratableObject(origin)\r
 \r
-        decoratable_method._decoratable_obj = decoratable\r
-        setattr(cls, name, decoratable_method)\r
-    else:\r
-        decoratable = origin._decoratable_obj\r
+            if install:\r
+                setattr(inspect.getmodule(origin), origin.__name__, decoratable)\r
 \r
-    return _create_decorator(decoratable, needs_origin, mode, method=True)\r
+            return decoratable\r
 \r
-def _decorate_function(origin, needs_origin, mode):\r
-    if not isinstance(origin, DecoratableObject):\r
-        mod = inspect.getmodule(origin)\r
+    return 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
+def decorate(origin, needs_origin=True):\r
+    origin = _check_decoratable(origin)\r
 \r
+    def decorator(fn):\r
+        origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=needs_origin)\r
+        \r
+    return decorator\r
 \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
+def _decorate_params(origin):\r
+    origin = _check_decoratable(origin)\r
 \r
     def decorator(fn):\r
-        return fn\r
+        origin._decorate(fn, DecoratableObject.MODE_PARAMS)\r
 \r
     return decorator\r
 \r
+decorate.params = _decorate_params\r
 \r
-def _decorate_params(origin):\r
-    return decorate(origin, mode=DecoratableObject.MODE_PARAMS)\r
+def _decorate_result(origin, needs_params=False):\r
+    origin = _check_decoratable(origin)\r
 \r
-decorate.params = _decorate_params\r
+    def decorator(fn):\r
+        origin._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
 \r
-def _decorate_result(origin):\r
-    return decorate(origin, mode=DecoratableObject.MODE_RESULT)\r
+    return decorator\r
 \r
 decorate.result = _decorate_result\r
 \r
 def _decorate_with(fn):\r
     def decorator(origin):\r
-        if not isinstance(origin, DecoratableObject):\r
-            mod = inspect.getmodule(origin)\r
+        origin = _check_decoratable(origin)\r
+        origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=True)\r
+        return origin\r
+    return decorator\r
 \r
-            name = origin.__name__\r
-            origin = DecoratableObject(origin)\r
+decorate.withfn = _decorate_with\r
 \r
-        origin._decorate(fn, True, False)\r
+def _decorate_result_with(fn, needs_params=False):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._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._decorate(fn, DecoratableObject.MODE_PARAMS)\r
+        return origin\r
+    return decorator\r
 \r
-decorate.withfn = _decorate_with
\ No newline at end of file
+decorate.params.withfn = _decorate_params_with
\ No newline at end of file