diff --git a/Lib/pdb.py b/Lib/pdb.py index a888a0a287f9c2..081a8449d41096 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -384,8 +384,7 @@ def default(self, line): sys.stdin = save_stdin sys.displayhook = save_displayhook except: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() def precmd(self, line): """Handle alias expansion and ';;' separator.""" @@ -1104,8 +1103,7 @@ def do_debug(self, arg): try: sys.call_tracing(p.run, (arg, globals, locals)) except Exception: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() self.message("LEAVING RECURSIVE DEBUGGER") sys.settrace(self.trace_dispatch) self.lastcmd = p.lastcmd @@ -1163,8 +1161,7 @@ def _getval(self, arg): try: return eval(arg, self.curframe.f_globals, self.curframe_locals) except: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() raise def _getval_except(self, arg, frame=None): @@ -1178,23 +1175,31 @@ def _getval_except(self, arg, frame=None): err = traceback.format_exception_only(*exc_info)[-1].strip() return _rstr('** raised %s **' % err) + def _error_exc(self): + exc_info = sys.exc_info()[:2] + self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + + def _msg_val_func(self, arg, func): + try: + val = self._getval(arg) + except: + return # _getval() has displayed the error + try: + self.message(func(val)) + except: + self._error_exc() + def do_p(self, arg): """p expression Print the value of the expression. """ - try: - self.message(repr(self._getval(arg))) - except: - pass + self._msg_val_func(arg, repr) def do_pp(self, arg): """pp expression Pretty-print the value of the expression. """ - try: - self.message(pprint.pformat(self._getval(arg))) - except: - pass + self._msg_val_func(arg, pprint.pformat) complete_print = _complete_expression complete_p = _complete_expression diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index b1cad22c830ffe..2339bff1a253bf 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -329,6 +329,34 @@ def test_pdb_breakpoint_commands(): """ +def test_pdb_pp_repr_exc(): + """Test that do_p/do_pp do not swallow exceptions. + + >>> class BadRepr: + ... def __repr__(self): + ... raise Exception('repr_exc') + >>> obj = BadRepr() + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'p obj', + ... 'pp obj', + ... 'continue', + ... ]): + ... test_function() + --Return-- + > (2)test_function()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) p obj + *** Exception: repr_exc + (Pdb) pp obj + *** Exception: repr_exc + (Pdb) continue + """ + + def do_nothing(): pass diff --git a/Misc/NEWS.d/next/Library/2020-01-25-12-58-20.bpo-37022.FUZI25.rst b/Misc/NEWS.d/next/Library/2020-01-25-12-58-20.bpo-37022.FUZI25.rst new file mode 100644 index 00000000000000..7b923b3aa6e444 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-01-25-12-58-20.bpo-37022.FUZI25.rst @@ -0,0 +1 @@ +:mod:`pdb` now displays exceptions from ``repr()`` with its ``p`` and ``pp`` commands. \ No newline at end of file