diff -r 2bbe7dc920de Lib/idlelib/idle.pyw --- a/Lib/idlelib/idle.pyw Sat Dec 10 17:55:31 2011 -0500 +++ b/Lib/idlelib/idle.pyw Sun Dec 11 13:25:00 2011 -0600 @@ -1,3 +1,123 @@ + + +from tkinter import * +class ErrorNotify: + """ A class to display stderr messages when using pythonw.exe. + Otherwise, IDLE will abruptly terminate with no message if an + error occurs. + """ + + root = Tk(className="Idle") + root.withdraw() + + def __init__(self, devnull=False): + self.buffer = [] + self.afterid = None + self.devnull = devnull # for stdout buffer + + def __getattr__(self, *args, **kwargs): + return lambda *args, **kwargs: None + + + def _devnull(func): + def f(self, *args, **kwargs): + if not self.devnull: + return func(self, *args, **kwargs) + else: + return None + return f + + @_devnull + def write(self, txt): + self.buffer.append(txt) + + # auto flush the error buffer 100 ms after last write + if self.afterid is not None: + self.root.after_cancel(self.afterid) + self.afterid = self.root.after(100, self.flush) + + @_devnull + def flush(self, *args, **kwargs): + if self.afterid is not None: + self.root.after_cancel(self.afterid) + try: + self._display() + except Exception as err: + pass # avoid recursive errors - this will only cause problems + + def _display(self): + msg = ''.join(self.buffer) + self.buffer = [] + if msg: + msg += '\n\n**This error may or may not be fatal. ' + msg += 'To be safe, you should save your work.**' + p = self.root + e = self.ErrorViewer(p, 'IDLE Internal Error', msg) + #e.wait_window() # uncomment to catch IDLE exiting errors + + class ErrorViewer(Toplevel): # based on TextViewer from textView.py + def __init__(self, master, title, text): + Toplevel.__init__(self, master=master) + self.withdraw() + self.configure(borderwidth=5) + self.bg = '#ffffff' + self.fg = '#000000' + self.CreateWidgets() + self.title(title) + self.protocol("WM_DELETE_WINDOW", self.Ok) + self.textView.focus_set() + #key bindings for this dialog + self.bind('',self.Ok) #dismiss dialog + self.textView.insert(0.0, text) + self.textView.config(state=DISABLED) + def ontop(self=self): + self.withdraw() + self.deiconify() + self.focus_set() + self.lift() + self.after(100, ontop) + + def CreateWidgets(self): + frameText = Frame(self, relief=SUNKEN, height=700) + frameButtons = Frame(self) + self.buttonOk = Button(frameButtons, text='Ok', + command=self.Ok, takefocus=FALSE) + self.scrollbarView = Scrollbar(frameText, orient=VERTICAL, + takefocus=FALSE, highlightthickness=0) + self.textView = Text(frameText, wrap=WORD, highlightthickness=0, + fg=self.fg, bg=self.bg) + self.scrollbarView.config(command=self.textView.yview) + self.textView.config(yscrollcommand=self.scrollbarView.set) + self.buttonOk.pack() + self.scrollbarView.pack(side=RIGHT,fill=Y) + self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH) + frameButtons.pack(side=BOTTOM,fill=X) + frameText.pack(side=TOP,expand=TRUE,fill=BOTH) + + def Ok(self, event=None): + self.destroy() + + +import sys + +##if 0: # For testing +## sys.__stderr__ = None +## sys.stderr = None + +if sys.__stderr__ is None: + sys.__stderr__ = ErrorNotify() + +if sys.stderr is None: + sys.stderr = ErrorNotify() + +if sys.__stdout__ is None: + sys.__stdout__ = ErrorNotify(devnull=True) + +if sys.stdout is None: + sys.stdout = ErrorNotify(devnull=True) + + + try: import idlelib.PyShell except ImportError: