mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
gh-128231: Use runcode()
return value for failing early (GH-129488)
This commit is contained in:
parent
9f25c1f012
commit
7ed3dc6392
5 changed files with 40 additions and 3 deletions
|
@ -152,6 +152,8 @@ class Console(ABC):
|
||||||
|
|
||||||
|
|
||||||
class InteractiveColoredConsole(code.InteractiveConsole):
|
class InteractiveColoredConsole(code.InteractiveConsole):
|
||||||
|
STATEMENT_FAILED = object()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
locals: dict[str, object] | None = None,
|
locals: dict[str, object] | None = None,
|
||||||
|
@ -173,6 +175,16 @@ class InteractiveColoredConsole(code.InteractiveConsole):
|
||||||
limit=traceback.BUILTIN_EXCEPTION_LIMIT)
|
limit=traceback.BUILTIN_EXCEPTION_LIMIT)
|
||||||
self.write(''.join(lines))
|
self.write(''.join(lines))
|
||||||
|
|
||||||
|
def runcode(self, code):
|
||||||
|
try:
|
||||||
|
exec(code, self.locals)
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except BaseException:
|
||||||
|
self.showtraceback()
|
||||||
|
return self.STATEMENT_FAILED
|
||||||
|
return None
|
||||||
|
|
||||||
def runsource(self, source, filename="<input>", symbol="single"):
|
def runsource(self, source, filename="<input>", symbol="single"):
|
||||||
try:
|
try:
|
||||||
tree = self.compile.compiler(
|
tree = self.compile.compiler(
|
||||||
|
@ -209,5 +221,7 @@ class InteractiveColoredConsole(code.InteractiveConsole):
|
||||||
if code is None:
|
if code is None:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.runcode(code)
|
result = self.runcode(code)
|
||||||
|
if result is self.STATEMENT_FAILED:
|
||||||
|
break
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -75,7 +75,7 @@ class AsyncIOInteractiveConsole(InteractiveColoredConsole):
|
||||||
self.write("\nKeyboardInterrupt\n")
|
self.write("\nKeyboardInterrupt\n")
|
||||||
else:
|
else:
|
||||||
self.showtraceback()
|
self.showtraceback()
|
||||||
|
return self.STATEMENT_FAILED
|
||||||
|
|
||||||
class REPLThread(threading.Thread):
|
class REPLThread(threading.Thread):
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,19 @@ class TestSimpleInteract(unittest.TestCase):
|
||||||
self.assertFalse(more)
|
self.assertFalse(more)
|
||||||
self.assertEqual(f.getvalue(), "1\n")
|
self.assertEqual(f.getvalue(), "1\n")
|
||||||
|
|
||||||
|
@force_not_colorized
|
||||||
|
def test_multiple_statements_fail_early(self):
|
||||||
|
console = InteractiveColoredConsole()
|
||||||
|
code = dedent("""\
|
||||||
|
raise Exception('foobar')
|
||||||
|
print('spam&eggs')
|
||||||
|
""")
|
||||||
|
f = io.StringIO()
|
||||||
|
with contextlib.redirect_stderr(f):
|
||||||
|
console.runsource(code)
|
||||||
|
self.assertIn('Exception: foobar', f.getvalue())
|
||||||
|
self.assertNotIn('spam&eggs', f.getvalue())
|
||||||
|
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
namespace = {}
|
namespace = {}
|
||||||
code = ""
|
code = ""
|
||||||
|
|
|
@ -294,7 +294,15 @@ class TestInteractiveModeSyntaxErrors(unittest.TestCase):
|
||||||
self.assertEqual(traceback_lines, expected_lines)
|
self.assertEqual(traceback_lines, expected_lines)
|
||||||
|
|
||||||
|
|
||||||
class TestAsyncioREPLContextVars(unittest.TestCase):
|
class TestAsyncioREPL(unittest.TestCase):
|
||||||
|
def test_multiple_statements_fail_early(self):
|
||||||
|
user_input = "1 / 0; print('afterwards')"
|
||||||
|
p = spawn_repl("-m", "asyncio")
|
||||||
|
p.stdin.write(user_input)
|
||||||
|
output = kill_python(p)
|
||||||
|
self.assertIn("ZeroDivisionError", output)
|
||||||
|
self.assertNotIn("afterwards", output)
|
||||||
|
|
||||||
def test_toplevel_contextvars_sync(self):
|
def test_toplevel_contextvars_sync(self):
|
||||||
user_input = dedent("""\
|
user_input = dedent("""\
|
||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Execution of multiple statements in the new REPL now stops immediately upon
|
||||||
|
the first exception encountered. Patch by Bartosz Sławecki.
|
Loading…
Add table
Add a link
Reference in a new issue