diff -r c76ab5f4fcc1 Lib/idlelib/Checker.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/Checker.py Sat Jul 05 19:59:01 2014 +0530 @@ -0,0 +1,186 @@ +import os +from pkgutil import iter_modules +from distutils.sysconfig import get_python_lib +from importlib import import_module +import tkinter as tk +import tkinter.messagebox as tkMessageBox +from idlelib.OutputWindow import OutputWindow +from idlelib.configHandler import idleConf + +def get_checkers(): + idlecheckers_path = os.path.join(get_python_lib(), 'idlecheckers') + checkers = [c[1][12:] for c in list(iter_modules([idlecheckers_path])) if \ + c[1].startswith('idlechecker_')] + return checkers + +def get_checker_config(checker): + if checker == '': + raise ValueError('Checker name cannot be empty') + config = {} + config['name'] = checker + config['additional'] = idleConf.GetOption('checker', checker,'additional', + default='', warn_on_default=False) + return config + +class Checker: + + menudefs = [ + ('run', [None, + ('Config Checkers', '<>') + ] + ) + ] + + def __init__(self, editwin): + self.editwin = editwin + self.parent = self.editwin.top + self.update_menu() + + def config_checker_event(self, event): + dialog = self.dialog = tk.Toplevel(self.parent) + dialog.transient(self.parent) + dialog.wm_title('Config Checkers') + dialog.geometry('+%d+%d' % (self.parent.winfo_rootx() + 30, + self.parent.winfo_rooty() + 30)) + titleLabel = tk.Label(dialog, text='Configure Checkers') + self.listbox = tk.Listbox(dialog, selectmode=tk.SINGLE) + self.update_listbox() + editButton = tk.Button(dialog, text='Edit Checker', + command=self.edit_checker) + titleLabel.pack() + self.listbox.pack() + editButton.pack(side=tk.LEFT) + + def update_listbox(self): + self.listbox.delete(0, tk.END) + checkers = get_checkers() + for c in checkers: + self.listbox.insert(tk.END, c) + + def _selected_checker(self): + index = self.listbox.curselection() + if index: + checker = self.listbox.get(index) + return checker + else: + return None + + def edit_checker(self): + checker = self._selected_checker() + if checker: + ConfigCheckerDialog(self.editwin, self, checker) + else: + tkMessageBox.showerror(title='No Checker Selected', + message='Select an existing checker to edit', + parent=self.dialog) + + def update_menu(self): + menu = self.editwin.menudict.get('run') + start = menu.index('Config Checkers') + 1 + end = menu.index(tk.END) + if start < end: + menu.delete(start, end) + if start == end: + menu.delete(start) + for checker in get_checkers(): + label = 'Run {}'.format(checker) + menu.add_command(label=label, + command=lambda checker=checker:self.run_checker(checker)) + + def run_checker(self, checker): + """Run the 3rd party checker 'checker'. + If it modifies the editwin buffer, update the editwin text widget + If not, display result in a new CheckerWindow """ #TODO + text = self.editwin.text.get('1.0', 'end') + filename = self.editwin.io.filename or 'Untitled' + additional_args = get_checker_config(checker) + module = import_module('idlecheckers.idlechecker_'+checker) + try: + modifies_buffer = module.modifies_buffer + except AttributeError: + modifies_buffer = False + if modifies_buffer: + text = module.process(text, filename, additional_args) + self.editwin.text.delete('1.0', 'end') + self.editwin.text.insert('1.0', text) + else: + output, error = module.process(text, filename, additional_args) + self.show_result(output, error) + + def show_result(self, output, error): + """Utility method to display 'output' and 'error' in a new + OutputWindow""" + theme = idleConf.CurrentTheme() + stdout = idleConf.GetHighlight(theme, 'stdout') + stderr = idleConf.GetHighlight(theme, 'stderr') + tagdefs = {'stdout':stdout, 'stderr':stderr} + outputwindow = OutputWindow(self.editwin.flist) + for tag, cnf in tagdefs.items(): + outputwindow.text.tag_configure(tag, **cnf) + outputwindow.write(error, 'stderr') + outputwindow.write(output, 'stdout') + + +class ConfigCheckerDialog(tk.Toplevel): + + def __init__(self, editwin, _checker, checker=None): + tk.Toplevel.__init__(self, editwin.top) + self.editwin = editwin + self._checker = _checker + self.checker = checker + self.parent = parent = self.editwin.top + self.additional = tk.StringVar(parent) + self.additional.set('ADDITIONAL ARGS NOT YET IMPLEMENTED') + if checker: + config = get_checker_config(checker) + self.additional.set(config['additional'] or '') + self.grab_set() + self.create_widgets() + + def create_widgets(self): + parent = self.parent + self.configure(borderwidth=5) + title = 'Edit {} checker'.format(self.checker) + self.wm_title(title) + self.geometry('+%d+%d' % (parent.winfo_rootx() + 30, + parent.winfo_rooty() + 30)) + self.transient(parent) + self.focus_set() + # frames creation + optionsFrame = tk.Frame(self) + buttonFrame = tk.Frame(self) + + # optionsFrame + additionalLabel = tk.Label(optionsFrame, text='Additional Args') + + self.additionalEntry = tk.Entry(optionsFrame, + textvariable=self.additional) + # buttonFrame + okButton = tk.Button(buttonFrame, text='Ok', command=self.ok) + cancelButton = tk.Button(buttonFrame, text='Cancel', + command=self.cancel) + + # frames packing + optionsFrame.pack() + buttonFrame.pack() + # optionsFrame packing + additionalLabel.pack() + self.additionalEntry.pack() + # buttonFrame packing + okButton.pack() + cancelButton.pack() + + def ok(self): + name = self.checker + idleConf.userCfg['checker'].SetOption(name, 'additional', + self.additional.get()) + idleConf.userCfg['checker'].Save() + self.close() + + def cancel(self): + self.close() + + def close(self): + self._checker.update_listbox() + self._checker.update_menu() + self.destroy() diff -r c76ab5f4fcc1 Lib/idlelib/config-extensions.def --- a/Lib/idlelib/config-extensions.def Fri Jul 04 15:06:45 2014 +0300 +++ b/Lib/idlelib/config-extensions.def Sat Jul 05 19:59:01 2014 +0530 @@ -94,3 +94,9 @@ enable_shell=0 enable_editor=1 +[Checker] +enable=1 +enable_shell=0 +enable_editor=1 +[Checker_bindings] +config-checker= diff -r c76ab5f4fcc1 Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py Fri Jul 04 15:06:45 2014 +0300 +++ b/Lib/idlelib/configHandler.py Sat Jul 05 19:59:01 2014 +0530 @@ -162,6 +162,7 @@ (user home dir)/.idlerc/config-extensions.cfg (user home dir)/.idlerc/config-highlight.cfg (user home dir)/.idlerc/config-keys.cfg + (user home dir)/.idlerc/config-checker.cfg """ def __init__(self): self.defaultCfg={} @@ -182,7 +183,7 @@ else: # we were exec'ed (for testing only) idleDir=os.path.abspath(sys.path[0]) userDir=self.GetUserCfgDir() - configTypes=('main','extensions','highlight','keys') + configTypes=('main','extensions','highlight','keys', 'checker') defCfgFiles={} usrCfgFiles={} for cfgType in configTypes: #build config file names @@ -282,9 +283,11 @@ Get a list of sections from either the user or default config for the given config type. configSet must be either 'user' or 'default' - configType must be one of ('main','extensions','highlight','keys') + configType must be one of ('main','extensions','highlight','keys', + 'checker') """ - if not (configType in ('main','extensions','highlight','keys')): + if not (configType in ('main','extensions','highlight','keys', + 'checker')): raise InvalidConfigType('Invalid configType specified') if configSet == 'user': cfgParser=self.userCfg[configType]