2015-05-12 60 views
6

我编写了一个与unittest.TestCase非常类似的Python流控制框架:用户创建一个从框架类派生的类,然后编写自定义的task_*(self)方法。该框架发现他们,并运行它们:检测方法是否在调用之前进行了修饰

################### 
# 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() 

输出:

Starting task 
Skipped task 

我想改变,这样的框架下,每当@skip_if条件为True,包装不打印"Starting task"。 我想这一点,但它不工作:

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) + " is not decorated" 
      pass 

     print "Starting task" 
     try: 
      self.task() 
     except Exception as e: 
      print "Failed task: " + str(e) 
      raise 
     else: 
      print "Finished task" 

输出:

decorating <function task at 0x194fcd70> 
<bound method MyUserClass.task of <__main__.MyUserClass object at 0x195010d0>> is not decorated 
Starting task 
Doing something 
Finished task 

为什么没有任务跳过呢?

+0

你能更具体比*“它不起作用”* - 你期望发生什么? – jonrsharpe

+0

@jonrsharpe:输出应该指示测试被跳过;而是运行。 –

回答

6

您正在使用双下划线名称,它在run方法中经历了private name mangling

当通过调试器步进,我得到:

AttributeError: "'function' object has no attribute '_MyFramework__skip_condition 

不要使用此双下划线的名称;如果你的函数属性重命名为_skip_condition代码工作(前提是你绑定的条件函数或self通过明确):

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) + " is not decorated" 
      pass 

     print "Starting task" 
     try: 
      self.task() 
     except Exception as e: 
      print "Failed task: " + str(e) 
      raise 
     else: 
      print "Finished task" 

随着这些变化,输出变为:

decorating <function task at 0x1071a1b90> 
Skipped task 
+0

谢谢!奇迹般有效 – crusaderky

相关问题