~romaia/pydojo/working

« back to all changes in this revision

Viewing changes to pydojo.py

  • Committer: Ronaldo Maia
  • Date: 2008-09-25 14:26:04 UTC
  • Revision ID: romaia@deadsea-20080925142604-xcuuhkkeou4o0x52
initial revision

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
# vi:si:et:sw=4:sts=4:ts=4
 
4
 
 
5
##
 
6
## This program is free software; you can redistribute it and/or modify
 
7
## it under the terms of the GNU General Public License as published by
 
8
## the Free Software Foundation; either version 2 of the License, or
 
9
## (at your option) any later version.
 
10
##
 
11
## This program is distributed in the hope that it will be useful,
 
12
## but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
## GNU Lesser General Public License for more details.
 
15
##
 
16
## You should have received a copy of the GNU General Public License
 
17
## along with this program; if not, write to the Free Software
 
18
## Foundation, Inc., or visit: http://www.gnu.org/.
 
19
##
 
20
## Author(s):   Ronaldo Maia <romaia@async.com.br>
 
21
##
 
22
##
 
23
 
 
24
 
 
25
import gtk
 
26
import gnomevfs
 
27
import pynotify
 
28
import gobject
 
29
 
 
30
import imp
 
31
import traceback
 
32
import time
 
33
 
 
34
import unittest
 
35
import sys
 
36
 
 
37
from kiwi.utils import gsignal
 
38
 
 
39
ROUND_TIME = 1 # minutes
 
40
 
 
41
class DojoMonitor(gobject.GObject):
 
42
    (STATUS_PASS,
 
43
     STATUS_FAIL,
 
44
     STATUS_ERROR,
 
45
     STATUS_LOAD_ERROR) = range(4)
 
46
 
 
47
    gsignal('status-changed', int, object)
 
48
 
 
49
    def __init__(self, name):
 
50
        gobject.GObject.__init__(self)
 
51
 
 
52
        uri = gnomevfs.make_uri_from_shell_arg(name)
 
53
        gnomevfs.monitor_add(uri,
 
54
                             gnomevfs.MONITOR_FILE,
 
55
                             self._on_monitor)
 
56
 
 
57
        self.name = name
 
58
 
 
59
    def _load_module(self):
 
60
        try:
 
61
            self.module = imp.load_source('tests', self.name)
 
62
        except:
 
63
            self.traceback = traceback.format_exc()
 
64
            self.module = None
 
65
 
 
66
    def _on_monitor(self, dir, file, event):
 
67
        if event == gnomevfs.MONITOR_EVENT_CHANGED:
 
68
            self.run_tests()
 
69
 
 
70
    def run_tests(self):
 
71
        self._load_module()
 
72
 
 
73
        if self.module is None:
 
74
            self.emit('status-changed',
 
75
                      self.STATUS_LOAD_ERROR,
 
76
                      self.traceback)
 
77
            return
 
78
 
 
79
        loader = unittest.TestLoader()
 
80
        suit = loader.loadTestsFromTestCase(self.module.StubTests)
 
81
        results = unittest.TestResult()
 
82
        suit.run(results)
 
83
 
 
84
        if results.failures:
 
85
            self.emit('status-changed', self.STATUS_FAIL, results)
 
86
        else:
 
87
            self.emit('status-changed', self.STATUS_PASS, results)
 
88
 
 
89
 
 
90
class DojoNotification(pynotify.Notification):
 
91
    def __init__(self):
 
92
        pynotify.init('DojoTools')
 
93
        pynotify.Notification.__init__(self, 'DojoTools', 'Foo Bar')
 
94
 
 
95
        #self.set_property('icon-name', gtk.STOCK_DIALOG_WARNING)
 
96
        self._add_timeout()
 
97
        self._waiting_next = False
 
98
 
 
99
    def _add_timeout(self):
 
100
        self.round_start = time.time()
 
101
        self._timeout = gobject.timeout_add(ROUND_TIME * 60 * 1000,
 
102
                                            self._on_timeout)
 
103
 
 
104
    def _on_timeout(self):
 
105
        self.notify_timeout()
 
106
 
 
107
    def _clear(self):
 
108
        self.close()
 
109
        self.clear_actions()
 
110
        self.clear_hints()
 
111
 
 
112
    def notify_failure(self, results):
 
113
        if self._waiting_next:
 
