gh-106670: Allow Pdb to move between chained exceptions#106676
Conversation
|
Addressed some of the comments in the linked issue, rebased pushed, and updated description of this issue to reflect the codebase status. |
Sorry, something went wrong.
gaogaotiantian
left a comment
There was a problem hiding this comment.
Left some comments. For this feature to be merged, you'll need to work on the docs as well (it's a new command). We need review from a core dev, especially on the interface. The main concern I have is about the conflict between backward-compatibility and readability:
def post_mortem(traceback=None):
# We allow(actually prefer) the input traceback to be an Exception.How should we deal with that? Changing the argument name traceback would break some backward compatibility, enforcing the argument to be an Exception would break a lot.
This is a more serious concern for public interfaces, but also on private methods, for example, Pdb.interaction takes a tb argument which can be an Exception now. This is not good for readability.
Could @iritkatriel or @brandtbucher share some thoughts on this? Thanks!
Sorry, something went wrong.
I'm' not a particularly huge fan of the following but we can do: That way we only emit on use that use the keyword way, and this avoid using *args, **kwargs and custom hard to understand logic. Then in N versions you can go to We can try to apply something similar to |
Sorry, something went wrong.
This might be too complicated. I'm personally leaning to the more aggressive way - rename the argument to I did a preliminary search on github with |
Sorry, something went wrong.
gaogaotiantian
left a comment
There was a problem hiding this comment.
I think the overall direction is great and we should have this feature in pdb. However, we do need opinions from core devs, especially for the backward compatibility part. I'll wait for a couple of days and reach out to core devs if no one volunteers :)
Sorry, something went wrong.
|
Thanks for the feedback and patience, I'm back from taking some time off and updated to reflect your comment. I'd appreciate if you can get a core dev review. |
Sorry, something went wrong.
|
Rebased on main (except last commit to allow to just see the changes since I now to a breadth first listing of the context/cause tree of exceptions. I've rephrased the first commit description as well as the PR description to mention I think we could have a better UI to see the chain as a tree when doing |
Sorry, something went wrong.
This lets Pdb receive an exception, instead of a traceback, and when
this is the case and the exception are chained, the new `exceptions` command
allows to both list (no arguments) and move between the chained exceptions.
That is to say if you have something like
def out():
try:
middle() # B
except Exception as e:
raise ValueError("foo(): bar failed") # A
def middle():
try:
return inner(0) # D
except Exception as e:
raise ValueError("Middle fail") from e # C
def inner(x):
1 / x # E
Only A was reachable after calling `out()` and doing post mortem debug.
With this all A-E points are reachable with a combination of up/down,
and ``exception <number>``.
This also change the default behavior of ``pdb.pm()``, as well as
`python -m pdb <script.py>` to receive `sys.last_exc` so that chained
exception navigation is enabled.
We do follow the logic of the ``traceback`` module and handle the
``_context__`` and ``__cause__`` in the same way. That is to say, we try
``__cause__`` first, and if not present chain with ``__context__``. In
the same vein, if we encounter an exception that has
``__suppress_context__`` (like when ``raise ... from None``), we do stop
walking the chain.
Some implementation notes:
- We do handle cycle in exceptions
- cleanup of references to tracebacks are not cleared in ``forget()``, as
``setup()`` and ``forget()`` are both for setting a single
exception.
- We do not handle sub-exceptions of exception groups.
Closes pythongh-106670
Also move the release of the list of exception to a context manager for security
iritkatriel
left a comment
There was a problem hiding this comment.
LGTM, just need to resolve the warning in the news file.
Sorry, something went wrong.
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Head branch was pushed to by a user without write access
|
@iritkatriel FYI the latest force-push automatically disabled auto-merge |
Sorry, something went wrong.
|
Thanks all for the reviews and the merge let me know if there is anything I can help with. |
Sorry, something went wrong.
Closes ipython#13982 This is a "backport" of python/cpython#106676 See documentation there
Closes ipython#13982 This is a "backport" of python/cpython#106676 See documentation there
Closes #13982 This is a "backport" of python/cpython#106676 See documentation there
The introduction of chained exception in pythongh-106676 would lead to File .../Lib/pdb.py", line 298, in setup self.curframe = self.stack[self.curindex][0] ~~~~~~~~~~^^^^^^^^^^^^^^^ IndexError: list index out of range This fixes that by filtering exceptions that that do not have a stack. Update tests to not use stack-less exceptions when testing another feature, and add an explicit test on how we handle stackless exceptions.
The introduction of chained exception in pythongh-106676 would lead to File .../Lib/pdb.py", line 298, in setup self.curframe = self.stack[self.curindex][0] ~~~~~~~~~~^^^^^^^^^^^^^^^ IndexError: list index out of range This fixes that by filtering exceptions that that do not have a stack. Update tests to not use stack-less exceptions when testing another feature, and add an explicit test on how we handle stackless exceptions.
The introduction of chained exception in pythongh-106676 would lead to File .../Lib/pdb.py", line 298, in setup self.curframe = self.stack[self.curindex][0] ~~~~~~~~~~^^^^^^^^^^^^^^^ IndexError: list index out of range This fixes that by filtering exceptions that that do not have a stack. Update tests to not use stack-less exceptions when testing another feature, and add an explicit test on how we handle stackless exceptions.
The introduction of chained exception in pythongh-106676 would sometime lead to File .../Lib/pdb.py", line 298, in setup self.curframe = self.stack[self.curindex][0] ~~~~~~~~~~^^^^^^^^^^^^^^^ IndexError: list index out of range This fixes that by filtering exceptions that that do not have a stack/traceback. Update tests to not use stack-less exceptions when testing another feature, and add an explicit test on how we handle stackless exceptions.
|
I seemed to have missed and edge case that make the debugger crash, see #108865 as a followup. |
Sorry, something went wrong.
|
Actually there's a bug in the documentation, it says you can use |
Sorry, something went wrong.
Allow Pdb to move between chained exception.
This lets Pdb receive an exception, instead of a traceback, and when
this is the case and the exception are chained, the new
exceptionscommandallows to both list (no arguments) and move between the chained exceptions.
That is to say if you have something like
Only A was reachable after calling
out()and doing post mortem debug.With this all A-E points are reachable with a combination of up/down,
and
exceptions <number>.This also change the default behavior of
pdb.pm(), as well aspython -m pdb <script.py>to receivesys.last_excso that chainedexception navigation is enabled.
We do follow the logic of the
tracebackmodule and handle the_context__and__cause__in the same way. That is to say, we try__cause__first, and if not present chain with__context__. Inthe same vein, if we encounter an exception that has
__suppress_context__(like whenraise ... from None), we do stopwalking the chain.
Some implementation notes:
forget(), assetup()andforget()are both for setting a singleexception.
context manager.
maximum number we allow
Closes gh-106670