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

Skip to content

Commit c7be482

Browse files
Joe LidbetterJoe Lidbetter
Joe Lidbetter
authored and
Joe Lidbetter
committed
Adds support to convert iterators to arrays
1 parent c97a380 commit c7be482

File tree

4 files changed

+53
-17
lines changed

4 files changed

+53
-17
lines changed

AUTHORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- Jan Krivanek ([@jakrivan](https://github.com/jakrivan))
3535
- Jeff Reback ([@jreback](https://github.com/jreback))
3636
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
37+
- Joe Lidbetter ([@jmlidbetter](https://github.com/jmlidbetter))
3738
- John Burnett ([@johnburnett](https://github.com/johnburnett))
3839
- John Wilkes ([@jbw3](https://github.com/jbw3))
3940
- Luke Stratman ([@lstratman](https://github.com/lstratman))

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1616
- Added argument types information to "No method matches given arguments" message
1717
- Moved wheel import in setup.py inside of a try/except to prevent pip collection failures
1818
- Removes PyLong_GetMax and PyClass_New when targetting Python3
19+
- Added support for converting python iterators to C# arrays
1920

2021
### Fixed
2122

src/runtime/converter.cs

+20-17
Original file line numberDiff line numberDiff line change
@@ -837,50 +837,53 @@ private static void SetConversionError(IntPtr value, Type target)
837837

838838
/// <summary>
839839
/// 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
841841
/// items in the sequence must be convertible to the target array type.
842842
/// </summary>
843843
private static bool ToArray(IntPtr value, Type obType, out object result, bool setError)
844844
{
845845
Type elementType = obType.GetElementType();
846-
var size = Runtime.PySequence_Size(value);
847846
result = null;
848847

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) {
851854
if (setError)
852855
{
853856
SetConversionError(value, obType);
854857
}
855858
return false;
856859
}
857860

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;
859868

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)
862870
{
863871
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-
}
873872

874873
if (!Converter.ToManaged(item, elementType, out obj, true))
875874
{
876875
Runtime.XDecref(item);
877876
return false;
878877
}
879878

880-
items.SetValue(obj, i);
879+
list.Add(obj);
881880
Runtime.XDecref(item);
882881
}
882+
Runtime.XDecref(IterObject);
883883

884+
items = Array.CreateInstance(elementType, list.Count);
885+
list.CopyTo(items, 0);
886+
884887
result = items;
885888
return true;
886889
}

src/tests/test_array.py

+31
Original file line numberDiff line numberDiff line change
@@ -1337,3 +1337,34 @@ def test_array_abuse():
13371337
with pytest.raises(TypeError):
13381338
desc = Test.PublicArrayTest.__dict__['__setitem__']
13391339
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+

0 commit comments

Comments
 (0)