2015-05-12 79 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

相關問題