From 2d54a2d2a93943b2fb33fc25f9604c7fef27aeb6 Mon Sep 17 00:00:00 2001 From: Ivo Petrov Date: Wed, 3 Dec 2025 10:27:55 +0000 Subject: [PATCH 1/3] fixes flatten --- DSPythonNet3/Encoders/ListEncodeDecoder.cs | 60 +++++++++++++++++++--- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/DSPythonNet3/Encoders/ListEncodeDecoder.cs b/DSPythonNet3/Encoders/ListEncodeDecoder.cs index 91b8c18..0820f48 100644 --- a/DSPythonNet3/Encoders/ListEncodeDecoder.cs +++ b/DSPythonNet3/Encoders/ListEncodeDecoder.cs @@ -28,18 +28,18 @@ public bool TryDecode(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(); } - else - { - value = (T)pyList.ToList(); - } return true; } + + var converted = ConvertToArrayList(pyObj); + value = (T)converted; + return true; } public PyObject TryEncode(object value) @@ -57,5 +57,53 @@ 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; + } + } } } From bba43db9d8a409b6e24f64b3fc93620a6d66fb66 Mon Sep 17 00:00:00 2001 From: Ivo Petrov Date: Wed, 3 Dec 2025 11:31:28 +0000 Subject: [PATCH 2/3] maximumItem fix --- DSPythonNet3/Encoders/ListEncodeDecoder.cs | 75 +++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/DSPythonNet3/Encoders/ListEncodeDecoder.cs b/DSPythonNet3/Encoders/ListEncodeDecoder.cs index 0820f48..eec28d6 100644 --- a/DSPythonNet3/Encoders/ListEncodeDecoder.cs +++ b/DSPythonNet3/Encoders/ListEncodeDecoder.cs @@ -30,6 +30,27 @@ public bool TryDecode(PyObject pyObj, out T value) if (typeof(T).IsGenericType) { + var genericDef = typeof(T).GetGenericTypeDefinition(); + var elementType = typeof(T).GetGenericArguments().FirstOrDefault(); + + if (elementType != null && (genericDef == typeof(IEnumerable<>) || genericDef == typeof(List<>) || genericDef == typeof(IList<>))) + { + using var pyList = PyList.AsList(pyObj); + var listType = typeof(List<>).MakeGenericType(elementType); + var typedList = (IList)Activator.CreateInstance(listType)!; + + foreach (PyObject item in pyList) + { + using (item) + { + typedList.Add(ConvertGenericItem(item, elementType)); + } + } + + value = (T)typedList; + return true; + } + using (var pyList = PyList.AsList(pyObj)) { value = pyList.ToList(); @@ -79,6 +100,22 @@ private static object ConvertItem(PyObject item) return clrObject; } + if (PyInt.IsIntType(item)) + { + using var pyLong = PyInt.AsInt(item); + try { return pyLong.ToInt64(); } + catch (PythonException ex) when (ex.Message.StartsWith("int too big")) + { + return pyLong.ToBigInteger(); + } + } + + if (PyFloat.IsFloatType(item)) + { + using var pyFloat = PyFloat.AsFloat(item); + return pyFloat.ToDouble(); + } + if (PyString.IsStringType(item)) { return item.AsManagedObject(typeof(string)); @@ -97,7 +134,12 @@ private static bool TryGetClrObject(PyObject pyObj, out object clrObject) try { clrObject = pyObj.GetManagedObject(); - return clrObject != null; + if (clrObject is PyObject || clrObject is null) + { + clrObject = null; + return false; + } + return true; } catch { @@ -105,5 +147,36 @@ private static bool TryGetClrObject(PyObject pyObj, out object clrObject) return false; } } + + private static object ConvertGenericItem(PyObject item, Type elementType) + { + if (elementType == typeof(object)) + { + return ConvertItem(item); + } + + if (TryGetClrObject(item, out var clrObject) && elementType.IsInstanceOfType(clrObject)) + { + return clrObject; + } + + if (PyList.IsListType(item) || PyTuple.IsTupleType(item)) + { + // recursively decode nested generics + var listType = typeof(List<>).MakeGenericType(elementType); + var nestedList = (IList)Activator.CreateInstance(listType)!; + using var pyList = PyList.AsList(item); + foreach (PyObject child in pyList) + { + using (child) + { + nestedList.Add(ConvertGenericItem(child, elementType)); + } + } + return nestedList; + } + + return item.AsManagedObject(elementType); + } } } From 78aaa6278bada5aa764866458ce1108ef2c6db39 Mon Sep 17 00:00:00 2001 From: Ivo Petrov Date: Wed, 3 Dec 2025 17:23:56 +0000 Subject: [PATCH 3/3] version bumped up to 1.4.6 --- pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline.yml b/pipeline.yml index b4193bb..7b179c5 100644 --- a/pipeline.yml +++ b/pipeline.yml @@ -1,4 +1,4 @@ -version: 1.4.5 +version: 1.4.6 pipeline_os: windows create_pr_release_to_master: true