diff --git a/capnp/capnp.pyx b/capnp/capnp.pyx index 8391a3f..9a3f89a 100644 --- a/capnp/capnp.pyx +++ b/capnp/capnp.pyx @@ -1163,7 +1163,7 @@ cdef class EventLoop: Py_INCREF(func) return Promise()._init(capnp.evalLater(self.thisptr, func)) - cpdef wait_remote(self, _RemotePromise promise) except +: + cpdef wait(self, _RemotePromise promise) except +: if promise.is_consumed: raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object') @@ -1263,6 +1263,28 @@ cdef class _DynamicCapabilityClient: return _partial(self._request, short_name) return _partial(self._send, name) + cpdef upcast(self, schema) except+: + cdef _InterfaceSchema s + if hasattr(schema, 'schema'): + s = schema.schema + else: + s = schema + + return _DynamicCapabilityClient()._init(self.thisptr.upcast(s.thisptr), self._parent) + + cpdef cast_as(self, schema) except+: + cdef _InterfaceSchema s + if hasattr(schema, 'schema'): + s = schema.schema + else: + s = schema + return _DynamicCapabilityClient()._init(self.thisptr.castAs(s.thisptr), self._parent) + + property schema: + """A property that returns the _InterfaceSchema object matching this client""" + def __get__(self): + return _InterfaceSchema()._init(self.thisptr.getSchema()) + cdef class _CapabilityClient: cdef C_Capability.Client * thisptr cdef public object _parent diff --git a/capnp/capnp_cpp.pxd b/capnp/capnp_cpp.pxd index c799849..eabefc9 100644 --- a/capnp/capnp_cpp.pxd +++ b/capnp/capnp_cpp.pxd @@ -157,6 +157,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": Client() Client(Client&) Client upcast(InterfaceSchema requestedSchema) + DynamicCapability.Client castAs"castAs< ::capnp::DynamicCapability>"(InterfaceSchema) InterfaceSchema getSchema() Request newRequest(char * methodName, uint firstSegmentWordSize) diff --git a/examples/example_capability.py b/examples/example_capability.py index ba356e8..78006d4 100644 --- a/examples/example_capability.py +++ b/examples/example_capability.py @@ -30,7 +30,7 @@ def example_simple_rpc(): cap = cap.cast_as(capability.TestInterface) remote = cap.foo(i=5) - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '125' diff --git a/examples/example_client.py b/examples/example_client.py index 075d6d0..90c65c3 100644 --- a/examples/example_client.py +++ b/examples/example_client.py @@ -18,7 +18,7 @@ def example_client(): cap = cap.cast_as(test_capnp.TestInterface) remote = cap.foo(i=5) - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == 'foo' diff --git a/test/test_capability.capnp b/test/test_capability.capnp index 8ce0030..9939e5f 100644 --- a/test/test_capability.capnp +++ b/test/test_capability.capnp @@ -29,11 +29,9 @@ interface TestInterface { # baz @2 (s: TestAllTypes); } -# interface TestExtends extends(TestInterface) { -# qux @0 (); -# corge @1 TestAllTypes -> (); -# grault @2 () -> TestAllTypes; -# } +interface TestExtends extends(TestInterface) { + qux @0 (); +} interface TestPipeline { getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box); diff --git a/test/test_capability.py b/test/test_capability.py index 857e319..230abaa 100644 --- a/test/test_capability.py +++ b/test/test_capability.py @@ -32,7 +32,7 @@ def test_client(capability): req.i = 5 remote = req.send() - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '26' @@ -40,7 +40,7 @@ def test_client(capability): req.i = 5 remote = req.send() - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '26' @@ -63,13 +63,13 @@ def test_simple_client(capability): client = capability.TestInterface.new_client(Server(), loop) remote = client._send('foo', i=5) - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '26' remote = client.foo(i=5) - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '26' @@ -93,10 +93,10 @@ def test_pipeline(capability): outCap = remote.outBox.cap pipelinePromise = outCap.foo(i=10) - response = loop.wait_remote(pipelinePromise) + response = loop.wait(pipelinePromise) assert response.x == '150' - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.s == '26_foo' class BadServer: @@ -114,7 +114,7 @@ def test_exception_client(capability): remote = client._send('foo', i=5) with pytest.raises(ValueError): - loop.wait_remote(remote) + loop.wait(remote) class BadPipelineServer: def getCap(self, context): @@ -135,7 +135,7 @@ def test_exception_chain(capability): remote = client.getCap(n=5, inCap=foo_client) try: - loop.wait_remote(remote) + loop.wait(remote) except Exception as e: assert str(e) == 'test' @@ -151,7 +151,17 @@ def test_pipeline_exception(capability): pipelinePromise = outCap.foo(i=10) with pytest.raises(Exception): - loop.wait_remote(pipelinePromise) + loop.wait(pipelinePromise) with pytest.raises(Exception): - loop.wait_remote(remote) + loop.wait(remote) + +def test_casting(capability): + loop = capnp.EventLoop() + + client = capability.TestExtends.new_client(Server(), loop) + client2 = client.upcast(capability.TestInterface) + client3 = client2.cast_as(capability.TestInterface) + + with pytest.raises(Exception): + client.upcast(capability.TestPipeline) diff --git a/test/test_rpc.py b/test/test_rpc.py index ec29984..bd0468a 100644 --- a/test/test_rpc.py +++ b/test/test_rpc.py @@ -35,6 +35,6 @@ def test_simple_rpc(capability): cap = cap.cast_as(capability.TestInterface) remote = cap.foo(i=5) - response = loop.wait_remote(remote) + response = loop.wait(remote) assert response.x == '125'