mirror of
https://fuchsia.googlesource.com/third_party/github.com/pylint-dev/pylint
synced 2024-09-20 23:51:39 +00:00
Remove pylint-gui
pylint-gui was removed, because it was deemed unfit for being included in *pylint*. It had a couple of bugs and misfeatures, its usability was subpar and since its development was neglected, we decided it is best to move on without it. Part of #975
This commit is contained in:
parent
e80778ae9c
commit
c70b281c62
|
@ -8,6 +8,8 @@ What's New in Pylint 2.0?
|
|||
|
||||
Release date: tba
|
||||
|
||||
* Removed pylint-gui from the package.
|
||||
|
||||
* ignored-argument-names is now used for ignoring arguments for unused-variable check.
|
||||
|
||||
This option was used for ignoring arguments when computing the correct number of arguments
|
||||
|
|
|
@ -78,4 +78,3 @@ Pylint is shipped with following additional commands:
|
|||
* pyreverse: an UML diagram generator
|
||||
* symilar: an independent similarities checker
|
||||
* epylint: Emacs and Flymake compatible Pylint
|
||||
* pylint-gui: a graphical interface
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
from pylint import run_pylint_gui
|
||||
run_pylint_gui()
|
|
@ -1,5 +0,0 @@
|
|||
@echo off
|
||||
rem Use python to execute the python script having the same name as this batch
|
||||
rem file, but without any extension, located in the same directory as this
|
||||
rem batch file
|
||||
"%~dpn0" %*
|
|
@ -32,8 +32,6 @@ Description: python code static checker and UML diagram generator
|
|||
The included command pyreverse generates UML class and package
|
||||
diagrams.
|
||||
.
|
||||
The recommended python-tk package is only for using the pylint-gui
|
||||
script.
|
||||
|
||||
Package: pylint3
|
||||
Architecture: all
|
||||
|
@ -57,5 +55,3 @@ Description: python code static checker and UML diagram generator
|
|||
The included command pyreverse generates UML class and package
|
||||
diagrams.
|
||||
.
|
||||
The recommended python-tk package is only for using the pylint-gui
|
||||
script.
|
||||
|
|
|
@ -29,7 +29,7 @@ override_dh_install:
|
|||
--root=$(CURDIR)/debian/$(PACKAGE3)/ \
|
||||
${py_setup_install_args}
|
||||
# rename executables
|
||||
for executable in pylint pylint-gui symilar epylint pyreverse ; do \
|
||||
for executable in pylint symilar epylint pyreverse ; do \
|
||||
new_exec="$$executable"3; \
|
||||
sed 's,^#!.*python$$,&3,' < $(CURDIR)/debian/$(PACKAGE3)/usr/bin/$$executable > $(CURDIR)/debian/$(PACKAGE3)/usr/bin/$$new_exec || exit 1; \
|
||||
done
|
||||
|
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -20,7 +20,7 @@ Depends: ${python:Depends},
|
|||
${misc:Depends},
|
||||
python-logilab-common (>= 0.53.0),
|
||||
python-astroid (>= 1.2)
|
||||
Suggests: python-tk, python-enchant
|
||||
Suggests: python-enchant
|
||||
XB-Python-Version: ${python:Versions}
|
||||
Description: python code static checker and UML diagram generator
|
||||
Pylint is a Python source code analyzer which looks for programming
|
||||
|
@ -39,5 +39,3 @@ Description: python code static checker and UML diagram generator
|
|||
The included command pyreverse generates UML class and package
|
||||
diagrams. The included symilar command is a separated similarities checker.
|
||||
.
|
||||
The recommended python-tk package is only for using the pylint-gui
|
||||
script.
|
||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -42,7 +42,7 @@ install: build
|
|||
rm -rf debian/pylint/usr/lib/python*/*-packages/pylint/test
|
||||
|
||||
# fixes shebangs
|
||||
for exec_file in pylint pylint-gui symilar epylint pyreverse ; do \
|
||||
for exec_file in pylint symilar epylint pyreverse ; do \
|
||||
if head -1 debian/pylint/usr/bin/$$exec_file | grep "^#! */usr/bin" | grep "python" >/dev/null ; then \
|
||||
sed -i "s@^#! */usr/bin/env \+python\$$@#!/usr/bin/python@" debian/pylint/usr/bin/$$exec_file; \
|
||||
fi ; \
|
||||
|
|
|
@ -34,15 +34,6 @@ python path.
|
|||
|
||||
For more details on this see the :ref:`faq`.
|
||||
|
||||
You can also start a thin gui around Pylint (require tkinter) by
|
||||
typing ::
|
||||
|
||||
pylint-gui
|
||||
|
||||
This should open a window where you can enter the name of the package
|
||||
or module to check, at Pylint messages will be displayed in the user
|
||||
interface.
|
||||
|
||||
It is also possible to call Pylint from an other python program,
|
||||
thanks to ``py_run()`` function in ``epylint`` module,
|
||||
assuming Pylint options are stored in ``pylint_options`` string, as:
|
||||
|
|
|
@ -16,3 +16,11 @@ Other Changes
|
|||
|
||||
* None yet.
|
||||
|
||||
|
||||
Removed Changes
|
||||
===============
|
||||
|
||||
* ``pylint-gui`` was removed, because it was deemed unfit for being included
|
||||
in *pylint*. It had a couple of bugs and misfeatures, its usability was subpar
|
||||
and since its development was neglected, we decided it is best to move on without it.
|
||||
|
||||
|
|
|
@ -10,13 +10,6 @@ def run_pylint():
|
|||
from pylint.lint import Run
|
||||
Run(sys.argv[1:])
|
||||
|
||||
def run_pylint_gui():
|
||||
"""run pylint-gui"""
|
||||
try:
|
||||
from pylint.gui import Run
|
||||
Run(sys.argv[1:])
|
||||
except ImportError:
|
||||
sys.exit('tkinter is not available')
|
||||
|
||||
def run_epylint():
|
||||
"""run pylint"""
|
||||
|
|
|
@ -67,11 +67,11 @@ long_desc = """\
|
|||
.
|
||||
Additionally, it is possible to write plugins to add your own checks.
|
||||
.
|
||||
Pylint is shipped with "pylint-gui", "pyreverse" (UML diagram generator)
|
||||
Pylint is shipped with "pyreverse" (UML diagram generator)
|
||||
and "symilar" (an independent similarities checker)."""
|
||||
|
||||
scripts = [join('bin', filename)
|
||||
for filename in ('pylint', 'pylint-gui', "symilar", "epylint",
|
||||
for filename in ('pylint', "symilar", "epylint",
|
||||
"pyreverse")]
|
||||
|
||||
include_dirs = [join('pylint', 'test')]
|
||||
|
|
519
pylint/gui.py
519
pylint/gui.py
|
@ -1,519 +0,0 @@
|
|||
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
|
||||
|
||||
"""Tkinker gui for pylint"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
from threading import Thread
|
||||
|
||||
import six
|
||||
|
||||
from six.moves.tkinter import (
|
||||
Tk, Frame, Listbox, Entry, Label, Button, Scrollbar,
|
||||
Checkbutton, Radiobutton, IntVar, StringVar, PanedWindow,
|
||||
TOP, LEFT, RIGHT, BOTTOM, END, X, Y, BOTH, SUNKEN, W,
|
||||
HORIZONTAL, DISABLED, NORMAL,
|
||||
)
|
||||
from six.moves.tkinter_tkfiledialog import (
|
||||
askopenfilename, askdirectory,
|
||||
)
|
||||
|
||||
import pylint.lint
|
||||
from pylint.reporters.guireporter import GUIReporter
|
||||
|
||||
HOME = os.path.expanduser('~/')
|
||||
HISTORY = '.pylint-gui-history'
|
||||
COLORS = {'(I)':'green',
|
||||
'(C)':'blue', '(R)':'darkblue',
|
||||
'(W)':'black', '(E)':'darkred',
|
||||
'(F)':'red'}
|
||||
|
||||
|
||||
def convert_to_string(msg):
|
||||
"""make a string representation of a message"""
|
||||
module_object = msg.module
|
||||
if msg.obj:
|
||||
module_object += ".%s" % msg.obj
|
||||
return "(%s) %s [%d]: %s" % (msg.C, module_object, msg.line, msg.msg)
|
||||
|
||||
class BasicStream(object):
|
||||
'''
|
||||
used in gui reporter instead of writing to stdout, it is written to
|
||||
this stream and saved in contents
|
||||
'''
|
||||
def __init__(self, gui):
|
||||
"""init"""
|
||||
self.curline = ""
|
||||
self.gui = gui
|
||||
self.contents = []
|
||||
self.outdict = {}
|
||||
self.currout = None
|
||||
self.next_title = None
|
||||
|
||||
def write(self, text):
|
||||
"""write text to the stream"""
|
||||
if re.match('^--+$', text.strip()) or re.match('^==+$', text.strip()):
|
||||
if self.currout:
|
||||
self.outdict[self.currout].remove(self.next_title)
|
||||
self.outdict[self.currout].pop()
|
||||
self.currout = self.next_title
|
||||
self.outdict[self.currout] = ['']
|
||||
|
||||
if text.strip():
|
||||
self.next_title = text.strip()
|
||||
|
||||
if text.startswith(os.linesep):
|
||||
self.contents.append('')
|
||||
if self.currout:
|
||||
self.outdict[self.currout].append('')
|
||||
self.contents[-1] += text.strip(os.linesep)
|
||||
if self.currout:
|
||||
self.outdict[self.currout][-1] += text.strip(os.linesep)
|
||||
if text.endswith(os.linesep) and text.strip():
|
||||
self.contents.append('')
|
||||
if self.currout:
|
||||
self.outdict[self.currout].append('')
|
||||
|
||||
def fix_contents(self):
|
||||
"""finalize what the contents of the dict should look like before output"""
|
||||
for item in self.outdict:
|
||||
num_empty = self.outdict[item].count('')
|
||||
for _ in range(num_empty):
|
||||
self.outdict[item].remove('')
|
||||
if self.outdict[item]:
|
||||
self.outdict[item].pop(0)
|
||||
|
||||
def output_contents(self):
|
||||
"""output contents of dict to the gui, and set the rating"""
|
||||
self.fix_contents()
|
||||
self.gui.tabs = self.outdict
|
||||
try:
|
||||
self.gui.rating.set(self.outdict['Global evaluation'][0])
|
||||
except KeyError:
|
||||
self.gui.rating.set('Error')
|
||||
self.gui.refresh_results_window()
|
||||
|
||||
#reset stream variables for next run
|
||||
self.contents = []
|
||||
self.outdict = {}
|
||||
self.currout = None
|
||||
self.next_title = None
|
||||
|
||||
|
||||
class LintGui(object):
|
||||
"""Build and control a window to interact with pylint"""
|
||||
|
||||
def __init__(self, root=None):
|
||||
"""init"""
|
||||
self.root = root or Tk()
|
||||
self.root.title('Pylint')
|
||||
#reporter
|
||||
self.reporter = None
|
||||
#message queue for output from reporter
|
||||
self.msg_queue = six.moves.queue.Queue()
|
||||
self.msgs = []
|
||||
self.visible_msgs = []
|
||||
self.filenames = []
|
||||
self.rating = StringVar()
|
||||
self.tabs = {}
|
||||
self.report_stream = BasicStream(self)
|
||||
#gui objects
|
||||
self.lb_messages = None
|
||||
self.showhistory = None
|
||||
self.results = None
|
||||
self.btnRun = None
|
||||
self.information_box = None
|
||||
self.convention_box = None
|
||||
self.refactor_box = None
|
||||
self.warning_box = None
|
||||
self.error_box = None
|
||||
self.fatal_box = None
|
||||
self.txtModule = None
|
||||
self.status = None
|
||||
self.msg_type_dict = None
|
||||
self.init_gui()
|
||||
|
||||
def init_gui(self):
|
||||
"""init helper"""
|
||||
|
||||
window = PanedWindow(self.root, orient="vertical")
|
||||
window.pack(side=TOP, fill=BOTH, expand=True)
|
||||
|
||||
top_pane = Frame(window)
|
||||
window.add(top_pane)
|
||||
mid_pane = Frame(window)
|
||||
window.add(mid_pane)
|
||||
bottom_pane = Frame(window)
|
||||
window.add(bottom_pane)
|
||||
|
||||
#setting up frames
|
||||
top_frame = Frame(top_pane)
|
||||
mid_frame = Frame(top_pane)
|
||||
history_frame = Frame(top_pane)
|
||||
radio_frame = Frame(mid_pane)
|
||||
rating_frame = Frame(mid_pane)
|
||||
res_frame = Frame(mid_pane)
|
||||
check_frame = Frame(bottom_pane)
|
||||
msg_frame = Frame(bottom_pane)
|
||||
btn_frame = Frame(bottom_pane)
|
||||
top_frame.pack(side=TOP, fill=X)
|
||||
mid_frame.pack(side=TOP, fill=X)
|
||||
history_frame.pack(side=TOP, fill=BOTH, expand=True)
|
||||
radio_frame.pack(side=TOP, fill=X)
|
||||
rating_frame.pack(side=TOP, fill=X)
|
||||
res_frame.pack(side=TOP, fill=BOTH, expand=True)
|
||||
check_frame.pack(side=TOP, fill=X)
|
||||
msg_frame.pack(side=TOP, fill=BOTH, expand=True)
|
||||
btn_frame.pack(side=TOP, fill=X)
|
||||
|
||||
# Binding F5 application-wide to run lint
|
||||
self.root.bind('<F5>', self.run_lint)
|
||||
|
||||
#Message ListBox
|
||||
rightscrollbar = Scrollbar(msg_frame)
|
||||
rightscrollbar.pack(side=RIGHT, fill=Y)
|
||||
bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL)
|
||||
bottomscrollbar.pack(side=BOTTOM, fill=X)
|
||||
self.lb_messages = Listbox(
|
||||
msg_frame,
|
||||
yscrollcommand=rightscrollbar.set,
|
||||
xscrollcommand=bottomscrollbar.set,
|
||||
bg="white")
|
||||
self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile)
|
||||
self.lb_messages.pack(expand=True, fill=BOTH)
|
||||
rightscrollbar.config(command=self.lb_messages.yview)
|
||||
bottomscrollbar.config(command=self.lb_messages.xview)
|
||||
|
||||
#History ListBoxes
|
||||
rightscrollbar2 = Scrollbar(history_frame)
|
||||
rightscrollbar2.pack(side=RIGHT, fill=Y)
|
||||
bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL)
|
||||
bottomscrollbar2.pack(side=BOTTOM, fill=X)
|
||||
self.showhistory = Listbox(
|
||||
history_frame,
|
||||
yscrollcommand=rightscrollbar2.set,
|
||||
xscrollcommand=bottomscrollbar2.set,
|
||||
bg="white")
|
||||
self.showhistory.pack(expand=True, fill=BOTH)
|
||||
rightscrollbar2.config(command=self.showhistory.yview)
|
||||
bottomscrollbar2.config(command=self.showhistory.xview)
|
||||
self.showhistory.bind('<Double-Button-1>', self.select_recent_file)
|
||||
self.set_history_window()
|
||||
|
||||
#status bar
|
||||
self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W)
|
||||
self.status.pack(side=BOTTOM, fill=X)
|
||||
|
||||
#labelbl_ratingls
|
||||
lbl_rating_label = Label(rating_frame, text='Rating:')
|
||||
lbl_rating_label.pack(side=LEFT)
|
||||
lbl_rating = Label(rating_frame, textvariable=self.rating)
|
||||
lbl_rating.pack(side=LEFT)
|
||||
Label(mid_frame, text='Recently Used:').pack(side=LEFT)
|
||||
Label(top_frame, text='Module or package').pack(side=LEFT)
|
||||
|
||||
#file textbox
|
||||
self.txt_module = Entry(top_frame, background='white')
|
||||
self.txt_module.bind('<Return>', self.run_lint)
|
||||
self.txt_module.pack(side=LEFT, expand=True, fill=X)
|
||||
|
||||
#results box
|
||||
rightscrollbar = Scrollbar(res_frame)
|
||||
rightscrollbar.pack(side=RIGHT, fill=Y)
|
||||
bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL)
|
||||
bottomscrollbar.pack(side=BOTTOM, fill=X)
|
||||
self.results = Listbox(
|
||||
res_frame,
|
||||
yscrollcommand=rightscrollbar.set,
|
||||
xscrollcommand=bottomscrollbar.set,
|
||||
bg="white", font="Courier")
|
||||
self.results.pack(expand=True, fill=BOTH, side=BOTTOM)
|
||||
rightscrollbar.config(command=self.results.yview)
|
||||
bottomscrollbar.config(command=self.results.xview)
|
||||
|
||||
#buttons
|
||||
Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT)
|
||||
Button(top_frame, text='Open Package',
|
||||
command=(lambda: self.file_open(package=True))).pack(side=LEFT)
|
||||
|
||||
self.btnRun = Button(top_frame, text='Run', command=self.run_lint)
|
||||
self.btnRun.pack(side=LEFT)
|
||||
Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM)
|
||||
|
||||
#radio buttons
|
||||
self.information_box = IntVar()
|
||||
self.convention_box = IntVar()
|
||||
self.refactor_box = IntVar()
|
||||
self.warning_box = IntVar()
|
||||
self.error_box = IntVar()
|
||||
self.fatal_box = IntVar()
|
||||
i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'],
|
||||
variable=self.information_box, command=self.refresh_msg_window)
|
||||
c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'],
|
||||
variable=self.convention_box, command=self.refresh_msg_window)
|
||||
r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'],
|
||||
variable=self.refactor_box, command=self.refresh_msg_window)
|
||||
w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'],
|
||||
variable=self.warning_box, command=self.refresh_msg_window)
|
||||
e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'],
|
||||
variable=self.error_box, command=self.refresh_msg_window)
|
||||
f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'],
|
||||
variable=self.fatal_box, command=self.refresh_msg_window)
|
||||
i.select()
|
||||
c.select()
|
||||
r.select()
|
||||
w.select()
|
||||
e.select()
|
||||
f.select()
|
||||
i.pack(side=LEFT)
|
||||
c.pack(side=LEFT)
|
||||
r.pack(side=LEFT)
|
||||
w.pack(side=LEFT)
|
||||
e.pack(side=LEFT)
|
||||
f.pack(side=LEFT)
|
||||
|
||||
#check boxes
|
||||
self.box = StringVar()
|
||||
# XXX should be generated
|
||||
report = Radiobutton(
|
||||
radio_frame, text="Report", variable=self.box,
|
||||
value="Report", command=self.refresh_results_window)
|
||||
raw_met = Radiobutton(
|
||||
radio_frame, text="Raw metrics", variable=self.box,
|
||||
value="Raw metrics", command=self.refresh_results_window)
|
||||
dup = Radiobutton(
|
||||
radio_frame, text="Duplication", variable=self.box,
|
||||
value="Duplication", command=self.refresh_results_window)
|
||||
ext = Radiobutton(
|
||||
radio_frame, text="External dependencies",
|
||||
variable=self.box, value="External dependencies",
|
||||
command=self.refresh_results_window)
|
||||
stat = Radiobutton(
|
||||
radio_frame, text="Statistics by type",
|
||||
variable=self.box, value="Statistics by type",
|
||||
command=self.refresh_results_window)
|
||||
msg_cat = Radiobutton(
|
||||
radio_frame, text="Messages by category",
|
||||
variable=self.box, value="Messages by category",
|
||||
command=self.refresh_results_window)
|
||||
msg = Radiobutton(
|
||||
radio_frame, text="Messages", variable=self.box,
|
||||
value="Messages", command=self.refresh_results_window)
|
||||
source_file = Radiobutton(
|
||||
radio_frame, text="Source File", variable=self.box,
|
||||
value="Source File", command=self.refresh_results_window)
|
||||
report.select()
|
||||
report.grid(column=0, row=0, sticky=W)
|
||||
raw_met.grid(column=1, row=0, sticky=W)
|
||||
dup.grid(column=2, row=0, sticky=W)
|
||||
msg.grid(column=3, row=0, sticky=W)
|
||||
stat.grid(column=0, row=1, sticky=W)
|
||||
msg_cat.grid(column=1, row=1, sticky=W)
|
||||
ext.grid(column=2, row=1, sticky=W)
|
||||
source_file.grid(column=3, row=1, sticky=W)
|
||||
|
||||
#dictionary for check boxes and associated error term
|
||||
self.msg_type_dict = {
|
||||
'I': lambda: self.information_box.get() == 1,
|
||||
'C': lambda: self.convention_box.get() == 1,
|
||||
'R': lambda: self.refactor_box.get() == 1,
|
||||
'E': lambda: self.error_box.get() == 1,
|
||||
'W': lambda: self.warning_box.get() == 1,
|
||||
'F': lambda: self.fatal_box.get() == 1
|
||||
}
|
||||
self.txt_module.focus_set()
|
||||
|
||||
|
||||
def select_recent_file(self, event): # pylint: disable=unused-argument
|
||||
"""adds the selected file in the history listbox to the Module box"""
|
||||
if not self.showhistory.size():
|
||||
return
|
||||
|
||||
selected = self.showhistory.curselection()
|
||||
item = self.showhistory.get(selected)
|
||||
#update module
|
||||
self.txt_module.delete(0, END)
|
||||
self.txt_module.insert(0, item)
|
||||
|
||||
def refresh_msg_window(self):
|
||||
"""refresh the message window with current output"""
|
||||
#clear the window
|
||||
self.lb_messages.delete(0, END)
|
||||
self.visible_msgs = []
|
||||
for msg in self.msgs:
|
||||
if self.msg_type_dict.get(msg.C)():
|
||||
self.visible_msgs.append(msg)
|
||||
msg_str = convert_to_string(msg)
|
||||
self.lb_messages.insert(END, msg_str)
|
||||
fg_color = COLORS.get(msg_str[:3], 'black')
|
||||
self.lb_messages.itemconfigure(END, fg=fg_color)
|
||||
|
||||
def refresh_results_window(self):
|
||||
"""refresh the results window with current output"""
|
||||
#clear the window
|
||||
self.results.delete(0, END)
|
||||
try:
|
||||
for res in self.tabs[self.box.get()]:
|
||||
self.results.insert(END, res)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def process_incoming(self):
|
||||
"""process the incoming messages from running pylint"""
|
||||
while self.msg_queue.qsize():
|
||||
try:
|
||||
msg = self.msg_queue.get(0)
|
||||
if msg == "DONE":
|
||||
self.report_stream.output_contents()
|
||||
return False
|
||||
|
||||
#adding message to list of msgs
|
||||
self.msgs.append(msg)
|
||||
|
||||
#displaying msg if message type is selected in check box
|
||||
if self.msg_type_dict.get(msg.C)():
|
||||
self.visible_msgs.append(msg)
|
||||
msg_str = convert_to_string(msg)
|
||||
self.lb_messages.insert(END, msg_str)
|
||||
fg_color = COLORS.get(msg_str[:3], 'black')
|
||||
self.lb_messages.itemconfigure(END, fg=fg_color)
|
||||
|
||||
except six.moves.queue.Empty:
|
||||
pass
|
||||
return True
|
||||
|
||||
def periodic_call(self):
|
||||
"""determine when to unlock the run button"""
|
||||
if self.process_incoming():
|
||||
self.root.after(100, self.periodic_call)
|
||||
else:
|
||||
#enabling button so it can be run again
|
||||
self.btnRun.config(state=NORMAL)
|
||||
|
||||
def mainloop(self):
|
||||
"""launch the mainloop of the application"""
|
||||
self.root.mainloop()
|
||||
|
||||
def quit(self, _=None):
|
||||
"""quit the application"""
|
||||
self.root.quit()
|
||||
|
||||
def halt(self): # pylint: disable=no-self-use
|
||||
"""program halt placeholder"""
|
||||
return
|
||||
|
||||
def file_open(self, package=False, _=None):
|
||||
"""launch a file browser"""
|
||||
if not package:
|
||||
filename = askopenfilename(parent=self.root,
|
||||
filetypes=[('pythonfiles', '*.py'),
|
||||
('allfiles', '*')],
|
||||
title='Select Module')
|
||||
else:
|
||||
filename = askdirectory(title="Select A Folder", mustexist=1)
|
||||
|
||||
if filename == ():
|
||||
return
|
||||
|
||||
self.txt_module.delete(0, END)
|
||||
self.txt_module.insert(0, filename)
|
||||
|
||||
def update_filenames(self):
|
||||
"""update the list of recent filenames"""
|
||||
filename = self.txt_module.get()
|
||||
if not filename:
|
||||
filename = os.getcwd()
|
||||
if filename+'\n' in self.filenames:
|
||||
index = self.filenames.index(filename+'\n')
|
||||
self.filenames.pop(index)
|
||||
|
||||
#ensure only 10 most recent are stored
|
||||
if len(self.filenames) == 10:
|
||||
self.filenames.pop()
|
||||
self.filenames.insert(0, filename+'\n')
|
||||
|
||||
def set_history_window(self):
|
||||
"""update the history window with info from the history file"""
|
||||
#clear the window
|
||||
self.showhistory.delete(0, END)
|
||||
# keep the last 10 most recent files
|
||||
try:
|
||||
view_history = open(HOME+HISTORY, 'r')
|
||||
for hist in view_history.readlines():
|
||||
if hist not in self.filenames:
|
||||
self.filenames.append(hist)
|
||||
self.showhistory.insert(END, hist.split('\n')[0])
|
||||
view_history.close()
|
||||
except IOError:
|
||||
# do nothing since history file will be created later
|
||||
return
|
||||
|
||||
def run_lint(self, _=None):
|
||||
"""launches pylint"""
|
||||
self.update_filenames()
|
||||
self.root.configure(cursor='watch')
|
||||
self.reporter = GUIReporter(self, output=self.report_stream)
|
||||
module = self.txt_module.get()
|
||||
if not module:
|
||||
module = os.getcwd()
|
||||
|
||||
#cleaning up msgs and windows
|
||||
self.msgs = []
|
||||
self.visible_msgs = []
|
||||
self.lb_messages.delete(0, END)
|
||||
self.tabs = {}
|
||||
self.results.delete(0, END)
|
||||
self.btnRun.config(state=DISABLED)
|
||||
|
||||
#setting up a worker thread to run pylint
|
||||
worker = Thread(target=lint_thread, args=(module, self.reporter, self,))
|
||||
self.periodic_call()
|
||||
worker.start()
|
||||
|
||||
# Overwrite the .pylint-gui-history file with all the new recently added files
|
||||
# in order from filenames but only save last 10 files
|
||||
write_history = open(HOME+HISTORY, 'w')
|
||||
write_history.writelines(self.filenames)
|
||||
write_history.close()
|
||||
self.set_history_window()
|
||||
|
||||
self.root.configure(cursor='')
|
||||
|
||||
def show_sourcefile(self, event=None): # pylint: disable=unused-argument
|
||||
selected = self.lb_messages.curselection()
|
||||
if not selected:
|
||||
return
|
||||
|
||||
msg = self.visible_msgs[int(selected[0])]
|
||||
scroll = msg.line - 3
|
||||
if scroll < 0:
|
||||
scroll = 0
|
||||
|
||||
self.tabs["Source File"] = open(msg.path, "r").readlines()
|
||||
self.box.set("Source File")
|
||||
self.refresh_results_window()
|
||||
self.results.yview(scroll)
|
||||
self.results.select_set(msg.line - 1)
|
||||
|
||||
|
||||
def lint_thread(module, reporter, gui):
|
||||
"""thread for pylint"""
|
||||
gui.status.text = "processing module(s)"
|
||||
pylint.lint.Run(args=[module], reporter=reporter, exit=False)
|
||||
gui.msg_queue.put("DONE")
|
||||
|
||||
|
||||
def Run(args):
|
||||
"""launch pylint gui from args"""
|
||||
if args:
|
||||
print('USAGE: pylint-gui\n launch a simple pylint gui using Tk')
|
||||
sys.exit(1)
|
||||
gui = LintGui()
|
||||
gui.mainloop()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
Run(sys.argv[1:])
|
|
@ -1,30 +0,0 @@
|
|||
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
|
||||
|
||||
""" reporter used by gui.py """
|
||||
|
||||
import sys
|
||||
|
||||
from pylint.interfaces import IReporter
|
||||
from pylint.reporters import BaseReporter
|
||||
from pylint.reporters.ureports.text_writer import TextWriter
|
||||
|
||||
|
||||
class GUIReporter(BaseReporter):
|
||||
"""saves messages"""
|
||||
|
||||
__implements__ = IReporter
|
||||
extension = ''
|
||||
|
||||
def __init__(self, gui, output=sys.stdout):
|
||||
"""init"""
|
||||
BaseReporter.__init__(self, output)
|
||||
self.gui = gui
|
||||
|
||||
def handle_message(self, msg):
|
||||
"""manage message of different type and in the context of path"""
|
||||
self.gui.msg_queue.put(msg)
|
||||
|
||||
def _display(self, layout):
|
||||
"""launch layouts display"""
|
||||
TextWriter().format(layout, self.out)
|
1
setup.py
1
setup.py
|
@ -149,7 +149,6 @@ def install(**kwargs):
|
|||
kwargs['dependency_links'] = dependency_links
|
||||
kwargs['entry_points'] = {'console_scripts': [
|
||||
'pylint = pylint:run_pylint',
|
||||
'pylint-gui = pylint:run_pylint_gui',
|
||||
'epylint = pylint:run_epylint',
|
||||
'pyreverse = pylint:run_pyreverse',
|
||||
'symilar = pylint:run_symilar',
|
||||
|
|
Loading…
Reference in New Issue
Block a user