Instead of using a metaclass in python 2.6+, you should use a class decorator. You can wrap function and class decorators as class methods, like this real-world example.
I use this example with djcelery; important aspects of this problem are the "tasks" method and the string "args, kw = self.marked [klass. dict [attr]]", which implicitly checks the "class. dict [attr] in self.marked". If you want to use @ methodtasks.task instead of @ methodtasks.task () as a decorator, you can remove the nested def and use the set instead of dict for self.marked. Using self.marked, instead of setting the marking attribute in the function as another answer, allows this to work for classmethods and staticmethods, which, since they use slots, will not allow the setting of arbitrary attributes. The disadvantage of this method is that the function decorator MUST go higher than other decorators, and the class decorator MUST go lower, so the functions do not change / re = are wrapped between one and the other.
class DummyClass(object): """Just a holder for attributes.""" pass class MethodTasksHolder(object): """Register tasks with class AND method decorators, then use as a dispatcher, like so: methodtasks = MethodTasksHolder() @methodtasks.serve_tasks class C: @methodtasks.task() #@other_decorators_come_below def some_task(self, *args): pass @methodtasks.task() @classmethod def classmethod_task(self, *args): pass def not_a_task(self): pass #..later methodtasks.C.some_task.delay(c_instance,*args) #always treat as unbound #analagous to c_instance.some_task(*args) (or C.some_task(c_instance,*args)) #... methodtasks.C.classmethod_task.delay(C,*args) #treat as unbound classmethod! #analagous to C.classmethod_task(*args) """ def __init__(self): self.marked = {} def task(self, *args, **kw): def mark(fun): self.marked[fun] = (args,kw) return fun return mark def serve_tasks(self, klass): setattr(self, klass.__name__, DummyClass()) for attr in klass.__dict__: try: args, kw = self.marked[klass.__dict__[attr]] setattr(getattr(self, klass.__name__), attr, task(*args,**kw)(getattr(klass, attr))) except KeyError: pass
source share