Add args checking to Void and RemotePromises then and check for double
send in Requests.
This commit is contained in:
@@ -1526,6 +1526,17 @@ cdef class _VoidPromise:
|
|||||||
if self.is_consumed:
|
if self.is_consumed:
|
||||||
raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object')
|
raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object')
|
||||||
|
|
||||||
|
argspec = None
|
||||||
|
try:
|
||||||
|
argspec = _inspect.getargspec(func)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if argspec:
|
||||||
|
args_length = len(argspec.args) if argspec.args else 0
|
||||||
|
defaults_length = len(argspec.defaults) if argspec.defaults else 0
|
||||||
|
if args_length - defaults_length != 0:
|
||||||
|
raise ValueError('Function passed to `then` call must take no arguments')
|
||||||
|
|
||||||
return Promise()._init(helpers.then(deref(self.thisptr), <PyObject *>func, <PyObject *>error_func).attach(capnp.makePyRefCounter(<PyObject *>func), capnp.makePyRefCounter(<PyObject *>error_func)), self)
|
return Promise()._init(helpers.then(deref(self.thisptr), <PyObject *>func, <PyObject *>error_func).attach(capnp.makePyRefCounter(<PyObject *>func), capnp.makePyRefCounter(<PyObject *>error_func)), self)
|
||||||
|
|
||||||
cpdef as_pypromise(self) except +reraise_kj_exception:
|
cpdef as_pypromise(self) except +reraise_kj_exception:
|
||||||
@@ -1587,6 +1598,17 @@ cdef class _RemotePromise:
|
|||||||
if self.is_consumed:
|
if self.is_consumed:
|
||||||
raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object')
|
raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object')
|
||||||
|
|
||||||
|
argspec = None
|
||||||
|
try:
|
||||||
|
argspec = _inspect.getargspec(func)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if argspec:
|
||||||
|
args_length = len(argspec.args) if argspec.args else 0
|
||||||
|
defaults_length = len(argspec.defaults) if argspec.defaults else 0
|
||||||
|
if args_length - defaults_length != 1:
|
||||||
|
raise ValueError('Function passed to `then` call must take exactly one argument')
|
||||||
|
|
||||||
Py_INCREF(func)
|
Py_INCREF(func)
|
||||||
Py_INCREF(error_func)
|
Py_INCREF(error_func)
|
||||||
|
|
||||||
@@ -1656,16 +1678,21 @@ cpdef join_promises(promises) except +reraise_kj_exception:
|
|||||||
|
|
||||||
cdef class _Request(_DynamicStructBuilder):
|
cdef class _Request(_DynamicStructBuilder):
|
||||||
cdef Request * thisptr_child
|
cdef Request * thisptr_child
|
||||||
|
cdef public bint is_consumed
|
||||||
|
|
||||||
cdef _init_child(self, Request other, parent):
|
cdef _init_child(self, Request other, parent):
|
||||||
self.thisptr_child = new Request(moveRequest(other))
|
self.thisptr_child = new Request(moveRequest(other))
|
||||||
self._init(<DynamicStruct_Builder>deref(self.thisptr_child), parent)
|
self._init(<DynamicStruct_Builder>deref(self.thisptr_child), parent)
|
||||||
|
self.is_consumed = False
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __dealloc__(self):
|
def __dealloc__(self):
|
||||||
del self.thisptr_child
|
del self.thisptr_child
|
||||||
|
|
||||||
cpdef send(self):
|
cpdef send(self):
|
||||||
|
if self.is_consumed:
|
||||||
|
raise ValueError('Request has already been sent. You can only send a request once.')
|
||||||
|
self.is_consumed = True
|
||||||
return _RemotePromise()._init(self.thisptr_child.send(), self._parent)
|
return _RemotePromise()._init(self.thisptr_child.send(), self._parent)
|
||||||
|
|
||||||
cdef class _Response(_DynamicStructReader):
|
cdef class _Response(_DynamicStructReader):
|
||||||
|
|||||||
@@ -291,6 +291,17 @@ def test_timer():
|
|||||||
joined.wait()
|
joined.wait()
|
||||||
|
|
||||||
|
|
||||||
|
def test_double_send():
|
||||||
|
client = capability.TestInterface._new_client(Server())
|
||||||
|
|
||||||
|
req = client._request('foo')
|
||||||
|
req.i = 5
|
||||||
|
|
||||||
|
req.send()
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
req.send()
|
||||||
|
|
||||||
|
|
||||||
def test_then_args():
|
def test_then_args():
|
||||||
capnp.Promise(0).then(lambda x: 1)
|
capnp.Promise(0).then(lambda x: 1)
|
||||||
|
|
||||||
@@ -299,3 +310,18 @@ def test_then_args():
|
|||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
capnp.Promise(0).then(lambda x, y: 1)
|
capnp.Promise(0).then(lambda x, y: 1)
|
||||||
|
|
||||||
|
capnp.getTimer().after_delay(1).then(lambda: 1) # after_delay is a VoidPromise
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
capnp.getTimer().after_delay(1).then(lambda x: 1)
|
||||||
|
|
||||||
|
client = capability.TestInterface._new_client(Server())
|
||||||
|
|
||||||
|
client.foo(i=5).then(lambda x: 1)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
client.foo(i=5).then(lambda: 1)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
client.foo(i=5).then(lambda x, y: 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user