Skip to content

Commit 752c751

Browse files
authored
DYN-8088: DSCore.List.Flatten does not work in PythonNet3 (#12)
* fixes flatten * maximumItem fix * version bumped up to 1.4.6
1 parent c0b315f commit 752c751

File tree

2 files changed

+127
-6
lines changed

2 files changed

+127
-6
lines changed

DSPythonNet3/Encoders/ListEncodeDecoder.cs

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,39 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
2828
return false;
2929
}
3030

31-
using (var pyList = PyList.AsList(pyObj))
31+
if (typeof(T).IsGenericType)
3232
{
33-
if (typeof(T).IsGenericType)
33+
var genericDef = typeof(T).GetGenericTypeDefinition();
34+
var elementType = typeof(T).GetGenericArguments().FirstOrDefault();
35+
36+
if (elementType != null && (genericDef == typeof(IEnumerable<>) || genericDef == typeof(List<>) || genericDef == typeof(IList<>)))
3437
{
35-
value = pyList.ToList<T>();
38+
using var pyList = PyList.AsList(pyObj);
39+
var listType = typeof(List<>).MakeGenericType(elementType);
40+
var typedList = (IList)Activator.CreateInstance(listType)!;
41+
42+
foreach (PyObject item in pyList)
43+
{
44+
using (item)
45+
{
46+
typedList.Add(ConvertGenericItem(item, elementType));
47+
}
48+
}
49+
50+
value = (T)typedList;
51+
return true;
3652
}
37-
else
53+
54+
using (var pyList = PyList.AsList(pyObj))
3855
{
39-
value = (T)pyList.ToList();
56+
value = pyList.ToList<T>();
4057
}
4158
return true;
4259
}
60+
61+
var converted = ConvertToArrayList(pyObj);
62+
value = (T)converted;
63+
return true;
4364
}
4465

4566
public PyObject TryEncode(object value)
@@ -57,5 +78,105 @@ bool IPyObjectDecoder.CanDecode(PyType objectType, Type targetType)
5778
}
5879
return decodableTypes.IndexOf(targetType) >= 0;
5980
}
81+
82+
private static IList ConvertToArrayList(PyObject pyObj)
83+
{
84+
using var pyList = PyList.AsList(pyObj);
85+
var result = new ArrayList();
86+
foreach (PyObject item in pyList)
87+
{
88+
using (item)
89+
{
90+
result.Add(ConvertItem(item));
91+
}
92+
}
93+
return result;
94+
}
95+
96+
private static object ConvertItem(PyObject item)
97+
{
98+
if (TryGetClrObject(item, out var clrObject))
99+
{
100+
return clrObject;
101+
}
102+
103+
if (PyInt.IsIntType(item))
104+
{
105+
using var pyLong = PyInt.AsInt(item);
106+
try { return pyLong.ToInt64(); }
107+
catch (PythonException ex) when (ex.Message.StartsWith("int too big"))
108+
{
109+
return pyLong.ToBigInteger();
110+
}
111+
}
112+
113+
if (PyFloat.IsFloatType(item))
114+
{
115+
using var pyFloat = PyFloat.AsFloat(item);
116+
return pyFloat.ToDouble();
117+
}
118+
119+
if (PyString.IsStringType(item))
120+
{
121+
return item.AsManagedObject(typeof(string));
122+
}
123+
124+
if (PyList.IsListType(item) || PyTuple.IsTupleType(item))
125+
{
126+
return ConvertToArrayList(item);
127+
}
128+
129+
return item.AsManagedObject(typeof(object));
130+
}
131+
132+
private static bool TryGetClrObject(PyObject pyObj, out object clrObject)
133+
{
134+
try
135+
{
136+
clrObject = pyObj.GetManagedObject();
137+
if (clrObject is PyObject || clrObject is null)
138+
{
139+
clrObject = null;
140+
return false;
141+
}
142+
return true;
143+
}
144+
catch
145+
{
146+
clrObject = null;
147+
return false;
148+
}
149+
}
150+
151+
private static object ConvertGenericItem(PyObject item, Type elementType)
152+
{
153+
if (elementType == typeof(object))
154+
{
155+
return ConvertItem(item);
156+
}
157+
158+
if (TryGetClrObject(item, out var clrObject) && elementType.IsInstanceOfType(clrObject))
159+
{
160+
return clrObject;
161+
}
162+
163+
if (PyList.IsListType(item) || PyTuple.IsTupleType(item))
164+
{
165+
// recursively decode nested generics
166+
var listType = typeof(List<>).MakeGenericType(elementType);
167+
var nestedList = (IList)Activator.CreateInstance(listType)!;
168+
using var pyList = PyList.AsList(item);
169+
foreach (PyObject child in pyList)
170+
{
171+
using (child)
172+
{
173+
nestedList.Add(ConvertGenericItem(child, elementType));
174+
}
175+
}
176+
return nestedList;
177+
}
178+
179+
return item.AsManagedObject(elementType);
180+
}
60181
}
61182
}

pipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 1.4.5
1+
version: 1.4.6
22
pipeline_os: windows
33
create_pr_release_to_master: true
44

0 commit comments

Comments
 (0)