Skip to content
Merged
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
12 changes: 11 additions & 1 deletion cpp/csp/python/PyStructList.hi
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,16 @@ static PyMappingMethods py_struct_list_as_mapping = {
py_struct_list_ass_subscript<StorageT>
};

static PyObject *
PyStructList_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
{
// Since the PyStructList has no real meaning when created from Python, we can reconstruct the PSL's value
// by just treating it as a list. Thus, we simply override the tp_new behaviour to return a list object here.
// Again, since we don't have tp_init for the PSL, we need to rely on the Python list's tp_init function.

return PyObject_Call( ( PyObject * ) &PyList_Type, args, kwds ); // Calls both tp_new and tp_init for a Python list
}

template<typename StorageT>
static int
PyStructList_tp_clear( PyStructList<StorageT> * self )
Expand Down Expand Up @@ -437,7 +447,7 @@ template<typename StorageT> PyTypeObject PyStructList<StorageT>::PyType = {
.tp_clear = ( inquiry ) PyStructList_tp_clear<StorageT>,
.tp_methods = PyStructList_methods<StorageT>,
.tp_alloc = PyType_GenericAlloc,
.tp_new = PyType_GenericNew,
.tp_new = PyStructList_new,
.tp_free = PyObject_GC_Del,
};

Expand Down
4 changes: 1 addition & 3 deletions csp/impl/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ def _obj_to_python(cls, obj):
)
elif isinstance(obj, dict):
return {k: cls._obj_to_python(v) for k, v in obj.items()}
elif isinstance(obj, list):
return list(cls._obj_to_python(v) for v in obj)
elif isinstance(obj, (tuple, set)):
elif isinstance(obj, (list, tuple, set)):
return type(obj)(cls._obj_to_python(v) for v in obj)
elif isinstance(obj, csp.Enum):
return obj.name # handled in _obj_from_python
Expand Down
13 changes: 13 additions & 0 deletions csp/tests/impl/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,19 @@ def test_from_dict_with_enum(self):
struct = StructWithDefaults.from_dict({"e": MyEnum.A})
self.assertEqual(MyEnum.A, getattr(struct, "e"))

def test_from_dict_with_list_derived_type(self):
class ListDerivedType(list):
def __init__(self, iterable=None):
super().__init__(iterable)

class StructWithListDerivedType(csp.Struct):
ldt: ListDerivedType

s1 = StructWithListDerivedType(ldt=ListDerivedType([1,2]))
self.assertTrue(isinstance(s1.to_dict()['ldt'], ListDerivedType))
s2 = StructWithListDerivedType.from_dict(s1.to_dict())
self.assertEqual(s1, s2)

def test_from_dict_loop_no_defaults(self):
looped = StructNoDefaults.from_dict(StructNoDefaults(a1=[9, 10]).to_dict())
self.assertEqual(looped, StructNoDefaults(a1=[9, 10]))
Expand Down