3 from datetime import datetime, timedelta
7 ### more generic code for waiting for any number of things
8 ### within a given timeframe i.e. given some timeout/silent/period
9 ### takes in argument a list of tasks that are instances
10 ### of a CompleterTask subclass
12 def __init__ (self, tasks, verbose=True, message=None):
15 self.message="({})".format(message) if message else ""
16 def run (self, timeout_timedelta, silent_timedelta, period):
17 begin = datetime.now()
18 timeout = begin+timeout_timedelta
19 timeout_seconds = timeout_timedelta.total_seconds()
20 timeout_minutes = timeout_seconds/60
21 graceout = datetime.now()+silent_timedelta
22 silent_seconds = silent_timedelta.total_seconds()
23 silent_minutes = silent_seconds/60
24 period_seconds=int(period.total_seconds())
26 if timeout_seconds >= 120:
27 utils.header("Completer [%d tasks]: max timeout is %d minutes, "
28 "silent for %d minutes (period is %s s)"%\
29 (len(self.tasks), timeout_minutes,
30 silent_minutes, period_seconds))
32 utils.header("Completer [%d tasks]: max timeout is %d seconds, "
33 "silent for %d seconds (period is %s s)"%\
34 (len(self.tasks), timeout_seconds,
35 silent_seconds, period_seconds))
40 success=task.run (silent=datetime.now() <= graceout)
41 if success: fine.append(task)
42 for task in fine: tasks.remove(task)
45 duration = datetime.now()-begin
46 print "total completer {} {}s".format(self.message,
47 int(duration.total_seconds()))
49 if datetime.now() > timeout:
51 task.failure_epilogue()
54 print '%ds..'%period_seconds,
55 time.sleep(period_seconds)
60 #################### CompleterTask
61 ### . run(silent) (return True or False)
62 ### silent is an input boolean indicating if we're within the silent period
63 ### . failure() (print a message)
65 ########## expectations (+ first arg self)
66 # failure() (to describe which went wrong once it's over)
74 def run (self, silent):
75 result=self.actual_run()
77 print '+' if result else '.',
80 print self.message(),"->","OK" if result else "KO"
82 def message (self): return "you-need-to-redefine-message"
83 def failure_epilogue (self): print "you-need-to-redefine-failure_epilogue"
86 class TaskTest (CompleterTask):
88 def __init__ (self,max):
90 self.counter=TaskTest.counter
92 self.delay=random.random()*max
93 self.fire=datetime.now()+timedelta(seconds=self.delay)
95 return datetime.now()>=self.fire
97 return "Task %d - delay was %d s"%(self.counter,self.delay)
99 def failure_epilogue (self): print "BOTTOM LINE: FAILURE with task (%s)"%self.counter
104 print "Usage: <command> number_tasks max_random timeout_s silent_s period_s"
106 [number,max,timeout,silent,period]= [ int(x) for x in sys.argv[1:]]
107 tasks = [ TaskTest(max) for i in range(number)]
108 success=Completer(tasks,verbose=True).run(timedelta(seconds=timeout),
109 timedelta(seconds=silent),
110 timedelta(seconds=period))
111 print "OVERALL",success
113 if __name__ == '__main__':