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):
14 self.verbose = verbose
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 [{} tasks]: max timeout is {} minutes, "
28 "silent for {} minutes (period is {} s)"\
29 .format(len(self.tasks), timeout_minutes,
30 silent_minutes, period_seconds))
32 utils.header("Completer [{} tasks]: max timeout is {} seconds, "
33 "silent for {} seconds (period is {} s)"\
34 .format(len(self.tasks), timeout_seconds,
35 silent_seconds, period_seconds))
40 success = task.run (silent=datetime.now() <= graceout)
47 duration = datetime.now() - begin
48 print("total completer {} {}s".format(self.message,
49 int(duration.total_seconds())))
51 if datetime.now() > timeout:
53 task.failure_epilogue()
56 print('{}s..'.format(period_seconds), end=' ')
57 time.sleep(period_seconds)
62 #################### CompleterTask
63 ### . run(silent) (return True or False)
64 ### silent is an input boolean indicating if we're within the silent period
65 ### . failure() (print a message)
67 ########## expectations (+ first arg self)
68 # failure() (to describe which went wrong once it's over)
76 def run (self, silent):
77 result = self.actual_run()
79 print('+' if result else '.', end=' ')
82 print(self.message(), "->", "OK" if result else "KO")
86 return "you-need-to-redefine-message"
88 def failure_epilogue (self):
89 print("you-need-to-redefine-failure_epilogue")
92 class TaskTest (CompleterTask):
94 def __init__ (self,max):
96 self.counter = TaskTest.counter
98 self.delay = random.random()*max
99 self.fire = datetime.now() + timedelta(seconds=self.delay)
100 def actual_run(self):
101 return datetime.now() >= self.fire
103 return "Task {} - delay was {}s".format(self.counter, self.delay)
105 def failure_epilogue (self):
106 print("BOTTOM LINE: FAILURE with task ({})".format(self.counter))
110 if len(sys.argv) != 6:
111 print("Usage: <command> number_tasks max_random timeout_s silent_s period_s")
113 [number, max, timeout, silent, period] = [ int(x) for x in sys.argv[1:]]
114 tasks = [ TaskTest(max) for i in range(number)]
115 success = Completer(tasks,verbose=True).run(timedelta(seconds=timeout),
116 timedelta(seconds=silent),
117 timedelta(seconds=period))
118 print("OVERALL",success)
120 if __name__ == '__main__':