diff -r 8734e881c400 Lib/idlelib/Checker.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/Checker.py Sun Jun 29 23:56:41 2014 +0530 @@ -0,0 +1,194 @@ +import tkinter as tk +from os import path +from subprocess import Popen, PIPE +from tempfile import NamedTemporaryFile +from idlelib.configHandler import idleConf +from idlelib.dynOptionMenuWidget import DynOptionMenu +from idlelib.OutputWindow import OutputWindow + +def get_checkers_list(): + checkers = idleConf.GetSectionList('user', 'checker') + return checkers + +def get_enabled_checkers(): + return [c for c in get_checkers_list() if idleConf.GetOption( + 'checker', c, 'enabled', type='bool')] + +def get_checker_config(checker): + """Return all config key/value pairs for 'checker'""" + config = {} + config['enabled'] = idleConf.GetOption( + 'checker', checker, 'enabled', type='bool') + config['additional_args'] = idleConf.GetOption( + 'checker', checker, 'additional_args') + return config + +class Checker: + + menudefs = [ + ('run', [None, + ('Config Checkers', '<>'), + ] + ) + ] + + def __init__(self, editwin): + self.editwin = editwin + self.update_menu() + + def config_checker_event(self, event): + self.checker = tk.StringVar(self.editwin.top) + self.checker.set('') + self.name = tk.StringVar(self.editwin.top) + self.enabled = tk.StringVar(self.editwin.top) + self.additional = tk.StringVar(self.editwin.top) + self.create_widgets() + + def create_widgets(self): + parent = self.editwin.top + dialog = tk.Toplevel(parent) + dialog.configure(borderwidth=5) + dialog.geometry("+%d+%d" % (parent.winfo_rootx() + 30, + parent.winfo_rooty() + 30)) + dialog.transient(parent) + # frames creation + displayFrame = tk.Frame(dialog) + modifyFrame = tk.Frame(dialog) + + # displayFrame + nameLabel = tk.Label(displayFrame, text='name') + additionalLabel = tk.Label(displayFrame, text='additional args') + self.nameEntry = tk.Entry(displayFrame, textvariable=self.name) + self.enabledCheckbutton = tk.Checkbutton(displayFrame, text="Enable?", + variable=self.enabled) + self.additionalEntry = tk.Entry(displayFrame, + textvariable=self.additional) + + # modifyFrame + self.checkersOptionMenu = DynOptionMenu(modifyFrame, self.checker, '', + *get_checkers_list(), command=self.update_entries) + addChecker = tk.Button(modifyFrame, command=self.add_checker, + text='Add/Update checker') + removeChecker = tk.Button(modifyFrame, command=self.remove_checker, + text='Remove checker') + testRun = tk.Button(modifyFrame, text='Test Run', + command=lambda: self.run_checker(self.name.get())) + # frame packing + displayFrame.pack() + modifyFrame.pack() + # displayFrame packing + nameLabel.pack(side=tk.TOP, anchor=tk.E) + self.nameEntry.pack(anchor=tk.E) + self.enabledCheckbutton.pack(anchor=tk.E) + additionalLabel.pack(side=tk.TOP, anchor=tk.E) + self.additionalEntry.pack(anchor=tk.E) + # modifyFrame packing + self.checkersOptionMenu.pack(side=tk.TOP) + addChecker.pack(side=tk.LEFT) + removeChecker.pack(side=tk.LEFT) + testRun.pack() + + 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) + for checker in get_enabled_checkers(): + label = 'Run {}'.format(checker) + menu.add_command(label=label, command=lambda checker=checker: + self.run_checker(checker)) + + def update_entries(self, event): + """Update all user entries in Config Checkers dialog""" + self.checkersOptionMenu.SetMenu(get_checkers_list()) + self.update_menu() + if not self.checker.get(): + return + config = get_checker_config(self.checker.get()) + self.name.set(self.checker.get()) + self.enabled.set(config['enabled']) + self.additional.set(config['additional_args']) + + def add_checker(self): + if self.checker.get() == '': + pass + idleConf.userCfg['checker'].SetOption( + self.name.get(), 'enabled', self.enabled.get()) + idleConf.userCfg['checker'].SetOption( + self.name.get(), 'additional_args', self.additional.get()) + idleConf.userCfg['checker'].Save() + self.update_entries('event') + + def remove_checker(self): + if self.checker.get() == '': + pass + section = self.name.get() + idleConf.userCfg['checker'].remove_option(section, 'enabled') + idleConf.userCfg['checker'].remove_option(section, 'additional_args') + idleConf.userCfg['checker'].Save() + self.name.set('') + self.enabled.set('') + self.additional.set('') + self.checker.set('') + self.update_entries('event') + + def run_checker(self, checker): + """Run the 3rd party checker 'checker' and display result in a new + outputwindow""" + orig_file = self.editwin.io.filename + if not orig_file: + return + temp_file = NamedTemporaryFile(suffix='.tmp').name + text = self.editwin.text.get('1.0', 'end') + with open(temp_file, 'w') as f: + f.write(text) + additional_args = get_checker_config(checker)['additional_args'] + args = [checker, temp_file, additional_args] + args = [arg for arg in args if arg] + try: + proc = Popen(args, stdout=PIPE, stderr=PIPE) + proc.wait() + output, error = map(lambda b:b.decode('utf-8'), proc.communicate()) + except Exception as e: + output = '' + error = str(e) + output, error = self.process_text(temp_file, output, error) + 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') + + def process_text(self,temp_file, output, error): + orig_file = self.editwin.io.filename + orig_dirname = path.dirname(orig_file) + orig_basename = path.basename(orig_file) + orig_modulename = path.splitext(orig_basename) + + temp_dirname = path.dirname(temp_file) + temp_basename = path.basename(temp_file) + temp_modulename = path.splitext(temp_basename) + + output = output.replace(temp_modulename[0], orig_modulename[0]) + output = output.replace(temp_modulename[1], orig_modulename[1]) + output = output.replace(temp_basename, orig_basename) + output = output.replace(temp_dirname, orig_dirname) + output = output.replace(temp_file, orig_file) + + error = error.replace(temp_modulename[0], orig_modulename[0]) + error = error.replace(temp_modulename[1], orig_modulename[1]) + error = error.replace(temp_basename, orig_basename) + error = error.replace(temp_dirname, orig_dirname) + error = error.replace(temp_file, temp_file) + + return output, error diff -r 8734e881c400 Lib/idlelib/config-extensions.def --- a/Lib/idlelib/config-extensions.def Sun Jun 29 00:46:45 2014 +0200 +++ b/Lib/idlelib/config-extensions.def Sun Jun 29 23:56:41 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 8734e881c400 Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py Sun Jun 29 00:46:45 2014 +0200 +++ b/Lib/idlelib/configHandler.py Sun Jun 29 23:56:41 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]