bpo-28603: Fix exception chaining for unhashable exceptions by zaneb · Pull Request #4014 · python/cpython (original) (raw)

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 andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation6 Commits3 Checks0 Files changed

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

zaneb

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

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

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.

@zaneb

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.

@zaneb

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

@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

@serhiy-storchaka

terryjreedy

@miss-islington

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

@zaneb @miss-islington

@bedevere-bot

@terryjreedy

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.

@zaneb zaneb mentioned this pull request

Nov 7, 2017

Labels

type-bug

An unexpected behavior, bug, or error