diff -r aa214fefbdc1 Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py Sat Jan 28 20:33:52 2012 -0500 +++ b/Lib/test/test_exceptions.py Sun Jan 29 15:07:48 2012 -0800 @@ -388,18 +388,18 @@ class ExceptionTests(unittest.TestCase): def testChainingAttrs(self): e = Exception() self.assertEqual(e.__context__, None) - self.assertEqual(e.__cause__, None) + self.assertEqual(e.__cause__, False) e = TypeError() self.assertEqual(e.__context__, None) - self.assertEqual(e.__cause__, None) + self.assertEqual(e.__cause__, False) class MyException(EnvironmentError): pass e = MyException() self.assertEqual(e.__context__, None) - self.assertEqual(e.__cause__, None) + self.assertEqual(e.__cause__, False) def testKeywordArgs(self): # test that builtin exception don't take keyword args, diff -r aa214fefbdc1 Lib/test/test_raise.py --- a/Lib/test/test_raise.py Sat Jan 28 20:33:52 2012 -0500 +++ b/Lib/test/test_raise.py Sun Jan 29 15:07:48 2012 -0800 @@ -77,6 +77,16 @@ class TestRaise(unittest.TestCase): nested_reraise() self.assertRaises(TypeError, reraise) + def test_raise_from_None(self): + try: + try: + raise TypeError("foo") + except: + raise ValueError() from None + except ValueError as e: + self.assertTrue(isinstance(e.__context__, TypeError)) + self.assertIsNone(e.__cause__) + def test_with_reraise1(self): def reraise(): try: diff -r aa214fefbdc1 Lib/traceback.py --- a/Lib/traceback.py Sat Jan 28 20:33:52 2012 -0500 +++ b/Lib/traceback.py Sun Jan 29 15:07:48 2012 -0800 @@ -120,8 +120,8 @@ def _iter_chain(exc, custom_tb=None, see seen.add(exc) its = [] cause = exc.__cause__ - if cause is not None and cause not in seen: - its.append(_iter_chain(cause, None, seen)) + if cause is not False and cause is not None and cause not in seen: + its.append(_iter_chain(cause, False, seen)) its.append([(_cause_message, None)]) else: context = exc.__context__ diff -r aa214fefbdc1 Objects/exceptions.c --- a/Objects/exceptions.c Sat Jan 28 20:33:52 2012 -0500 +++ b/Objects/exceptions.c Sun Jan 29 15:07:48 2012 -0800 @@ -293,7 +293,7 @@ static PyObject * BaseException_get_cause(PyObject *self) { PyObject *res = PyException_GetCause(self); if (res) return res; /* new reference already returned above */ - Py_RETURN_NONE; + Py_RETURN_FALSE; } static int diff -r aa214fefbdc1 Python/ceval.c --- a/Python/ceval.c Sat Jan 28 20:33:52 2012 -0500 +++ b/Python/ceval.c Sun Jan 29 15:07:48 2012 -0800 @@ -3576,6 +3576,11 @@ do_raise(PyObject *exc, PyObject *cause) else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; } + else if (cause == Py_None) { + fixed_cause = Py_None; + Py_INCREF(Py_None); + Py_DECREF(cause); + } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " diff -r aa214fefbdc1 Python/pythonrun.c --- a/Python/pythonrun.c Sat Jan 28 20:33:52 2012 -0500 +++ b/Python/pythonrun.c Sun Jan 29 15:07:48 2012 -0800 @@ -1691,7 +1691,11 @@ print_exception_recursive(PyObject *f, P else if (PyExceptionInstance_Check(value)) { cause = PyException_GetCause(value); context = PyException_GetContext(value); - if (cause) { + if (cause && cause == Py_None) { + /* print neither cause nor context */ + ; + } + else if (cause) { res = PySet_Contains(seen, cause); if (res == -1) PyErr_Clear();