Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DSPythonNet3/DSPythonNet3.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}</ProjectGuid>
<OutputType>Library</OutputType>
Expand All @@ -10,6 +10,7 @@
<ItemGroup>
<InternalsVisibleTo Include="PythonMigrationViewExtension" />
<InternalsVisibleTo Include="DynamoPythonTests" />
<InternalsVisibleTo Include="DSPythonNet3Tests" />

<PackageReference Include="DynamoVisualProgramming.Core" Version="$(DynamoPackageVersion)" ExcludeAssets="runtime" />
<PackageReference Include="DynamoVisualProgramming.DynamoServices" Version="$(DynamoPackageVersion)" ExcludeAssets="runtime" />
Expand Down
61 changes: 55 additions & 6 deletions DSPythonNet3/Encoders/ListEncodeDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
return false;
}

using (var pyList = PyList.AsList(pyObj))
if (typeof(T).IsGenericType)
{
if (typeof(T).IsGenericType)
using (var pyList = PyList.AsList(pyObj))
{
value = pyList.ToList<T>();
}
else
{
value = (T)pyList.ToList();
}
return true;
}

var converted = ConvertToArrayList(pyObj);
value = (T)converted;
return true;
}

public PyObject TryEncode(object value)
Expand All @@ -57,5 +57,54 @@ bool IPyObjectDecoder.CanDecode(PyType objectType, Type targetType)
}
return decodableTypes.IndexOf(targetType) >= 0;
}

private static IList ConvertToArrayList(PyObject pyObj)
{
using var pyList = PyList.AsList(pyObj);
var result = new ArrayList();
foreach (PyObject item in pyList)
{
using (item)
{
result.Add(ConvertItem(item));
}
}

return result;
}

private static object ConvertItem(PyObject item)
{
if (TryGetClrObject(item, out var clrObject))
{
return clrObject;
}

if (PyString.IsStringType(item))
{
return item.AsManagedObject(typeof(string));
}

if (PyList.IsListType(item) || PyTuple.IsTupleType(item))
{
return ConvertToArrayList(item);
}

return item.AsManagedObject(typeof(object));
}

private static bool TryGetClrObject(PyObject pyObj, out object clrObject)
{
try
{
clrObject = pyObj.GetManagedObject();
return clrObject != null;
}
catch
{
clrObject = null;
return false;
}
}
}
}
72 changes: 72 additions & 0 deletions DSpythonNet3Tests/ListEncoderDecoderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Collections;
using NUnit.Framework;
using DSPythonNet3;

namespace DSPythonNet3Tests
{
public class ListEncoderDecoderTests
{
[Test]
public void TryDecode_ConvertsNestedPythonListsToClrLists()
{
DSPythonNet3Evaluator.InitializePython();

string code = @"
import clr
clr.AddReference('DSCoreNodes')
from DSCore import List

data = [[[1, 2], [3]], [[4, 5], [6]]]
OUT = data, List.Flatten(data, 1), List.Flatten(data, 2), List.Flatten(data, -1)
";
var empty = new ArrayList();
var expected = new ArrayList
{
new ArrayList
{
new ArrayList
{
new ArrayList { 1, 2 },
new ArrayList { 3 }
},
new ArrayList
{
new ArrayList { 4, 5 },
new ArrayList { 6 }
}
},
new ArrayList
{
new ArrayList { 1, 2 },
new ArrayList { 3 },
new ArrayList { 4, 5 },
new ArrayList { 6 }
},
new ArrayList { 1, 2, 3, 4, 5, 6 },
new ArrayList { 1, 2, 3, 4, 5, 6 }
};

var result = DSPythonNet3Evaluator.EvaluatePythonScript(code, empty, empty);
Assert.That(result, Is.InstanceOf<IEnumerable>());

var normalizedResult = NormalizeResult(result);
CollectionAssert.AreEqual(expected, normalizedResult as IEnumerable);
}

private static object NormalizeResult(object value)
{
if (value is string || value is not IEnumerable enumerable)
{
return value;
}

var list = new ArrayList();
foreach (var item in enumerable)
{
list.Add(NormalizeResult(item));
}

return list;
}
}
}