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

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.)

serhiy-storchaka

terryjreedy

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request

Oct 17, 2017

@zaneb @miss-islington

@zaneb zaneb mentioned this pull request

Nov 7, 2017