mirror of
https://github.com/python/cpython.git
synced 2025-09-30 12:21:51 +00:00
bpo-43008: Make IDLE respect sys.excepthook (GH-24302)
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
(cherry picked from commit 7a34380ad7
)
Co-authored-by: Ken <kenny2minecraft@gmail.com>
This commit is contained in:
parent
fd668bc62b
commit
68102fb998
5 changed files with 65 additions and 15 deletions
|
@ -250,7 +250,7 @@ View Last Restart
|
||||||
Scroll the shell window to the last Shell restart.
|
Scroll the shell window to the last Shell restart.
|
||||||
|
|
||||||
Restart Shell
|
Restart Shell
|
||||||
Restart the shell to clean the environment.
|
Restart the shell to clean the environment and reset display and exception handling.
|
||||||
|
|
||||||
Previous History
|
Previous History
|
||||||
Cycle through earlier commands in history which match the current entry.
|
Cycle through earlier commands in history which match the current entry.
|
||||||
|
|
|
@ -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-33065: Fix problem debugging user classes with __repr__ method.
|
||||||
|
|
||||||
bpo-32631: Finish zzdummy example extension module: make menu entries
|
bpo-32631: Finish zzdummy example extension module: make menu entries
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
"Test run, coverage 49%."
|
"Test run, coverage 49%."
|
||||||
|
|
||||||
from idlelib import run
|
from idlelib import run
|
||||||
import unittest
|
|
||||||
from unittest import mock
|
|
||||||
from idlelib.idle_test.mock_idle import Func
|
|
||||||
from test.support import captured_output, captured_stderr
|
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import sys
|
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
|
||||||
|
|
||||||
|
idlelib.testing = True # Use {} for executing test user code.
|
||||||
|
|
||||||
|
|
||||||
class RunTest(unittest.TestCase):
|
class PrintExceptionTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_print_exception_unhashable(self):
|
def test_print_exception_unhashable(self):
|
||||||
class UnhashableException(Exception):
|
class UnhashableException(Exception):
|
||||||
|
@ -351,5 +353,38 @@ class HandleErrorTest(unittest.TestCase):
|
||||||
self.assertIn('IndexError', msg)
|
self.assertIn('IndexError', msg)
|
||||||
eq(func.called, 2)
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import _thread as thread
|
||||||
import threading
|
import threading
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import idlelib # testing
|
||||||
from idlelib import autocomplete # AutoComplete, fetch_encodings
|
from idlelib import autocomplete # AutoComplete, fetch_encodings
|
||||||
from idlelib import calltip # Calltip
|
from idlelib import calltip # Calltip
|
||||||
from idlelib import debugger_r # start_debugger
|
from idlelib import debugger_r # start_debugger
|
||||||
|
@ -542,14 +543,17 @@ class Executive:
|
||||||
|
|
||||||
def __init__(self, rpchandler):
|
def __init__(self, rpchandler):
|
||||||
self.rpchandler = rpchandler
|
self.rpchandler = rpchandler
|
||||||
|
if idlelib.testing is False:
|
||||||
self.locals = __main__.__dict__
|
self.locals = __main__.__dict__
|
||||||
self.calltip = calltip.Calltip()
|
self.calltip = calltip.Calltip()
|
||||||
self.autocomplete = autocomplete.AutoComplete()
|
self.autocomplete = autocomplete.AutoComplete()
|
||||||
|
else:
|
||||||
|
self.locals = {}
|
||||||
|
|
||||||
def runcode(self, code):
|
def runcode(self, code):
|
||||||
global interruptable
|
global interruptable
|
||||||
try:
|
try:
|
||||||
self.usr_exc_info = None
|
self.user_exc_info = None
|
||||||
interruptable = True
|
interruptable = True
|
||||||
try:
|
try:
|
||||||
exec(code, self.locals)
|
exec(code, self.locals)
|
||||||
|
@ -562,9 +566,16 @@ class Executive:
|
||||||
print('SystemExit: ' + str(ob), file=sys.stderr)
|
print('SystemExit: ' + str(ob), file=sys.stderr)
|
||||||
# Return to the interactive prompt.
|
# Return to the interactive prompt.
|
||||||
except:
|
except:
|
||||||
self.usr_exc_info = sys.exc_info()
|
self.user_exc_info = sys.exc_info() # For testing, hook, viewer.
|
||||||
if quitting:
|
if quitting:
|
||||||
exit()
|
exit()
|
||||||
|
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()
|
print_exception()
|
||||||
jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
|
jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
|
||||||
if jit:
|
if jit:
|
||||||
|
@ -590,8 +601,8 @@ class Executive:
|
||||||
return self.autocomplete.fetch_completions(what, mode)
|
return self.autocomplete.fetch_completions(what, mode)
|
||||||
|
|
||||||
def stackviewer(self, flist_oid=None):
|
def stackviewer(self, flist_oid=None):
|
||||||
if self.usr_exc_info:
|
if self.user_exc_info:
|
||||||
typ, val, tb = self.usr_exc_info
|
typ, val, tb = self.user_exc_info
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
flist = None
|
flist = None
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Make IDLE invoke :func:`sys.excepthook` in normal, 2-process mode.
|
Loading…
Add table
Add a link
Reference in a new issue