diff --git a/traceback2/__init__.py b/traceback2/__init__.py index c68958e..acf9b81 100644 --- a/traceback2/__init__.py +++ b/traceback2/__init__.py @@ -438,11 +438,11 @@ def __init__(self, exc_type, exc_value, exc_traceback, limit=None, # Handle loops in __cause__ or __context__. if _seen is None: _seen = set() - _seen.add(exc_value) + _seen.add(id(exc_value)) # Gracefully handle (the way Python 2.4 and earlier did) the case of # being called with no type or value (None, None, None). if (exc_value and getattr(exc_value, '__cause__', None) is not None - and exc_value.__cause__ not in _seen): + and id(exc_value.__cause__) not in _seen): cause = TracebackException( type(exc_value.__cause__), exc_value.__cause__, @@ -454,7 +454,7 @@ def __init__(self, exc_type, exc_value, exc_traceback, limit=None, else: cause = None if (exc_value and getattr(exc_value, '__context__', None) is not None - and exc_value.__context__ not in _seen): + and id(exc_value.__context__) not in _seen): context = TracebackException( type(exc_value.__context__), exc_value.__context__, diff --git a/traceback2/tests/test_traceback.py b/traceback2/tests/test_traceback.py index adfd1eb..6aaa88d 100644 --- a/traceback2/tests/test_traceback.py +++ b/traceback2/tests/test_traceback.py @@ -747,6 +747,30 @@ def test_context(self): self.assertEqual(exc_info[0], exc.exc_type) self.assertEqual(str(exc_info[1]), str(exc)) + def test_unhashable(self): + class UnhashableException(Exception): + __hash__ = None + + def __eq__(self, other): + return True + + ex1 = UnhashableException('ex1') + ex2 = UnhashableException('ex2') + try: + raise_from(ex2, ex1) + except UnhashableException: + try: + raise ex1 + except UnhashableException: + exc_info = sys.exc_info() + exc = traceback.TracebackException(*exc_info) + formatted = list(exc.format()) + if six.PY2: + self.assertIn('UnhashableException: ex1\n', formatted[2]) + else: + self.assertIn('UnhashableException: ex2\n', formatted[3]) + self.assertIn('UnhashableException: ex1\n', formatted[7]) + def test_limit(self): def recurse(n): if n: