~3v1n0/unity/overlay-border-scale

« back to all changes in this revision

Viewing changes to tools/unity-introspection-visualiser.py

  • Committer: Daniel van Vugt
  • Date: 2012-03-14 06:24:18 UTC
  • mfrom: (2108 unity)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: daniel.van.vugt@canonical.com-20120314062418-nprucpbr0m7qky5e
MergedĀ latestĀ lp:unity

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
#
 
4
# Script to generate a nice PNG file of the currently running unity introspection tree.
 
5
from argparse import ArgumentParser
 
6
from os import remove
 
7
from os.path import splitext
 
8
import dbus
 
9
 
 
10
try:
 
11
    from autopilot.emulators.unity import get_state_by_path
 
12
except ImportError, e:
 
13
    print "Error: could not import the autopilot python module."
 
14
    print "Make sure the autopilot module is in your $PYTHONPATH."
 
15
    exit(1)
 
16
 
 
17
try:
 
18
    import pydot
 
19
except ImportError:
 
20
    print "Error: the 'pydot' module is required to run this script."
 
21
    print "Try installing the 'python-pydot' package."
 
22
    exit(1)
 
23
 
 
24
NEXT_NODE_ID=1
 
25
NODE_BLACKLIST=["Result"]
 
26
 
 
27
def string_rep(dbus_type):
 
28
    """Get a string representation of various dbus types."""
 
29
    if type(dbus_type) == dbus.Boolean:
 
30
        return repr(bool(dbus_type))
 
31
    if type(dbus_type) == dbus.String:
 
32
        return dbus_type.encode('ascii', errors='ignore')
 
33
    if type(dbus_type) in (dbus.Int16, dbus.UInt16, dbus.Int32, dbus.UInt32, dbus.Int64, dbus.UInt64):
 
34
        return repr(int(dbus_type))
 
35
    if type(dbus_type) == dbus.Double:
 
36
        return repr(float(dbus_type))
 
37
    if type(dbus_type) == dbus.Array:
 
38
        return ', '.join([string_rep(i) for i in dbus_type])
 
39
    else:
 
40
        return repr(dbus_type)
 
41
 
 
42
 
 
43
def escape(s):
 
44
    """Escape a string so it can be use in a dot label."""
 
45
    return pydot.quote_if_necessary(s).replace('<','\\<').replace('>', '\\>').replace("'", "\\'")
 
46
 
 
47
 
 
48
def traverse_tree(state, parent, graph):
 
49
    """Recursively traverse state tree, building dot graph as we go."""
 
50
    global NEXT_NODE_ID
 
51
    lbl = parent.get_comment() + "|"
 
52
    # first, set labels for this node:
 
53
    bits = ["%s=%s" % (k, string_rep(state[k])) for k in sorted(state.keys()) if k != 'Children']
 
54
    lbl += "\l".join(bits)
 
55
    parent.set_label(escape('"{' + lbl + '}"'))
 
56
    if state.has_key('Children'):
 
57
        # Add all array nodes as children of this node.
 
58
        for child_name, child_state in state['Children']:
 
59
            if child_name in NODE_BLACKLIST:
 
60
                continue
 
61
            child = pydot.Node(str(NEXT_NODE_ID))
 
62
            NEXT_NODE_ID+=1
 
63
            child.set_comment(child_name)
 
64
            graph.add_node(child)
 
65
            graph.add_edge(pydot.Edge(parent, child))
 
66
 
 
67
            traverse_tree(child_state, child, graph)
 
68
 
 
69
 
 
70
if __name__ == '__main__':
 
71
    parser = ArgumentParser()
 
72
    mg = parser.add_mutually_exclusive_group(required=True)
 
73
    mg.add_argument('-o', '--output', nargs=1,
 
74
        help='Store output in specified file on disk.')
 
75
    mg.add_argument('-d','--display', action='store_true',
 
76
        help='Display output in image viewer.')
 
77
 
 
78
    args = parser.parse_args()
 
79
 
 
80
    introspection_tree = get_state_by_path('/')
 
81
    graph = pydot.Dot()
 
82
    graph.set_simplify(False)
 
83
    graph.set_node_defaults(shape='Mrecord')
 
84
    graph.set_fontname('Ubuntu')
 
85
    graph.set_fontsize('10')
 
86
 
 
87
    gnode_unity = pydot.Node("Unity")
 
88
    gnode_unity.set_comment("Unity")
 
89
    traverse_tree(introspection_tree[0], gnode_unity, graph)
 
90
 
 
91
    if args.output:
 
92
        base, extension = splitext(args.output[0])
 
93
        write_method_name = 'write_' + extension[1:]
 
94
        if hasattr(graph, write_method_name):
 
95
            getattr(graph, write_method_name)(args.output[0])
 
96
        else:
 
97
            print "Error: unsupported format: '%s'" % (extension)
 
98
    elif args.display:
 
99
        from tempfile import NamedTemporaryFile
 
100
        from subprocess import call
 
101
        tf = NamedTemporaryFile(suffix='.png', delete=False)
 
102
        tf.write(graph.create_png())
 
103
        tf.close()
 
104
        call(["eog", tf.name])
 
105
        remove(tf.name)
 
106
    else:
 
107
        print 'unknown output mode!'
 
108
 
 
109