From 9b6be99a1eed1adddfd062642f6ca23f79d14aea Mon Sep 17 00:00:00 2001 From: hernani Date: Wed, 16 Jun 2010 23:25:40 +0000 Subject: [PATCH] Removes the necessity of the "decoratable" decorator in modules and makes the api a bit more powerfull. git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@434 0cfe37f9-358a-4d5e-be75-b63607b5c754 --- forum/models/question.py | 2 - forum/modules/__init__.py | 2 + forum/modules/decorators.py | 64 ++++++++++++++++------------ forum/views/commands.py | 2 - forum/views/readers.py | 1 - forum/views/writers.py | 3 -- forum_modules/akismet/startup.py | 2 +- forum_modules/pgfulltext/handlers.py | 2 +- 8 files changed, 40 insertions(+), 38 deletions(-) diff --git a/forum/models/question.py b/forum/models/question.py index 1cc0884..7902a50 100644 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -1,12 +1,10 @@ from base import * from tag import Tag from django.utils.translation import ugettext as _ -from forum.modules.decorators import decoratable question_view = django.dispatch.Signal(providing_args=['instance', 'user']) class QuestionManager(NodeManager): - @decoratable.method def search(self, keywords): return self.filter(models.Q(title__icontains=keywords) | models.Q(body__icontains=keywords)) diff --git a/forum/modules/__init__.py b/forum/modules/__init__.py index cd59875..14c56e8 100644 --- a/forum/modules/__init__.py +++ b/forum/modules/__init__.py @@ -105,3 +105,5 @@ def module_templates_loader(name, dirs=None): raise TemplateDoesNotExist, name module_templates_loader.is_usable = True + +from decorators import decorate diff --git a/forum/modules/decorators.py b/forum/modules/decorators.py index a4c1fad..90109a9 100644 --- a/forum/modules/decorators.py +++ b/forum/modules/decorators.py @@ -4,7 +4,7 @@ class DecoratableObject(object): def __init__(self, fn): self._callable = fn - def decorate(self, fn, needs_origin): + def _decorate(self, fn, needs_origin): origin = self._callable if needs_origin: @@ -12,48 +12,56 @@ class DecoratableObject(object): else: self._callable = lambda *args, **kwargs: fn(*args, **kwargs) - def __call__(self, *args, **kwargs): - return self._callable(*args, **kwargs) + def _decorate_method(self, fn, needs_origin): + origin = self._callable + 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) -def decoratable(fn): - return DecoratableObject(fn) -def decoratable_method(fn): - obj = DecoratableObject(fn) - def decorated(self, *args, **kwargs): - return obj(self, *args, **kwargs) + def __call__(self, *args, **kwargs): + return self._callable(*args, **kwargs) - decorated.__obj = obj - return decorated -decoratable.method = decoratable_method +def _decorate_method(origin, needs_origin): + if not hasattr(origin, '_decoratable_obj'): + name = origin.__name__ + cls = origin.im_class -def decorate(origin, needs_origin=True): - if not isinstance(origin, DecoratableObject): - if hasattr(origin, '__obj'): - def decorator(fn): - origin.__obj.decorate(fn, needs_origin) - return origin - return decorator + decoratable = DecoratableObject(origin) + + def decoratable_method(self, *args, **kwargs): + return decoratable(self, *args, **kwargs) - raise TypeError('Not a decoratable function: %s' % origin.__name__) + decoratable_method._decoratable_obj = decoratable + setattr(cls, name, decoratable_method) + else: + decoratable = origin._decoratable_obj def decorator(fn): - origin.decorate(fn, needs_origin) - return origin + decoratable._decorate_method(fn, needs_origin) return decorator +def _decorate_function(origin, needs_origin): + if not isinstance(origin, DecoratableObject): + mod = inspect.getmodule(origin) -def decorate_all(module): - [setattr(module, n, decoratable(f)) for n, f in - [(n, getattr(module, n)) for n in dir(module)] - if (callable(f)) and (not inspect.isclass(f)) and (f.__module__ == module.__name__)] - - + name = origin.__name__ + origin = DecoratableObject(origin) + setattr(mod, name, DecoratableObject(origin)) + def decorator(fn): + origin._decorate(fn, needs_origin) + return decorator +def decorate(origin, needs_origin=True): + if inspect.ismethod(origin): + return _decorate_method(origin, needs_origin) + if inspect.isfunction(origin): + return _decorate_function(origin, needs_origin) \ No newline at end of file diff --git a/forum/views/commands.py b/forum/views/commands.py index f04bd35..a8f6d42 100644 --- a/forum/views/commands.py +++ b/forum/views/commands.py @@ -12,7 +12,6 @@ from forum.actions import * from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required from forum.utils.decorators import ajax_method, ajax_login_required -from forum.modules.decorators import decoratable from decorators import command, CommandException, RefreshPageCommand from forum import settings import logging @@ -222,7 +221,6 @@ def mark_favorite(request, id): } } -@decoratable @command def comment(request, id): post = get_object_or_404(Node, id=id) diff --git a/forum/views/readers.py b/forum/views/readers.py index d988230..860f54c 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -26,7 +26,6 @@ from forum.forms import * from forum.models import * from forum.forms import get_next_url from forum.actions import QuestionViewAction -from forum.modules.decorators import decoratable import decorators # used in index page diff --git a/forum/views/writers.py b/forum/views/writers.py index c7dbbf3..e6309c8 100644 --- a/forum/views/writers.py +++ b/forum/views/writers.py @@ -14,7 +14,6 @@ from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied from forum.actions import AskAction, AnswerAction, ReviseAction, RollbackAction, RetagAction -from forum.modules.decorators import decoratable from forum.forms import * from forum.models import * from forum.forms import get_next_url @@ -64,7 +63,6 @@ def upload(request):#ajax upload file to a question or answer return HttpResponse(result, mimetype="application/xml") -@decoratable def ask(request): if request.POST and "text" in request.POST: form = AskForm(request.POST, user=request.user) @@ -197,7 +195,6 @@ def edit_answer(request, id): 'form': form, }, context_instance=RequestContext(request)) -@decoratable def answer(request, id): question = get_object_or_404(Question, id=id) if request.POST: diff --git a/forum_modules/akismet/startup.py b/forum_modules/akismet/startup.py index c1d548c..159efe1 100644 --- a/forum_modules/akismet/startup.py +++ b/forum_modules/akismet/startup.py @@ -3,7 +3,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.utils import simplejson from django.utils.encoding import smart_str from django.shortcuts import render_to_response -from forum.modules.decorators import decorate +from forum.modules import decorate from forum import views from lib.akismet import Akismet from forum.settings import APP_URL, OSQA_VERSION diff --git a/forum_modules/pgfulltext/handlers.py b/forum_modules/pgfulltext/handlers.py index 18a23e3..6952758 100644 --- a/forum_modules/pgfulltext/handlers.py +++ b/forum_modules/pgfulltext/handlers.py @@ -1,7 +1,7 @@ import re from django.db.models import Q from forum.models.question import Question, QuestionManager -from forum.modules.decorators import decorate +from forum.modules import decorate repl_re = re.compile(r"^'|[^\'\-_\s\w]|'$", re.UNICODE) sing_quote_re = re.compile(r"\'+") -- 2.39.5