Adds support to convert iterators to arrays (#928)
This commit is contained in:
Родитель
c97a380bd3
Коммит
51a1868580
|
@ -34,6 +34,7 @@
|
|||
- Jan Krivanek ([@jakrivan](https://github.com/jakrivan))
|
||||
- Jeff Reback ([@jreback](https://github.com/jreback))
|
||||
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
|
||||
- Joe Lidbetter ([@jmlidbetter](https://github.com/jmlidbetter))
|
||||
- John Burnett ([@johnburnett](https://github.com/johnburnett))
|
||||
- John Wilkes ([@jbw3](https://github.com/jbw3))
|
||||
- Luke Stratman ([@lstratman](https://github.com/lstratman))
|
||||
|
|
|
@ -16,6 +16,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
|
|||
- Added argument types information to "No method matches given arguments" message
|
||||
- Moved wheel import in setup.py inside of a try/except to prevent pip collection failures
|
||||
- Removes PyLong_GetMax and PyClass_New when targetting Python3
|
||||
- Added support for converting python iterators to C# arrays
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -837,17 +837,20 @@ namespace Python.Runtime
|
|||
|
||||
/// <summary>
|
||||
/// Convert a Python value to a correctly typed managed array instance.
|
||||
/// The Python value must support the Python sequence protocol and the
|
||||
/// The Python value must support the Python iterator protocol or and the
|
||||
/// items in the sequence must be convertible to the target array type.
|
||||
/// </summary>
|
||||
private static bool ToArray(IntPtr value, Type obType, out object result, bool setError)
|
||||
{
|
||||
Type elementType = obType.GetElementType();
|
||||
var size = Runtime.PySequence_Size(value);
|
||||
result = null;
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
bool IsSeqObj = Runtime.PySequence_Check(value);
|
||||
var len = IsSeqObj ? Runtime.PySequence_Size(value) : -1;
|
||||
|
||||
IntPtr IterObject = Runtime.PyObject_GetIter(value);
|
||||
|
||||
if(IterObject==IntPtr.Zero) {
|
||||
if (setError)
|
||||
{
|
||||
SetConversionError(value, obType);
|
||||
|
@ -855,21 +858,17 @@ namespace Python.Runtime
|
|||
return false;
|
||||
}
|
||||
|
||||
Array items = Array.CreateInstance(elementType, size);
|
||||
Array items;
|
||||
|
||||
// XXX - is there a better way to unwrap this if it is a real array?
|
||||
for (var i = 0; i < size; i++)
|
||||
var listType = typeof(List<>);
|
||||
var constructedListType = listType.MakeGenericType(elementType);
|
||||
IList list = IsSeqObj ? (IList) Activator.CreateInstance(constructedListType, new Object[] {(int) len}) :
|
||||
(IList) Activator.CreateInstance(constructedListType);
|
||||
IntPtr item;
|
||||
|
||||
while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero)
|
||||
{
|
||||
object obj = null;
|
||||
IntPtr item = Runtime.PySequence_GetItem(value, i);
|
||||
if (item == IntPtr.Zero)
|
||||
{
|
||||
if (setError)
|
||||
{
|
||||
SetConversionError(value, obType);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Converter.ToManaged(item, elementType, out obj, true))
|
||||
{
|
||||
|
@ -877,10 +876,14 @@ namespace Python.Runtime
|
|||
return false;
|
||||
}
|
||||
|
||||
items.SetValue(obj, i);
|
||||
list.Add(obj);
|
||||
Runtime.XDecref(item);
|
||||
}
|
||||
Runtime.XDecref(IterObject);
|
||||
|
||||
items = Array.CreateInstance(elementType, list.Count);
|
||||
list.CopyTo(items, 0);
|
||||
|
||||
result = items;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1337,3 +1337,34 @@ def test_array_abuse():
|
|||
with pytest.raises(TypeError):
|
||||
desc = Test.PublicArrayTest.__dict__['__setitem__']
|
||||
desc(0, 0, 0)
|
||||
|
||||
|
||||
@pytest.mark.skipif(PY2, reason="Only applies in Python 3")
|
||||
def test_iterator_to_array():
|
||||
from System import Array, String
|
||||
|
||||
d = {"a": 1, "b": 2, "c": 3}
|
||||
keys_iterator = iter(d.keys())
|
||||
arr = Array[String](keys_iterator)
|
||||
|
||||
Array.Sort(arr)
|
||||
|
||||
assert arr[0] == "a"
|
||||
assert arr[1] == "b"
|
||||
assert arr[2] == "c"
|
||||
|
||||
|
||||
@pytest.mark.skipif(PY2, reason="Only applies in Python 3")
|
||||
def test_dict_keys_to_array():
|
||||
from System import Array, String
|
||||
|
||||
d = {"a": 1, "b": 2, "c": 3}
|
||||
d_keys = d.keys()
|
||||
arr = Array[String](d_keys)
|
||||
|
||||
Array.Sort(arr)
|
||||
|
||||
assert arr[0] == "a"
|
||||
assert arr[1] == "b"
|
||||
assert arr[2] == "c"
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче