Back to index

unity  6.0.0
unity-introspection-visualiser.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 #
00004 # Script to generate a nice PNG file of the currently running unity introspection tree.
00005 from argparse import ArgumentParser
00006 from os import remove
00007 from os.path import splitext
00008 import dbus
00009 
00010 try:
00011     from autopilot.emulators.unity import get_state_by_path
00012 except ImportError, e:
00013     print "Error: could not import the autopilot python module."
00014     print "Make sure the autopilot module is in your $PYTHONPATH."
00015     exit(1)
00016 
00017 try:
00018     import pydot
00019 except ImportError:
00020     print "Error: the 'pydot' module is required to run this script."
00021     print "Try installing the 'python-pydot' package."
00022     exit(1)
00023 
00024 NEXT_NODE_ID=1
00025 NODE_BLACKLIST=["Result"]
00026 
00027 def string_rep(dbus_type):
00028     """Get a string representation of various dbus types."""
00029     if type(dbus_type) == dbus.Boolean:
00030         return repr(bool(dbus_type))
00031     if type(dbus_type) == dbus.String:
00032         return dbus_type.encode('ascii', errors='ignore')
00033     if type(dbus_type) in (dbus.Int16, dbus.UInt16, dbus.Int32, dbus.UInt32, dbus.Int64, dbus.UInt64):
00034         return repr(int(dbus_type))
00035     if type(dbus_type) == dbus.Double:
00036         return repr(float(dbus_type))
00037     if type(dbus_type) == dbus.Array:
00038         return ', '.join([string_rep(i) for i in dbus_type])
00039     else:
00040         return repr(dbus_type)
00041 
00042 
00043 def escape(s):
00044     """Escape a string so it can be use in a dot label."""
00045     return pydot.quote_if_necessary(s).replace('<','\\<').replace('>', '\\>').replace("'", "\\'")
00046 
00047 
00048 def traverse_tree(state, parent, graph):
00049     """Recursively traverse state tree, building dot graph as we go."""
00050     global NEXT_NODE_ID
00051     lbl = parent.get_comment() + "|"
00052     # first, set labels for this node:
00053     bits = ["%s=%s" % (k, string_rep(state[k])) for k in sorted(state.keys()) if k != 'Children']
00054     lbl += "\l".join(bits)
00055     parent.set_label(escape('"{' + lbl + '}"'))
00056     if state.has_key('Children'):
00057         # Add all array nodes as children of this node.
00058         for child_name, child_state in state['Children']:
00059             if child_name in NODE_BLACKLIST:
00060                 continue
00061             child = pydot.Node(str(NEXT_NODE_ID))
00062             NEXT_NODE_ID+=1
00063             child.set_comment(child_name)
00064             graph.add_node(child)
00065             graph.add_edge(pydot.Edge(parent, child))
00066 
00067             traverse_tree(child_state, child, graph)
00068 
00069 
00070 if __name__ == '__main__':
00071     parser = ArgumentParser()
00072     mg = parser.add_mutually_exclusive_group(required=True)
00073     mg.add_argument('-o', '--output', nargs=1,
00074         help='Store output in specified file on disk.')
00075     mg.add_argument('-d','--display', action='store_true',
00076         help='Display output in image viewer.')
00077 
00078     args = parser.parse_args()
00079 
00080     introspection_tree = get_state_by_path('/')
00081     graph = pydot.Dot()
00082     graph.set_simplify(False)
00083     graph.set_node_defaults(shape='Mrecord')
00084     graph.set_fontname('Ubuntu')
00085     graph.set_fontsize('10')
00086 
00087     gnode_unity = pydot.Node("Unity")
00088     gnode_unity.set_comment("Unity")
00089     traverse_tree(introspection_tree[0], gnode_unity, graph)
00090 
00091     if args.output:
00092         base, extension = splitext(args.output[0])
00093         write_method_name = 'write_' + extension[1:]
00094         if hasattr(graph, write_method_name):
00095             getattr(graph, write_method_name)(args.output[0])
00096         else:
00097             print "Error: unsupported format: '%s'" % (extension)
00098     elif args.display:
00099         from tempfile import NamedTemporaryFile
00100         from subprocess import call
00101         tf = NamedTemporaryFile(suffix='.png', delete=False)
00102         tf.write(graph.create_png())
00103         tf.close()
00104         call(["eog", tf.name])
00105         remove(tf.name)
00106     else:
00107         print 'unknown output mode!'
00108 
00109