| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,6 +34,7 @@ | |||
| 34 | 34 | - Jan Krivanek ([@jakrivan](https://github.com/jakrivan)) | |
| 35 | 35 | - Jeff Reback ([@jreback](https://github.com/jreback)) | |
| 36 | 36 | - Joe Frayne ([@jfrayne](https://github.com/jfrayne)) | |
| 37 | + - Joe Lidbetter ([@jmlidbetter](https://github.com/jmlidbetter)) | ||
| 37 | 38 | - John Burnett ([@johnburnett](https://github.com/johnburnett)) | |
| 38 | 39 | - John Wilkes ([@jbw3](https://github.com/jbw3)) | |
| 39 | 40 | - Luke Stratman ([@lstratman](https://github.com/lstratman)) | |
| 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 argument types information to "No method matches given arguments" message | |
| 17 | 17 | - Moved wheel import in setup.py inside of a try/except to prevent pip collection failures | |
| 18 | 18 | - Removes PyLong_GetMax and PyClass_New when targetting Python3 | |
| 19 | + - Added support for converting python iterators to C# arrays | ||
| 19 | 20 | ||
| 20 | 21 | ### Fixed | |
| 21 | 22 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -837,50 +837,53 @@ private static void SetConversionError(IntPtr value, Type target) | |||
| 837 | 837 | ||
| 838 | 838 | /// <summary> | |
| 839 | 839 | /// Convert a Python value to a correctly typed managed array instance. | |
| 840 | - /// The Python value must support the Python sequence protocol and the | ||
| 840 | + /// The Python value must support the Python iterator protocol or and the | ||
| 841 | 841 | /// items in the sequence must be convertible to the target array type. | |
| 842 | 842 | /// </summary> | |
| 843 | 843 | private static bool ToArray(IntPtr value, Type obType, out object result, bool setError) | |
| 844 | 844 | { | |
| 845 | 845 | Type elementType = obType.GetElementType(); | |
| 846 | - var size = Runtime.PySequence_Size(value); | ||
| 847 | 846 | result = null; | |
| 848 | 847 | ||
| 849 | - if (size < 0) | ||
| 850 | - { | ||
| 848 | + bool IsSeqObj = Runtime.PySequence_Check(value); | ||
| 849 | + var len = IsSeqObj ? Runtime.PySequence_Size(value) : -1; | ||
| 850 | + | ||
| 851 | + IntPtr IterObject = Runtime.PyObject_GetIter(value); | ||
| 852 | + | ||
| 853 | + if(IterObject==IntPtr.Zero) { | ||
| 851 | 854 | if (setError) | |
| 852 | 855 | { | |
| 853 | 856 | SetConversionError(value, obType); | |
| 854 | 857 | } | |
| 855 | 858 | return false; | |
| 856 | 859 | } | |
| 857 | 860 | ||
| 858 | - Array items = Array.CreateInstance(elementType, size); | ||
| 861 | + Array items; | ||
| 862 | + | ||
| 863 | + var listType = typeof(List<>); | ||
| 864 | + var constructedListType = listType.MakeGenericType(elementType); | ||
| 865 | + IList list = IsSeqObj ? (IList) Activator.CreateInstance(constructedListType, new Object[] {(int) len}) : | ||
| 866 | + (IList) Activator.CreateInstance(constructedListType); | ||
| 867 | + IntPtr item; | ||
| 859 | 868 | ||
| 860 | - // XXX - is there a better way to unwrap this if it is a real array? | ||
| 861 | - for (var i = 0; i < size; i++) | ||
| 869 | + while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero) | ||
| 862 | 870 | { | |
| 863 | 871 | object obj = null; | |
| 864 | - IntPtr item = Runtime.PySequence_GetItem(value, i); | ||
| 865 | - if (item == IntPtr.Zero) | ||
| 866 | - { | ||
| 867 | - if (setError) | ||
| 868 | - { | ||
| 869 | - SetConversionError(value, obType); | ||
| 870 | - return false; | ||
| 871 | - } | ||
| 872 | - } | ||
| 873 | 872 | ||
| 874 | 873 | if (!Converter.ToManaged(item, elementType, out obj, true)) | |
| 875 | 874 | { | |
| 876 | 875 | Runtime.XDecref(item); | |
| 877 | 876 | return false; | |
| 878 | 877 | } | |
| 879 | 878 | ||
| 880 | - items.SetValue(obj, i); | ||
| 879 | + list.Add(obj); | ||
| 881 | 880 | Runtime.XDecref(item); | |
| 882 | 881 | } | |
| 882 | + Runtime.XDecref(IterObject); | ||
| 883 | 883 | ||
| 884 | + items = Array.CreateInstance(elementType, list.Count); | ||
| 885 | + list.CopyTo(items, 0); | ||
| 886 | + | ||
| 884 | 887 | result = items; | |
| 885 | 888 | return true; | |
| 886 | 889 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1337,3 +1337,34 @@ def test_array_abuse(): | |||
| 1337 | 1337 | with pytest.raises(TypeError): | |
| 1338 | 1338 | desc = Test.PublicArrayTest.__dict__['__setitem__'] | |
| 1339 | 1339 | desc(0, 0, 0) | |
| 1340 | + | ||
| 1341 | + | ||
| 1342 | + @pytest.mark.skipif(PY2, reason="Only applies in Python 3") | ||
| 1343 | + def test_iterator_to_array(): | ||
| 1344 | + from System import Array, String | ||
| 1345 | + | ||
| 1346 | + d = {"a": 1, "b": 2, "c": 3} | ||
| 1347 | + keys_iterator = iter(d.keys()) | ||
| 1348 | + arr = Array[String](keys_iterator) | ||
| 1349 | + | ||
| 1350 | + Array.Sort(arr) | ||
| 1351 | + | ||
| 1352 | + assert arr[0] == "a" | ||
| 1353 | + assert arr[1] == "b" | ||
| 1354 | + assert arr[2] == "c" | ||
| 1355 | + | ||
| 1356 | + | ||
| 1357 | + @pytest.mark.skipif(PY2, reason="Only applies in Python 3") | ||
| 1358 | + def test_dict_keys_to_array(): | ||
| 1359 | + from System import Array, String | ||
| 1360 | + | ||
| 1361 | + d = {"a": 1, "b": 2, "c": 3} | ||
| 1362 | + d_keys = d.keys() | ||
| 1363 | + arr = Array[String](d_keys) | ||
| 1364 | + | ||
| 1365 | + Array.Sort(arr) | ||
| 1366 | + | ||
| 1367 | + assert arr[0] == "a" | ||
| 1368 | + assert arr[1] == "b" | ||
| 1369 | + assert arr[2] == "c" | ||
| 1370 | + | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments