Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Lib/idlelib/idle_test/test_runscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,44 @@ def test_run_module_event_shell_busy_no_restart(self):
interp.runcode.assert_not_called()
ew._close()

def test_checksyntax_reports_error_in_shell(self):
ew = EditorWindow(root=self.root)
self.addCleanup(ew._close)

sb = runscript.ScriptBinding(ew)
shell = mock.Mock()
sb.flist = mock.Mock()
sb.flist.open_shell.return_value = shell

source = b"def hello()\n print('hello')\n"

with (
mock.patch("builtins.open", mock.mock_open(read_data=source)),
mock.patch.object(sb, "errorbox") as errorbox,
mock.patch.object(ew, "colorize_syntax_error") as colorize,
):
result = sb.checksyntax("example.py")
self.assertFalse(result)

# The Shell receives the complete syntax diagnostic.
output = ''.join(
call.args[0] for call in shell.stderr.write.call_args_list
)
self.assertIn("example.py", output)
self.assertIn("line 1", output)
self.assertIn("def hello()", output)
self.assertIn("^", output)
self.assertIn("SyntaxError: expected ':'", output)

# No modal error dialog.
errorbox.assert_not_called()

# Preserve error highlighting in the editor.
colorize.assert_called_once()
# Make the Shell visible and focus it.
shell.top.lift.assert_called_once()
shell.text.focus_set.assert_called_once()


if __name__ == '__main__':
unittest.main(verbosity=2)
10 changes: 8 additions & 2 deletions Lib/idlelib/runscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import tabnanny
import time
import tokenize
import traceback

from tkinter import messagebox

Expand Down Expand Up @@ -94,14 +95,19 @@ def checksyntax(self, filename):
# If successful, return the compiled code
return compile(source, filename, "exec")
except SyntaxError as value:
msg = value.msg or "<no detail available>"
lineno = value.lineno or 1
offset = value.offset or 0
if offset == 0:
lineno += 1 #mark end of offending line
pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
editwin.colorize_syntax_error(text, pos)
self.errorbox(type(value).__name__, msg)

shell.stderr.write(
''.join(traceback.format_exception_only(value))
)
shell.text.see("end")
shell.top.lift()
shell.text.focus_set()
return False
except Exception as value:
msg = str(value) or "<no detail available>"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IDLE now displays detailed syntax error diagnostics in the Shell instead of a modal dialog, while preserving error highlighting in the editor.
Loading