aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2021-01-26 16:24:14 -0800
committerGitHub <noreply@github.com>2021-01-26 16:24:14 -0800
commit68102fb9987338a70d69a0162917866e5710458d (patch)
tree9b47c4b72be2daa2b01823359c7dda35863b3f00
parent[3.9] bpo-41841: Prepare IDLE NEWS for 3.9.2 (#GH-4343) (diff)
downloadcpython-68102fb9987338a70d69a0162917866e5710458d.tar.gz
cpython-68102fb9987338a70d69a0162917866e5710458d.tar.bz2
cpython-68102fb9987338a70d69a0162917866e5710458d.zip
bpo-43008: Make IDLE respect sys.excepthook (GH-24302)
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu> (cherry picked from commit 7a34380ad788886f5ad50d4175ceb2d5715b8cff) Co-authored-by: Ken <kenny2minecraft@gmail.com>
-rw-r--r--Doc/library/idle.rst2
-rw-r--r--Lib/idlelib/NEWS.txt3
-rw-r--r--Lib/idlelib/idle_test/test_run.py43
-rw-r--r--Lib/idlelib/run.py27
-rw-r--r--Misc/NEWS.d/next/IDLE/2021-01-26-18-12-17.bpo-43008.mbQUc7.rst1
5 files changed, 63 insertions, 13 deletions
diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst
index a59a5d3a465..e7eaabd8bfa 100644
--- a/Doc/library/idle.rst
+++ b/Doc/library/idle.rst
@@ -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.
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index f9b09ed25df..2c52295e418 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -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
diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py
index 37c0d4525e5..a31671ee048 100644
--- a/Lib/idlelib/idle_test/test_run.py
+++ b/Lib/idlelib/idle_test/test_run.py
@@ -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)
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index ec575c3d483..07e9a2bf9ce 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -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
index 00000000000..3e0b80a909d
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2021-01-26-18-12-17.bpo-43008.mbQUc7.rst
@@ -0,0 +1 @@
+Make IDLE invoke :func:`sys.excepthook` in normal, 2-process mode.