Skip to content
10 changes: 6 additions & 4 deletions Lib/_pyrepl/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,13 @@ def __init__(
super().__init__(locals=locals, filename=filename, local_exit=local_exit) # type: ignore[call-arg]
self.can_colorize = _colorize.can_colorize()

def _showtraceback(self, typ, value, tb, colorize=False, limit=None):
def _excepthook(self, typ, value, tb):
import traceback
return super()._showtraceback(
typ, value, tb, colorize=self.can_colorize,
limit=traceback.BUILTIN_EXCEPTION_LIMIT)
lines = traceback.format_exception(
typ, value, tb,
colorize=self.can_colorize,
limit=traceback.BUILTIN_EXCEPTION_LIMIT)
self.write(''.join(lines))

def runsource(self, source, filename="<input>", symbol="single"):
try:
Expand Down
16 changes: 8 additions & 8 deletions Lib/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,12 @@ def showtraceback(self):
finally:
typ = value = tb = None

def _showtraceback(self, typ, value, tb, colorize=False, limit=None):
# This method is being overwritten in
# _pyrepl.console.InteractiveColoredConsole to pass different values of
# colorize and limit
def _showtraceback(self, typ, value, tb):
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,
limit=limit)
self.write(''.join(lines))
self._excepthook(typ, value, tb)
else:
# If someone has set sys.excepthook, we let that take precedence
# over self.write
Expand All @@ -164,6 +158,12 @@ def _showtraceback(self, typ, value, tb, colorize=False, limit=None):
print('Original exception was:', file=sys.stderr)
sys.__excepthook__(typ, value, tb)

def _excepthook(self, typ, value, tb):
# This method is being overwritten in
# _pyrepl.console.InteractiveColoredConsole
lines = traceback.format_exception(typ, value, tb)
self.write(''.join(lines))

def write(self, data):
"""Write a string.

Expand Down
57 changes: 35 additions & 22 deletions Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ def test_dumb_terminal_exits_cleanly(self):
env.update({"TERM": "dumb"})
output, exit_code = self.run_repl("exit()\n", env=env)
self.assertEqual(exit_code, 0)
self.assertIn("warning: can\'t use pyrepl", output)
self.assertIn("warning: can't use pyrepl", output)
self.assertNotIn("Exception", output)
self.assertNotIn("Traceback", output)

Expand Down Expand Up @@ -1103,27 +1103,40 @@ def test_not_wiping_history_file(self):
@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 <module>", 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 <module>", output)
for set_tracebacklimit in [True, False]:
commands = ("import sys\n" +
("sys.tracebacklimit = 1\n" if set_tracebacklimit else "") +
"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:
Comment thread
cfbolz marked this conversation as resolved.
Outdated
self.skipTest("pyrepl not available")
self.assertIn("in x1", output)
if set_tracebacklimit:
self.assertNotIn("in x2", output)
self.assertNotIn("in x3", output)
self.assertNotIn("in <module>", output)
else:
self.assertIn("in x2", output)
self.assertIn("in x3", output)
self.assertIn("in <module>", output)

env["PYTHON_BASIC_REPL"] = "1"
Comment thread
cfbolz marked this conversation as resolved.
Outdated
output, exit_code = self.run_repl(commands, env=env)
self.assertIn("in x1", output)
if set_tracebacklimit:
self.assertNotIn("in x2", output)
self.assertNotIn("in x3", output)
self.assertNotIn("in <module>", output)
else:
self.assertIn("in x2", output)
self.assertIn("in x3", output)
self.assertIn("in <module>", output)

def run_repl(
self,
Expand Down