From 9012c0ec288d0bba8ccbd984118d6a2db72a8f9e Mon Sep 17 00:00:00 2001 From: Lasse Blaauwbroek Date: Tue, 7 Nov 2023 05:18:29 +0100 Subject: [PATCH] Support `_DynamicListReader` in `_setDynamicField` See the test for an explanation. Note that I'm not sure what the purpose of `_setDynamicFieldWithField` and `_setDynamicFieldStatic` is. It does not appear to be used. I've kept them for now (they are a public API), but perhaps this can be removed. --- capnp/includes/capnp_cpp.pxd | 1 + capnp/lib/capnp.pyx | 22 ++++++++++++++++++++++ test/test_capability.capnp | 2 ++ test/test_capability.py | 12 ++++++++++++ 4 files changed, 37 insertions(+) diff --git a/capnp/includes/capnp_cpp.pxd b/capnp/includes/capnp_cpp.pxd index 9191eae1..a7ca4c63 100644 --- a/capnp/includes/capnp_cpp.pxd +++ b/capnp/includes/capnp_cpp.pxd @@ -362,6 +362,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": void adopt(uint, DynamicOrphan) except +reraise_kj_exception DynamicOrphan disown(uint) StructSchema getStructElementType'getSchema().getStructElementType'() + DynamicList.Reader asReader() except +reraise_kj_exception cdef extern from "capnp/any.h" namespace " ::capnp": cdef cppclass AnyPointer nogil: diff --git a/capnp/lib/capnp.pyx b/capnp/lib/capnp.pyx index 2deac643..ea31e731 100644 --- a/capnp/lib/capnp.pyx +++ b/capnp/lib/capnp.pyx @@ -714,6 +714,14 @@ cdef C_DynamicValue.Reader _extract_dynamic_struct_reader(_DynamicStructReader v return C_DynamicValue.Reader(value.thisptr) +cdef C_DynamicValue.Reader _extract_dynamic_list_builder(_DynamicListBuilder value): + return C_DynamicValue.Reader(value.thisptr.asReader()) + + +cdef C_DynamicValue.Reader _extract_dynamic_list_reader(_DynamicListReader value): + return C_DynamicValue.Reader(value.thisptr) + + cdef C_DynamicValue.Reader _extract_dynamic_client(_DynamicCapabilityClient value): return C_DynamicValue.Reader(value.thisptr) @@ -805,6 +813,10 @@ cdef _setDynamicField(_DynamicSetterClasses thisptr, field, value, parent): thisptr.set(field, _extract_dynamic_struct_builder(value)) elif value_type is _DynamicStructReader: thisptr.set(field, _extract_dynamic_struct_reader(value)) + elif value_type is _DynamicListBuilder: + thisptr.set(field, _extract_dynamic_list_builder(value)) + elif value_type is _DynamicListReader: + thisptr.set(field, _extract_dynamic_list_reader(value)) elif value_type is _DynamicCapabilityClient: thisptr.set(field, _extract_dynamic_client(value)) elif isinstance(value, _DynamicCapabilityServer): @@ -821,6 +833,7 @@ cdef _setDynamicField(_DynamicSetterClasses thisptr, field, value, parent): .format(field, str(value), str(type(value)))) +# TODO: Is this function used by anyone? Can it be removed? cdef _setDynamicFieldWithField(DynamicStruct_Builder thisptr, _StructSchemaField field, value, parent): cdef C_DynamicValue.Reader temp value_type = type(value) @@ -854,6 +867,10 @@ cdef _setDynamicFieldWithField(DynamicStruct_Builder thisptr, _StructSchemaField thisptr.setByField(field.thisptr, _extract_dynamic_struct_builder(value)) elif value_type is _DynamicStructReader: thisptr.setByField(field.thisptr, _extract_dynamic_struct_reader(value)) + elif value_type is _DynamicListBuilder: + thisptr.setByField(field.thisptr, _extract_dynamic_list_builder(value)) + elif value_type is _DynamicListReader: + thisptr.setByField(field.thisptr, _extract_dynamic_list_reader(value)) elif value_type is _DynamicCapabilityClient: thisptr.setByField(field.thisptr, _extract_dynamic_client(value)) elif isinstance(value, _DynamicCapabilityServer): @@ -870,6 +887,7 @@ cdef _setDynamicFieldWithField(DynamicStruct_Builder thisptr, _StructSchemaField .format(field, str(value), str(type(value)))) +# TODO: Is this function used by anyone? Can it be removed? cdef _setDynamicFieldStatic(DynamicStruct_Builder thisptr, field, value, parent): cdef C_DynamicValue.Reader temp value_type = type(value) @@ -903,6 +921,10 @@ cdef _setDynamicFieldStatic(DynamicStruct_Builder thisptr, field, value, parent) thisptr.set(field, _extract_dynamic_struct_builder(value)) elif value_type is _DynamicStructReader: thisptr.set(field, _extract_dynamic_struct_reader(value)) + elif value_type is _DynamicListBuilder: + thisptr.set(field, _extract_dynamic_list_builder(value)) + elif value_type is _DynamicListReader: + thisptr.set(field, _extract_dynamic_list_reader(value)) elif value_type is _DynamicCapabilityClient: thisptr.set(field, _extract_dynamic_client(value)) elif isinstance(value, _DynamicCapabilityServer): diff --git a/test/test_capability.capnp b/test/test_capability.capnp index 6770a3a1..a7355384 100644 --- a/test/test_capability.capnp +++ b/test/test_capability.capnp @@ -28,6 +28,8 @@ interface TestInterface { bar @1 () -> (); buz @2 (i: TestSturdyRefHostId) -> (x: Text); bam @3 (i :UInt32, j :Bool) -> (x: Text, i:UInt32); + bak1 @4 () -> (i:List(UInt32)); + bak2 @5 (i:List(UInt32)) -> (); # baz @2 (s: TestAllTypes); } diff --git a/test/test_capability.py b/test/test_capability.py index da732b2c..acc84710 100644 --- a/test/test_capability.py +++ b/test/test_capability.py @@ -26,6 +26,12 @@ async def buz(self, i, **kwargs): async def bam(self, i, **kwargs): return str(i) + "_test", i + async def bak1(self, **kwargs): + return [1,2,3,4,5] + + async def bak2(self, i, **kwargs): + assert i[4] == 5 + class PipelineServer(capability.TestPipeline.Server): async def getCap(self, n, inCap, _context, **kwargs): @@ -67,6 +73,12 @@ async def test_client(): with pytest.raises(AttributeError): req.baz = 1 + resp = await client.bak1() + # Used to fail with + # capnp.lib.capnp.KjException: Tried to set field: 'i' with a value of: '[1, 2, 3, 4, 5]' + # which is an unsupported type: '' + await client.bak2(resp.i) + async def test_simple_client(): client = capability.TestInterface._new_client(Server())