| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7a03b61 commit 7149d5e
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,6 +26,7 @@ details about the cause of the failure | |||
| 26 | 26 | - BREAKING: Parameters marked with `ParameterAttributes.Out` are no longer returned in addition | |
| 27 | 27 | to the regular method return value (unless they are passed with `ref` or `out` keyword). | |
| 28 | 28 | - BREAKING: Drop support for the long-deprecated CLR.* prefix. | |
| 29 | + - `PyObject` now implements `IEnumerable<PyObject>` in addition to `IEnumerable` | ||
| 29 | 30 | ||
| 30 | 31 | ### Fixed | |
| 31 | 32 | ||
@@ -40,6 +41,7 @@ details about the cause of the failure | |||
| 40 | 41 | - Fixed a bug where indexers could not be used if they were inherited | |
| 41 | 42 | - Made it possible to use `__len__` also on `ICollection<>` interface objects | |
| 42 | 43 | - Made it possible to call `ToString`, `GetHashCode`, and `GetType` on inteface objects | |
| 44 | + - Fixed objects returned by enumerating `PyObject` being disposed too soon | ||
| 43 | 45 | ||
| 44 | 46 | ### Removed | |
| 45 | 47 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,37 @@ | |||
| 1 | + using System.Linq; | ||
| 2 | + using System.Text; | ||
| 3 | + | ||
| 4 | + using NUnit.Framework; | ||
| 5 | + | ||
| 6 | + using Python.Runtime; | ||
| 7 | + | ||
| 8 | + namespace Python.EmbeddingTest | ||
| 9 | + { | ||
| 10 | + class TestPyIter | ||
| 11 | + { | ||
| 12 | + [OneTimeSetUp] | ||
| 13 | + public void SetUp() | ||
| 14 | + { | ||
| 15 | + PythonEngine.Initialize(); | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + [OneTimeTearDown] | ||
| 19 | + public void Dispose() | ||
| 20 | + { | ||
| 21 | + PythonEngine.Shutdown(); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + [Test] | ||
| 25 | + public void KeepOldObjects() | ||
| 26 | + { | ||
| 27 | + using (Py.GIL()) | ||
| 28 | + using (var testString = new PyString("hello world! !$%&/()=?")) | ||
| 29 | + { | ||
| 30 | + PyObject[] chars = testString.ToArray(); | ||
| 31 | + Assert.IsTrue(chars.Length > 1); | ||
| 32 | + string reconstructed = string.Concat(chars.Select(c => c.As<string>())); | ||
| 33 | + Assert.AreEqual(testString.As<string>(), reconstructed); | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,7 +9,7 @@ namespace Python.Runtime | |||
| 9 | 9 | /// PY3: https://docs.python.org/3/c-api/iterator.html | |
| 10 | 10 | /// for details. | |
| 11 | 11 | /// </summary> | |
| 12 | - public class PyIter : PyObject, IEnumerator<object> | ||
| 12 | + public class PyIter : PyObject, IEnumerator<PyObject> | ||
| 13 | 13 | { | |
| 14 | 14 | private PyObject _current; | |
| 15 | 15 | ||
@@ -46,41 +46,35 @@ public static PyIter GetIter(PyObject iterable) | |||
| 46 | 46 | ||
| 47 | 47 | protected override void Dispose(bool disposing) | |
| 48 | 48 | { | |
| 49 | - if (null != _current) | ||
| 50 | - { | ||
| 51 | - _current.Dispose(); | ||
| 52 | - _current = null; | ||
| 53 | - } | ||
| 49 | + _current = null; | ||
| 54 | 50 | base.Dispose(disposing); | |
| 55 | 51 | } | |
| 56 | 52 | ||
| 57 | 53 | public bool MoveNext() | |
| 58 | 54 | { | |
| 59 | - // dispose of the previous object, if there was one | ||
| 60 | - if (null != _current) | ||
| 55 | + NewReference next = Runtime.PyIter_Next(Reference); | ||
| 56 | + if (next.IsNull()) | ||
| 61 | 57 | { | |
| 62 | - _current.Dispose(); | ||
| 63 | - _current = null; | ||
| 64 | - } | ||
| 58 | + if (Exceptions.ErrorOccurred()) | ||
| 59 | + { | ||
| 60 | + throw new PythonException(); | ||
| 61 | + } | ||
| 65 | 62 | ||
| 66 | - IntPtr next = Runtime.PyIter_Next(obj); | ||
| 67 | - if (next == IntPtr.Zero) | ||
| 68 | - { | ||
| 63 | + // stop holding the previous object, if there was one | ||
| 64 | + _current = null; | ||
| 69 | 65 | return false; | |
| 70 | 66 | } | |
| 71 | 67 | ||
| 72 | - _current = new PyObject(next); | ||
| 68 | + _current = next.MoveToPyObject(); | ||
| 73 | 69 | return true; | |
| 74 | 70 | } | |
| 75 | 71 | ||
| 76 | 72 | public void Reset() | |
| 77 | 73 | { | |
| 78 | - //Not supported in python. | ||
| 74 | + throw new NotSupportedException(); | ||
| 79 | 75 | } | |
| 80 | 76 | ||
| 81 | - public object Current | ||
| 82 | - { | ||
| 83 | - get { return _current; } | ||
| 84 | - } | ||
| 77 | + public PyObject Current => _current; | ||
| 78 | + object System.Collections.IEnumerator.Current => _current; | ||
| 85 | 79 | } | |
| 86 | 80 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,7 @@ namespace Python.Runtime | |||
| 16 | 16 | /// for details. | |
| 17 | 17 | /// </summary> | |
| 18 | 18 | [Serializable] | |
| 19 | - public partial class PyObject : DynamicObject, IEnumerable, IDisposable | ||
| 19 | + public partial class PyObject : DynamicObject, IEnumerable<PyObject>, IDisposable | ||
| 20 | 20 | { | |
| 21 | 21 | #if TRACE_ALLOC | |
| 22 | 22 | /// <summary> | |
@@ -705,10 +705,11 @@ public PyObject GetIterator() | |||
| 705 | 705 | /// python object to be iterated over in C#. A PythonException will be | |
| 706 | 706 | /// raised if the object is not iterable. | |
| 707 | 707 | /// </remarks> | |
| 708 | - public IEnumerator GetEnumerator() | ||
| 708 | + public IEnumerator<PyObject> GetEnumerator() | ||
| 709 | 709 | { | |
| 710 | 710 | return PyIter.GetIter(this); | |
| 711 | 711 | } | |
| 712 | + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); | ||
| 712 | 713 | ||
| 713 | 714 | ||
| 714 | 715 | /// <summary> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1854,6 +1854,8 @@ internal static bool PyIter_Check(IntPtr pointer) | |||
| 1854 | 1854 | ||
| 1855 | 1855 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1856 | 1856 | internal static extern IntPtr PyIter_Next(IntPtr pointer); | |
| 1857 | + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | ||
| 1858 | + internal static extern NewReference PyIter_Next(BorrowedReference pointer); | ||
| 1857 | 1859 | ||
| 1858 | 1860 | ||
| 1859 | 1861 | //==================================================================== | |
| Back | FazBrowse Home | New Git URL |
0 commit comments