]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-43008: Make IDLE respect sys.excepthook (GH-24302)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 27 Jan 2021 00:24:30 +0000 (16:24 -0800)
committerGitHub <noreply@github.com>
Wed, 27 Jan 2021 00:24:30 +0000 (16:24 -0800)
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
(cherry picked from commit 7a34380ad788886f5ad50d4175ceb2d5715b8cff)

Co-authored-by: Ken <kenny2minecraft@gmail.com>
Doc/library/idle.rst
Lib/idlelib/NEWS.txt
Lib/idlelib/idle_test/test_run.py
Lib/idlelib/run.py
Misc/NEWS.d/next/IDLE/2021-01-26-18-12-17.bpo-43008.mbQUc7.rst [new file with mode: 0644]

index a59a5d3a465703c1a09c3e518626e903e47bc8fd..e7eaabd8bfa25a209c1ab9cc38cb59cb57dbb341 100644 (file)
@@ -250,7 +250,7 @@ View Last Restart
   Scroll the shell window to the last Shell restart.
 
 Restart Shell
-  Restart the shell to clean the environment.
+  Restart the shell to clean the environment and reset display and exception handling.
 
 Previous History
   Cycle through earlier commands in history which match the current entry.
index c122e596b5cb16ab13db39af26f8f002f6aa1590..0affc55da8f0ad5f7f87e8ae71929a38f1984456 100644 (file)
@@ -3,6 +3,9 @@ Released on 2021-02-15?
 ======================================
 
 
+bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal,
+2-process mode.
+
 bpo-33065: Fix problem debugging user classes with __repr__ method.
 
 bpo-32631: Finish zzdummy example extension module: make menu entries
index 37c0d4525e56cd99566e4cbf4fe499a39b7b080b..a31671ee0485fa4e04c305426c0643502bc2cac9 100644 (file)
@@ -1,16 +1,18 @@
 "Test run, coverage 49%."
 
 from idlelib import run
+import io
+import sys
+from test.support import captured_output, captured_stderr
 import unittest
 from unittest import mock
+import idlelib
 from idlelib.idle_test.mock_idle import Func
-from test.support import captured_output, captured_stderr
 
-import io
-import sys
+idlelib.testing = True  # Use {} for executing test user code.
 
 
-class RunTest(unittest.TestCase):
+class PrintExceptionTest(unittest.TestCase):
 
     def test_print_exception_unhashable(self):
         class UnhashableException(Exception):
@@ -351,5 +353,38 @@ class HandleErrorTest(unittest.TestCase):
             self.assertIn('IndexError', msg)
             eq(func.called, 2)
 
+
+class ExecRuncodeTest(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.addClassCleanup(setattr,run,'print_exception',run.print_exception)
+        cls.prt = Func()  # Need reference.
+        run.print_exception = cls.prt
+        mockrpc = mock.Mock()
+        mockrpc.console.getvar = Func(result=False)
+        cls.ex = run.Executive(mockrpc)
+
+    @classmethod
+    def tearDownClass(cls):
+        assert sys.excepthook == sys.__excepthook__
+
+    def test_exceptions(self):
+        ex = self.ex
+        ex.runcode('1/0')
+        self.assertIs(ex.user_exc_info[0], ZeroDivisionError)
+
+        self.addCleanup(setattr, sys, 'excepthook', sys.__excepthook__)
+        sys.excepthook = lambda t, e, tb: run.print_exception(t)
+        ex.runcode('1/0')
+        self.assertIs(self.prt.args[0], ZeroDivisionError)
+
+        sys.excepthook = lambda: None
+        ex.runcode('1/0')
+        t, e, tb = ex.user_exc_info
+        self.assertIs(t, TypeError)
+        self.assertTrue(isinstance(e.__context__, ZeroDivisionError))
+
+
 if __name__ == '__main__':
     unittest.main(verbosity=2)
index ec575c3d4836315abc0c501ffcd7a40fe26b33d1..07e9a2bf9ceeae1d356e404c58c2247cd43a688f 100644 (file)
@@ -16,6 +16,7 @@ import _thread as thread
 import threading
 import warnings
 
+import idlelib  # testing
 from idlelib import autocomplete  # AutoComplete, fetch_encodings
 from idlelib import calltip  # Calltip
 from idlelib import debugger_r  # start_debugger
@@ -542,14 +543,17 @@ class Executive:
 
     def __init__(self, rpchandler):
         self.rpchandler = rpchandler
-        self.locals = __main__.__dict__
-        self.calltip = calltip.Calltip()
-        self.autocomplete = autocomplete.AutoComplete()
+        if idlelib.testing is False:
+            self.locals = __main__.__dict__
+            self.calltip = calltip.Calltip()
+            self.autocomplete = autocomplete.AutoComplete()
+        else:
+            self.locals = {}
 
     def runcode(self, code):
         global interruptable
         try:
-            self.usr_exc_info = None
+            self.user_exc_info = None
             interruptable = True
             try:
                 exec(code, self.locals)
@@ -562,10 +566,17 @@ class Executive:
                     print('SystemExit: ' + str(ob), file=sys.stderr)
             # Return to the interactive prompt.
         except:
-            self.usr_exc_info = sys.exc_info()
+            self.user_exc_info = sys.exc_info()  # For testing, hook, viewer.
             if quitting:
                 exit()
-            print_exception()
+            if sys.excepthook is sys.__excepthook__:
+                print_exception()
+            else:
+                try:
+                    sys.excepthook(*self.user_exc_info)
+                except:
+                    self.user_exc_info = sys.exc_info()  # For testing.
+                    print_exception()
             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
             if jit:
                 self.rpchandler.interp.open_remote_stack_viewer()
@@ -590,8 +601,8 @@ class Executive:
         return self.autocomplete.fetch_completions(what, mode)
 
     def stackviewer(self, flist_oid=None):
-        if self.usr_exc_info:
-            typ, val, tb = self.usr_exc_info
+        if self.user_exc_info:
+            typ, val, tb = self.user_exc_info
         else:
             return None
         flist = None
diff --git a/Misc/NEWS.d/next/IDLE/2021-01-26-18-12-17.bpo-43008.mbQUc7.rst b/Misc/NEWS.d/next/IDLE/2021-01-26-18-12-17.bpo-43008.mbQUc7.rst
new file mode 100644 (file)
index 0000000..3e0b80a
--- /dev/null
@@ -0,0 +1 @@
+Make IDLE invoke :func:`sys.excepthook` in normal, 2-process mode.