1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
#!/usr/bin/env python
import os.path
import json
import collections
import yaml
import graphviz
from jinja2 import Environment, FileSystemLoader
Dagmap = collections.namedtuple('Dagmap',
['version', 'meta', 'style', 'tasks'])
def parse_yaml(filename):
with open(filename, 'r') as f:
contents = yaml.safe_load(f)
meta = contents['meta']
version = meta['version']
if version > 1:
raise Exception('Unsupported version %d' % version)
del meta['version']
style = contents['style']
tasks = contents['tasks']
if not isinstance(tasks, list):
raise Exception('"tasks" must be a list')
return Dagmap(version=version, meta=meta, style=style, tasks=tasks)
def to_graphviz(dagmap):
G = graphviz.Digraph(format='svg', engine='neato',
graph_attr=dict(bgcolor="#f4f4f4", pad="0.5", overlap="false"),
node_attr=dict(width="0.6", style="filled",
fillcolor="#83c6de", color="#83c6de", penwidth="3", label="",
fontname="helvetica Neue Ultra Light", fontsize="28"),
edge_attr=dict(color="#616a72", arrowsize="2.0", penwidth="4", fontname="helvetica Neue Ultra Light"))
G.node(name='_nothing', label='', style='invis')
for task in dagmap.tasks:
G.node(name=task['id'], label=task['label'],
tooltip=task['description'].strip())
depends_on = task.get('depends_on', ['_nothing'])
for dep in depends_on:
if dep == '_nothing':
attrs = {
'style': 'invis',
}
else:
attrs = {}
G.edge(dep, task['id'], **attrs)
return G
def main(argv):
import argparse
parser = argparse.ArgumentParser(description='Render Dagmap to Graphviz')
parser.add_argument('-o', '--output', required=True, help='output svg filename')
parser.add_argument('-t', '--template', default='template.html', help='HTML rendering template')
parser.add_argument('input', metavar='INPUT', type=str,
help='YAML input filename')
args = parser.parse_args(argv[1:])
dagmap = parse_yaml(args.input)
graph = to_graphviz(dagmap)
svg = graph.pipe().decode('utf-8')
template_env = Environment(loader=FileSystemLoader(os.path.dirname(__file__)))
template = template_env.get_template(args.template)
html = template.render(svg=json.dumps(svg))
with open(args.output, 'w') as f:
f.write(html)
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
|