X-Git-Url: https://git.openstreetmap.org./osqa.git/blobdiff_plain/9b6be99a1eed1adddfd062642f6ca23f79d14aea..441ed176bdff586e94390740969e103d783bd5f8:/forum/modules/decorators.py?ds=sidebyside diff --git a/forum/modules/decorators.py b/forum/modules/decorators.py index 90109a9..8fbee7e 100644 --- a/forum/modules/decorators.py +++ b/forum/modules/decorators.py @@ -1,31 +1,68 @@ import inspect class DecoratableObject(object): + MODE_OVERRIDE = 0 + MODE_PARAMS = 1 + MODE_RESULT = 2 + def __init__(self, fn): + a = inspect.getargspec(fn) self._callable = fn + self._params_decoration = None + self._result_decoration = None - def _decorate(self, fn, needs_origin): + def _decorate(self, fn, needs_origin, method=False): origin = self._callable if needs_origin: - self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs) + if method: + self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs) + else: + self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs) else: - self._callable = lambda *args, **kwargs: fn(*args, **kwargs) + self._callable = fn - def _decorate_method(self, fn, needs_origin): - origin = self._callable + def _decorate_params(self, fn): + if not self._params_decoration: + self._params_decoration = [] - if needs_origin: - self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs) - else: - self._callable = lambda inst, *args, **kwargs: fn(inst, *args, **kwargs) + self._params_decoration.append(fn) + def _decorate_result(self, fn): + if not self._result_decoration: + self._result_decoration = [] + + self._result_decoration.append(fn) def __call__(self, *args, **kwargs): - return self._callable(*args, **kwargs) + if self._params_decoration: + for dec in self._params_decoration: + args, kwargs = dec(*args, **kwargs) + + res = self._callable(*args, **kwargs) + + if self._result_decoration: + for dec in self._result_decoration: + res = dec(res) + return res + + +def _create_decorator(origin, needs_origin, mode, method=False): + def decorator(fn): + if mode == DecoratableObject.MODE_OVERRIDE: + origin._decorate(fn, needs_origin, method=method) + elif mode == DecoratableObject.MODE_PARAMS: + origin._decorate_params(fn) + elif mode == DecoratableObject.MODE_RESULT: + origin._decorate_result(fn) + + return fn + + return decorator -def _decorate_method(origin, needs_origin): + +def _decorate_method(origin, needs_origin, mode): if not hasattr(origin, '_decoratable_obj'): name = origin.__name__ cls = origin.im_class @@ -40,28 +77,36 @@ def _decorate_method(origin, needs_origin): else: decoratable = origin._decoratable_obj - def decorator(fn): - decoratable._decorate_method(fn, needs_origin) - - return decorator + return _create_decorator(decoratable, needs_origin, mode, method=True) -def _decorate_function(origin, needs_origin): +def _decorate_function(origin, needs_origin, mode): if not isinstance(origin, DecoratableObject): mod = inspect.getmodule(origin) name = origin.__name__ origin = DecoratableObject(origin) - setattr(mod, name, DecoratableObject(origin)) + setattr(mod, name, origin) + + return _create_decorator(origin, needs_origin, mode) + + +def decorate(origin, needs_origin=True, mode=DecoratableObject.MODE_OVERRIDE): + if inspect.ismethod(origin): + return _decorate_method(origin, needs_origin, mode) + + if inspect.isfunction(origin) or isinstance(origin, DecoratableObject): + return _decorate_function(origin, needs_origin, mode) def decorator(fn): - origin._decorate(fn, needs_origin) + return fn - return decorator +def _decorate_params(origin): + return decorate(origin, mode=DecoratableObject.MODE_PARAMS) -def decorate(origin, needs_origin=True): - if inspect.ismethod(origin): - return _decorate_method(origin, needs_origin) +decorate.params = _decorate_params + +def _decorate_result(origin): + return decorate(origin, mode=DecoratableObject.MODE_RESULT) - if inspect.isfunction(origin): - return _decorate_function(origin, needs_origin) \ No newline at end of file +decorate.result = _decorate_result