1import sys, re, traceback 2 3# these statuses are ordered such that a status earlier in the list will 4# override a status later in a list (e.g. ERROR during a test will override 5# prior GOOD results, but WARN will not override a FAIL) 6job_statuses = ["TEST_NA", "ABORT", "ERROR", "FAIL", "WARN", "GOOD", "ALERT", 7 "RUNNING", "NOSTATUS"] 8 9def is_valid_status(status): 10 if not re.match(r'(START|INFO|(END )?(' + '|'.join(job_statuses) + '))$', 11 status): 12 return False 13 else: 14 return True 15 16 17def is_failure(status): 18 if not is_valid_status(status): 19 return False 20 if status in ('START', 'INFO'): 21 return False 22 if status.startswith('END '): 23 status = status[len('END '):] 24 return job_statuses.index(status) <= job_statuses.index("FAIL") 25 26 27def record(fn): 28 """ 29 Generic method decorator for logging calls under the 30 assumption that return=GOOD, exception=FAIL. The method 31 determines parameters as: 32 subdir = self.subdir if it exists, or None 33 operation = "class name"."method name" 34 status = None on GOOD, str(exception) on FAIL 35 The object using this method must have a job attribute 36 for the logging to actually occur, otherwise the logging 37 will silently fail. 38 39 Logging can explicitly be disabled for a call by passing 40 a logged=False parameter 41 """ 42 def recorded_func(self, *args, **dargs): 43 logged = dargs.pop('logged', True) 44 job = getattr(self, 'job', None) 45 # if logging is disabled/unavailable, just 46 # call the method 47 if not logged or job is None: 48 return fn(self, *args, **dargs) 49 # logging is available, so wrap the method call 50 # in success/failure logging 51 subdir = getattr(self, 'subdir', None) 52 operation = '%s.%s' % (self.__class__.__name__, 53 fn.__name__) 54 try: 55 result = fn(self, *args, **dargs) 56 job.record('GOOD', subdir, operation) 57 except Exception, detail: 58 job.record('FAIL', subdir, operation, str(detail)) 59 raise 60 return result 61 return recorded_func 62 63 64def log_and_ignore_errors(msg): 65 """ A decorator for wrapping functions in a 'log exception and ignore' 66 try-except block. """ 67 def decorator(fn): 68 def decorated_func(*args, **dargs): 69 try: 70 fn(*args, **dargs) 71 except Exception: 72 print >> sys.stderr, msg 73 traceback.print_exc(file=sys.stderr) 74 return decorated_func 75 return decorator 76