1
# ubuntuone.syncdaemon.fsm.fsm_draw - draw a fsm
3
# Author: Lucio Torre <lucio.torre@canonical.com>
5
# Copyright 2009-2012 Canonical Ltd.
7
# This program is free software: you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License version 3, as published
9
# by the Free Software Foundation.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranties of
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
# PURPOSE. See the GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License along
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
# In addition, as a special exception, the copyright holders give
20
# permission to link the code of portions of this program with the
21
# OpenSSL library under certain conditions as described in each
22
# individual source file, and distribute linked combinations
24
# You must obey the GNU General Public License in all respects
25
# for all of the code used other than OpenSSL. If you modify
26
# file(s) with this exception, you may extend this exception to your
27
# version of the file(s), but you are not obligated to do so. If you
28
# do not wish to do so, delete this exception statement from your
29
# version. If you delete this exception statement from all source
30
# files in the program, then also delete it here.
31
"""This module is useful for debugging states machines by plotting them."""
37
# pylint: disable-msg=F0401
41
from ubuntuone.syncdaemon.fsm import fsm
45
'transform a dictionary into a label'
46
t = '"%s"' % "\\n".join("%s=%s" % x for x in sorted(d.items()))
50
def main(filename, debug=False):
51
'draw the state machine that is in $filename'
53
print "Parsing file... (%s)" % time.ctime()
54
machine = fsm.StateMachine(filename)
56
print "Building graph... (%s)" % time.ctime()
58
graph_base = u'digraph G {\n%s [label="despair"]\n%%s\n}' % id(despair)
61
for state in machine.states.values():
62
line = "%s [label=%s]" % (id(state), dict2label(state.values))
63
graph_lines.append(line)
65
for event in machine.events.values():
66
for transition in event.draw_transitions:
67
if all(map(lambda x: x == "*", transition.target.values())):
71
target = machine.get_state(transition.target)
75
l = s2s.setdefault((fsm.hash_dict(transition.source),
76
fsm.hash_dict(transition.target)), [])
79
for (source, target), ts in s2s.items():
81
source = machine.get_state(dict(source))
82
if all(map(lambda x: x == "*", dict(target).values())):
85
target = machine.get_state(dict(target))
90
ps = " ".join(["%s:%s" % (k, v) for k, v in t.parameters.items()])
91
cases.append("%s:%s" % (t.event, ps))
92
line = '%s [label="%s", shape=box, fontsize=7]' % (
93
id(ts), "\\n".join(cases))
94
graph_lines.append(line)
96
arrow = '%s -> %s' % (
98
graph_lines.append(arrow)
99
arrow = '%s -> %s' % (
101
graph_lines.append(arrow)
103
dotcode = graph_base % "\n".join(graph_lines)
105
filename = tempfile.mkstemp(prefix='graph-', suffix='.debug')
106
a = open(filename, "w")
111
print "Drawing... (%s)" % time.ctime()
112
window = xdot.DotWindow()
113
window.set_dotcode(dotcode)
114
window.connect('destroy', gtk.main_quit)
117
if __name__ == "__main__":
118
main(sys.argv[1], True)