pvl/dot.py
author Tero Marttila <terom@paivola.fi>
Mon, 09 Mar 2015 23:31:13 +0200
changeset 738 3104fdf7ea26
parent 737 6ba76ac0bc72
permissions -rw-r--r--
pvl.hosts.hosts: drop support for instanced ip.* in favor of improved interface:ip.* =
737
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
import contextlib
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
import string
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
"""
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     5
    Syntax sugar for generating .dot files
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
    
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
        http://www.graphviz.org/content/dot-language
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
        http://www.graphviz.org/content/attrs
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
"""
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    10
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
ID = string.ascii_letters + string.digits + '_'
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    12
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    13
def quote (value):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    14
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    15
        (quoted) dot word.
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    16
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    17
        >>> print quote('foo')
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    18
        foo
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    19
        >>> print quote(5)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
        5
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    21
        >>> print quote("five two")
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
        "five two"
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    24
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    25
    value = str(value)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    26
    
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    27
    if all(c in ID for c in value):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    28
        return value
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    29
    else:
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    30
        return '"{value}"'.format(value=value)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    31
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    32
def attr_list (**attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    33
    for name, value in attrs.iteritems():
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    34
        if value is None:
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    35
            continue
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    36
        
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    37
        yield '{name}={value}'.format(name=name, value=quote(value))
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    38
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    39
def print_stmt (*line, **attrs) :
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    40
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    41
        >>> print_stmt(quote("Foo"), foo="bar")
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    42
          Foo [foo=bar];
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    43
        >>> print_stmt(quote("Foo"), asdf=5, quux="Test Me")
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    44
          Foo [quux="Test Me", asdf=5];
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    45
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    46
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    47
    print "  {line}{attrs};".format(
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    48
            line    = ' '.join(item for item in line if item is not None),
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
            attrs   = ' [' + ', '.join(attr_list(**attrs)) + ']' if attrs else '',
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    50
    )
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    51
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    52
def print_edge(left, edgeop, right, **attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    53
    print_stmt(quote(left), edgeop, quote(right), **attrs)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    54
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
@contextlib.contextmanager
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
def print_block (*block, **attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    58
        >>> with print_block('graph', 'foo'):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    59
        ...     print_stmt('foo', '--', 'bar')
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    60
        graph foo {
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    61
          foo -- bar;
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    62
        }
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    63
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    64
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    65
    print ' '.join(item for item in block if item is not None) + ' {'
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    66
    for attr in attr_list(**attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    67
        print '  {attr};'.format(attr=attr)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
    yield
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
    print '}'
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
def print_node(node, **attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
    print_stmt(quote(node), **attrs)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
def print_graph(id=None, **attrs):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    76
        >>> with print_graph(): print_node("foo", label="Foo Bar")
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    77
        graph {
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    78
          foo [label="Foo Bar"];
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
        }
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    80
    """
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    81
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    82
    return print_block('graph', quote(id) if id else None, **attrs)
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    83
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    84
def print_subgraph(id=None):
6ba76ac0bc72 pvl.dot: dot graph output
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    85
    return print_block('subgraph', quote(id) if id else None)