# HG changeset patch # User Tero Marttila # Date 1425936103 -7200 # Node ID 6ba76ac0bc7285d056728c511d353cb64b69fac1 # Parent 75938aa0390b0862885e90e8536c570f57a5b52f pvl.dot: dot graph output diff -r 75938aa0390b -r 6ba76ac0bc72 pvl/dot.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pvl/dot.py Mon Mar 09 23:21:43 2015 +0200 @@ -0,0 +1,85 @@ +import contextlib +import string + +""" + Syntax sugar for generating .dot files + + http://www.graphviz.org/content/dot-language + http://www.graphviz.org/content/attrs +""" + +ID = string.ascii_letters + string.digits + '_' + +def quote (value): + """ + (quoted) dot word. + + >>> print quote('foo') + foo + >>> print quote(5) + 5 + >>> print quote("five two") + "five two" + """ + + value = str(value) + + if all(c in ID for c in value): + return value + else: + return '"{value}"'.format(value=value) + +def attr_list (**attrs): + for name, value in attrs.iteritems(): + if value is None: + continue + + yield '{name}={value}'.format(name=name, value=quote(value)) + +def print_stmt (*line, **attrs) : + """ + >>> print_stmt(quote("Foo"), foo="bar") + Foo [foo=bar]; + >>> print_stmt(quote("Foo"), asdf=5, quux="Test Me") + Foo [quux="Test Me", asdf=5]; + """ + + print " {line}{attrs};".format( + line = ' '.join(item for item in line if item is not None), + attrs = ' [' + ', '.join(attr_list(**attrs)) + ']' if attrs else '', + ) + +def print_edge(left, edgeop, right, **attrs): + print_stmt(quote(left), edgeop, quote(right), **attrs) + +@contextlib.contextmanager +def print_block (*block, **attrs): + """ + >>> with print_block('graph', 'foo'): + ... print_stmt('foo', '--', 'bar') + graph foo { + foo -- bar; + } + """ + + print ' '.join(item for item in block if item is not None) + ' {' + for attr in attr_list(**attrs): + print ' {attr};'.format(attr=attr) + yield + print '}' + +def print_node(node, **attrs): + print_stmt(quote(node), **attrs) + +def print_graph(id=None, **attrs): + """ + >>> with print_graph(): print_node("foo", label="Foo Bar") + graph { + foo [label="Foo Bar"]; + } + """ + + return print_block('graph', quote(id) if id else None, **attrs) + +def print_subgraph(id=None): + return print_block('subgraph', quote(id) if id else None) diff -r 75938aa0390b -r 6ba76ac0bc72 setup.py --- a/setup.py Mon Mar 09 21:17:06 2015 +0200 +++ b/setup.py Mon Mar 09 23:21:43 2015 +0200 @@ -57,6 +57,9 @@ 'pvl.dns', 'pvl.hosts', ], + py_modules = [ + 'pvl.dot', + ], # lib/pvl data_files = [