2015-05-12 13 views
6

unittest.TestCase'a çok benzer bir şekilde çalışan bir Python akış denetimi çerçevesi yazdım: kullanıcı, framework sınıfından türetilen bir sınıf oluşturur ve sonra özel task_*(self) yöntemlerini yazar. Çerçeve onları keşfeder ve onları çalıştırır:Yöntemi çağırmadan önce dekore edildiyse algıla.

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

Çıktı: @skip_if durumu True olduğunda

Starting task 
Skipped task 

ben böylece çerçeveyi değiştirmek istiyorum, sarıcı "Starting task" yazdırmaz. Bunu denedim, ama çalışmıyor:

Çıktı
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 

Neden görev yerine atlandı edilmedi?

+0

Eğer daha açık olabilir misin: çıktı olur Bu değişikliklerle

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" 

* “işe yaramıyor” * - ne olmasını bekliyordunuz? – jonrsharpe

+0

@jonrsharpe: çıktı testin atlandığını göstermelidir; bunun yerine çalışır. –

cevap

6

Sen run yönteminde private name mangling uğramıştır bir çift alt çizgi adını kullanıyorsunuz.

ayıklayıcıya atlama, alıyorum:

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

çift burada ada altını kullanmayın; Eğer _skip_condition işlev özelliğini adlandırmak eğer kod (eğer durum işlevini bağlamak veya açıkça self geçmek şartıyla) işleri:

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

Teşekkürler! ÇALIŞIYOR bir cazibe gibi – crusaderky

İlgili konular