knipknap/SpiffWorkflow — pull request #39 by chrisns (2014-03-10 15:49:40+00:00)
Title: graphviz visualiser

Hi,
This is my first bit of python, so probably isn't in a good state to bring in as a pull immediately.
I'm working on a project with a pretty complex workflow design (>3000 nodes), and looking at moving from ezcWorkflow in php to SpiffWorkflow the big missing piece to our solution was being able to visualise the development of the workflow spec
So I've built this,
```
from SpiffWorkflow import Workflow
from SpiffWorkflow.storage import dotVisualizer
serializer = dotVisualizer()
spec = TestWorkflowSpec()
print(spec.serialize(serializer))}
```
with your example workflow produces this image
![with your example workflow produces this image](https://f.cloud.github.com/assets/715120/2375377/ed2dd6b6-a86a-11e3-9191-fa45976942d0.png)

or in dot file format:
```DOT
digraph G {
compound=true;
subgraph cluster1 {
label="Workflow";
node31 [ignore="this",shape="rect",label="task_b2"];
node30 [ignore="this",shape="rect",label="task_b1"];
node29 [ignore="this",shape="rect",label="task_c3"];
node28 [ignore="this",shape="rect",label="task_c2"];
node27 [ignore="this",shape="rect",label="task_d3"];
node26 [ignore="this",shape="rect",label="task_d2"];
node25 [ignore="this",shape="rect",label="task_e3"];
node24 [ignore="this",shape="rect",label="task_e2"];
node23 [ignore="this",shape="rect",label="task_f3"];
node22 [ignore="this",shape="rect",label="task_f2"];
node21 [ignore="this",shape="rect",label="task_g2"];
node20 [ignore="this",shape="rect",label="End"];
node19 [ignore="this",shape="rect",label="last"];
node18 [ignore="this",shape="invtriangle",label="struct_synch_merge_2"];
node17 [ignore="this",shape="rect",label="task_g1"];
node16 [ignore="this",shape="box",label="multi_instance_1"];
node15 [ignore="this",shape="diamond",label="excl_choice_3"];
node14 [ignore="this",shape="invtriangle",label="struct_discriminator_1"];
node13 [ignore="this",shape="rect",label="task_f1"];
node12 [ignore="this",shape="invtriangle",label="struct_synch_merge_1"];
node11 [ignore="this",shape="rect",label="task_e1"];
node10 [ignore="this",shape="diamond",label="multi_choice_1"];
node9 [ignore="this",shape="rect",label="task_d1"];
node8 [ignore="this",shape="diamond",label="excl_choice_2"];
node7 [ignore="this",shape="rect",label="task_c1"];
node6 [ignore="this",shape="diamond",label="excl_choice_1"];
node5 [ignore="this",shape="invtriangle",label="synch_1"];
node4 [ignore="this",shape="rect",label="task_a2"];
node3 [ignore="this",shape="rect",label="task_a1"];
node2 [ignore="this",shape="oval",label="Start"];
}
node31->node5;
node30->node31;
node29->node8;
node28->node8;
node27->node10;
node26->node10;
node25->node12;
node24->node12;
node23->node14;
node22->node14;
node21->node18;
node19->node20;
node18->node19;
node17->node18;
node16->node17;
node16->node21;
node15->node6;
node15->node16;
node14->node15;
node13->node14;
node12->node13;
node12->node22;
node12->node23;
node11->node12;
node10->node11;
node10->node24;
node10->node25;
node9->node10;
node8->node9;
node8->node26;
node8->node27;
node7->node8;
node6->node7;
node6->node28;
node6->node29;
node5->node6;
node4->node5;
node3->node4;
node2->node3;
node2->node30;
}
```
It could do with making the workflow elements the right shapes and some other tidying I expect but the principal is there and it serves our immediate requirements.
Thanks for a great workflow solution by the way :)
Cheers
Chris