Skip to content

Commit

Permalink
pyflyby-dbg: Support chained exceptions
Browse files Browse the repository at this point in the history
This commit adds support of stepping through chained exceptions with
pyflyby debugger.

```
$ cat chained_exc.py
-------------------------------------------------------------
def inner():
    raise ValueError("inner")

def outer():
    try:
        inner()
    except Exception as e:
        raise ValueError("outer") from e

if __name__ == "__main__":
    outer()

--------------------------------------------------------------------------
$ py /u/anis/scratch/chained_exc.py
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~/scratch/chained_exc.py:6, in outer()
      5 try:
----> 6     inner()
      7 except Exception as e:

File ~/scratch/chained_exc.py:2, in inner()
      1 def inner():
----> 2     raise ValueError("inner")

ValueError: inner

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
File ~/scratch/chained_exc.py:11
      8         raise ValueError("outer") from e
     10 if __name__ == "__main__":
---> 11     outer()

File ~/scratch/chained_exc.py:8, in outer()
      6     inner()
      7 except Exception as e:
----> 8     raise ValueError("outer") from e

ValueError: outer
> /u/anis/scratch/chained_exc.py(8)outer()
      6         inner()
      7     except Exception as e:
----> 8         raise ValueError("outer") from e
      9
     10 if __name__ == "__main__":

ipdb> exceptions
    0 ValueError('inner')
>   1 ValueError('outer')
```

The support uses native Ipython's debugger or python's pdb support for
chained exceptions and is available with `exceptions` command under
ipdb/pdb command prompt.

Implementation notes
=============================================================

Starting Py3.13, pdb.interaction() supports chained exceptions in case
exception (and not traceback) is specified. This support is backported
to IPython8.16 for earlier Python versions. So the conditions where
chained exceptions won't be supported from pyflyby's debugger would be with Python
version < 3.13 and ipython is not being installed, or IPython's version is
lesser than 8.16.

Ref: PyInf#14001
Reviewer: dhamodha
  • Loading branch information
Umair Anis committed Nov 25, 2024
1 parent 0435043 commit fdda27e
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion lib/python/pyflyby/_dbg.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,27 @@ def _debug_exception(*exc_info, **kwargs):
# keep the process waiting for debugger to attach.
pdb.postloop = _prompt_continue_waiting_for_debugger
print_verbose_tb(*exc_info)
pdb.interaction(None, exc_info[2])
# Starting Py3.13, pdb.interaction() supports chained exceptions in case
# exception (and not traceback) is specified. This support is backported
# to IPython8.16 for earlier Python versions. So the conditions where
# chained exceptions won't be supported from here would be with the
# Python version < 3.13 and ipython not installed, or IPython's version
# is lesser than 8.16.
tb_or_exc = exc_info[2]
if sys.version_info < (3, 13):
# Check if the instance is of IPython's Pdb and its version.
try:
import IPython
if IPython.__version__ >= '8.16':
from IPython.core.debugger import Pdb as IPdb
# This is expected to be True, hence just a safe check.
if isinstance(pdb, IPdb):
tb_or_exc = exc_info[1]
except ImportError:
pass
else:
tb_or_exc = exc_info[1]
pdb.interaction(None, tb_or_exc)


def _debug_code(arg, globals=None, locals=None, auto_import=True, tty="/dev/tty"):
Expand Down

0 comments on commit fdda27e

Please sign in to comment.