Skip to content

Commit d519644

Browse files
committed
IDLE: Display syntax errors in Shell instead of dialogs
1 parent e878e1e commit d519644

2 files changed

Lines changed: 46 additions & 2 deletions

File tree

‎Lib/idlelib/idle_test/test_runscript.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,44 @@ def test_run_module_event_shell_busy_no_restart(self):
6262
interp.runcode.assert_not_called()
6363
ew._close()
6464

65+
def test_checksyntax_reports_error_in_shell(self):
66+
ew = EditorWindow(root=self.root)
67+
self.addCleanup(ew._close)
68+
69+
sb = runscript.ScriptBinding(ew)
70+
shell = mock.Mock()
71+
sb.flist = mock.Mock()
72+
sb.flist.open_shell.return_value = shell
73+
74+
source = b"def hello()\n print('hello')\n"
75+
76+
with (
77+
mock.patch("builtins.open", mock.mock_open(read_data=source)),
78+
mock.patch.object(sb, "errorbox") as errorbox,
79+
mock.patch.object(ew, "colorize_syntax_error") as colorize,
80+
):
81+
result = sb.checksyntax("example.py")
82+
self.assertFalse(result)
83+
84+
# The Shell receives the complete syntax diagnostic.
85+
output = ''.join(
86+
call.args[0] for call in shell.stderr.write.call_args_list
87+
)
88+
self.assertIn("example.py", output)
89+
self.assertIn("line 1", output)
90+
self.assertIn("def hello()", output)
91+
self.assertIn("^", output)
92+
self.assertIn("SyntaxError: expected ':'", output)
93+
94+
# No modal error dialog.
95+
errorbox.assert_not_called()
96+
97+
# Preserve error highlighting in the editor.
98+
colorize.assert_called_once()
99+
# Make the Shell visible and focus it.
100+
shell.top.lift.assert_called_once()
101+
shell.text.focus_set.assert_called_once()
102+
65103

66104
if __name__ == '__main__':
67105
unittest.main(verbosity=2)

‎Lib/idlelib/runscript.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import tabnanny
1414
import time
1515
import tokenize
16+
import traceback
1617

1718
from tkinter import messagebox
1819

@@ -94,14 +95,19 @@ def checksyntax(self, filename):
9495
# If successful, return the compiled code
9596
return compile(source, filename, "exec")
9697
except SyntaxError as value:
97-
msg = value.msg or "<no detail available>"
9898
lineno = value.lineno or 1
9999
offset = value.offset or 0
100100
if offset == 0:
101101
lineno += 1 #mark end of offending line
102102
pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
103103
editwin.colorize_syntax_error(text, pos)
104-
self.errorbox(type(value).__name__, msg)
104+
105+
shell.stderr.write(
106+
''.join(traceback.format_exception_only(value))
107+
)
108+
shell.text.see("end")
109+
shell.top.lift()
110+
shell.text.focus_set()
105111
return False
106112
except Exception as value:
107113
msg = str(value) or "<no detail available>"

0 commit comments

Comments
 (0)