6 def __init__(self, items):
9 class BaseItem(object):
12 predicate = lambda task: True
13 name = property(lambda self: self.__class__.__name__)
15 return '<'+self.name+'('+self.__class__.__bases__[0].__name__+') instance>'
18 INCOMPLETE = 'INCOMPLETE'
20 IN_PROGRESS = 'IN_PROGRESS'
21 CANNOT_AUTOMATE = 'CANNOT_AUTOMATE'
24 allowed_states = set((INCOMPLETE,FAILED,IN_PROGRESS,CANNOT_AUTOMATE,COMPLETE))
25 def __init__(self, data=None):
27 data = dict(state=self.INCOMPLETE)
30 return self.data['state'] == self.COMPLETE
32 class TaskComplete(Item):
33 '''sentinal task that contains all items required for completion'''
34 def __init__(self, goals=None, data=None):
36 self.depends = tuple(goals)
37 if len(self.depends) == 0:
38 raise ValueError('MUST provide goals to create TaskComplete')
39 Item.__init__(self,data)
46 class Group(BaseItem):
47 '''"logical" groups containing items
48 groups are sets of items that cannot be started until the group's dependencies are satisfied.
50 This sounds perfectly sane until you realise that what you're actually
51 doing is defining every item in the group to be dependent on every dependency of the
52 group. As groups can contain groups, every item in the whole graph is actually
53 dependent on all dependencies of any groups that contain it, any groups that contain that
54 group, and so on recursively. This is actually a digraph not a chain so a naive implementation
55 to see which groups contain an item is not going to work.
57 Groups make intuitive sense to humans, and make things so much more hackish to implement.
58 They do make it easier for humans to build the original set of dependencies, at the expense
59 of using somewhat of a shotgun approach in dependencies at times. It can also be used to
60 effectively partition the dependency digraph through critical nodes.
62 One solution to applying dependencies of groups to those it contains is to:
63 - For every group, find the group contents plus the contents of any groups
64 contained by the group recursively
65 - For each item, add to it's dependencies the union of the set of dependencies of all
66 groups it is contained in.
68 Once that is complete, it is then (if needed) possible to perform a reduction to remove the
69 groups. A simple implementation would be to for each group, find each dependency on that group
70 and replace it with the contents of the group.
72 Groups are currently not serialised and stored as state; They should be removed as quickly
73 as possible after task creation
75 contains = NotImplemented
78 def __init__(self, items, requirements, goal, uuid=None, data=None):
83 self.uuid, self.items, self.requirements, self.data = uuid, items, requirements, data
84 assert isinstance(goal, TaskComplete)
87 return "Task(uuid='%s')" % (self.uuid,)