mirror of https://github.com/python/cpython
bpo-37022: Fix bug where pdb's do_p/do_pp commands swallow exceptions from repr (GH-18180)
This commit is contained in:
parent
8a4f0850d7
commit
6544b2532d
33
Lib/pdb.py
33
Lib/pdb.py
|
@ -384,8 +384,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
sys.stdin = save_stdin
|
sys.stdin = save_stdin
|
||||||
sys.displayhook = save_displayhook
|
sys.displayhook = save_displayhook
|
||||||
except:
|
except:
|
||||||
exc_info = sys.exc_info()[:2]
|
self._error_exc()
|
||||||
self.error(traceback.format_exception_only(*exc_info)[-1].strip())
|
|
||||||
|
|
||||||
def precmd(self, line):
|
def precmd(self, line):
|
||||||
"""Handle alias expansion and ';;' separator."""
|
"""Handle alias expansion and ';;' separator."""
|
||||||
|
@ -1104,8 +1103,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
try:
|
try:
|
||||||
sys.call_tracing(p.run, (arg, globals, locals))
|
sys.call_tracing(p.run, (arg, globals, locals))
|
||||||
except Exception:
|
except Exception:
|
||||||
exc_info = sys.exc_info()[:2]
|
self._error_exc()
|
||||||
self.error(traceback.format_exception_only(*exc_info)[-1].strip())
|
|
||||||
self.message("LEAVING RECURSIVE DEBUGGER")
|
self.message("LEAVING RECURSIVE DEBUGGER")
|
||||||
sys.settrace(self.trace_dispatch)
|
sys.settrace(self.trace_dispatch)
|
||||||
self.lastcmd = p.lastcmd
|
self.lastcmd = p.lastcmd
|
||||||
|
@ -1163,8 +1161,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
try:
|
try:
|
||||||
return eval(arg, self.curframe.f_globals, self.curframe_locals)
|
return eval(arg, self.curframe.f_globals, self.curframe_locals)
|
||||||
except:
|
except:
|
||||||
exc_info = sys.exc_info()[:2]
|
self._error_exc()
|
||||||
self.error(traceback.format_exception_only(*exc_info)[-1].strip())
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _getval_except(self, arg, frame=None):
|
def _getval_except(self, arg, frame=None):
|
||||||
|
@ -1178,23 +1175,31 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
err = traceback.format_exception_only(*exc_info)[-1].strip()
|
err = traceback.format_exception_only(*exc_info)[-1].strip()
|
||||||
return _rstr('** raised %s **' % err)
|
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):
|
def do_p(self, arg):
|
||||||
"""p expression
|
"""p expression
|
||||||
Print the value of the expression.
|
Print the value of the expression.
|
||||||
"""
|
"""
|
||||||
try:
|
self._msg_val_func(arg, repr)
|
||||||
self.message(repr(self._getval(arg)))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def do_pp(self, arg):
|
def do_pp(self, arg):
|
||||||
"""pp expression
|
"""pp expression
|
||||||
Pretty-print the value of the expression.
|
Pretty-print the value of the expression.
|
||||||
"""
|
"""
|
||||||
try:
|
self._msg_val_func(arg, pprint.pformat)
|
||||||
self.message(pprint.pformat(self._getval(arg)))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
complete_print = _complete_expression
|
complete_print = _complete_expression
|
||||||
complete_p = _complete_expression
|
complete_p = _complete_expression
|
||||||
|
|
|
@ -391,6 +391,34 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions():
|
||||||
(Pdb) continue
|
(Pdb) continue
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
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--
|
||||||
|
> <doctest test.test_pdb.test_pdb_pp_repr_exc[2]>(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():
|
def do_nothing():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
:mod:`pdb` now displays exceptions from ``repr()`` with its ``p`` and ``pp`` commands.
|
Loading…
Reference in New Issue