From 49a5fe107fceb0239d87119842b20a7421043b5a Mon Sep 17 00:00:00 2001 From: "Kurt B. Kaiser" Date: Sun, 4 Jul 2004 01:25:56 +0000 Subject: Redirect the warning stream to the shell during the ScriptBinding check of user code and format the warning similarly to an exception for both that check and for warnings raised in the subprocess. M NEWS.txt M Pyshell.py M ScriptBinding.py M run.py --- Lib/idlelib/NEWS.txt | 4 ++++ Lib/idlelib/PyShell.py | 31 ++++++++++++++++++++++++++++--- Lib/idlelib/ScriptBinding.py | 40 +++++++++++++++++++++++----------------- Lib/idlelib/run.py | 17 +++++++++++++++++ 4 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 921c8b7..6fb668e 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,10 @@ What's New in IDLE 1.1a0? *Release date: XX-XXX-2004* +- Redirect the warning stream to the shell during the ScriptBinding check of + user code and format the warning similarly to an exception for both that + check and for runtime warnings raised in the subprocess. + - CodeContext hint pane visibility state is now persistent across sessions. The pane no longer appears in the shell window. Added capability to limit extensions to shell window or editor windows. Noam Raphael addition diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py index 951fde2..0ee70d9 100644 --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -44,16 +44,34 @@ try: except ImportError: SIGTERM = 15 -# Change warnings module to write to sys.__stderr__ +# Override warnings module to write to warning_stream. Initialize to send IDLE +# internal warnings to the console. ScriptBinding.check_syntax() will +# temporarily redirect the stream to the shell window to display warnings when +# checking user's code. +global warning_stream +warning_stream = sys.__stderr__ try: import warnings except ImportError: pass else: def idle_showwarning(message, category, filename, lineno): - file = sys.__stderr__ - file.write(warnings.formatwarning(message, category, filename, lineno)) + file = warning_stream + try: + file.write(warnings.formatwarning(message, category, filename, lineno)) + except IOError: + pass ## file (probably __stderr__) is invalid, warning dropped. warnings.showwarning = idle_showwarning + def idle_formatwarning(message, category, filename, lineno): + """Format warnings the IDLE way""" + s = "\nWarning (from warnings module):\n" + s += ' File \"%s\", line %s\n' % (filename, lineno) + line = linecache.getline(filename, lineno).strip() + if line: + s += " %s\n" % line + s += "%s: %s\n>>> " % (category.__name__, message) + return s + warnings.formatwarning = idle_formatwarning def extended_linecache_checkcache(orig_checkcache=linecache.checkcache): """Extend linecache.checkcache to preserve the entries @@ -815,6 +833,13 @@ class PyShell(OutputWindow): endoffile = False closing = False + def set_warning_stream(self, stream): + global warning_stream + warning_stream = stream + + def get_warning_stream(self): + return warning_stream + def toggle_debugger(self, event=None): if self.executing: tkMessageBox.showerror("Don't debug now", diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py index a1d937b..8ad02a4 100644 --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -82,6 +82,9 @@ class ScriptBinding: return True def checksyntax(self, filename): + self.shell = shell = self.flist.open_shell() + saved_stream = shell.get_warning_stream() + shell.set_warning_stream(shell.stderr) f = open(filename, 'r') source = f.read() f.close() @@ -92,20 +95,23 @@ class ScriptBinding: text = self.editwin.text text.tag_remove("ERROR", "1.0", "end") try: - # If successful, return the compiled code - return compile(source, filename, "exec") - except (SyntaxError, OverflowError), err: try: - msg, (errorfilename, lineno, offset, line) = err - if not errorfilename: - err.args = msg, (filename, lineno, offset, line) - err.filename = filename - self.colorize_syntax_error(msg, lineno, offset) - except: - msg = "*** " + str(err) - self.errorbox("Syntax error", - "There's an error in your program:\n" + msg) - return False + # If successful, return the compiled code + return compile(source, filename, "exec") + except (SyntaxError, OverflowError), err: + try: + msg, (errorfilename, lineno, offset, line) = err + if not errorfilename: + err.args = msg, (filename, lineno, offset, line) + err.filename = filename + self.colorize_syntax_error(msg, lineno, offset) + except: + msg = "*** " + str(err) + self.errorbox("Syntax error", + "There's an error in your program:\n" + msg) + return False + finally: + shell.set_warning_stream(saved_stream) def colorize_syntax_error(self, msg, lineno, offset): text = self.editwin.text @@ -135,10 +141,7 @@ class ScriptBinding: code = self.checksyntax(filename) if not code: return - flist = self.editwin.flist - shell = flist.open_shell() - if not shell: - return # couldn't open the shell + shell = self.shell interp = shell.interp if PyShell.use_subprocess: shell.restart_shell() @@ -156,6 +159,9 @@ class ScriptBinding: del _filename, _sys, _basename, _os \n""" % (filename, dirname)) interp.prepend_syspath(filename) + # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still + # go to __stderr__. With subprocess, they go to the shell. + # Need to change streams in PyShell.ModifiedInterpreter. interp.runcode(code) def getfilename(self): diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 96da459..98b8c13 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,5 +1,6 @@ import sys import os +import linecache import time import socket import traceback @@ -17,6 +18,22 @@ import __main__ LOCALHOST = '127.0.0.1' +try: + import warnings +except ImportError: + pass +else: + def idle_formatwarning_subproc(message, category, filename, lineno): + """Format warnings the IDLE way""" + s = "\nWarning (from warnings module):\n" + s += ' File \"%s\", line %s\n' % (filename, lineno) + line = linecache.getline(filename, lineno).strip() + if line: + s += " %s\n" % line + s += "%s: %s\n" % (category.__name__, message) + return s + warnings.formatwarning = idle_formatwarning_subproc + # Thread shared globals: Establish a queue between a subthread (which handles # the socket) and the main thread (which runs user code), plus global # completion and exit flags: -- cgit v0.12