Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 071f25d

Browse files
filmordenfromufa
authored and
denfromufa
committed
Implement writing the __cause__ attribute on exceptions. (#287)
1 parent 3b9e18a commit 071f25d

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

src/runtime/clrobject.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ internal CLRObject(Object ob, IntPtr tp) : base()
3131
this.gcHandle = gc;
3232
inst = ob;
3333

34-
// Fix the BaseException args slot if wrapping a CLR exception
35-
Exceptions.SetArgs(py);
34+
// Fix the BaseException args (and __cause__ in case of Python 3)
35+
// slot if wrapping a CLR exception
36+
Exceptions.SetArgsAndCause(py);
3637
}
3738

3839

@@ -70,4 +71,4 @@ internal static IntPtr GetInstHandle(Object ob)
7071
return co.pyHandle;
7172
}
7273
}
73-
}
74+
}

src/runtime/exceptions.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ internal static void Shutdown()
144144
/// </summary>
145145
/// <param name="e">A CLR exception</param>
146146
/// <param name="ob">The python object wrapping </param>
147-
internal static void SetArgs(IntPtr ob)
147+
internal static void SetArgsAndCause(IntPtr ob)
148148
{
149149
var e = ExceptionClassObject.ToException(ob);
150150
if (e == null)
@@ -163,6 +163,14 @@ internal static void SetArgs(IntPtr ob)
163163
}
164164

165165
Marshal.WriteIntPtr(ob, ExceptionOffset.args, args);
166+
167+
#if !(PYTHON25 || PYTHON26 || PYTHON27)
168+
if (e.InnerException != null)
169+
{
170+
IntPtr cause = CLRObject.GetInstHandle(e.InnerException);
171+
Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause);
172+
}
173+
#endif
166174
}
167175

168176
/// <summary>
@@ -434,4 +442,4 @@ puplic static variables on the Exceptions class filled in from
434442
//PyAPI_DATA(PyObject *) PyExc_BytesWarning;
435443
#endif
436444
}
437-
}
445+
}

src/testing/exceptiontest.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22

3-
43
namespace Python.Test
54
{
65
//========================================================================
@@ -55,6 +54,25 @@ public static bool ThrowException()
5554
{
5655
throw new OverflowException("error");
5756
}
57+
58+
public static void ThrowChainedExceptions()
59+
{
60+
try
61+
{
62+
try
63+
{
64+
throw new Exception("Innermost exception");
65+
}
66+
catch (Exception exc)
67+
{
68+
throw new Exception("Inner exception", exc);
69+
}
70+
}
71+
catch (Exception exc2)
72+
{
73+
throw new Exception("Outer exception", exc2);
74+
}
75+
}
5876
}
5977

6078

src/tests/test_exceptions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,27 @@ def testPicklingExceptions(self):
345345

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

348+
def testChainedExceptions(self):
349+
if six.PY3:
350+
from Python.Test import ExceptionTest
351+
352+
try:
353+
ExceptionTest.ThrowChainedExceptions()
354+
except Exception as exc:
355+
msgs = [
356+
"Outer exception",
357+
"Inner exception",
358+
"Innermost exception"
359+
]
360+
361+
for msg in msgs:
362+
self.assertEqual(exc.Message, msg)
363+
self.assertEqual(exc.__cause__, exc.InnerException)
364+
exc = exc.__cause__
365+
366+
else:
367+
self.fail("Test should raise an exception")
368+
348369

349370
def test_suite():
350371
return unittest.makeSuite(ExceptionTests)

0 commit comments

Comments
 (0)