1
# -*- coding: utf-8 -*-
3
# Copyright © 2009-2010 Pierre Raybaut
4
# Licensed under the terms of the MIT License
5
# (see spyderlib/__init__.py for details)
9
# pylint: disable=C0103
10
# pylint: disable=R0903
11
# pylint: disable=R0911
12
# pylint: disable=R0201
14
from __future__ import with_statement
16
from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QTreeWidgetItem,
17
QMessageBox, QVBoxLayout, QLabel)
18
from spyderlib.qt.QtCore import SIGNAL, QProcess, QByteArray, QTextCodec
19
locale_codec = QTextCodec.codecForLocale()
20
from spyderlib.qt.compat import getopenfilename
30
from spyderlib.utils import programs
31
from spyderlib.utils.qthelpers import create_toolbutton
32
from spyderlib.baseconfig import get_conf_path, get_translation
33
from spyderlib.guiconfig import get_icon
34
from spyderlib.widgets.onecolumntree import OneColumnTree
35
from spyderlib.widgets.texteditor import TextEditor
36
from spyderlib.widgets.comboboxes import (PythonModulesComboBox,
38
_ = get_translation("p_pylint", dirname="spyderplugins")
41
PYLINT_PATH = programs.find_program('pylint')
44
#TODO: display results on 3 columns instead of 1: msg_id, lineno, message
45
class ResultsTree(OneColumnTree):
46
def __init__(self, parent):
47
OneColumnTree.__init__(self, parent)
53
def activated(self, item):
54
"""Double-click event"""
55
data = self.data.get(item)
58
self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
61
def clicked(self, item):
65
def clear_results(self):
69
def set_results(self, filename, results):
70
self.filename = filename
71
self.results = results
75
title = _('Results for ')+self.filename
80
results = ((_('Convention'),
81
get_icon('convention.png'), self.results['C:']),
83
get_icon('refactor.png'), self.results['R:']),
85
get_icon('warning.png'), self.results['W:']),
87
get_icon('error.png'), self.results['E:']))
88
for title, icon, messages in results:
89
title += ' (%d message%s)' % (len(messages),
90
's' if len(messages)>1 else '')
91
title_item = QTreeWidgetItem(self, [title], QTreeWidgetItem.Type)
92
title_item.setIcon(0, icon)
94
title_item.setDisabled(True)
96
for module, lineno, message, msg_id in messages:
97
basename = osp.splitext(osp.basename(self.filename))[0]
98
if not module.startswith(basename):
100
i_base = module.find(basename)
101
module = module[i_base:]
102
dirname = osp.dirname(self.filename)
103
if module.startswith('.') or module == basename:
104
modname = osp.join(dirname, module)
106
modname = osp.join(dirname, *module.split('.'))
107
if osp.isdir(modname):
108
modname = osp.join(modname, '__init__')
109
for ext in ('.py', '.pyw'):
110
if osp.isfile(modname+ext):
111
modname = modname + ext
113
if osp.isdir(self.filename):
114
parent = modules.get(modname)
116
item = QTreeWidgetItem(title_item, [module],
117
QTreeWidgetItem.Type)
118
item.setIcon(0, get_icon('py.png'))
119
modules[modname] = item
124
text = "[%s] %d : %s" % (msg_id, lineno, message)
126
text = "%d : %s" % (lineno, message)
127
msg_item = QTreeWidgetItem(parent, [text], QTreeWidgetItem.Type)
128
msg_item.setIcon(0, get_icon('arrow.png'))
129
self.data[msg_item] = (modname, lineno)
132
class PylintWidget(QWidget):
136
DATAPATH = get_conf_path('.pylint.results')
139
def __init__(self, parent, max_entries=100):
140
QWidget.__init__(self, parent)
142
self.setWindowTitle("Pylint")
145
self.error_output = None
147
self.max_entries = max_entries
149
if osp.isfile(self.DATAPATH):
151
data = cPickle.loads(file(self.DATAPATH, 'U').read())
152
if data[0] == self.VERSION:
153
self.rdata = data[1:]
157
self.filecombo = PythonModulesComboBox(self)
159
self.remove_obsolete_items()
160
self.filecombo.addItems(self.get_filenames())
162
self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
164
tip=_("Run analysis"),
165
triggered=self.start, text_beside_icon=True)
166
self.stop_button = create_toolbutton(self,
167
icon=get_icon('terminate.png'),
170
"Stop current analysis"),
171
text_beside_icon=True)
172
self.connect(self.filecombo, SIGNAL('valid(bool)'),
173
self.start_button.setEnabled)
174
self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
176
browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
177
tip=_('Select Python script'),
178
triggered=self.select_file)
180
self.ratelabel = QLabel()
181
self.datelabel = QLabel()
182
self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
184
text_beside_icon=True,
185
tip=_("Complete Pylint output"),
186
triggered=self.show_log)
187
self.treewidget = ResultsTree(self)
189
hlayout1 = QHBoxLayout()
190
hlayout1.addWidget(self.filecombo)
191
hlayout1.addWidget(browse_button)
192
hlayout1.addWidget(self.start_button)
193
hlayout1.addWidget(self.stop_button)
195
hlayout2 = QHBoxLayout()
196
hlayout2.addWidget(self.ratelabel)
197
hlayout2.addStretch()
198
hlayout2.addWidget(self.datelabel)
199
hlayout2.addStretch()
200
hlayout2.addWidget(self.log_button)
202
layout = QVBoxLayout()
203
layout.addLayout(hlayout1)
204
layout.addLayout(hlayout2)
205
layout.addWidget(self.treewidget)
206
self.setLayout(layout)
209
self.set_running_state(False)
211
if PYLINT_PATH is None:
212
for widget in (self.treewidget, self.filecombo,
213
self.start_button, self.stop_button):
214
widget.setDisabled(True)
216
and programs.is_module_installed("pylint"):
217
# Pylint is installed but pylint script is not in PATH
218
# (AFAIK, could happen only on Windows)
219
text = _('Pylint script was not found. Please add "%s" to PATH.')
220
text = unicode(text) % osp.join(sys.prefix, "Scripts")
222
text = _('Please install <b>pylint</b>:')
223
url = 'http://www.logilab.fr'
224
text += ' <a href=%s>%s</a>' % (url, url)
225
self.ratelabel.setText(text)
229
def analyze(self, filename):
230
if PYLINT_PATH is None:
232
filename = unicode(filename) # filename is a QString instance
233
self.kill_if_running()
234
index, _data = self.get_data(filename)
236
self.filecombo.addItem(filename)
237
self.filecombo.setCurrentIndex(self.filecombo.count()-1)
239
self.filecombo.setCurrentIndex(self.filecombo.findText(filename))
240
self.filecombo.selected()
241
if self.filecombo.is_valid():
244
def select_file(self):
245
self.emit(SIGNAL('redirect_stdio(bool)'), False)
246
filename, _selfilter = getopenfilename(self, _("Select Python script"),
247
os.getcwdu(), _("Python scripts")+" (*.py ; *.pyw)")
248
self.emit(SIGNAL('redirect_stdio(bool)'), False)
250
self.analyze(filename)
252
def remove_obsolete_items(self):
253
"""Removing obsolete items"""
254
self.rdata = [(filename, data) for filename, data in self.rdata
255
if is_module_or_package(filename)]
257
def get_filenames(self):
258
return [filename for filename, _data in self.rdata]
260
def get_data(self, filename):
261
filename = osp.abspath(filename)
262
for index, (fname, data) in enumerate(self.rdata):
263
if fname == filename:
268
def set_data(self, filename, data):
269
filename = osp.abspath(filename)
270
index, _data = self.get_data(filename)
271
if index is not None:
272
self.rdata.pop(index)
273
self.rdata.append( (filename, data) )
277
while len(self.rdata) > self.max_entries:
279
cPickle.dump([self.VERSION]+self.rdata, file(self.DATAPATH, 'w'))
283
TextEditor(self.output, title=_("Pylint output"),
284
readonly=True, size=(700, 500)).exec_()
287
filename = unicode(self.filecombo.currentText())
289
self.process = QProcess(self)
290
self.process.setProcessChannelMode(QProcess.SeparateChannels)
291
self.process.setWorkingDirectory(osp.dirname(filename))
292
self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
294
self.connect(self.process, SIGNAL("readyReadStandardError()"),
295
lambda: self.read_output(error=True))
296
self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
298
self.connect(self.stop_button, SIGNAL("clicked()"),
302
self.error_output = ''
303
p_args = ['-i', 'yes', osp.basename(filename)]
304
self.process.start(PYLINT_PATH, p_args)
306
running = self.process.waitForStarted()
307
self.set_running_state(running)
309
QMessageBox.critical(self, _("Error"),
310
_("Process failed to start"))
312
def set_running_state(self, state=True):
313
self.start_button.setEnabled(not state)
314
self.stop_button.setEnabled(state)
316
def read_output(self, error=False):
318
self.process.setReadChannel(QProcess.StandardError)
320
self.process.setReadChannel(QProcess.StandardOutput)
322
while self.process.bytesAvailable():
324
bytes += self.process.readAllStandardError()
326
bytes += self.process.readAllStandardOutput()
327
text = unicode( locale_codec.toUnicode(bytes.data()) )
329
self.error_output += text
334
self.set_running_state(False)
338
# Convention, Refactor, Warning, Error
339
results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
340
txt_module = '************* Module '
342
module = '' # Should not be needed - just in case something goes wrong
343
for line in self.output.splitlines():
344
if line.startswith(txt_module):
346
module = line[len(txt_module):]
348
# Supporting option include-ids: ('R3873:' instead of 'R:')
349
if not re.match('^[CRWE]+([0-9]{4})?:', line):
355
i2 = line.find(':', i1+1)
358
line_nb = line[i1+1:i2].strip()
361
line_nb = int(line_nb.split(',')[0])
362
message = line[i2+1:]
363
item = (module, line_nb, message, msg_id)
364
results[line[0]+':'].append(item)
368
txt_rate = 'Your code has been rated at '
369
i_rate = self.output.find(txt_rate)
371
i_rate_end = self.output.find('/10', i_rate)
373
rate = self.output[i_rate+len(txt_rate):i_rate_end]
378
txt_prun = 'previous run: '
379
i_prun = self.output.find(txt_prun, i_rate_end)
381
i_prun_end = self.output.find('/10', i_prun)
382
previous = self.output[i_prun+len(txt_prun):i_prun_end]
385
filename = unicode(self.filecombo.currentText())
386
self.set_data(filename, (time.localtime(), rate, previous, results))
387
self.output = self.error_output + self.output
388
self.show_data(justanalyzed=True)
390
def kill_if_running(self):
391
if self.process is not None:
392
if self.process.state() == QProcess.Running:
394
self.process.waitForFinished()
396
def show_data(self, justanalyzed=False):
399
self.log_button.setEnabled(self.output is not None \
400
and len(self.output) > 0)
401
self.kill_if_running()
402
filename = unicode(self.filecombo.currentText())
406
_index, data = self.get_data(filename)
408
text = _('Source code has not been rated yet.')
409
self.treewidget.clear_results()
412
datetime, rate, previous_rate, results = data
414
text = _('Analysis did not succeed '
415
'(see output for more details).')
416
self.treewidget.clear_results()
419
text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
420
rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
421
prevrate_style = "<span style=\'color: #666666\'>%s</span>"
425
elif float(rate) > 3.:
427
text = _('Global evaluation:')
428
text = (text_style % text)+(rate_style % (color,
431
text_prun = _('previous run:')
432
text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
433
text += prevrate_style % text_prun
434
self.treewidget.set_results(filename, results)
435
date_text = text_style % time.strftime("%d %b %Y %H:%M",
438
self.ratelabel.setText(text)
439
self.datelabel.setText(date_text)
443
"""Run pylint widget test"""
444
from spyderlib.utils.qthelpers import qapplication
446
widget = PylintWidget(None)
448
widget.analyze(__file__)
449
sys.exit(app.exec_())
451
if __name__ == '__main__':
1
# -*- coding: utf-8 -*-
3
# Copyright © 2009-2010 Pierre Raybaut
4
# Licensed under the terms of the MIT License
5
# (see spyderlib/__init__.py for details)
9
# pylint: disable=C0103
10
# pylint: disable=R0903
11
# pylint: disable=R0911
12
# pylint: disable=R0201
14
from __future__ import with_statement
16
from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QTreeWidgetItem,
17
QMessageBox, QVBoxLayout, QLabel)
18
from spyderlib.qt.QtCore import SIGNAL, QProcess, QByteArray, QTextCodec
19
locale_codec = QTextCodec.codecForLocale()
20
from spyderlib.qt.compat import getopenfilename
30
from spyderlib.utils import programs
31
from spyderlib.utils.qthelpers import get_icon, create_toolbutton
32
from spyderlib.baseconfig import get_conf_path, get_translation
33
from spyderlib.widgets.onecolumntree import OneColumnTree
34
from spyderlib.widgets.texteditor import TextEditor
35
from spyderlib.widgets.comboboxes import (PythonModulesComboBox,
37
_ = get_translation("p_pylint", dirname="spyderplugins")
40
PYLINT_PATH = programs.find_program('pylint')
43
#TODO: display results on 3 columns instead of 1: msg_id, lineno, message
44
class ResultsTree(OneColumnTree):
45
def __init__(self, parent):
46
OneColumnTree.__init__(self, parent)
52
def activated(self, item):
53
"""Double-click event"""
54
data = self.data.get(item)
57
self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
60
def clicked(self, item):
64
def clear_results(self):
68
def set_results(self, filename, results):
69
self.filename = filename
70
self.results = results
74
title = _('Results for ')+self.filename
79
results = ((_('Convention'),
80
get_icon('convention.png'), self.results['C:']),
82
get_icon('refactor.png'), self.results['R:']),
84
get_icon('warning.png'), self.results['W:']),
86
get_icon('error.png'), self.results['E:']))
87
for title, icon, messages in results:
88
title += ' (%d message%s)' % (len(messages),
89
's' if len(messages)>1 else '')
90
title_item = QTreeWidgetItem(self, [title], QTreeWidgetItem.Type)
91
title_item.setIcon(0, icon)
93
title_item.setDisabled(True)
95
for module, lineno, message, msg_id in messages:
96
basename = osp.splitext(osp.basename(self.filename))[0]
97
if not module.startswith(basename):
99
i_base = module.find(basename)
100
module = module[i_base:]
101
dirname = osp.dirname(self.filename)
102
if module.startswith('.') or module == basename:
103
modname = osp.join(dirname, module)
105
modname = osp.join(dirname, *module.split('.'))
106
if osp.isdir(modname):
107
modname = osp.join(modname, '__init__')
108
for ext in ('.py', '.pyw'):
109
if osp.isfile(modname+ext):
110
modname = modname + ext
112
if osp.isdir(self.filename):
113
parent = modules.get(modname)
115
item = QTreeWidgetItem(title_item, [module],
116
QTreeWidgetItem.Type)
117
item.setIcon(0, get_icon('py.png'))
118
modules[modname] = item
123
text = "[%s] %d : %s" % (msg_id, lineno, message)
125
text = "%d : %s" % (lineno, message)
126
msg_item = QTreeWidgetItem(parent, [text], QTreeWidgetItem.Type)
127
msg_item.setIcon(0, get_icon('arrow.png'))
128
self.data[msg_item] = (modname, lineno)
131
class PylintWidget(QWidget):
135
DATAPATH = get_conf_path('.pylint.results')
138
def __init__(self, parent, max_entries=100):
139
QWidget.__init__(self, parent)
141
self.setWindowTitle("Pylint")
144
self.error_output = None
146
self.max_entries = max_entries
148
if osp.isfile(self.DATAPATH):
150
data = cPickle.loads(file(self.DATAPATH, 'U').read())
151
if data[0] == self.VERSION:
152
self.rdata = data[1:]
156
self.filecombo = PythonModulesComboBox(self)
158
self.remove_obsolete_items()
159
self.filecombo.addItems(self.get_filenames())
161
self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
163
tip=_("Run analysis"),
164
triggered=self.start, text_beside_icon=True)
165
self.stop_button = create_toolbutton(self,
166
icon=get_icon('terminate.png'),
169
"Stop current analysis"),
170
text_beside_icon=True)
171
self.connect(self.filecombo, SIGNAL('valid(bool)'),
172
self.start_button.setEnabled)
173
self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
175
browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
176
tip=_('Select Python script'),
177
triggered=self.select_file)
179
self.ratelabel = QLabel()
180
self.datelabel = QLabel()
181
self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
183
text_beside_icon=True,
184
tip=_("Complete Pylint output"),
185
triggered=self.show_log)
186
self.treewidget = ResultsTree(self)
188
hlayout1 = QHBoxLayout()
189
hlayout1.addWidget(self.filecombo)
190
hlayout1.addWidget(browse_button)
191
hlayout1.addWidget(self.start_button)
192
hlayout1.addWidget(self.stop_button)
194
hlayout2 = QHBoxLayout()
195
hlayout2.addWidget(self.ratelabel)
196
hlayout2.addStretch()
197
hlayout2.addWidget(self.datelabel)
198
hlayout2.addStretch()
199
hlayout2.addWidget(self.log_button)
201
layout = QVBoxLayout()
202
layout.addLayout(hlayout1)
203
layout.addLayout(hlayout2)
204
layout.addWidget(self.treewidget)
205
self.setLayout(layout)
208
self.set_running_state(False)
210
if PYLINT_PATH is None:
211
for widget in (self.treewidget, self.filecombo,
212
self.start_button, self.stop_button):
213
widget.setDisabled(True)
215
and programs.is_module_installed("pylint"):
216
# Pylint is installed but pylint script is not in PATH
217
# (AFAIK, could happen only on Windows)
218
text = _('Pylint script was not found. Please add "%s" to PATH.')
219
text = unicode(text) % osp.join(sys.prefix, "Scripts")
221
text = _('Please install <b>pylint</b>:')
222
url = 'http://www.logilab.fr'
223
text += ' <a href=%s>%s</a>' % (url, url)
224
self.ratelabel.setText(text)
228
def analyze(self, filename):
229
if PYLINT_PATH is None:
231
filename = unicode(filename) # filename is a QString instance
232
self.kill_if_running()
233
index, _data = self.get_data(filename)
235
self.filecombo.addItem(filename)
236
self.filecombo.setCurrentIndex(self.filecombo.count()-1)
238
self.filecombo.setCurrentIndex(self.filecombo.findText(filename))
239
self.filecombo.selected()
240
if self.filecombo.is_valid():
243
def select_file(self):
244
self.emit(SIGNAL('redirect_stdio(bool)'), False)
245
filename, _selfilter = getopenfilename(self, _("Select Python script"),
246
os.getcwdu(), _("Python scripts")+" (*.py ; *.pyw)")
247
self.emit(SIGNAL('redirect_stdio(bool)'), False)
249
self.analyze(filename)
251
def remove_obsolete_items(self):
252
"""Removing obsolete items"""
253
self.rdata = [(filename, data) for filename, data in self.rdata
254
if is_module_or_package(filename)]
256
def get_filenames(self):
257
return [filename for filename, _data in self.rdata]
259
def get_data(self, filename):
260
filename = osp.abspath(filename)
261
for index, (fname, data) in enumerate(self.rdata):
262
if fname == filename:
267
def set_data(self, filename, data):
268
filename = osp.abspath(filename)
269
index, _data = self.get_data(filename)
270
if index is not None:
271
self.rdata.pop(index)
272
self.rdata.append( (filename, data) )
276
while len(self.rdata) > self.max_entries:
278
cPickle.dump([self.VERSION]+self.rdata, file(self.DATAPATH, 'w'))
282
TextEditor(self.output, title=_("Pylint output"),
283
readonly=True, size=(700, 500)).exec_()
286
filename = unicode(self.filecombo.currentText())
288
self.process = QProcess(self)
289
self.process.setProcessChannelMode(QProcess.SeparateChannels)
290
self.process.setWorkingDirectory(osp.dirname(filename))
291
self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
293
self.connect(self.process, SIGNAL("readyReadStandardError()"),
294
lambda: self.read_output(error=True))
295
self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
297
self.connect(self.stop_button, SIGNAL("clicked()"),
301
self.error_output = ''
302
p_args = ['-i', 'yes', osp.basename(filename)]
303
self.process.start(PYLINT_PATH, p_args)
305
running = self.process.waitForStarted()
306
self.set_running_state(running)
308
QMessageBox.critical(self, _("Error"),
309
_("Process failed to start"))
311
def set_running_state(self, state=True):
312
self.start_button.setEnabled(not state)
313
self.stop_button.setEnabled(state)
315
def read_output(self, error=False):
317
self.process.setReadChannel(QProcess.StandardError)
319
self.process.setReadChannel(QProcess.StandardOutput)
321
while self.process.bytesAvailable():
323
bytes += self.process.readAllStandardError()
325
bytes += self.process.readAllStandardOutput()
326
text = unicode( locale_codec.toUnicode(bytes.data()) )
328
self.error_output += text
333
self.set_running_state(False)
337
# Convention, Refactor, Warning, Error
338
results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
339
txt_module = '************* Module '
341
module = '' # Should not be needed - just in case something goes wrong
342
for line in self.output.splitlines():
343
if line.startswith(txt_module):
345
module = line[len(txt_module):]
347
# Supporting option include-ids: ('R3873:' instead of 'R:')
348
if not re.match('^[CRWE]+([0-9]{4})?:', line):
354
i2 = line.find(':', i1+1)
357
line_nb = line[i1+1:i2].strip()
360
line_nb = int(line_nb.split(',')[0])
361
message = line[i2+1:]
362
item = (module, line_nb, message, msg_id)
363
results[line[0]+':'].append(item)
367
txt_rate = 'Your code has been rated at '
368
i_rate = self.output.find(txt_rate)
370
i_rate_end = self.output.find('/10', i_rate)
372
rate = self.output[i_rate+len(txt_rate):i_rate_end]
377
txt_prun = 'previous run: '
378
i_prun = self.output.find(txt_prun, i_rate_end)
380
i_prun_end = self.output.find('/10', i_prun)
381
previous = self.output[i_prun+len(txt_prun):i_prun_end]
384
filename = unicode(self.filecombo.currentText())
385
self.set_data(filename, (time.localtime(), rate, previous, results))
386
self.output = self.error_output + self.output
387
self.show_data(justanalyzed=True)
389
def kill_if_running(self):
390
if self.process is not None:
391
if self.process.state() == QProcess.Running:
393
self.process.waitForFinished()
395
def show_data(self, justanalyzed=False):
398
self.log_button.setEnabled(self.output is not None \
399
and len(self.output) > 0)
400
self.kill_if_running()
401
filename = unicode(self.filecombo.currentText())
405
_index, data = self.get_data(filename)
407
text = _('Source code has not been rated yet.')
408
self.treewidget.clear_results()
411
datetime, rate, previous_rate, results = data
413
text = _('Analysis did not succeed '
414
'(see output for more details).')
415
self.treewidget.clear_results()
418
text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
419
rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
420
prevrate_style = "<span style=\'color: #666666\'>%s</span>"
424
elif float(rate) > 3.:
426
text = _('Global evaluation:')
427
text = (text_style % text)+(rate_style % (color,
430
text_prun = _('previous run:')
431
text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
432
text += prevrate_style % text_prun
433
self.treewidget.set_results(filename, results)
434
date_text = text_style % time.strftime("%d %b %Y %H:%M",
437
self.ratelabel.setText(text)
438
self.datelabel.setText(date_text)
442
"""Run pylint widget test"""
443
from spyderlib.utils.qthelpers import qapplication
445
widget = PylintWidget(None)
447
widget.analyze(__file__)
448
sys.exit(app.exec_())
450
if __name__ == '__main__':