python - Detect if method is decorated before invoking it -
i wrote python flow control framework works unittest.testcase
: user creates class derived framework class, , writes custom task_*(self)
methods. framework discovers them , runs them:
################### # framework library ################### import functools class skiptask(baseexception): pass def skip_if(condition): def decorator(task): @functools.wraps(task) def wrapper(self, *args, **kargs): if condition(self): raise skiptask() return task(self, *args, **kargs) return wrapper return decorator class myframework(object): def run(self): print "starting task" try: self.task() except skiptask: print "skipped task" except exception: print "failed task" raise else: print "finished task" ############# # user script ############# class myuserclass(myframework): skip_flag = true @skip_if(lambda self: self.skip_flag) def task(self): print "doing something" if __name__ == '__main__': myuserclass().run()
output:
starting task skipped task
i want change framework that, whenever condition of @skip_if
true
, wrapper not print "starting task"
. tried this, doesn't work:
def skip_if(condition): def decorator(task): print "decorating " + str(task) task.__skip_condition = condition return task return decorator class myframework(object): def run(self): try: if self.task.__skip_condition(): print "skipped task" return except attributeerror: print str(self.task) + " not decorated" pass print "starting task" try: self.task() except exception e: print "failed task: " + str(e) raise else: print "finished task"
output:
decorating <function task @ 0x194fcd70> <bound method myuserclass.task of <__main__.myuserclass object @ 0x195010d0>> not decorated starting task doing finished task
why wasn't task skipped instead?
you using double underscore name, has undergone private name mangling in run
method.
when stepping through debugger, get:
attributeerror: "'function' object has no attribute '_myframework__skip_condition
don't use double underscore names here; if rename function attribute _skip_condition
code works (provided bind condition function or pass in self
explicitly):
def skip_if(condition): def decorator(task): print "decorating " + str(task) task._skip_condition = condition return task return decorator class myframework(object): def run(self): try: if self.task._skip_condition(self): print "skipped task" return except attributeerror: print str(self.task) + " not decorated" pass print "starting task" try: self.task() except exception e: print "failed task: " + str(e) raise else: print "finished task"
with these changes output becomes:
decorating <function task @ 0x1071a1b90> skipped task
Comments
Post a Comment