Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-28603: Fix exception chaining for unhashable exceptions #4014

Merged
merged 3 commits into from
Oct 17, 2017

Conversation

zaneb
Copy link
Contributor

@zaneb zaneb commented Oct 16, 2017

Compare exceptions by identity rather than equality when checking for loops in the context/cause chain. This allows unhashable exceptions to be processed without error by the traceback module, and ensures that exception chaining can continue even after encountering either an exception that is either unhashable or compares as equal to a different exception in the chain (or both).

https://bugs.python.org/issue28603

@serhiy-storchaka
Copy link
Member

LGTM, but the code in Lib/idlelib/run.py should be fixed too.

Please add a news entry and your name in Misc/ACKS.

zaneb added 3 commits October 17, 2017 13:32
In the traceback module, TracebackException checks for loops between
exceptions to prevent an infinite traceback. It does this by putting the
already-seen exception into a set. This means that unhashable exception
objects will cause an error - an error that itself can likely not be
printed because of the presence of the unhashable exception in the
chain.

In this case, we don't actually care about equality of the objects as
defined by the class designer; we want to check that we don't encounter
the self-same exception object, from a chain that is necessarily all in
memory at the same time. We can trivially do so by comparing identities
instead of equality.
IDLE effectively has its own implementation of
traceback.print_exception() to allow it to clean up the tracebacks.
Unhashable exceptions caused a TypeError in the exception printer, which
caused the shell to restart. This change eliminates the problem by
comparing exceptions by identity rather than equality, analagous to how
the traceback module now does it.
Previously when printing an exception traceback in PyErr_Display(), it
would stop traversing the context/cause chain when it encountered an
exception that was either unhashable or compared equal to one already
seen in the chain. With this change, we only stop traversing the chain
when we encounter the same exception object again (indicating a loop.)
@zaneb
Copy link
Contributor Author

zaneb commented Oct 17, 2017

@serhiy-storchaka thanks! I missed that one in idlelib. I've added another patch to address that instance of the problem, and also updated NEWS and ACKS.

@serhiy-storchaka
Copy link
Member

Thank you @zaneb. I left on to @terryjreedy to approve the new IDLE test.

@serhiy-storchaka serhiy-storchaka merged commit de86073 into python:master Oct 17, 2017
@miss-islington
Copy link
Contributor

Thanks @zaneb for the PR, and @serhiy-storchaka for merging it 🌮🎉.. I'm working now to backport this PR to: 3.6.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 17, 2017
@bedevere-bot
Copy link

GH-4024 is a backport of this pull request to the 3.6 branch.

@terryjreedy
Copy link
Member

The goal is that IDLE print the same traceback as python without IDLE. Testing this more thoroughly is another issue. It is almost good enough for me here that it print something rather than raise, and the test exceeds that minimun. In use, the uncaught TypeError causes the IDLE run process to exit and the IDLE GUI process to start a new run process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants