def draw_workflow(workflow, workflow_name, filename=None, remove_dependencies=True): try: import pygraphviz as pgv except ImportError: print "You need PyGraphviz to run this command." return starttask = workflow.starttask redundant_deps = set(edge for edge, _ in find_redundant_deps(starttask)) graph = pgv.AGraph(strict=False, directed=True) graph.graph_attr['label'] = "Workflow name: %s" % taskid(workflow) for task in walk(starttask): for t in task.deps: a = taskid(task) b = taskid(t) color = '' if (a, b) in redundant_deps: if remove_dependencies: continue color = 'red' graph.add_edge(b, a, color=color) graph.layout(prog='dot') filename = filename or "%s%s.png" % (workflow_name, '-nodeps' if remove_dependencies else '') graph.draw(filename) print "Workflow graphical representation drawn : %s." % filename if remove_dependencies: print "Unnecesary dependencies were removed from the graph to make it" print "clear. Use 'lint' command if you want to see them"
def test_mixed_declaration(self): t1 = Task(taskname='T1') class T(Task): taskname = 'T' deps = [t1] t2 = Task(taskname='T2', deps=[T]) t3 = Task(taskname='T3', deps=[t1, t2]) class S(Task): taskname = 'S' deps = [T, t1, t3, T] self.assertEqual([t.taskname for t in walk(S)], ['T1', 'T', 'T2', 'T3', 'S'])
def test_class_declaration(self): class T1(Task): taskname = 'T1' class T2(Task): taskname = 'T2' deps = [T1] class T3(Task): taskname = 'T3' deps = [T2] class T4(Task): taskname = 'T4' deps = [T3, T1] self.assertEqual(map(type, walk(T4)), [T1, T2, T3, T4])
def test_invalid_task(self): t1 = Task() t2 = Task(deps=[t1, None]) self.assertRaises(AssertionError, list, walk(t2))
def test_cyclic_reference(self): t1 = Task(taskname='T1') t2 = Task(taskname='T2', deps=[t1]) t1.deps = [t2] self.assertRaises(AssertionError, list, walk(t1))
def test_instance_declaration(self): t1 = Task(taskname='T1') t2 = Task(taskname='T2', deps=[t1]) t3 = Task(taskname='T3', deps=[t2]) t4 = Task(taskname='T4', deps=[t3, t1]) self.assertEqual(list(walk(t4)), [t1, t2, t3, t4])