diff --git a/Lib/_pyrepl/console.py b/Lib/_pyrepl/console.py index a8d3f520340dcf..3c9c45bb49440f 100644 --- a/Lib/_pyrepl/console.py +++ b/Lib/_pyrepl/console.py @@ -162,10 +162,12 @@ def __init__( self.can_colorize = _colorize.can_colorize() def showsyntaxerror(self, filename=None): - super().showsyntaxerror(colorize=self.can_colorize) + import traceback + super().showsyntaxerror(colorize=self.can_colorize, limit=traceback.BUILTIN_EXCEPTION_LIMIT) def showtraceback(self): - super().showtraceback(colorize=self.can_colorize) + import traceback + super().showtraceback(colorize=self.can_colorize, limit=traceback.BUILTIN_EXCEPTION_LIMIT) def runsource(self, source, filename="", symbol="single"): try: diff --git a/Lib/code.py b/Lib/code.py index a1fd389b5a1015..755a2f411c6aa5 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -107,6 +107,7 @@ def showsyntaxerror(self, filename=None, **kwargs): """ colorize = kwargs.pop('colorize', False) + limit = kwargs.pop('limit', None) try: typ, value, tb = sys.exc_info() if filename and typ is SyntaxError: @@ -119,7 +120,7 @@ def showsyntaxerror(self, filename=None, **kwargs): else: # Stuff in the right filename value = SyntaxError(msg, (filename, lineno, offset, line)) - self._showtraceback(typ, value, None, colorize) + self._showtraceback(typ, value, None, colorize, limit) finally: typ = value = tb = None @@ -132,19 +133,21 @@ def showtraceback(self, **kwargs): """ colorize = kwargs.pop('colorize', False) + limit = kwargs.pop('limit', None) try: typ, value, tb = sys.exc_info() - self._showtraceback(typ, value, tb.tb_next, colorize) + self._showtraceback(typ, value, tb.tb_next, colorize, limit) finally: typ = value = tb = None - def _showtraceback(self, typ, value, tb, colorize): + def _showtraceback(self, typ, value, tb, colorize, limit): sys.last_type = typ sys.last_traceback = tb sys.last_exc = sys.last_value = value = value.with_traceback(tb) if sys.excepthook is sys.__excepthook__: lines = traceback.format_exception(typ, value, tb, - colorize=colorize) + colorize=colorize, + limit=limit) self.write(''.join(lines)) else: # If someone has set sys.excepthook, we let that take precedence diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index d5eafc5eb58cac..edb5c1bfc3488b 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1100,6 +1100,31 @@ def test_not_wiping_history_file(self): self.assertIn("spam", output) self.assertNotEqual(pathlib.Path(hfile.name).stat().st_size, 0) + @force_not_colorized + def test_proper_tracebacklimit(self): + env = os.environ.copy() + commands = ("import sys\n" + "sys.tracebacklimit = 1\n" + "def x1(): 1/0\n\n" + "def x2(): x1()\n\n" + "def x3(): x2()\n\n" + "x3()\n" + "exit()\n") + + env.pop("PYTHON_BASIC_REPL", None) + output, exit_code = self.run_repl(commands, env=env) + if "can\'t use pyrepl" in output: + self.skipTest("pyrepl not available") + self.assertIn("in x1", output) + self.assertNotIn("in x3", output) + self.assertNotIn("in ", output) + + env["PYTHON_BASIC_REPL"] = "1" + output, exit_code = self.run_repl(commands, env=env) + self.assertIn("in x1", output) + self.assertNotIn("in x3", output) + self.assertNotIn("in ", output) + def run_repl( self, repl_input: str | list[str], diff --git a/Misc/NEWS.d/next/Library/2024-07-31-14-55-41.gh-issue-82378.eZvYmR.rst b/Misc/NEWS.d/next/Library/2024-07-31-14-55-41.gh-issue-82378.eZvYmR.rst new file mode 100644 index 00000000000000..8af016e7c82fcb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-31-14-55-41.gh-issue-82378.eZvYmR.rst @@ -0,0 +1,2 @@ +Make sure that the new :term:`REPL` interprets :data:`sys.tracebacklimit` in +the same way that the classic REPL did.