Skip to content

Commit dc2a5f2

Browse files
committed
Fix SystemError during REPL input compilation corrupting display
1 parent 1d4e965 commit dc2a5f2

6 files changed

Lines changed: 19 additions & 6 deletions

File tree

Lib/_pyrepl/simple_interact.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ def _more_lines(console: code.InteractiveConsole, unicodetext: str) -> bool:
9393
not_empty = last_line.strip() != ""
9494
incomplete = not last_line.endswith("\n")
9595
return (was_indented or not_empty) and incomplete
96+
except SystemError:
97+
return False
9698
else:
9799
return code is None
98100

Lib/code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
6262
"""
6363
try:
6464
code = self.compile(source, filename, symbol)
65-
except (OverflowError, SyntaxError, ValueError):
65+
except (OverflowError, SyntaxError, ValueError, SystemError):
6666
# Case 1
6767
self.showsyntaxerror(filename, source=source)
6868
return False

Lib/codeop.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ def _maybe_compile(compiler, source, filename, symbol, flags):
7171
except SyntaxError:
7272
pass
7373
# fallthrough
74+
except SystemError as exc:
75+
raise exc from None
7476

7577
return compiler(source, filename, symbol, incomplete_input=False)
7678

@@ -147,8 +149,8 @@ def __call__(self, source, filename="<input>", symbol="single"):
147149
148150
- Return a code object if the command is complete and valid
149151
- Return None if the command is incomplete
150-
- Raise SyntaxError, ValueError or OverflowError if the command is a
151-
syntax error (OverflowError and ValueError can be produced by
152-
malformed literals).
152+
- Raise SyntaxError, ValueError, OverflowError or SystemError.
153+
OverflowError and ValueError can be produced by malformed
154+
literals, SystemError if source cannot be compiled.
153155
"""
154156
return _maybe_compile(self.compiler, source, filename, symbol, flags=self.compiler.flags)

Lib/test/test_codeop.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import warnings
77
from test.support import warnings_helper
88
from textwrap import dedent
9+
from unittest.mock import Mock
910

10-
from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT
11+
from codeop import compile_command, _maybe_compile, PyCF_DONT_IMPLY_DEDENT
1112

1213
class CodeopTests(unittest.TestCase):
1314

@@ -325,6 +326,5 @@ def foo(x,x):
325326
"""), "duplicate parameter 'x' in function definition")
326327

327328

328-
329329
if __name__ == "__main__":
330330
unittest.main()

Lib/test/test_pyrepl/test_interact.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,13 @@ def test_incomplete_statement(self):
275275
console = InteractiveColoredConsole(namespace, filename="<stdin>")
276276
self.assertTrue(_more_lines(console, code))
277277

278+
def test_system_error_during_compilation(self):
279+
namespace = {}
280+
console = InteractiveColoredConsole(namespace, filename="<stdin>")
281+
with patch.object(console, "compile", side_effect=SystemError("compiler bug")):
282+
result = _more_lines(console, "some code")
283+
self.assertFalse(result)
284+
278285

279286
class TestWarnings(unittest.TestCase):
280287
def test_pep_765_warning(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :exc:`SystemError` raised during input compilation in the REPL corrupting
2+
the display and leaking :exc:`!_IncompleteInputError` in the exception chain.

0 commit comments

Comments
 (0)