taskflow/tools/state_graph.py
Joshua Harlow e54cb21d55 Use the state_graph.py for all states diagrams
Switch to using the `state_graph.py` and dot output
as the source of all of the state diagrams (this
makes it easy for anyone to recreate them by just
running the script in the tools directory).

Also update the state diagram creator to have engine
states as well as retry states and replaces all
existing state diagrams with the updated prettified
versions.

Also adjusts some nits around wording and grammar that
were encountered during this updating process.

Change-Id: Ia783aed6c4136763e1e34cbd0b3e57ffb1109abe
2014-07-06 12:21:34 -07:00

131 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python
import optparse
import os
import sys
top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
os.pardir))
sys.path.insert(0, top_dir)
import networkx as nx
# To get this installed you may have to follow:
# https://code.google.com/p/pydot/issues/detail?id=93 (until fixed).
import pydot
from taskflow import states
def main():
parser = optparse.OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write svg to FILE", metavar="FILE")
parser.add_option("-t", "--tasks", dest="tasks",
action='store_true',
help="use task state transitions",
default=False)
parser.add_option("-r", "--retries", dest="retries",
action='store_true',
help="use retry state transitions",
default=False)
parser.add_option("-e", "--engines", dest="engines",
action='store_true',
help="use engine state transitions",
default=False)
parser.add_option("-T", "--format", dest="format",
help="output in given format",
default='svg')
(options, args) = parser.parse_args()
if options.filename is None:
options.filename = 'states.%s' % options.format
types = [options.engines, options.retries, options.tasks]
if sum([int(i) for i in types]) > 1:
parser.error("Only one of task/retry/engines may be specified.")
disallowed = set()
start_node = states.PENDING
if options.tasks:
source = list(states._ALLOWED_TASK_TRANSITIONS)
source_type = "Tasks"
disallowed.add(states.RETRYING)
elif options.retries:
source = list(states._ALLOWED_TASK_TRANSITIONS)
source_type = "Retries"
elif options.engines:
# TODO(harlowja): place this in states.py
source = [
(states.RESUMING, states.SCHEDULING),
(states.SCHEDULING, states.WAITING),
(states.WAITING, states.ANALYZING),
(states.ANALYZING, states.SCHEDULING),
(states.ANALYZING, states.WAITING),
]
for u in (states.SCHEDULING, states.ANALYZING):
for v in (states.SUSPENDED, states.SUCCESS, states.REVERTED):
source.append((u, v))
source_type = "Engines"
start_node = states.RESUMING
else:
source = list(states._ALLOWED_FLOW_TRANSITIONS)
source_type = "Flow"
transitions = nx.DiGraph()
for (u, v) in source:
if u not in disallowed:
transitions.add_node(u)
if v not in disallowed:
transitions.add_node(v)
for (u, v) in source:
if not transitions.has_node(u) or not transitions.has_node(v):
continue
transitions.add_edge(u, v)
graph_name = "%s states" % source_type
g = pydot.Dot(graph_name=graph_name, rankdir='LR',
nodesep='0.25', overlap='false',
ranksep="0.5", size="11x8.5",
splines='true', ordering='in')
node_attrs = {
'fontsize': '11',
}
nodes = {}
nodes_order = []
edges_added = []
for (u, v) in nx.bfs_edges(transitions, source=start_node):
if u not in nodes:
nodes[u] = pydot.Node(u, **node_attrs)
g.add_node(nodes[u])
nodes_order.append(u)
if v not in nodes:
nodes[v] = pydot.Node(v, **node_attrs)
g.add_node(nodes[v])
nodes_order.append(v)
for u in nodes_order:
for v in transitions.successors_iter(u):
if (u, v) not in edges_added:
g.add_edge(pydot.Edge(nodes[u], nodes[v]))
edges_added.append((u, v))
start = pydot.Node("__start__", shape="point", width="0.1",
xlabel='start', fontcolor='green', **node_attrs)
g.add_node(start)
g.add_edge(pydot.Edge(start, nodes[start_node], style='dotted'))
print("*" * len(graph_name))
print(graph_name)
print("*" * len(graph_name))
print(g.to_string().strip())
g.write(options.filename, format=options.format)
print("Created %s at '%s'" % (options.format, options.filename))
# To make the svg more pretty use the following:
# $ xsltproc ../diagram-tools/notugly.xsl ./states.svg > pretty-states.svg
# Get diagram-tools from https://github.com/vidarh/diagram-tools.git
if __name__ == '__main__':
main()