114
            return
 
115
 
 
116
        self._clear()
 
117
        messages = []
 
118
 
 
119
        for test, trace in results.failures:
 
120
            message = ""
 
121
            lines = trace.split('\n')
 
122
            line_number = lines[-4].split(', ')[1]
 
123
            message += "<b>%s</b>: %s \n%s" % (test, line_number, lines[-2])
 
124
 
 
125
            messages.append(message)
 
126
 
 
127
        message = '\n'.join(messages)
 
128
 
 
129
        self.set_property('summary',
 
130
                          '%s Failures' % len(results.failures))
 
131
        self.set_property('body',
 
132
                          message)
 
133
        self.show()
 
134
 
 
135
    def notify_error(self, message):
 
136
        if self._waiting_next:
 
137
            return
 
138
 
 
139
        self._clear()
 
140
        self.set_property('summary', 'Error')
 
141
        self.set_property('body',  message)
 
142
        self.show()
 
143
 
 
144
    def notify_load_error(self, message):
 
145
        if self._waiting_next:
 
146
            return
 
147
 
 
148
        self._clear()
 
149
        self.set_property('summary', 'Load Error')
 
150
        self.set_property('body',  message)
 
151
        self.show()
 
152
 
 
153
    def notify_timeout(self):
 
154
        self._clear()
 
155
        self.set_timeout(0)
 
156
        self.add_action('continue', 'Continue', self._on_continue)
 
157
        self.set_property('summary', 'Next, please')
 
158
        self.set_property('body', 'Get your ass out of there!')
 
159
        self.set_property('icon-name', gtk.STOCK_DIALOG_WARNING)
 
160
        self.show()
 
161
 
 
162
        self._waiting_next = True
 
163
 
 
164
    def _on_continue(self, notification, action):
 
165
        self._add_timeout()
 
166
        self._waiting_next = False
 
167
 
 
168
 
 
169
 
 
170
 
 
171
class DojoTray(gtk.StatusIcon):
 
172
    def __init__(self, monitor, notification):
 
173
        gtk.StatusIcon.__init__(self)
 
174
 
 
175
        self.notification = notification
 
176
        notification.attach_to_status_icon(self)
 
177
        self.set_status(monitor.STATUS_PASS)
 
178
 
 
179
        monitor.connect('status-changed', self._on_status_changed)
 
180
        gobject.timeout_add(1000, self._update_tooltip)
 
181
 
 
182
    def _update_tooltip(self):
 
183
        elapsed =  int(time.time() - self.notification.round_start)
 
184
 
 
185
        minutes = int(elapsed/60.0)
 
186
        seconds = elapsed - minutes*60
 
187
 
 
188
        self.set_tooltip("time elapsed: %d:%02d" % (minutes, seconds))
 
189
        return True
 
190
 
 
191
    def _on_status_changed(self, monitor, status, results):
 
192
        self.set_status(status, results)
 
193
 
 
194
    def set_status(self, status, results=None):
 
195
        if status == DojoMonitor.STATUS_PASS:
 
196
            self.set_from_stock(gtk.STOCK_YES)
 
197
            self.notification.close()
 
198
 
 
199
        elif status == DojoMonitor.STATUS_FAIL:
 
200
            self.set_from_stock(gtk.STOCK_NO)
 
201
            self.notification.notify_failure(results)
 
202
 
 
203
        elif status == DojoMonitor.STATUS_ERROR:
 
204
            self.set_from_stock(gtk.STOCK_DIALOG_WARNING)
 
205
            self.notification.notify_error(results)
 
206
 
 
207
        elif status == DojoMonitor.STATUS_LOAD_ERROR:
 
208
            self.set_from_stock(gtk.STOCK_DIALOG_WARNING)
 
209
            self.notification.notify_load_error(results)
 
210
 
 
211
 
 
212
class DojoTools:
 
213
    def __init__(self, name):
 
214
        self.monitor = DojoMonitor(name)
 
215
        self.notification = DojoNotification()
 
216
        self.tray = DojoTray(self.monitor, self.notification)
 
217
 
 
218
 
 
219
if __name__ == '__main__':
 
220
    if len(sys.argv) < 2:
 
221
        print 'usage:'
 
222
    else:
 
223
        name = sys.argv[1]
 
224
        dojo = DojoTools(name)
 
225
        gtk.main()