[Python-checkins] bpo-37022: Fix bug where pdb's do_p/do_pp commands swallow exceptions from repr (GH-18180) (GH-26651)

iritkatriel webhook-mailer at python.org
Thu Jun 10 17:24:17 EDT 2021


https://github.com/python/cpython/commit/175ebc60d52f2e88cf5cba5224c15074d2623c10
commit: 175ebc60d52f2e88cf5cba5224c15074d2623c10
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com>
date: 2021-06-10T22:24:03+01:00
summary:

bpo-37022: Fix bug where pdb's do_p/do_pp commands swallow exceptions from repr (GH-18180) (GH-26651)

(cherry picked from commit 6544b2532df82d137b71323445a07a6e29bcdec0)

Co-authored-by: Daniel Hahler <git at thequod.de>

files:
A Misc/NEWS.d/next/Library/2020-01-25-12-58-20.bpo-37022.FUZI25.rst
M Lib/pdb.py
M Lib/test/test_pdb.py

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--
+    > <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():
     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



More information about the Python-checkins mailing list