| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,6 +16,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 16 | 16 | - Added `clr.GetClrType` (#432, #433) | |
| 17 | 17 | - Allowed passing `None` for nullable args (#460) | |
| 18 | 18 | - Added keyword arguments based on C# syntax for calling CPython methods (#461) | |
| 19 | + - Catches exceptions thrown in C# iterators (yield returns) and rethrows them in python (#475) | ||
| 19 | 20 | - Implemented GetDynamicMemberNames() for PyObject to allow dynamic object members to be visible in the debugger (#443) | |
| 20 | 21 | ||
| 21 | 22 | ### Changed | |
@@ -29,7 +30,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 29 | 30 | - Fixed conversion of 'float' and 'double' values (#486) | |
| 30 | 31 | - Fixed 'clrmethod' for python 2 (#492) | |
| 31 | 32 | - Fixed double calling of constructor when deriving from .NET class (#495) | |
| 32 | - - Fixed `clr.GetClrType` when iterating over `System` members (#607) | ||
| 33 | + - Fixed `clr.GetClrType` when iterating over `System` members (#607) | ||
| 33 | 34 | - Fixed `LockRecursionException` when loading assemblies (#627) | |
| 34 | 35 | - Fixed errors breaking .NET Remoting on method invoke (#276) | |
| 35 | 36 | - Fixed PyObject.GetHashCode (#676) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,9 +23,21 @@ public Iterator(IEnumerator e) | |||
| 23 | 23 | public static IntPtr tp_iternext(IntPtr ob) | |
| 24 | 24 | { | |
| 25 | 25 | var self = GetManagedObject(ob) as Iterator; | |
| 26 | - if (!self.iter.MoveNext()) | ||
| 26 | + try | ||
| 27 | 27 | { | |
| 28 | - Exceptions.SetError(Exceptions.StopIteration, Runtime.PyNone); | ||
| 28 | + if (!self.iter.MoveNext()) | ||
| 29 | + { | ||
| 30 | + Exceptions.SetError(Exceptions.StopIteration, Runtime.PyNone); | ||
| 31 | + return IntPtr.Zero; | ||
| 32 | + } | ||
| 33 | + } | ||
| 34 | + catch (Exception e) | ||
| 35 | + { | ||
| 36 | + if (e.InnerException != null) | ||
| 37 | + { | ||
| 38 | + e = e.InnerException; | ||
| 39 | + } | ||
| 40 | + Exceptions.SetError(e); | ||
| 29 | 41 | return IntPtr.Zero; | |
| 30 | 42 | } | |
| 31 | 43 | object item = self.iter.Current; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,6 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections; | ||
| 3 | + using System.Collections.Generic; | ||
| 2 | 4 | ||
| 3 | 5 | namespace Python.Test | |
| 4 | 6 | { | |
@@ -54,6 +56,13 @@ public static bool ThrowException() | |||
| 54 | 56 | throw new OverflowException("error"); | |
| 55 | 57 | } | |
| 56 | 58 | ||
| 59 | + public static IEnumerable<int> ThrowExceptionInIterator(Exception e) | ||
| 60 | + { | ||
| 61 | + yield return 1; | ||
| 62 | + yield return 2; | ||
| 63 | + throw e; | ||
| 64 | + } | ||
| 65 | + | ||
| 57 | 66 | public static void ThrowChainedExceptions() | |
| 58 | 67 | { | |
| 59 | 68 | try | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -345,3 +345,44 @@ def test_chained_exceptions(): | |||
| 345 | 345 | assert exc.Message == msg | |
| 346 | 346 | assert exc.__cause__ == exc.InnerException | |
| 347 | 347 | exc = exc.__cause__ | |
| 348 | + | ||
| 349 | + def test_iteration_exception(): | ||
| 350 | + from Python.Test import ExceptionTest | ||
| 351 | + from System import OverflowException | ||
| 352 | + | ||
| 353 | + exception = OverflowException("error") | ||
| 354 | + | ||
| 355 | + val = ExceptionTest.ThrowExceptionInIterator(exception).__iter__() | ||
| 356 | + assert next(val) == 1 | ||
| 357 | + assert next(val) == 2 | ||
| 358 | + with pytest.raises(OverflowException) as cm: | ||
| 359 | + next(val) | ||
| 360 | + | ||
| 361 | + exc = cm.value | ||
| 362 | + | ||
| 363 | + assert exc == exception | ||
| 364 | + | ||
| 365 | + # after exception is thrown iterator is no longer valid | ||
| 366 | + with pytest.raises(StopIteration): | ||
| 367 | + next(val) | ||
| 368 | + | ||
| 369 | + | ||
| 370 | + def test_iteration_innerexception(): | ||
| 371 | + from Python.Test import ExceptionTest | ||
| 372 | + from System import OverflowException | ||
| 373 | + | ||
| 374 | + exception = System.Exception("message", OverflowException("error")) | ||
| 375 | + | ||
| 376 | + val = ExceptionTest.ThrowExceptionInIterator(exception).__iter__() | ||
| 377 | + assert next(val) == 1 | ||
| 378 | + assert next(val) == 2 | ||
| 379 | + with pytest.raises(OverflowException) as cm: | ||
| 380 | + next(val) | ||
| 381 | + | ||
| 382 | + exc = cm.value | ||
| 383 | + | ||
| 384 | + assert exc == exception.InnerException | ||
| 385 | + | ||
| 386 | + # after exception is thrown iterator is no longer valid | ||
| 387 | + with pytest.raises(StopIteration): | ||
| 388 | + next(val) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments