Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/runtime/clrobject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ internal CLRObject(Object ob, IntPtr tp) : base()
this.gcHandle = gc;
inst = ob;

// Fix the BaseException args slot if wrapping a CLR exception
Exceptions.SetArgs(py);
// Fix the BaseException args (and __cause__ in case of Python 3)
// slot if wrapping a CLR exception
Exceptions.SetArgsAndCause(py);
}


Expand Down Expand Up @@ -70,4 +71,4 @@ internal static IntPtr GetInstHandle(Object ob)
return co.pyHandle;
}
}
}
}
12 changes: 10 additions & 2 deletions src/runtime/exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ internal static void Shutdown()
/// </summary>
/// <param name="e">A CLR exception</param>
/// <param name="ob">The python object wrapping </param>
internal static void SetArgs(IntPtr ob)
internal static void SetArgsAndCause(IntPtr ob)
{
var e = ExceptionClassObject.ToException(ob);
if (e == null)
Expand All @@ -163,6 +163,14 @@ internal static void SetArgs(IntPtr ob)
}

Marshal.WriteIntPtr(ob, ExceptionOffset.args, args);

#if !(PYTHON25 || PYTHON26 || PYTHON27)
if (e.InnerException != null)
{
IntPtr cause = CLRObject.GetInstHandle(e.InnerException);
Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause);
}
#endif
}

/// <summary>
Expand Down Expand Up @@ -434,4 +442,4 @@ puplic static variables on the Exceptions class filled in from
//PyAPI_DATA(PyObject *) PyExc_BytesWarning;
#endif
}
}
}
20 changes: 19 additions & 1 deletion src/testing/exceptiontest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;


namespace Python.Test
{
//========================================================================
Expand Down Expand Up @@ -55,6 +54,25 @@ public static bool ThrowException()
{
throw new OverflowException("error");
}

public static void ThrowChainedExceptions()
{
try
{
try
{
throw new Exception("Innermost exception");
}
catch (Exception exc)
{
throw new Exception("Inner exception", exc);
}
}
catch (Exception exc2)
{
throw new Exception("Outer exception", exc2);
}
}
}


Expand Down
21 changes: 21 additions & 0 deletions src/tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,27 @@ def testPicklingExceptions(self):

self.assertEqual(exc.args, loaded.args)

def testChainedExceptions(self):
if six.PY3:
from Python.Test import ExceptionTest

try:
ExceptionTest.ThrowChainedExceptions()
except Exception as exc:
msgs = [
"Outer exception",
"Inner exception",
"Innermost exception"
]

for msg in msgs:
self.assertEqual(exc.Message, msg)
self.assertEqual(exc.__cause__, exc.InnerException)
exc = exc.__cause__

else:
self.fail("Test should raise an exception")


def test_suite():
return unittest.makeSuite(ExceptionTests)
Expand Down