cpython/Lib/idlelib/idle_test/test_runscript.py
Miss Islington (bot) e2b711c950
[3.15] gh-69919: Catch all compile errors in the code module, pyrepl and IDLE (GH-157585) (#158025)
gh-69919: Catch all compile errors in the code module, pyrepl and IDLE (GH-157585)

compile() can raise MemoryError or RecursionError for too deeply
nested source, not only SyntaxError, OverflowError and ValueError.
IDLE's Shell then lost its prompt until the input was deleted.
(cherry picked from commit 4bc392c134)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-09 17:17:29 -04:00

67 lines
2.3 KiB
Python

"Test runscript, coverage 16%."
from idlelib import runscript
import unittest
from unittest import mock
from test.support import requires
from tkinter import Tk
from idlelib.editor import EditorWindow
class ScriptBindingTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()
@classmethod
def tearDownClass(cls):
cls.root.update_idletasks()
for id in cls.root.after_info():
cls.root.after_cancel(id) # Need for EditorWindow.
cls.root.destroy()
del cls.root
def test_init(self):
ew = EditorWindow(root=self.root)
sb = runscript.ScriptBinding(ew)
ew._close()
def test_checksyntax_compile_error(self):
# gh-69919: any error raised by compile() is reported.
ew = EditorWindow(root=self.root)
sb = runscript.ScriptBinding(ew)
sb.flist = mock.Mock()
sb.errorbox = mock.Mock()
with (mock.patch('idlelib.runscript.compile', create=True,
side_effect=MemoryError()),
mock.patch('idlelib.runscript.open', mock.mock_open(read_data=b'x\n'))):
self.assertFalse(sb.checksyntax('test.py'))
sb.errorbox.assert_called_once_with('MemoryError', '<no detail available>')
ew._close()
def test_run_module_event_shell_busy_no_restart(self):
# gh-82183: running without restarting the busy shell aborts.
ew = EditorWindow(root=self.root)
sb = runscript.ScriptBinding(ew)
sb.getfilename = mock.Mock(return_value='test.py')
sb.checksyntax = mock.Mock(return_value='code')
sb.tabnanny = mock.Mock(return_value=True)
sb.shell = shell = mock.Mock()
shell.executing = True
interp = shell.interp
with mock.patch.object(runscript, 'CustomRun') as customrun:
# Restart shell unchecked.
customrun.return_value.result = (['arg'], False)
result = sb.run_module_event(None, customize=True)
self.assertEqual(result, 'break')
interp.display_executing_dialog.assert_called_once()
interp.restart_subprocess.assert_not_called()
interp.runcode.assert_not_called()
ew._close()
if __name__ == '__main__':
unittest.main(verbosity=2)