]> granicus.if.org Git - python/commitdiff
Redirect the warning stream to the shell during the ScriptBinding check of user code
authorKurt B. Kaiser <kbk@shore.net>
Sun, 4 Jul 2004 01:25:56 +0000 (01:25 +0000)
committerKurt B. Kaiser <kbk@shore.net>
Sun, 4 Jul 2004 01:25:56 +0000 (01:25 +0000)
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
Lib/idlelib/PyShell.py
Lib/idlelib/ScriptBinding.py
Lib/idlelib/run.py

index 921c8b7b11427c5ca9891a80945bb7eb26878789..6fb668e562ce9477bc7c14c8d39d23c507f04394 100644 (file)
@@ -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
index 951fde217d917c20a8e704d6313da357ff2d42ca..0ee70d9f86b2bf7e3c2d1ff629af0a06efa7c791 100644 (file)
@@ -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 <pyshell#...> 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",
index a1d937ba0a85965f7fd30785b6e7b7b9d8208929..8ad02a43f222c332751049b3a3dba0ee330f2193 100644 (file)
@@ -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):
index 96da4593b47b3e803de9a28010abe6f58cc2344a..98b8c13030ecdfee1ad2256eb3ab172be84b533b 100644 (file)
@@ -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: