comparison python/ppci/tasks.py @ 342:86b02c98a717 devel

Moved target directory
author Windel Bouwman
date Sat, 01 Mar 2014 15:40:31 +0100
parents 6f4753202b9a
children 3bb7dcfe5529
comparison
equal deleted inserted replaced
341:4d204f6f7d4e 342:86b02c98a717
1 """
2 This module defines tasks and a runner for these tasks. Tasks can
3 have dependencies and it can be determined if they need to be run.
4 """
1 5
2 import logging 6 import logging
3 7
4 class TaskError(Exception): 8 class TaskError(Exception):
5 pass 9 pass
7 11
8 class Task: 12 class Task:
9 """ Task that can run, and depend on other tasks """ 13 """ Task that can run, and depend on other tasks """
10 def __init__(self, name): 14 def __init__(self, name):
11 self.name = name 15 self.name = name
12 self.subtasks = []
13 self.completed = False 16 self.completed = False
14 self.dependencies = [] 17 self.dependencies = set()
15 self.duration = 1 18 self.duration = 1
16 19
17 def run(self): 20 def run(self):
18 raise NotImplementedError("Implement this abstract method!") 21 raise NotImplementedError("Implement this abstract method!")
19 22
20 def fire(self): 23 def fire(self):
24 """ Wrapper around run that marks the task as done """
21 assert all(t.completed for t in self.dependencies) 25 assert all(t.completed for t in self.dependencies)
22 self.run() 26 self.run()
23 self.completed = True 27 self.completed = True
24 28
25 def addSubTask(self, tsk): 29 def add_dependency(self, task):
26 self.subtasks.append(tsk) 30 """ Add another task as a dependency for this task """
27 return tsk 31 if task is self:
32 raise TaskError('Can not add dependency on task itself!')
33 if self in task.down_stream_tasks:
34 raise TaskError('Can not introduce circular task')
35 self.dependencies.add(task)
36 return task
28 37
29 def addDependency(self, task): 38 @property
30 self.dependencies.append(task) 39 def down_stream_tasks(self):
31 return task 40 """ Return a set of all tasks that follow this task """
41 # TODO: is this upstream or downstream???
42 cdst = list(dep.down_stream_tasks for dep in self.dependencies)
43 cdst.append(self.dependencies)
44 return set.union(*cdst)
45
46 def __gt__(self, other):
47 return other in self.down_stream_tasks
32 48
33 def __repr__(self): 49 def __repr__(self):
34 return 'Task "{}"'.format(self.name) 50 return 'Task "{}"'.format(self.name)
51
52
53 class EmptyTask(Task):
54 """ Basic task that does nothing """
55 def run(self):
56 pass
35 57
36 58
37 class TaskRunner: 59 class TaskRunner:
38 """ Basic task runner that can run some tasks in sequence """ 60 """ Basic task runner that can run some tasks in sequence """
39 def __init__(self): 61 def __init__(self):
46 @property 68 @property
47 def total_duration(self): 69 def total_duration(self):
48 return sum(t.duration for t in self.task_list) 70 return sum(t.duration for t in self.task_list)
49 71
50 def run_tasks(self): 72 def run_tasks(self):
73 # First sort tasks:
74 self.task_list.sort()
75
76 # Run tasks:
51 passed_time = 0.0 77 passed_time = 0.0
52 total_time = self.total_duration 78 total_time = self.total_duration
53 try: 79 try:
54 for t in self.task_list: 80 for t in self.task_list:
55 self.report_progress(passed_time / total_time, t.name) 81 self.report_progress(passed_time / total_time, t.name)
56 t.fire() 82 t.fire()
57 passed_time += t.duration 83 passed_time += t.duration
58 except TaskError as e: 84 except TaskError as e:
59 print('Error: {}'.format(e)) 85 self.logger.error(str(e.msg))
60 return 1 86 return 1
61 self.report_progress(1, 'OK') 87 self.report_progress(1, 'OK')
62 return 0 88 return 0
63 89
64 def display(self): 90 def display(self):