Skip to content

Commit

Permalink
Implement List Conversion, Reflect PR #37 Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
C-SELLERS committed Feb 15, 2021
1 parent 863530d commit 5839d21
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 8 deletions.
24 changes: 24 additions & 0 deletions src/embed_tests/TestConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ public void Dispose()
PythonEngine.Shutdown();
}

[Test]
public void ConvertListRoundTrip()
{
var list = new List<Type> { typeof(decimal), typeof(int) };
var py = list.ToPython();
object result;
var converted = Converter.ToManaged(py.Handle, typeof(List<Type>), out result, false);

Assert.IsTrue(converted);
Assert.AreEqual(result, list);
}

[Test]
public void ConvertPyListToArray()
{
var array = new List<Type> { typeof(decimal), typeof(int) };
var py = array.ToPython();
object result;
var converted = Converter.ToManaged(py.Handle, typeof(Type[]), out result, false);

Assert.IsTrue(converted);
Assert.AreEqual(result, array);
}

[Test]
public void TestConvertSingleToManaged(
[Values(float.PositiveInfinity, float.NegativeInfinity, float.MinValue, float.MaxValue, float.NaN,
Expand Down
59 changes: 51 additions & 8 deletions src/runtime/converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,15 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
return true;
}

if (obType.IsGenericType && Runtime.PyObject_TYPE(value) == Runtime.PyListType)
{
var typeDefinition = obType.GetGenericTypeDefinition();
if (typeDefinition == typeof(List<>))
{
return ToList(value, obType, out result, setError);
}
}

// Common case: if the Python value is a wrapped managed object
// instance, just return the wrapped object.
ManagedType mt = ManagedType.GetManagedObject(value);
Expand Down Expand Up @@ -948,7 +957,7 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
result = null;

IntPtr IterObject = Runtime.PyObject_GetIter(value);
if (IterObject == IntPtr.Zero)
if (IterObject == IntPtr.Zero || elementType.IsGenericType)
{
if (setError)
{
Expand All @@ -962,6 +971,43 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
return false;
}

var list = MakeList(value, IterObject, obType, elementType, setError);
if (list == null)
{
return false;
}

Array items = Array.CreateInstance(elementType, list.Count);
list.CopyTo(items, 0);

result = items;
return true;
}

/// <summary>
/// Convert a Python value to a correctly typed managed list instance.
/// The Python value must support the Python sequence protocol and the
/// items in the sequence must be convertible to the target list type.
/// </summary>
private static bool ToList(IntPtr value, Type obType, out object result, bool setError)
{
var elementType = obType.GetGenericArguments()[0];
IntPtr IterObject = Runtime.PyObject_GetIter(value);
result = MakeList(value, IterObject, obType, elementType, setError);
return result != null;
}

/// <summary>
/// Helper function for ToArray and ToList that creates a IList out of iterable objects
/// </summary>
/// <param name="value"></param>
/// <param name="IterObject"></param>
/// <param name="obType"></param>
/// <param name="elementType"></param>
/// <param name="setError"></param>
/// <returns></returns>
private static IList MakeList(IntPtr value, IntPtr IterObject, Type obType, Type elementType, bool setError)
{
IList list;
try
{
Expand Down Expand Up @@ -989,7 +1035,8 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
Exceptions.SetError(e);
SetConversionError(value, obType);
}
return false;

return null;
}

IntPtr item;
Expand All @@ -1001,19 +1048,15 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
if (!Converter.ToManaged(item, elementType, out obj, setError))
{
Runtime.XDecref(item);
return false;
return null;
}

list.Add(obj);
Runtime.XDecref(item);
}
Runtime.XDecref(IterObject);

Array items = Array.CreateInstance(elementType, list.Count);
list.CopyTo(items, 0);

result = items;
return true;
return list;
}


Expand Down

0 comments on commit 5839d21

Please sign in to comment.