diff options
author | Mark Spruiell <mes@zeroc.com> | 2016-12-09 15:18:08 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2016-12-09 15:18:08 -0800 |
commit | 3b7e9f99b61538e0bbd6f07deeb7f7cb12013ed5 (patch) | |
tree | a8edbf5d1043527cc50880b34ee83458ed7e4855 /python | |
parent | Merge remote-tracking branch 'origin/3.6' (diff) | |
download | ice-3b7e9f99b61538e0bbd6f07deeb7f7cb12013ed5.tar.bz2 ice-3b7e9f99b61538e0bbd6f07deeb7f7cb12013ed5.tar.xz ice-3b7e9f99b61538e0bbd6f07deeb7f7cb12013ed5.zip |
ICE-7138 - new Python AMI mapping based on futures and modified AMD mapping
Diffstat (limited to 'python')
46 files changed, 5468 insertions, 1891 deletions
diff --git a/python/modules/IcePy/Communicator.cpp b/python/modules/IcePy/Communicator.cpp index eb223c85853..927c3cab5d2 100644 --- a/python/modules/IcePy/Communicator.cpp +++ b/python/modules/IcePy/Communicator.cpp @@ -723,6 +723,48 @@ communicatorFlushBatchRequests(CommunicatorObject* self) extern "C" #endif static PyObject* +communicatorFlushBatchRequestsAsync(CommunicatorObject* self, PyObject* /*args*/, PyObject* /*kwds*/) +{ + assert(self->communicator); + const string op = "flushBatchRequests"; + + FlushAsyncCallbackPtr d = new FlushAsyncCallback(op); + Ice::Callback_Communicator_flushBatchRequestsPtr cb = + Ice::newCallback_Communicator_flushBatchRequests(d, &FlushAsyncCallback::exception, &FlushAsyncCallback::sent); + + Ice::AsyncResultPtr result; + + try + { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + + result = (*self->communicator)->begin_flushBatchRequests(cb); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + return 0; + } + + PyObjectHandle asyncResultObj = createAsyncResult(result, 0, 0, self->wrapper); + if(!asyncResultObj.get()) + { + return 0; + } + + PyObjectHandle future = createFuture(op, asyncResultObj.get()); + if(!future.get()) + { + return 0; + } + d->setFuture(future.get()); + return future.release(); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* communicatorBeginFlushBatchRequests(CommunicatorObject* self, PyObject* args, PyObject* kwds) { assert(self->communicator); @@ -1608,6 +1650,8 @@ static PyMethodDef CommunicatorMethods[] = PyDoc_STR(STRCAST("setDefaultLocator(proxy) -> None")) }, { STRCAST("flushBatchRequests"), reinterpret_cast<PyCFunction>(communicatorFlushBatchRequests), METH_NOARGS, PyDoc_STR(STRCAST("flushBatchRequests() -> None")) }, + { STRCAST("flushBatchRequestsAsync"), reinterpret_cast<PyCFunction>(communicatorFlushBatchRequestsAsync), + METH_NOARGS, PyDoc_STR(STRCAST("flushBatchRequestsAsync() -> Ice.Future")) }, { STRCAST("begin_flushBatchRequests"), reinterpret_cast<PyCFunction>(communicatorBeginFlushBatchRequests), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_flushBatchRequests([_ex][, _sent]) -> Ice.AsyncResult")) }, @@ -1734,8 +1778,19 @@ IcePy::getCommunicatorWrapper(const Ice::CommunicatorPtr& communicator) CommunicatorMap::iterator p = _communicatorMap.find(communicator); assert(p != _communicatorMap.end()); CommunicatorObject* obj = reinterpret_cast<CommunicatorObject*>(p->second); - Py_INCREF(obj->wrapper); - return obj->wrapper; + if(obj->wrapper) + { + Py_INCREF(obj->wrapper); + return obj->wrapper; + } + else + { + // + // Communicator must have been destroyed already. + // + Py_INCREF(Py_None); + return Py_None; + } } extern "C" diff --git a/python/modules/IcePy/Connection.cpp b/python/modules/IcePy/Connection.cpp index 2f5998bffc9..ec1e4f8db68 100644 --- a/python/modules/IcePy/Connection.cpp +++ b/python/modules/IcePy/Connection.cpp @@ -379,6 +379,50 @@ connectionFlushBatchRequests(ConnectionObject* self) extern "C" #endif static PyObject* +connectionFlushBatchRequestsAsync(ConnectionObject* self, PyObject* /*args*/, PyObject* /*kwds*/) +{ + assert(self->connection); + const string op = "flushBatchRequests"; + + FlushAsyncCallbackPtr d = new FlushAsyncCallback(op); + Ice::Callback_Connection_flushBatchRequestsPtr cb = + Ice::newCallback_Connection_flushBatchRequests(d, &FlushAsyncCallback::exception, &FlushAsyncCallback::sent); + + Ice::AsyncResultPtr result; + + try + { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + + result = (*self->connection)->begin_flushBatchRequests(cb); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + return 0; + } + + PyObjectHandle communicatorObj = getCommunicatorWrapper(*self->communicator); + PyObjectHandle asyncResultObj = + createAsyncResult(result, 0, reinterpret_cast<PyObject*>(self), communicatorObj.get()); + if(!asyncResultObj.get()) + { + return 0; + } + + PyObjectHandle future = createFuture(op, asyncResultObj.get()); + if(!future.get()) + { + return 0; + } + d->setFuture(future.get()); + return future.release(); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* connectionBeginFlushBatchRequests(ConnectionObject* self, PyObject* args, PyObject* kwds) { assert(self->connection); @@ -821,6 +865,8 @@ static PyMethodDef ConnectionMethods[] = PyDoc_STR(STRCAST("getAdapter() -> Ice.ObjectAdapter")) }, { STRCAST("flushBatchRequests"), reinterpret_cast<PyCFunction>(connectionFlushBatchRequests), METH_NOARGS, PyDoc_STR(STRCAST("flushBatchRequests() -> None")) }, + { STRCAST("flushBatchRequestsAsync"), reinterpret_cast<PyCFunction>(connectionFlushBatchRequestsAsync), + METH_NOARGS, PyDoc_STR(STRCAST("flushBatchRequestsAsync() -> Ice.Future")) }, { STRCAST("begin_flushBatchRequests"), reinterpret_cast<PyCFunction>(connectionBeginFlushBatchRequests), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_flushBatchRequests([_ex][, _sent]) -> Ice.AsyncResult")) }, { STRCAST("end_flushBatchRequests"), reinterpret_cast<PyCFunction>(connectionEndFlushBatchRequests), METH_VARARGS, diff --git a/python/modules/IcePy/ObjectAdapter.cpp b/python/modules/IcePy/ObjectAdapter.cpp index a51cca80c93..d2718b1ca50 100644 --- a/python/modules/IcePy/ObjectAdapter.cpp +++ b/python/modules/IcePy/ObjectAdapter.cpp @@ -181,7 +181,7 @@ IcePy::ServantLocatorWrapper::locate(const Ice::Current& current, Ice::LocalObje { if(PyTuple_GET_SIZE(res.get()) > 2) { - PyErr_Warn(PyExc_RuntimeWarning, STRCAST("invalid return value for ServantLocator::locate")); + PyErr_WarnEx(PyExc_RuntimeWarning, STRCAST("invalid return value for ServantLocator::locate"), 1); return 0; } servantObj = PyTuple_GET_ITEM(res.get(), 0); @@ -200,7 +200,7 @@ IcePy::ServantLocatorWrapper::locate(const Ice::Current& current, Ice::LocalObje // if(!PyObject_IsInstance(servantObj, _objectType)) { - PyErr_Warn(PyExc_RuntimeWarning, STRCAST("return value of ServantLocator::locate is not an Ice object")); + PyErr_WarnEx(PyExc_RuntimeWarning, STRCAST("return value of ServantLocator::locate is not an Ice object"), 1); return 0; } diff --git a/python/modules/IcePy/Operation.cpp b/python/modules/IcePy/Operation.cpp index 3b62b8aef59..6c32d861806 100644 --- a/python/modules/IcePy/Operation.cpp +++ b/python/modules/IcePy/Operation.cpp @@ -27,6 +27,7 @@ #include <Ice/AsyncResult.h> #include <Ice/Properties.h> #include <Ice/Proxy.h> +#include <IceUtil/Time.h> #include <Slice/PythonUtil.h> using namespace std; @@ -104,50 +105,44 @@ public: protected: - Ice::ObjectPrx _prx; -}; -typedef IceUtil::Handle<Invocation> InvocationPtr; - -// -// TypedInvocation uses the information in the given Operation to validate, marshal, and unmarshal -// parameters and exceptions. -// -class TypedInvocation : virtual public Invocation -{ -public: + // + // Helpers for typed invocations. + // - TypedInvocation(const Ice::ObjectPrx&, const OperationPtr&); + enum MappingType { SyncMapping, AsyncMapping, NewAsyncMapping }; -protected: + bool prepareRequest(const OperationPtr&, PyObject*, MappingType, Ice::OutputStream*, + pair<const Ice::Byte*, const Ice::Byte*>&); + PyObject* unmarshalResults(const OperationPtr&, const pair<const Ice::Byte*, const Ice::Byte*>&); + PyObject* unmarshalException(const OperationPtr&, const pair<const Ice::Byte*, const Ice::Byte*>&); + bool validateException(const OperationPtr&, PyObject*) const; + void checkTwowayOnly(const OperationPtr&, const Ice::ObjectPrx&) const; - OperationPtr _op; + Ice::ObjectPrx _prx; Ice::CommunicatorPtr _communicator; - - enum MappingType { SyncMapping, AsyncMapping, OldAsyncMapping }; - - bool prepareRequest(PyObject*, MappingType, Ice::OutputStream*, pair<const Ice::Byte*, const Ice::Byte*>&); - PyObject* unmarshalResults(const pair<const Ice::Byte*, const Ice::Byte*>&); - PyObject* unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>&); - bool validateException(PyObject*) const; - void checkTwowayOnly(const Ice::ObjectPrx&) const; }; +typedef IceUtil::Handle<Invocation> InvocationPtr; // // Synchronous typed invocation. // -class SyncTypedInvocation : virtual public TypedInvocation +class SyncTypedInvocation : public Invocation { public: SyncTypedInvocation(const Ice::ObjectPrx&, const OperationPtr&); virtual PyObject* invoke(PyObject*, PyObject* = 0); + +private: + + OperationPtr _op; }; // // Asynchronous typed invocation. // -class AsyncTypedInvocation : virtual public TypedInvocation +class AsyncTypedInvocation : public Invocation { public: @@ -163,10 +158,11 @@ public: void exception(const Ice::Exception&); void sent(bool); -protected: +private: void checkAsyncTwowayOnly(const Ice::ObjectPrx&) const; + OperationPtr _op; PyObject* _pyProxy; PyObject* _response; PyObject* _ex; @@ -175,14 +171,14 @@ protected: typedef IceUtil::Handle<AsyncTypedInvocation> AsyncTypedInvocationPtr; // -// Old-style asynchronous typed invocation. +// Asynchronous invocation with futures. // -class OldAsyncTypedInvocation : virtual public TypedInvocation +class NewAsyncInvocation : public Invocation { public: - OldAsyncTypedInvocation(const Ice::ObjectPrx&, const OperationPtr&); - ~OldAsyncTypedInvocation(); + NewAsyncInvocation(const Ice::ObjectPrx&, PyObject*, const string&); + ~NewAsyncInvocation(); virtual PyObject* invoke(PyObject*, PyObject* = 0); @@ -192,13 +188,47 @@ public: protected: - PyObject* _callback; + virtual Ice::AsyncResultPtr handleInvoke(PyObject*, PyObject*) = 0; + virtual void handleResponse(PyObject*, bool, const pair<const Ice::Byte*, const Ice::Byte*>&) = 0; + + PyObject* _pyProxy; + string _operation; + bool _twoway; + bool _sent; + bool _sentSynchronously; + bool _done; + PyObject* _future; + bool _ok; + vector<Ice::Byte> _results; + PyObject* _exception; +}; +typedef IceUtil::Handle<NewAsyncInvocation> NewAsyncInvocationPtr; + +// +// New-style asynchronous typed invocation. +// +class NewAsyncTypedInvocation : public NewAsyncInvocation +{ +public: + + NewAsyncTypedInvocation(const Ice::ObjectPrx&, PyObject*, const OperationPtr&); + +protected: + + virtual Ice::AsyncResultPtr handleInvoke(PyObject*, PyObject*); + virtual void handleResponse(PyObject*, bool, const pair<const Ice::Byte*, const Ice::Byte*>&); + +private: + + void checkAsyncTwowayOnly(const Ice::ObjectPrx&) const; + + OperationPtr _op; }; // // Synchronous blobject invocation. // -class SyncBlobjectInvocation : virtual public Invocation +class SyncBlobjectInvocation : public Invocation { public: @@ -210,7 +240,7 @@ public: // // Asynchronous blobject invocation. // -class AsyncBlobjectInvocation : virtual public Invocation +class AsyncBlobjectInvocation : public Invocation { public: @@ -235,80 +265,83 @@ protected: typedef IceUtil::Handle<AsyncBlobjectInvocation> AsyncBlobjectInvocationPtr; // -// Old-style asynchronous blobject invocation. +// New-style asynchronous blobject invocation. // -class OldAsyncBlobjectInvocation : virtual public Invocation +class NewAsyncBlobjectInvocation : public NewAsyncInvocation { public: - OldAsyncBlobjectInvocation(const Ice::ObjectPrx&); - ~OldAsyncBlobjectInvocation(); - - virtual PyObject* invoke(PyObject*, PyObject* = 0); - - void response(bool, const pair<const Ice::Byte*, const Ice::Byte*>&); - void exception(const Ice::Exception&); - void sent(bool); + NewAsyncBlobjectInvocation(const Ice::ObjectPrx&, PyObject*); protected: + virtual Ice::AsyncResultPtr handleInvoke(PyObject*, PyObject*); + virtual void handleResponse(PyObject*, bool, const pair<const Ice::Byte*, const Ice::Byte*>&); + string _op; - PyObject* _callback; }; // // The base class for server-side upcalls. // -class Upcall : virtual public IceUtil::Shared +class Upcall : public IceUtil::Shared { public: virtual void dispatch(PyObject*, const pair<const Ice::Byte*, const Ice::Byte*>&, const Ice::Current&) = 0; - virtual void response(PyObject*, const Ice::EncodingVersion&) = 0; - virtual void exception(PyException&, const Ice::EncodingVersion&) = 0; + virtual void response(PyObject*) = 0; + virtual void exception(PyException&) = 0; + virtual void exception(const Ice::Exception&) = 0; + +protected: + + void dispatchImpl(PyObject*, const string&, PyObject*, const Ice::Current&); }; typedef IceUtil::Handle<Upcall> UpcallPtr; // -// TypedInvocation uses the information in the given Operation to validate, marshal, and unmarshal +// TypedUpcall uses the information in the given Operation to validate, marshal, and unmarshal // parameters and exceptions. // -class TypedUpcall : virtual public Upcall +class TypedUpcall; +typedef IceUtil::Handle<TypedUpcall> TypedUpcallPtr; + +class TypedUpcall : public Upcall { public: TypedUpcall(const OperationPtr&, const Ice::AMD_Object_ice_invokePtr&, const Ice::CommunicatorPtr&); virtual void dispatch(PyObject*, const pair<const Ice::Byte*, const Ice::Byte*>&, const Ice::Current&); - virtual void response(PyObject*, const Ice::EncodingVersion&); - virtual void exception(PyException&, const Ice::EncodingVersion&); + virtual void response(PyObject*); + virtual void exception(PyException&); + virtual void exception(const Ice::Exception&); private: OperationPtr _op; Ice::AMD_Object_ice_invokePtr _callback; Ice::CommunicatorPtr _communicator; - bool _finished; + Ice::EncodingVersion _encoding; }; // // Upcall for blobject servants. // -class BlobjectUpcall : virtual public Upcall +class BlobjectUpcall : public Upcall { public: - BlobjectUpcall(bool, const Ice::AMD_Object_ice_invokePtr&); + BlobjectUpcall(const Ice::AMD_Object_ice_invokePtr&); virtual void dispatch(PyObject*, const pair<const Ice::Byte*, const Ice::Byte*>&, const Ice::Current&); - virtual void response(PyObject*, const Ice::EncodingVersion&); - virtual void exception(PyException&, const Ice::EncodingVersion&); + virtual void response(PyObject*); + virtual void exception(PyException&); + virtual void exception(const Ice::Exception&); private: - bool _amd; Ice::AMD_Object_ice_invokePtr _callback; - bool _finished; }; // @@ -356,11 +389,19 @@ struct OperationObject OperationPtr* op; }; -struct AMDCallbackObject +struct DoneCallbackObject +{ + PyObject_HEAD + UpcallPtr* upcall; +#if PY_VERSION_HEX >= 0x03050000 + PyObject* coroutine; +#endif +}; + +struct DispatchCallbackObject { PyObject_HEAD UpcallPtr* upcall; - Ice::EncodingVersion encoding; }; struct AsyncResultObject @@ -374,7 +415,6 @@ struct AsyncResultObject }; extern PyTypeObject OperationType; -extern PyTypeObject AMDCallbackType; class UserExceptionFactory : public Ice::UserExceptionFactory { @@ -424,8 +464,7 @@ handleException() void callException(PyObject* method, PyObject* ex) { - PyObjectHandle args = Py_BuildValue(STRCAST("(O)"), ex); - PyObjectHandle tmp = PyObject_Call(method, args.get(), 0); + PyObjectHandle tmp = callMethod(method, ex); if(PyErr_Occurred()) { handleException(); // Callback raised an exception. @@ -441,61 +480,20 @@ callException(PyObject* method, const Ice::Exception& ex) } void -callException(PyObject* callback, const string& op, const string& method, PyObject* ex) -{ - if(!PyObject_HasAttrString(callback, STRCAST(method.c_str()))) - { - ostringstream ostr; - ostr << "AMI callback object for operation `" << op << "' does not define " << method << "()"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - } - else - { - PyObjectHandle m = PyObject_GetAttrString(callback, STRCAST(method.c_str())); - assert(m.get()); - callException(m.get(), ex); - } -} - -void -callException(PyObject* callback, const string& op, const string& method, const Ice::Exception& ex) -{ - PyObjectHandle exh = convertException(ex); - assert(exh.get()); - callException(callback, op, method, exh.get()); -} - -void callSent(PyObject* method, bool sentSynchronously, bool passArg) { - PyObjectHandle args; + PyObject* arg = 0; if(passArg) { - args = Py_BuildValue(STRCAST("(O)"), sentSynchronously ? getTrue() : getFalse()); + arg = sentSynchronously ? getTrue() : getFalse(); } - else - { - args = PyTuple_New(0); - } - PyObjectHandle tmp = PyObject_Call(method, args.get(), 0); + PyObjectHandle tmp = callMethod(method, arg); if(PyErr_Occurred()) { handleException(); // Callback raised an exception. } } -void -callSent(PyObject* callback, const string& method, bool sentSynchronously, bool passArg) -{ - if(PyObject_HasAttrString(callback, STRCAST(method.c_str()))) - { - PyObjectHandle m = PyObject_GetAttrString(callback, STRCAST(method.c_str())); - assert(m.get()); - callSent(m.get(), sentSynchronously, passArg); - } -} - } #ifdef WIN32 @@ -581,17 +579,15 @@ extern "C" static PyObject* operationInvokeAsync(OperationObject* self, PyObject* args) { - PyObject* pyProxy; + PyObject* proxy; PyObject* opArgs; - if(!PyArg_ParseTuple(args, STRCAST("O!O!"), &ProxyType, &pyProxy, &PyTuple_Type, &opArgs)) + if(!PyArg_ParseTuple(args, STRCAST("O!O!"), &ProxyType, &proxy, &PyTuple_Type, &opArgs)) { return 0; } - Ice::ObjectPrx prx = getProxy(pyProxy); - assert(self->op); - - InvocationPtr i = new OldAsyncTypedInvocation(prx, *self->op); + Ice::ObjectPrx p = getProxy(proxy); + InvocationPtr i = new NewAsyncTypedInvocation(p, proxy, *self->op); return i->invoke(opArgs); } @@ -654,26 +650,28 @@ operationDeprecate(OperationObject* self, PyObject* args) assert(self->op); (*self->op)->deprecate(msg); - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } // -// AMDCallback operations +// DoneCallback operations // #ifdef WIN32 extern "C" #endif -static AMDCallbackObject* -amdCallbackNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) +static DoneCallbackObject* +doneCallbackNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) { - AMDCallbackObject* self = reinterpret_cast<AMDCallbackObject*>(type->tp_alloc(type, 0)); + DoneCallbackObject* self = reinterpret_cast<DoneCallbackObject*>(type->tp_alloc(type, 0)); if(!self) { return 0; } self->upcall = 0; +#if PY_VERSION_HEX >= 0x03050000 + self->coroutine = 0; +#endif return self; } @@ -681,9 +679,12 @@ amdCallbackNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) extern "C" #endif static void -amdCallbackDealloc(AMDCallbackObject* self) +doneCallbackDealloc(DoneCallbackObject* self) { delete self->upcall; +#if PY_VERSION_HEX >= 0x03050000 + Py_XDECREF(self->coroutine); +#endif Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); } @@ -691,12 +692,32 @@ amdCallbackDealloc(AMDCallbackObject* self) extern "C" #endif static PyObject* -amdCallbackIceResponse(AMDCallbackObject* self, PyObject* args) +doneCallbackInvoke(DoneCallbackObject* self, PyObject* args) { + PyObject* future = 0; + if(!PyArg_ParseTuple(args, STRCAST("O"), &future)) + { + return 0; + } + try { assert(self->upcall); - (*self->upcall)->response(args, self->encoding); + + PyObjectHandle resultMethod = PyObject_GetAttrString(future, STRCAST("result")); + assert(resultMethod.get()); + PyObjectHandle empty = PyTuple_New(0); + PyObjectHandle result = PyObject_Call(resultMethod.get(), empty.get(), 0); + + if(PyErr_Occurred()) + { + PyException ex; + (*self->upcall)->exception(ex); + } + else + { + (*self->upcall)->response(result.get()); + } } catch(...) { @@ -706,33 +727,83 @@ amdCallbackIceResponse(AMDCallbackObject* self, PyObject* args) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); +} + +// +// DispatchCallbackObject operations +// + +#ifdef WIN32 +extern "C" +#endif +static DispatchCallbackObject* +dispatchCallbackNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) +{ + DispatchCallbackObject* self = reinterpret_cast<DispatchCallbackObject*>(type->tp_alloc(type, 0)); + if(!self) + { + return 0; + } + self->upcall = 0; + return self; +} + +#ifdef WIN32 +extern "C" +#endif +static void +dispatchCallbackDealloc(DispatchCallbackObject* self) +{ + delete self->upcall; + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); } #ifdef WIN32 extern "C" #endif static PyObject* -amdCallbackIceException(AMDCallbackObject* self, PyObject* args) +dispatchCallbackResponse(DispatchCallbackObject* self, PyObject* args) { - PyObject* ex; - if(!PyArg_ParseTuple(args, STRCAST("O"), &ex)) + PyObject* result = 0; + if(!PyArg_ParseTuple(args, STRCAST("O"), &result)) { return 0; } - if(!PyObject_IsInstance(ex, PyExc_Exception)) + try + { + assert(self->upcall); + (*self->upcall)->response(result); + } + catch(...) + { + // + // No exceptions should propagate to Python. + // + assert(false); + } + + return incRef(Py_None); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +dispatchCallbackException(DispatchCallbackObject* self, PyObject* args) +{ + PyObject* ex = 0; + if(!PyArg_ParseTuple(args, STRCAST("O"), &ex)) { - PyErr_Format(PyExc_TypeError, "ice_exception argument is not an exception"); return 0; } try { assert(self->upcall); - PyException pye(ex); // No traceback information available. - (*self->upcall)->exception(pye, self->encoding); + PyException pyex(ex); + (*self->upcall)->exception(pyex); } catch(...) { @@ -742,8 +813,7 @@ amdCallbackIceException(AMDCallbackObject* self, PyObject* args) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } // @@ -791,12 +861,10 @@ asyncResultGetCommunicator(AsyncResultObject* self) { if(self->communicator) { - Py_INCREF(self->communicator); - return self->communicator; + return incRef(self->communicator); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -814,8 +882,7 @@ asyncResultCancel(AsyncResultObject* self) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -826,12 +893,10 @@ asyncResultGetConnection(AsyncResultObject* self) { if(self->connection) { - Py_INCREF(self->connection); - return self->connection; + return incRef(self->connection); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -842,12 +907,10 @@ asyncResultGetProxy(AsyncResultObject* self) { if(self->proxy) { - Py_INCREF(self->proxy); - return self->proxy; + return incRef(self->proxy); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -888,8 +951,7 @@ asyncResultWaitForCompleted(AsyncResultObject* self) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -930,8 +992,7 @@ asyncResultWaitForSent(AsyncResultObject* self) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -955,8 +1016,7 @@ asyncResultThrowLocalException(AsyncResultObject* self) assert(false); } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } #ifdef WIN32 @@ -1017,6 +1077,72 @@ asyncResultGetOperation(AsyncResultObject* self) return createString(op); } +#ifdef WIN32 +extern "C" +#endif +static PyObject* +asyncResultCallLater(AsyncResultObject* self, PyObject* args) +{ + PyObject* callback; + if(!PyArg_ParseTuple(args, STRCAST("O"), &callback)) + { + return 0; + } + + if(!PyCallable_Check(callback)) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid argument passed to callLater")); + return 0; + } + + class CallbackI : public Ice::AsyncResult::Callback + { + public: + + CallbackI(PyObject* callback) : + _callback(incRef(callback)) + { + } + + ~CallbackI() + { + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + Py_DECREF(_callback); + } + + virtual void run() + { + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + PyObjectHandle args = PyTuple_New(0); + assert(args.get()); + PyObjectHandle tmp = PyObject_Call(_callback, args.get(), 0); + PyErr_Clear(); + } + + private: + + PyObject* _callback; + }; + + try + { + (*self->result)->scheduleCallback(new CallbackI(callback)); + } + catch(const Ice::CommunicatorDestroyedException& ex) + { + setPythonException(ex); + return 0; + } + catch(...) + { + assert(false); + } + + return incRef(Py_None); +} + // // ParamInfo implementation. // @@ -1025,8 +1151,7 @@ IcePy::ParamInfo::unmarshaled(PyObject* val, PyObject* target, void* closure) { assert(PyTuple_Check(target)); Py_ssize_t i = reinterpret_cast<Py_ssize_t>(closure); - PyTuple_SET_ITEM(target, i, val); - Py_INCREF(val); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(target, i, incRef(val)); // PyTuple_SET_ITEM steals a reference. } // @@ -1055,14 +1180,7 @@ IcePy::Operation::Operation(const char* n, PyObject* m, PyObject* sm, int amdFla // amd // amd = amdFlag ? true : false; - if(amd) - { - dispatchName = name + "_async"; - } - else - { - dispatchName = fixIdent(name); - } + dispatchName = fixIdent(name); // Use the same dispatch name regardless of AMD. // // format @@ -1252,11 +1370,18 @@ static PyMethodDef OperationMethods[] = { 0, 0 } /* sentinel */ }; -static PyMethodDef AMDCallbackMethods[] = +static PyMethodDef DoneCallbackMethods[] = +{ + { STRCAST("invoke"), reinterpret_cast<PyCFunction>(doneCallbackInvoke), METH_VARARGS, + PyDoc_STR(STRCAST("internal function")) }, + { 0, 0 } /* sentinel */ +}; + +static PyMethodDef DispatchCallbackMethods[] = { - { STRCAST("ice_response"), reinterpret_cast<PyCFunction>(amdCallbackIceResponse), METH_VARARGS, + { STRCAST("response"), reinterpret_cast<PyCFunction>(dispatchCallbackResponse), METH_VARARGS, PyDoc_STR(STRCAST("internal function")) }, - { STRCAST("ice_exception"), reinterpret_cast<PyCFunction>(amdCallbackIceException), METH_VARARGS, + { STRCAST("exception"), reinterpret_cast<PyCFunction>(dispatchCallbackException), METH_VARARGS, PyDoc_STR(STRCAST("internal function")) }, { 0, 0 } /* sentinel */ }; @@ -1285,6 +1410,8 @@ static PyMethodDef AsyncResultMethods[] = PyDoc_STR(STRCAST("returns true if the request was sent synchronously")) }, { STRCAST("getOperation"), reinterpret_cast<PyCFunction>(asyncResultGetOperation), METH_NOARGS, PyDoc_STR(STRCAST("returns the name of the operation")) }, + { STRCAST("callLater"), reinterpret_cast<PyCFunction>(asyncResultCallLater), METH_VARARGS, + PyDoc_STR(STRCAST("internal function")) }, { 0, 0 } /* sentinel */ }; @@ -1338,16 +1465,16 @@ PyTypeObject OperationType = 0, /* tp_is_gc */ }; -PyTypeObject AMDCallbackType = +static PyTypeObject DoneCallbackType = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyVarObject_HEAD_INIT(0, 0) - STRCAST("IcePy.AMDCallback"), /* tp_name */ - sizeof(AMDCallbackObject), /* tp_basicsize */ + STRCAST("IcePy.DoneCallback"), /* tp_name */ + sizeof(DoneCallbackObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - reinterpret_cast<destructor>(amdCallbackDealloc), /* tp_dealloc */ + reinterpret_cast<destructor>(doneCallbackDealloc), /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -1370,7 +1497,7 @@ PyTypeObject AMDCallbackType = 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - AMDCallbackMethods, /* tp_methods */ + DoneCallbackMethods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1380,7 +1507,54 @@ PyTypeObject AMDCallbackType = 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - reinterpret_cast<newfunc>(amdCallbackNew), /* tp_new */ + reinterpret_cast<newfunc>(doneCallbackNew), /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +static PyTypeObject DispatchCallbackType = +{ + /* The ob_type field must be initialized in the module init function + * to be portable to Windows without using C++. */ + PyVarObject_HEAD_INIT(0, 0) + STRCAST("IcePy.Dispatch"), /* tp_name */ + sizeof(DispatchCallbackObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + reinterpret_cast<destructor>(dispatchCallbackDealloc), /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + DispatchCallbackMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + reinterpret_cast<newfunc>(dispatchCallbackNew), /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ }; @@ -1447,12 +1621,22 @@ IcePy::initOperation(PyObject* module) return false; } - if(PyType_Ready(&AMDCallbackType) < 0) + if(PyType_Ready(&DoneCallbackType) < 0) { return false; } - PyTypeObject* cbType = &AMDCallbackType; // Necessary to prevent GCC's strict-alias warnings. - if(PyModule_AddObject(module, STRCAST("AMDCallback"), reinterpret_cast<PyObject*>(cbType)) < 0) + PyTypeObject* cbType = &DoneCallbackType; // Necessary to prevent GCC's strict-alias warnings. + if(PyModule_AddObject(module, STRCAST("DoneCallback"), reinterpret_cast<PyObject*>(cbType)) < 0) + { + return false; + } + + if(PyType_Ready(&DispatchCallbackType) < 0) + { + return false; + } + PyTypeObject* dispatchType = &DispatchCallbackType; // Necessary to prevent GCC's strict-alias warnings. + if(PyModule_AddObject(module, STRCAST("DispatchCallback"), reinterpret_cast<PyObject*>(dispatchType)) < 0) { return false; } @@ -1474,21 +1658,13 @@ IcePy::initOperation(PyObject* module) // Invocation // IcePy::Invocation::Invocation(const Ice::ObjectPrx& prx) : - _prx(prx) -{ -} - -// -// TypedInvocation -// -IcePy::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const OperationPtr& op) : - Invocation(prx), _op(op), _communicator(prx->ice_getCommunicator()) + _prx(prx), _communicator(prx->ice_getCommunicator()) { } bool -IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice::OutputStream* os, - pair<const Ice::Byte*, const Ice::Byte*>& params) +IcePy::Invocation::prepareRequest(const OperationPtr& op, PyObject* args, MappingType mapping, Ice::OutputStream* os, + pair<const Ice::Byte*, const Ice::Byte*>& params) { assert(PyTuple_Check(args)); params.first = params.second = static_cast<const Ice::Byte*>(0); @@ -1497,35 +1673,35 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: // Validate the number of arguments. // Py_ssize_t argc = PyTuple_GET_SIZE(args); - Py_ssize_t paramCount = static_cast<Py_ssize_t>(_op->inParams.size()); + Py_ssize_t paramCount = static_cast<Py_ssize_t>(op->inParams.size()); if(argc != paramCount) { string opName; - if(mapping == OldAsyncMapping) + if(mapping == NewAsyncMapping) { - opName = _op->name + "_async"; + opName = op->name + "Async"; } else if(mapping == AsyncMapping) { - opName = "begin_" + _op->name; + opName = "begin_" + op->name; } else { - opName = fixIdent(_op->name); + opName = fixIdent(op->name); } PyErr_Format(PyExc_RuntimeError, STRCAST("%s expects %d in parameters"), opName.c_str(), static_cast<int>(paramCount)); return false; } - if(!_op->inParams.empty()) + if(!op->inParams.empty()) { try { // // Marshal the in parameters. // - os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); + os->startEncapsulation(_prx->ice_getEncodingVersion(), op->format); ObjectMap objectMap; ParamInfoList::iterator p; @@ -1533,28 +1709,27 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: // // Validate the supplied arguments. // - for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + for(p = op->inParams.begin(); p != op->inParams.end(); ++p) { ParamInfoPtr info = *p; PyObject* arg = PyTuple_GET_ITEM(args, info->pos); if((!info->optional || arg != Unset) && !info->type->validate(arg)) { string name; - if(mapping == OldAsyncMapping) + if(mapping == NewAsyncMapping) { - name = _op->name + "_async"; + name = op->name + "Async"; } else if(mapping == AsyncMapping) { - name = "begin_" + _op->name; + name = "begin_" + op->name; } else { - name = fixIdent(_op->name); + name = fixIdent(op->name); } PyErr_Format(PyExc_ValueError, STRCAST("invalid value for argument %d in operation `%s'"), - mapping == OldAsyncMapping ? info->pos + 2 : info->pos + 1, - const_cast<char*>(name.c_str())); + info->pos + 1, const_cast<char*>(name.c_str())); return false; } } @@ -1562,7 +1737,7 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: // // Marshal the required parameters. // - for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + for(p = op->inParams.begin(); p != op->inParams.end(); ++p) { ParamInfoPtr info = *p; if(!info->optional) @@ -1575,7 +1750,7 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: // // Marshal the optional parameters. // - for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + for(p = op->optionalInParams.begin(); p != op->optionalInParams.end(); ++p) { ParamInfoPtr info = *p; PyObject* arg = PyTuple_GET_ITEM(args, info->pos); @@ -1585,7 +1760,7 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: } } - if(_op->sendsClasses) + if(op->sendsClasses) { os->writePendingValues(); } @@ -1609,10 +1784,10 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, Ice: } PyObject* -IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice::Byte*>& bytes) +IcePy::Invocation::unmarshalResults(const OperationPtr& op, const pair<const Ice::Byte*, const Ice::Byte*>& bytes) { - Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); - if(_op->returnType) + Py_ssize_t numResults = static_cast<Py_ssize_t>(op->outParams.size()); + if(op->returnType) { numResults++; } @@ -1637,7 +1812,7 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: // // Unmarshal the required out parameters. // - for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + for(p = op->outParams.begin(); p != op->outParams.end(); ++p) { ParamInfoPtr info = *p; if(!info->optional) @@ -1650,17 +1825,17 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: // // Unmarshal the required return value, if any. // - if(_op->returnType && !_op->returnType->optional) + if(op->returnType && !op->returnType->optional) { - assert(_op->returnType->pos == 0); - void* closure = reinterpret_cast<void*>(static_cast<Py_ssize_t>(_op->returnType->pos)); - _op->returnType->type->unmarshal(&is, _op->returnType, results.get(), closure, false, &_op->metaData); + assert(op->returnType->pos == 0); + void* closure = reinterpret_cast<void*>(static_cast<Py_ssize_t>(op->returnType->pos)); + op->returnType->type->unmarshal(&is, op->returnType, results.get(), closure, false, &op->metaData); } // // Unmarshal the optional results. This includes an optional return value. // - for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + for(p = op->optionalOutParams.begin(); p != op->optionalOutParams.end(); ++p) { ParamInfoPtr info = *p; if(is.readOptional(info->tag, info->type->optionalFormat())) @@ -1670,15 +1845,11 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: } else { - if(PyTuple_SET_ITEM(results.get(), info->pos, Unset) < 0) - { - return 0; - } - Py_INCREF(Unset); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(results.get(), info->pos, incRef(Unset)); // PyTuple_SET_ITEM steals a reference. } } - if(_op->returnsClasses) + if(op->returnsClasses) { is.readPendingValues(); } @@ -1692,7 +1863,7 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: } PyObject* -IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& bytes) +IcePy::Invocation::unmarshalException(const OperationPtr& op, const pair<const Ice::Byte*, const Ice::Byte*>& bytes) { Ice::InputStream is(_communicator, bytes); @@ -1717,7 +1888,7 @@ IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ic PyObject* ex = r.getException(); - if(validateException(ex)) + if(validateException(op, ex)) { util.updateSlicedData(); @@ -1727,8 +1898,7 @@ IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ic StreamUtil::setSlicedDataMember(ex, slicedData); } - Py_INCREF(ex); - return ex; + return incRef(ex); } else { @@ -1758,9 +1928,9 @@ IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ic } bool -IcePy::TypedInvocation::validateException(PyObject* ex) const +IcePy::Invocation::validateException(const OperationPtr& op, PyObject* ex) const { - for(ExceptionInfoList::const_iterator p = _op->exceptions.begin(); p != _op->exceptions.end(); ++p) + for(ExceptionInfoList::const_iterator p = op->exceptions.begin(); p != op->exceptions.end(); ++p) { if(PyObject_IsInstance(ex, (*p)->pythonType.get())) { @@ -1772,12 +1942,12 @@ IcePy::TypedInvocation::validateException(PyObject* ex) const } void -IcePy::TypedInvocation::checkTwowayOnly(const Ice::ObjectPrx& proxy) const +IcePy::Invocation::checkTwowayOnly(const OperationPtr& op, const Ice::ObjectPrx& proxy) const { - if((_op->returnType != 0 || !_op->outParams.empty() || !_op->exceptions.empty()) && !proxy->ice_isTwoway()) + if((op->returnType != 0 || !op->outParams.empty() || !op->exceptions.empty()) && !proxy->ice_isTwoway()) { Ice::TwowayOnlyException ex(__FILE__, __LINE__); - ex.operation = _op->name; + ex.operation = op->name; throw ex; } } @@ -1786,7 +1956,7 @@ IcePy::TypedInvocation::checkTwowayOnly(const Ice::ObjectPrx& proxy) const // SyncTypedInvocation // IcePy::SyncTypedInvocation::SyncTypedInvocation(const Ice::ObjectPrx& prx, const OperationPtr& op) : - Invocation(prx), TypedInvocation(prx, op) + Invocation(prx), _op(op) { } @@ -1804,14 +1974,14 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // Ice::OutputStream os(_communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, SyncMapping, &os, params)) + if(!prepareRequest(_op, pyparams, SyncMapping, &os, params)) { return 0; } try { - checkTwowayOnly(_prx); + checkTwowayOnly(_op, _prx); // // Invoke the operation. @@ -1861,7 +2031,7 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) rb.first = &result[0]; rb.second = &result[0] + result.size(); } - PyObjectHandle ex = unmarshalException(rb); + PyObjectHandle ex = unmarshalException(_op, rb); // // Set the Python exception. @@ -1882,7 +2052,7 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) rb.first = &result[0]; rb.second = &result[0] + result.size(); } - PyObjectHandle results = unmarshalResults(rb); + PyObjectHandle results = unmarshalResults(_op, rb); if(!results.get()) { return 0; @@ -1901,8 +2071,7 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) } else { - Py_INCREF(ret); - return ret; + return incRef(ret); } } } @@ -1919,8 +2088,7 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) return 0; } - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } // @@ -1928,7 +2096,7 @@ IcePy::SyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // IcePy::AsyncTypedInvocation::AsyncTypedInvocation(const Ice::ObjectPrx& prx, PyObject* pyProxy, const OperationPtr& op) : - Invocation(prx), TypedInvocation(prx, op), _pyProxy(pyProxy), _response(0), _ex(0), _sent(0) + Invocation(prx), _op(op), _pyProxy(pyProxy), _response(0), _ex(0), _sent(0) { Py_INCREF(_pyProxy); } @@ -1956,8 +2124,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) callable = PyTuple_GET_ITEM(args, 1); if(PyCallable_Check(callable)) { - _response = callable; - Py_INCREF(_response); + _response = incRef(callable); } else if(callable != Py_None) { @@ -1968,8 +2135,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) callable = PyTuple_GET_ITEM(args, 2); if(PyCallable_Check(callable)) { - _ex = callable; - Py_INCREF(_ex); + _ex = incRef(callable); } else if(callable != Py_None) { @@ -1980,8 +2146,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) callable = PyTuple_GET_ITEM(args, 3); if(PyCallable_Check(callable)) { - _sent = callable; - Py_INCREF(_sent); + _sent = incRef(callable); } else if(callable != Py_None) { @@ -2008,7 +2173,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // Ice::OutputStream os(_communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, AsyncMapping, &os, params)) + if(!prepareRequest(_op, pyparams, AsyncMapping, &os, params)) { return 0; } @@ -2092,8 +2257,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) } obj->result = new Ice::AsyncResultPtr(result); obj->invocation = new InvocationPtr(this); - obj->proxy = _pyProxy; - Py_INCREF(obj->proxy); + obj->proxy = incRef(_pyProxy); obj->communicator = getCommunicatorWrapper(_communicator); return reinterpret_cast<PyObject*>(obj); } @@ -2122,7 +2286,7 @@ IcePy::AsyncTypedInvocation::end(const Ice::ObjectPrx& proxy, const OperationPtr // // Unmarshal the results. // - PyObjectHandle args = unmarshalResults(results); + PyObjectHandle args = unmarshalResults(_op, results); if(args.get()) { // @@ -2132,14 +2296,12 @@ IcePy::AsyncTypedInvocation::end(const Ice::ObjectPrx& proxy, const OperationPtr assert(PyTuple_Check(args.get())); if(PyTuple_GET_SIZE(args.get()) == 0) { - Py_INCREF(Py_None); - return Py_None; + return incRef(Py_None); } else if(PyTuple_GET_SIZE(args.get()) == 1) { PyObject* res = PyTuple_GET_ITEM(args.get(), 0); - Py_INCREF(res); - return res; + return incRef(res); } else { @@ -2149,7 +2311,7 @@ IcePy::AsyncTypedInvocation::end(const Ice::ObjectPrx& proxy, const OperationPtr } else { - PyObjectHandle ex = unmarshalException(results); + PyObjectHandle ex = unmarshalException(_op, results); setPythonException(ex.get()); } } @@ -2193,7 +2355,7 @@ IcePy::AsyncTypedInvocation::response(bool ok, const pair<const Ice::Byte*, cons PyObjectHandle args; try { - args = unmarshalResults(results); + args = unmarshalResults(_op, results); if(!args.get()) { assert(PyErr_Occurred()); @@ -2218,7 +2380,7 @@ IcePy::AsyncTypedInvocation::response(bool ok, const pair<const Ice::Byte*, cons else { assert(_ex); - PyObjectHandle ex = unmarshalException(results); + PyObjectHandle ex = unmarshalException(_op, results); callException(_ex, ex.get()); } } @@ -2263,114 +2425,344 @@ IcePy::AsyncTypedInvocation::checkAsyncTwowayOnly(const Ice::ObjectPrx& proxy) c } // -// OldAsyncTypedInvocation +// NewAsyncInvocation // -IcePy::OldAsyncTypedInvocation::OldAsyncTypedInvocation(const Ice::ObjectPrx& prx, const OperationPtr& op) - : Invocation(prx), TypedInvocation(prx, op), _callback(0) +IcePy::NewAsyncInvocation::NewAsyncInvocation(const Ice::ObjectPrx& prx, PyObject* pyProxy, const string& operation) + : Invocation(prx), _pyProxy(pyProxy), _operation(operation), _twoway(prx->ice_isTwoway()), _sent(false), + _sentSynchronously(false), _done(false), _future(0), _ok(false), _exception(0) { + Py_INCREF(_pyProxy); } -IcePy::OldAsyncTypedInvocation::~OldAsyncTypedInvocation() +IcePy::NewAsyncInvocation::~NewAsyncInvocation() { AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - Py_XDECREF(_callback); + Py_DECREF(_pyProxy); + Py_XDECREF(_future); + Py_XDECREF(_exception); } PyObject* -IcePy::OldAsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) +IcePy::NewAsyncInvocation::invoke(PyObject* args, PyObject* kwds) { - assert(PyTuple_Check(args)); - assert(PyTuple_GET_SIZE(args) == 3); // Format is (callback, (params...), context|None) - _callback = PyTuple_GET_ITEM(args, 0); - Py_INCREF(_callback); - PyObject* pyparams = PyTuple_GET_ITEM(args, 1); - assert(PyTuple_Check(pyparams)); - PyObject* pyctx = PyTuple_GET_ITEM(args, 2); - // - // Marshal the input parameters to a byte sequence. + // Called from Python code, so the GIL is already acquired. // - Ice::OutputStream os(_communicator); - pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(pyparams, OldAsyncMapping, &os, params)) + + Ice::AsyncResultPtr result; + + try + { + result = handleInvoke(args, kwds); + } + catch(const Ice::CommunicatorDestroyedException& ex) + { + // + // CommunicatorDestroyedException can propagate directly. + // + setPythonException(ex); + return 0; + } + catch(const IceUtil::IllegalArgumentException& ex) { + // + // IllegalArgumentException can propagate directly. + // (Raised by checkAsyncTwowayOnly) + // + PyErr_Format(PyExc_RuntimeError, "%s", STRCAST(ex.reason().c_str())); return 0; } + catch(const Ice::Exception&) + { + // + // No other exceptions should be raised by begin_ice_invoke. + // + assert(false); + } - bool sentSynchronously = false; - try + if(PyErr_Occurred()) { - checkTwowayOnly(_prx); + return 0; + } - Ice::Callback_Object_ice_invokePtr cb = - Ice::newCallback_Object_ice_invoke(this, &OldAsyncTypedInvocation::response, - &OldAsyncTypedInvocation::exception, &OldAsyncTypedInvocation::sent); + assert(result); - Ice::AsyncResultPtr result; + PyObjectHandle communicatorObj = getCommunicatorWrapper(_communicator); + PyObjectHandle asyncResultObj; - // - // Invoke the operation asynchronously. - // - if(pyctx != Py_None) + // + // Pass the AsyncResult object to the future. Note that this creates a circular reference. + // Don't do this for batch invocations because there is no opportunity to break the circular + // reference. + // + if(!_prx->ice_isBatchOneway() && !_prx->ice_isBatchDatagram()) + { + asyncResultObj = createAsyncResult(result, _pyProxy, 0, communicatorObj.get()); + if(!asyncResultObj.get()) { - Ice::Context ctx; + return 0; + } + } + + // + // NOTE: Any time we call into interpreted Python code there's a chance that another thread will be + // allowed to run! + // + + PyObjectHandle future = createFuture(_operation, asyncResultObj.get()); // Calls into Python code. + if(!future.get()) + { + return 0; + } + + // + // Check if any callbacks have been invoked already. + // + + if(_sent) + { + PyObjectHandle tmp = callMethod(future.get(), "set_sent", _sentSynchronously ? getTrue() : getFalse()); + if(PyErr_Occurred()) + { + return 0; + } - if(!PyDict_Check(pyctx)) + if(!_twoway) + { + // + // For a oneway/datagram invocation, we consider it complete when sent. + // + tmp = callMethod(future.get(), "set_result", Py_None); + if(PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, STRCAST("context argument must be None or a dictionary")); return 0; } + } + } - if(!dictionaryToContext(pyctx, ctx)) + if(_done) + { + if(_exception) + { + PyObjectHandle tmp = callMethod(future.get(), "set_exception", _exception); + if(PyErr_Occurred()) { return 0; } - - AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. - result = _prx->begin_ice_invoke(_op->name, _op->sendMode, params, ctx, cb); } else { - AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. - result = _prx->begin_ice_invoke(_op->name, _op->sendMode, params, cb); + // + // Delegate to the subclass. + // + pair<const Ice::Byte*, const Ice::Byte*> p(&_results[0], &_results[0] + _results.size()); + handleResponse(future.get(), _ok, p); + if(PyErr_Occurred()) + { + return 0; + } } - - sentSynchronously = result->sentSynchronously(); } - catch(const Ice::CommunicatorDestroyedException& ex) + + _future = future.release(); + return incRef(_future); +} + +void +IcePy::NewAsyncInvocation::response(bool ok, const pair<const Ice::Byte*, const Ice::Byte*>& results) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) { // - // CommunicatorDestroyedException can propagate directly. + // The future hasn't been created yet, which means invoke() is still running. Save the results for later. // - setPythonException(ex); - return 0; + _ok = ok; + vector<Ice::Byte> v(results.first, results.second); + _results.swap(v); + _done = true; + return; + } + + PyObjectHandle future = _future; // Steals a reference. + + if(_sent) + { + _future = 0; // Break cyclic dependency. } - catch(const Ice::TwowayOnlyException& ex) + else { + assert(!_done); + // - // Raised by checkTwowayOnly. + // The sent callback will release our reference. // - callException(_callback, _op->name, "ice_exception", ex); + Py_INCREF(_future); } - catch(const Ice::Exception&) + + _done = true; + + // + // Delegate to the subclass. + // + handleResponse(future.get(), ok, results); + if(PyErr_Occurred()) + { + handleException(); + } +} + +void +IcePy::NewAsyncInvocation::exception(const Ice::Exception& ex) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) { // - // No other exceptions should be raised by begin_ice_invoke. + // The future hasn't been created yet, which means invoke() is still running. Save the exception for later. // - assert(false); + _exception = convertException(ex); + _done = true; + return; } - PyRETURN_BOOL(sentSynchronously); + PyObjectHandle future = _future; // Steals a reference. + _future = 0; // Break cyclic dependency. + _done = true; + + PyObjectHandle exh = convertException(ex); + assert(exh.get()); + PyObjectHandle tmp = callMethod(future.get(), "set_exception", exh.get()); + if(PyErr_Occurred()) + { + handleException(); + } } void -IcePy::OldAsyncTypedInvocation::response(bool ok, const pair<const Ice::Byte*, const Ice::Byte*>& results) +IcePy::NewAsyncInvocation::sent(bool sentSynchronously) { AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - assert(_callback); + if(!_future) + { + // + // The future hasn't been created yet, which means invoke() is still running. + // + _sent = true; + _sentSynchronously = sentSynchronously; + return; + } + + PyObjectHandle future = _future; + + if(_done || !_twoway) + { + _future = 0; // Break cyclic dependency. + } + else + { + _sent = true; + + // + // The reference to _future will be released in response() or exception(). + // + Py_INCREF(_future); + } + + PyObjectHandle tmp = callMethod(future.get(), "set_sent", sentSynchronously ? getTrue() : getFalse()); + if(PyErr_Occurred()) + { + handleException(); + } + + if(!_twoway) + { + // + // For a oneway/datagram invocation, we consider it complete when sent. + // + tmp = callMethod(future.get(), "set_result", Py_None); + if(PyErr_Occurred()) + { + handleException(); + } + } +} + +// +// NewAsyncTypedInvocation +// +IcePy::NewAsyncTypedInvocation::NewAsyncTypedInvocation(const Ice::ObjectPrx& prx, PyObject* pyProxy, + const OperationPtr& op) + : NewAsyncInvocation(prx, pyProxy, op->name), _op(op) +{ +} + +Ice::AsyncResultPtr +IcePy::NewAsyncTypedInvocation::handleInvoke(PyObject* args, PyObject* /* kwds */) +{ + // + // Called from Python code, so the GIL is already acquired. + // + + assert(PyTuple_Check(args)); + assert(PyTuple_GET_SIZE(args) == 2); // Format is ((params...), context|None) + PyObject* pyparams = PyTuple_GET_ITEM(args, 0); + assert(PyTuple_Check(pyparams)); + PyObject* pyctx = PyTuple_GET_ITEM(args, 1); + + // + // Marshal the input parameters to a byte sequence. + // + Ice::OutputStream os(_communicator); + pair<const Ice::Byte*, const Ice::Byte*> params; + if(!prepareRequest(_op, pyparams, NewAsyncMapping, &os, params)) + { + return 0; + } + + checkAsyncTwowayOnly(_prx); + + NewAsyncInvocationPtr self = this; + Ice::Callback_Object_ice_invokePtr cb = + Ice::newCallback_Object_ice_invoke(self, &NewAsyncInvocation::response, &NewAsyncInvocation::exception, + &NewAsyncInvocation::sent); + + // + // Invoke the operation asynchronously. + // + if(pyctx != Py_None) + { + Ice::Context ctx; + + if(!PyDict_Check(pyctx)) + { + PyErr_Format(PyExc_ValueError, STRCAST("context argument must be None or a dictionary")); + return 0; + } + + if(!dictionaryToContext(pyctx, ctx)) + { + return 0; + } + + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + return _prx->begin_ice_invoke(_op->name, _op->sendMode, params, ctx, cb); + } + else + { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + return _prx->begin_ice_invoke(_op->name, _op->sendMode, params, cb); + } +} +void +IcePy::NewAsyncTypedInvocation::handleResponse(PyObject* future, bool ok, + const pair<const Ice::Byte*, const Ice::Byte*>& results) +{ try { if(ok) @@ -2379,69 +2771,70 @@ IcePy::OldAsyncTypedInvocation::response(bool ok, const pair<const Ice::Byte*, c // Unmarshal the results. // PyObjectHandle args; + try { - args = unmarshalResults(results); + args = unmarshalResults(_op, results); if(!args.get()) { assert(PyErr_Occurred()); - PyErr_Print(); return; } } catch(const Ice::Exception& ex) { - callException(_callback, _op->name, "ice_exception", ex); + PyObjectHandle exh = convertException(ex); + assert(exh.get()); + PyObjectHandle tmp = callMethod(future, "set_exception", exh.get()); + PyErr_Clear(); return; } - const string methodName = "ice_response"; - if(!PyObject_HasAttrString(_callback, STRCAST(methodName.c_str()))) + // + // The future's result is always one value: + // + // - If the operation has no out parameters, the result is None + // - If the operation returns one value, the result is the value + // - If the operation returns multiple values, the result is a tuple containing the values + // + PyObjectHandle r; + if(PyTuple_GET_SIZE(args.get()) == 0) { - ostringstream ostr; - ostr << "AMI callback object for operation `" << _op->name << "' does not define " << methodName - << "()"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + r = incRef(Py_None); + } + else if(PyTuple_GET_SIZE(args.get()) == 1) + { + r = incRef(PyTuple_GET_ITEM(args.get(), 0)); // PyTuple_GET_ITEM steals a reference. } else { - PyObjectHandle method = PyObject_GetAttrString(_callback, STRCAST(methodName.c_str())); - assert(method.get()); - PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), 0); - if(PyErr_Occurred()) - { - handleException(); // Callback raised an exception. - } + r = args; } + + PyObjectHandle tmp = callMethod(future, "set_result", r.get()); + PyErr_Clear(); } else { - PyObjectHandle ex = unmarshalException(results); - callException(_callback, _op->name, "ice_exception", ex.get()); + PyObjectHandle ex = unmarshalException(_op, results); + PyObjectHandle tmp = callMethod(future, "set_exception", ex.get()); + PyErr_Clear(); } } catch(const AbortMarshaling&) { assert(PyErr_Occurred()); - PyErr_Print(); } } void -IcePy::OldAsyncTypedInvocation::exception(const Ice::Exception& ex) +IcePy::NewAsyncTypedInvocation::checkAsyncTwowayOnly(const Ice::ObjectPrx& proxy) const { - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - callException(_callback, _op->name, "ice_exception", ex); -} - -void -IcePy::OldAsyncTypedInvocation::sent(bool) -{ - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - callSent(_callback, "ice_sent", false, false); + if((_op->returnType != 0 || !_op->outParams.empty() || !_op->exceptions.empty()) && !proxy->ice_isTwoway()) + { + throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, + "`" + _op->name + "' can only be called with a twoway proxy"); + } } // @@ -2574,11 +2967,7 @@ IcePy::SyncBlobjectInvocation::invoke(PyObject* args, PyObject* /* kwds */) } #endif - if(PyTuple_SET_ITEM(result.get(), 1, op.get()) < 0) - { - throwPythonException(); - } - op.release(); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(result.get(), 1, op.release()); // PyTuple_SET_ITEM steals a reference. return result.release(); } @@ -2652,8 +3041,7 @@ IcePy::AsyncBlobjectInvocation::invoke(PyObject* args, PyObject* kwds) if(PyCallable_Check(response)) { - _response = response; - Py_INCREF(_response); + _response = incRef(response); } else if(response != Py_None) { @@ -2663,8 +3051,7 @@ IcePy::AsyncBlobjectInvocation::invoke(PyObject* args, PyObject* kwds) if(PyCallable_Check(ex)) { - _ex = ex; - Py_INCREF(_ex); + _ex = incRef(ex); } else if(ex != Py_None) { @@ -2674,8 +3061,7 @@ IcePy::AsyncBlobjectInvocation::invoke(PyObject* args, PyObject* kwds) if(PyCallable_Check(sent)) { - _sent = sent; - Py_INCREF(_sent); + _sent = incRef(sent); } else if(sent != Py_None) { @@ -2787,8 +3173,7 @@ IcePy::AsyncBlobjectInvocation::invoke(PyObject* args, PyObject* kwds) } obj->result = new Ice::AsyncResultPtr(result); obj->invocation = new InvocationPtr(this); - obj->proxy = _pyProxy; - Py_INCREF(obj->proxy); + obj->proxy = incRef(_pyProxy); obj->communicator = getCommunicatorWrapper(_prx->ice_getCommunicator()); return reinterpret_cast<PyObject*>(obj); } @@ -2855,11 +3240,7 @@ IcePy::AsyncBlobjectInvocation::end(const Ice::ObjectPrx& proxy, const Ice::Asyn memcpy(buf, results.first, sz); #endif - if(PyTuple_SET_ITEM(args.get(), 1, op.get()) < 0) - { - return 0; - } - op.release(); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(args.get(), 1, op.release()); // PyTuple_SET_ITEM steals a reference. return args.release(); } @@ -2946,13 +3327,7 @@ IcePy::AsyncBlobjectInvocation::response(bool ok, const pair<const Ice::Byte*, c memcpy(buf, results.first, sz); #endif - if(PyTuple_SET_ITEM(args.get(), 1, op.get()) < 0) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } - op.release(); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(args.get(), 1, op.release()); // PyTuple_SET_ITEM steals a reference. PyObjectHandle tmp = PyObject_Call(_response, args.get(), 0); if(PyErr_Occurred()) @@ -2981,22 +3356,15 @@ IcePy::AsyncBlobjectInvocation::sent(bool sentSynchronously) } // -// OldAsyncBlobjectInvocation +// NewAsyncBlobjectInvocation // -IcePy::OldAsyncBlobjectInvocation::OldAsyncBlobjectInvocation(const Ice::ObjectPrx& prx) : - Invocation(prx), _callback(0) -{ -} - -IcePy::OldAsyncBlobjectInvocation::~OldAsyncBlobjectInvocation() +IcePy::NewAsyncBlobjectInvocation::NewAsyncBlobjectInvocation(const Ice::ObjectPrx& prx, PyObject* pyProxy) : + NewAsyncInvocation(prx, pyProxy, "ice_invoke") { - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - Py_XDECREF(_callback); } -PyObject* -IcePy::OldAsyncBlobjectInvocation::invoke(PyObject* args, PyObject* /* kwds */) +Ice::AsyncResultPtr +IcePy::NewAsyncBlobjectInvocation::handleInvoke(PyObject* args, PyObject* /* kwds */) { char* operation; PyObject* mode; @@ -3004,20 +3372,19 @@ IcePy::OldAsyncBlobjectInvocation::invoke(PyObject* args, PyObject* /* kwds */) PyObject* operationModeType = lookupType("Ice.OperationMode"); PyObject* ctx = 0; #if PY_VERSION_HEX >= 0x03000000 - if(!PyArg_ParseTuple(args, STRCAST("OsO!O!|O"), &_callback, &operation, operationModeType, &mode, + if(!PyArg_ParseTuple(args, STRCAST("sO!O!|O"), &operation, operationModeType, &mode, &PyBytes_Type, &inParams, &ctx)) { return 0; } #else - if(!PyArg_ParseTuple(args, STRCAST("OsO!O!|O"), &_callback, &operation, operationModeType, &mode, + if(!PyArg_ParseTuple(args, STRCAST("sO!O!|O"), &operation, operationModeType, &mode, &PyBuffer_Type, &inParams, &ctx)) { return 0; } #endif - Py_INCREF(_callback); _op = operation; PyObjectHandle modeValue = PyObject_GetAttrString(mode, STRCAST("value")); @@ -3049,169 +3416,175 @@ IcePy::OldAsyncBlobjectInvocation::invoke(PyObject* args, PyObject* /* kwds */) } #endif - bool sentSynchronously = false; - try - { - Ice::AsyncResultPtr result; - Ice::Callback_Object_ice_invokePtr cb = - Ice::newCallback_Object_ice_invoke(this, &OldAsyncBlobjectInvocation::response, - &OldAsyncBlobjectInvocation::exception, - &OldAsyncBlobjectInvocation::sent); + NewAsyncInvocationPtr self = this; + Ice::Callback_Object_ice_invokePtr cb = + Ice::newCallback_Object_ice_invoke(self, &NewAsyncInvocation::response, &NewAsyncInvocation::exception, + &NewAsyncInvocation::sent); - if(ctx == 0 || ctx == Py_None) - { - AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. - result = _prx->begin_ice_invoke(operation, sendMode, in, cb); - } - else - { - Ice::Context context; - if(!dictionaryToContext(ctx, context)) - { - return 0; - } - - AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. - result = _prx->begin_ice_invoke(operation, sendMode, in, context, cb); - } - - sentSynchronously = result->sentSynchronously(); - } - catch(const Ice::CommunicatorDestroyedException& ex) + if(ctx == 0 || ctx == Py_None) { // - // CommunicatorDestroyedException is the only exception that can propagate directly. + // Don't release the GIL here. We want other threads to block until we've had a chance + // to create the future. // - setPythonException(ex); - return 0; + //AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + return _prx->begin_ice_invoke(operation, sendMode, in, cb); } - catch(const Ice::Exception&) + else { + Ice::Context context; + if(!dictionaryToContext(ctx, context)) + { + return 0; + } + // - // No other exceptions should be raised by begin_ice_invoke. + // Don't release the GIL here. We want other threads to block until we've had a chance + // to create the future. // - assert(false); + //AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + return _prx->begin_ice_invoke(operation, sendMode, in, context, cb); } - - PyRETURN_BOOL(sentSynchronously); } void -IcePy::OldAsyncBlobjectInvocation::response(bool ok, const pair<const Ice::Byte*, const Ice::Byte*>& results) +IcePy::NewAsyncBlobjectInvocation::handleResponse(PyObject* future, bool ok, + const pair<const Ice::Byte*, const Ice::Byte*>& results) { - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. - - try + // + // Prepare the args as a tuple of the bool and out param buffer. + // + PyObjectHandle args = PyTuple_New(2); + if(!args.get()) { - // - // Prepare the args as a tuple of the bool and out param buffer. - // - PyObjectHandle args = PyTuple_New(2); - if(!args.get()) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } - if(PyTuple_SET_ITEM(args.get(), 0, ok ? incTrue() : incFalse()) < 0) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } + if(PyTuple_SET_ITEM(args.get(), 0, ok ? incTrue() : incFalse()) < 0) + { + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } #if PY_VERSION_HEX >= 0x03000000 - Py_ssize_t sz = results.second - results.first; - PyObjectHandle op; - if(sz == 0) - { - op = PyBytes_FromString(""); - } - else - { - op = PyBytes_FromStringAndSize(reinterpret_cast<const char*>(results.first), sz); - } - if(!op.get()) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } + Py_ssize_t sz = results.second - results.first; + PyObjectHandle op; + if(sz == 0) + { + op = PyBytes_FromString(""); + } + else + { + op = PyBytes_FromStringAndSize(reinterpret_cast<const char*>(results.first), sz); + } + if(!op.get()) + { + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } #else - // - // Create the output buffer and copy in the outParams. - // - PyObjectHandle op = PyBuffer_New(results.second - results.first); - if(!op.get()) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } + // + // Create the output buffer and copy in the outParams. + // + PyObjectHandle op = PyBuffer_New(results.second - results.first); + if(!op.get()) + { + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } - void* buf; - Py_ssize_t sz; - if(PyObject_AsWriteBuffer(op.get(), &buf, &sz)) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } - assert(sz == results.second - results.first); - memcpy(buf, results.first, sz); + void* buf; + Py_ssize_t sz; + if(PyObject_AsWriteBuffer(op.get(), &buf, &sz)) + { + assert(PyErr_Occurred()); + PyErr_Print(); + return; + } + assert(sz == results.second - results.first); + memcpy(buf, results.first, sz); #endif - if(PyTuple_SET_ITEM(args.get(), 1, op.get()) < 0) - { - assert(PyErr_Occurred()); - PyErr_Print(); - return; - } - op.release(); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(args.get(), 1, op.release()); // PyTuple_SET_ITEM steals a reference. - const string methodName = "ice_response"; - if(!PyObject_HasAttrString(_callback, STRCAST(methodName.c_str()))) - { - ostringstream ostr; - ostr << "AMI callback object for operation `ice_invoke_async' does not define " << methodName << "()"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - } - else - { - PyObjectHandle method = PyObject_GetAttrString(_callback, STRCAST(methodName.c_str())); - assert(method.get()); - PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), 0); - if(PyErr_Occurred()) - { - handleException(); // Callback raised an exception. - } - } + PyObjectHandle tmp = callMethod(future, "set_result", args.get()); + PyErr_Clear(); +} + +// +// Upcall +// +void +Upcall::dispatchImpl(PyObject* servant, const string& dispatchName, PyObject* args, const Ice::Current& current) +{ + Ice::CommunicatorPtr communicator = current.adapter->getCommunicator(); + + // + // Find the servant method for the operation. Use dispatchName here, not current.operation. + // + PyObjectHandle servantMethod = PyObject_GetAttrString(servant, const_cast<char*>(dispatchName.c_str())); + if(!servantMethod.get()) + { + ostringstream ostr; + ostr << "servant for identity " << communicator->identityToString(current.id) + << " does not define operation `" << dispatchName << "'"; + string str = ostr.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + Ice::UnknownException ex(__FILE__, __LINE__); + ex.unknown = str; + throw ex; } - catch(const Ice::Exception& ex) + + // + // Get the _dispatch method. The _dispatch method will invoke the servant method and pass it the arguments. + // + PyObjectHandle dispatchMethod = PyObject_GetAttrString(servant, STRCAST("_dispatch")); + if(!dispatchMethod.get()) { ostringstream ostr; - ostr << "Exception raised by AMI callback for operation `ice_invoke_async':" << ex; + ostr << "_dispatch method not found for identity " << communicator->identityToString(current.id) + << " and operation `" << dispatchName << "'"; string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + Ice::UnknownException ex(__FILE__, __LINE__); + ex.unknown = str; + throw ex; } -} -void -IcePy::OldAsyncBlobjectInvocation::exception(const Ice::Exception& ex) -{ - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + PyObjectHandle dispatchArgs = PyTuple_New(3); + if(!dispatchArgs.get()) + { + throwPythonException(); + } - callException(_callback, "ice_invoke", "ice_exception", ex); -} + DispatchCallbackObject* callback = dispatchCallbackNew(&DispatchCallbackType, 0, 0); + if(!callback) + { + throwPythonException(); + } + callback->upcall = new UpcallPtr(this); + PyTuple_SET_ITEM(dispatchArgs.get(), 0, reinterpret_cast<PyObject*>(callback)); // Steals a reference. + PyTuple_SET_ITEM(dispatchArgs.get(), 1, servantMethod.release()); // Steals a reference. + PyTuple_SET_ITEM(dispatchArgs.get(), 2, incRef(args)); // Steals a reference. -void -IcePy::OldAsyncBlobjectInvocation::sent(bool) -{ - AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + // + // Ignore the return value of _dispatch -- it will use the dispatch callback. + // + PyObjectHandle ignore = PyObject_Call(dispatchMethod.get(), dispatchArgs.get(), 0); - callSent(_callback, "ice_sent", false, false); + // + // Check for exceptions. + // + if(PyErr_Occurred()) + { + PyException ex; // Retrieve it before another Python API call clears it. + exception(ex); + } } // @@ -3219,7 +3592,7 @@ IcePy::OldAsyncBlobjectInvocation::sent(bool) // IcePy::TypedUpcall::TypedUpcall(const OperationPtr& op, const Ice::AMD_Object_ice_invokePtr& callback, const Ice::CommunicatorPtr& communicator) : - _op(op), _callback(callback), _communicator(communicator), _finished(false) + _op(op), _callback(callback), _communicator(communicator) { } @@ -3227,19 +3600,14 @@ void IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, const Ice::Byte*>& inBytes, const Ice::Current& current) { + _encoding = current.encoding; + // // Unmarshal the in parameters. We have to leave room in the arguments for a trailing // Ice::Current object. // Py_ssize_t count = static_cast<Py_ssize_t>(_op->inParams.size()) + 1; - Py_ssize_t offset = 0; - if(_op->amd) - { - ++count; // Leave room for a leading AMD callback argument. - offset = 1; - } - PyObjectHandle args = PyTuple_New(count); if(!args.get()) { @@ -3272,7 +3640,7 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con ParamInfoPtr info = *p; if(!info->optional) { - void* closure = reinterpret_cast<void*>(info->pos + offset); + void* closure = reinterpret_cast<void*>(info->pos); info->type->unmarshal(&is, info, args.get(), closure, false, &info->metaData); } } @@ -3285,16 +3653,12 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con ParamInfoPtr info = *p; if(is.readOptional(info->tag, info->type->optionalFormat())) { - void* closure = reinterpret_cast<void*>(info->pos + offset); + void* closure = reinterpret_cast<void*>(info->pos); info->type->unmarshal(&is, info, args.get(), closure, true, &info->metaData); } else { - if(PyTuple_SET_ITEM(args.get(), info->pos + offset, Unset) < 0) - { - throwPythonException(); - } - Py_INCREF(Unset); // PyTuple_SET_ITEM steals a reference. + PyTuple_SET_ITEM(args.get(), info->pos, incRef(Unset)); // PyTuple_SET_ITEM steals a reference. } } @@ -3317,209 +3681,149 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con // Create an object to represent Ice::Current. We need to append this to the argument tuple. // PyObjectHandle curr = createCurrent(current); - if(PyTuple_SET_ITEM(args.get(), PyTuple_GET_SIZE(args.get()) - 1, curr.get()) < 0) - { - throwPythonException(); - } - curr.release(); // PyTuple_SET_ITEM steals a reference. - - if(_op->amd) - { - // - // Create the callback object and pass it as the first argument. - // - AMDCallbackObject* obj = amdCallbackNew(&AMDCallbackType, 0, 0); - if(!obj) - { - throwPythonException(); - } - obj->upcall = new UpcallPtr(this); - obj->encoding = current.encoding; - if(PyTuple_SET_ITEM(args.get(), 0, (PyObject*)obj) < 0) // PyTuple_SET_ITEM steals a reference. - { - Py_DECREF(obj); - throwPythonException(); - } - } - - // - // Dispatch the operation. Use _dispatchName here, not current.operation. - // - PyObjectHandle method = PyObject_GetAttrString(servant, const_cast<char*>(_op->dispatchName.c_str())); - if(!method.get()) - { - ostringstream ostr; - ostr << "servant for identity " << _communicator->identityToString(current.id) - << " does not define operation `" << _op->dispatchName << "'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - Ice::UnknownException ex(__FILE__, __LINE__); - ex.unknown = str; - throw ex; - } - - PyObjectHandle result = PyObject_Call(method.get(), args.get(), 0); - - // - // Check for exceptions. - // - if(PyErr_Occurred()) - { - PyException ex; // Retrieve it before another Python API call clears it. - exception(ex, current.encoding); - return; - } + PyTuple_SET_ITEM(args.get(), PyTuple_GET_SIZE(args.get()) - 1, + curr.release()); // PyTuple_SET_ITEM steals a reference. - if(!_op->amd) - { - response(result.get(), current.encoding); - } + dispatchImpl(servant, _op->dispatchName, args.get(), current); } void -IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encoding) +IcePy::TypedUpcall::response(PyObject* result) { - if(_finished) + try { // - // This method could be called more than once if the application calls - // ice_response multiple times. We ignore subsequent calls. + // Marshal the results. If there is more than one value to be returned, then they must be + // returned in a tuple of the form (result, outParam1, ...). // - return; - } - _finished = true; + Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); + if(_op->returnType) + { + numResults++; + } + + if(numResults > 1 && (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != numResults)) + { + ostringstream ostr; + ostr << "operation `" << fixIdent(_op->name) << "' should return a tuple of length " << numResults; + string str = ostr.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + throw Ice::MarshalException(__FILE__, __LINE__); + } - try - { // - // Marshal the results. If there is more than one value to be returned, then they must be - // returned in a tuple of the form (result, outParam1, ...). + // Normalize the result value. When there are multiple result values, result is already a tuple. + // Otherwise, we create a tuple to make the code a little simpler. // - Ice::OutputStream os(_communicator); - try + PyObjectHandle t; + if(numResults > 1) + { + t = incRef(result); + } + else { - Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); - if(_op->returnType) + t = PyTuple_New(1); + if(!t.get()) { - numResults++; + throw AbortMarshaling(); } + PyTuple_SET_ITEM(t.get(), 0, incRef(result)); + } + + ObjectMap objectMap; + ParamInfoList::iterator p; - if(numResults > 1 && (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) != numResults)) + // + // Validate the results. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + { + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); + if((!info->optional || arg != Unset) && !info->type->validate(arg)) { + // TODO: Provide the parameter name instead? ostringstream ostr; - ostr << "operation `" << fixIdent(_op->name) << "' should return a tuple of length " << numResults; + ostr << "invalid value for out argument " << (info->pos + 1) << " in operation `" + << _op->dispatchName << "'"; string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); throw Ice::MarshalException(__FILE__, __LINE__); } - - // - // Normalize the args value. For an AMD operation, or when there are multiple - // result values, args is already a tuple. Otherwise, we create a tuple to - // make the code a little simpler. - // - PyObjectHandle t; - if(_op->amd || numResults > 1) - { - t = args; - } - else + } + if(_op->returnType) + { + PyObject* res = PyTuple_GET_ITEM(t.get(), 0); + if((!_op->returnType->optional || res != Unset) && !_op->returnType->type->validate(res)) { - t = PyTuple_New(1); - if(!t.get()) - { - throw AbortMarshaling(); - } - PyTuple_SET_ITEM(t.get(), 0, args); + ostringstream ostr; + ostr << "invalid return value for operation `" << _op->dispatchName << "'"; + string str = ostr.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + throw Ice::MarshalException(__FILE__, __LINE__); } - Py_INCREF(args); - - os.startEncapsulation(encoding, _op->format); + } - ObjectMap objectMap; - ParamInfoList::iterator p; + Ice::OutputStream os(_communicator); + os.startEncapsulation(_encoding, _op->format); - // - // Validate the results. - // - for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + // + // Marshal the required out parameters. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) { - ParamInfoPtr info = *p; PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); - if((!info->optional || arg != Unset) && !info->type->validate(arg)) - { - // TODO: Provide the parameter name instead? - ostringstream ostr; - ostr << "invalid value for out argument " << (info->pos + 1) << " in operation `" - << _op->dispatchName << "'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); - } - } - if(_op->returnType) - { - PyObject* res = PyTuple_GET_ITEM(t.get(), 0); - if((!_op->returnType->optional || res != Unset) && !_op->returnType->type->validate(res)) - { - ostringstream ostr; - ostr << "invalid return value for operation `" << _op->dispatchName << "'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); - } - } - - // - // Marshal the required out parameters. - // - for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) - { - ParamInfoPtr info = *p; - if(!info->optional) - { - PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); - info->type->marshal(arg, &os, &objectMap, false, &info->metaData); - } + info->type->marshal(arg, &os, &objectMap, false, &info->metaData); } + } - // - // Marshal the required return value, if any. - // - if(_op->returnType && !_op->returnType->optional) - { - PyObject* res = PyTuple_GET_ITEM(t.get(), 0); - _op->returnType->type->marshal(res, &os, &objectMap, false, &_op->metaData); - } + // + // Marshal the required return value, if any. + // + if(_op->returnType && !_op->returnType->optional) + { + PyObject* res = PyTuple_GET_ITEM(t.get(), 0); + _op->returnType->type->marshal(res, &os, &objectMap, false, &_op->metaData); + } - // - // Marshal the optional results. - // - for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + // + // Marshal the optional results. + // + for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + { + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); + if(arg != Unset && os.writeOptional(info->tag, info->type->optionalFormat())) { - ParamInfoPtr info = *p; - PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); - if(arg != Unset && os.writeOptional(info->tag, info->type->optionalFormat())) - { - info->type->marshal(arg, &os, &objectMap, true, &info->metaData); - } + info->type->marshal(arg, &os, &objectMap, true, &info->metaData); } + } - if(_op->returnsClasses) - { - os.writePendingValues(); - } + if(_op->returnsClasses) + { + os.writePendingValues(); + } - os.endEncapsulation(); + os.endEncapsulation(); - AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_response(true, os.finished()); - } - catch(const AbortMarshaling&) + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + _callback->ice_response(true, os.finished()); + } + catch(const AbortMarshaling&) + { + try { throwPythonException(); } + catch(const Ice::Exception& ex) + { + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + _callback->ice_exception(ex); + } } catch(const Ice::Exception& ex) { @@ -3529,19 +3833,8 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin } void -IcePy::TypedUpcall::exception(PyException& ex, const Ice::EncodingVersion& encoding) +IcePy::TypedUpcall::exception(PyException& ex) { - if(_finished) - { - // - // An asynchronous response or exception has already been sent. We just - // raise an exception and let the C++ run time handle it. - // - ex.raise(); - } - - _finished = true; - try { try @@ -3567,7 +3860,7 @@ IcePy::TypedUpcall::exception(PyException& ex, const Ice::EncodingVersion& encod assert(info); Ice::OutputStream os(_communicator); - os.startEncapsulation(encoding, _op->format); + os.startEncapsulation(_encoding, _op->format); ExceptionWriter writer(ex.ex, info); os.writeException(writer); @@ -3589,16 +3882,22 @@ IcePy::TypedUpcall::exception(PyException& ex, const Ice::EncodingVersion& encod } catch(const Ice::Exception& ex) { - AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_exception(ex); + exception(ex); } } +void +IcePy::TypedUpcall::exception(const Ice::Exception& ex) +{ + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + _callback->ice_exception(ex); +} + // // BlobjectUpcall // -IcePy::BlobjectUpcall::BlobjectUpcall(bool amd, const Ice::AMD_Object_ice_invokePtr& callback) : - _amd(amd), _callback(callback), _finished(false) +IcePy::BlobjectUpcall::BlobjectUpcall(const Ice::AMD_Object_ice_invokePtr& callback) : + _callback(callback) { } @@ -3611,11 +3910,6 @@ IcePy::BlobjectUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, Py_ssize_t count = 2; // First is the inParams, second is the Ice::Current object. Py_ssize_t start = 0; - if(_amd) - { - ++count; // Leave room for a leading AMD callback argument. - start = 1; - } PyObjectHandle args = PyTuple_New(count); if(!args.get()) @@ -3636,196 +3930,113 @@ IcePy::BlobjectUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, } #else // - // If using AMD we need to copy the bytes since the bytes may be - // accessed after this method is over, otherwise - // PyBuffer_FromMemory can be used which doesn't do a copy. + // Make a copy of the bytes since the bytes may be accessed after this method is over. // - if(!_amd) + ip = PyBuffer_New(inBytes.second - inBytes.first); + if(!ip.get()) { - ip = PyBuffer_FromMemory((void*)inBytes.first, inBytes.second - inBytes.first); - if(!ip.get()) - { - throwPythonException(); - } + throwPythonException(); } - else + void* buf; + Py_ssize_t sz; + if(PyObject_AsWriteBuffer(ip.get(), &buf, &sz)) { - ip = PyBuffer_New(inBytes.second - inBytes.first); - if(!ip.get()) - { - throwPythonException(); - } - void* buf; - Py_ssize_t sz; - if(PyObject_AsWriteBuffer(ip.get(), &buf, &sz)) - { - throwPythonException(); - } - assert(sz == inBytes.second - inBytes.first); - memcpy(buf, inBytes.first, sz); + throwPythonException(); } + assert(sz == inBytes.second - inBytes.first); + memcpy(buf, inBytes.first, sz); #endif - if(PyTuple_SET_ITEM(args.get(), start, ip.get()) < 0) - { - throwPythonException(); - } + PyTuple_SET_ITEM(args.get(), start, ip.release()); // PyTuple_SET_ITEM steals a reference. ++start; - ip.release(); // PyTuple_SET_ITEM steals a reference. // // Create an object to represent Ice::Current. We need to append // this to the argument tuple. // PyObjectHandle curr = createCurrent(current); - if(PyTuple_SET_ITEM(args.get(), start, curr.get()) < 0) - { - throwPythonException(); - } - curr.release(); // PyTuple_SET_ITEM steals a reference. - - string dispatchName = "ice_invoke"; - if(_amd) - { - dispatchName += "_async"; - // - // Create the callback object and pass it as the first argument. - // - AMDCallbackObject* obj = amdCallbackNew(&AMDCallbackType, 0, 0); - if(!obj) - { - throwPythonException(); - } - obj->upcall = new UpcallPtr(this); - obj->encoding = current.encoding; - if(PyTuple_SET_ITEM(args.get(), 0, (PyObject*)obj) < 0) // PyTuple_SET_ITEM steals a reference. - { - Py_DECREF(obj); - throwPythonException(); - } - } - - // - // Dispatch the operation. - // - PyObjectHandle method = PyObject_GetAttrString(servant, const_cast<char*>(dispatchName.c_str())); - if(!method.get()) - { - ostringstream ostr; - ostr << "servant for identity " << communicator->identityToString(current.id) - << " does not define operation `" << dispatchName << "'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - Ice::UnknownException ex(__FILE__, __LINE__); - ex.unknown = str; - throw ex; - } - - PyObjectHandle result = PyObject_Call(method.get(), args.get(), 0); - - // - // Check for exceptions. - // - if(PyErr_Occurred()) - { - PyException ex; // Retrieve it before another Python API call clears it. - exception(ex, current.encoding); - return; - } + PyTuple_SET_ITEM(args.get(), start, curr.release()); // PyTuple_SET_ITEM steals a reference. - if(!_amd) - { - response(result.get(), current.encoding); - } + dispatchImpl(servant, "ice_invoke", args.get(), current); } void -IcePy::BlobjectUpcall::response(PyObject* args, const Ice::EncodingVersion&) +IcePy::BlobjectUpcall::response(PyObject* result) { - if(_finished) + try { // - // This method could be called more than once if the application calls - // ice_response multiple times. We ignore subsequent calls. + // The result is a tuple of (bool, results). // - return; - } + if(!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 2) + { + string str = "operation `ice_invoke' should return a tuple of length 2"; + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + throw Ice::MarshalException(__FILE__, __LINE__); + } - _finished = true; + PyObject* arg = PyTuple_GET_ITEM(result, 0); + bool isTrue = PyObject_IsTrue(arg) == 1; - // - // The return value is a tuple of (bool, results). - // - if(!PyTuple_Check(args) || PyTuple_GET_SIZE(args) != 2) - { - ostringstream ostr; - string name = "ice_invoke"; - if(_amd) + arg = PyTuple_GET_ITEM(result, 1); + +#if PY_VERSION_HEX >= 0x03000000 + if(!PyBytes_Check(arg)) { - name += "_async"; + ostringstream ostr; + ostr << "invalid return value for operation `ice_invoke'"; + string str = ostr.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + throw Ice::MarshalException(__FILE__, __LINE__); } - ostr << "operation `" << name << "' should return a tuple of length 2"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); - } - PyObject* arg = PyTuple_GET_ITEM(args, 0); - bool isTrue = PyObject_IsTrue(arg) == 1; + Py_ssize_t sz = PyBytes_GET_SIZE(arg); + pair<const ::Ice::Byte*, const ::Ice::Byte*> r(static_cast<const Ice::Byte*>(0), + static_cast<const Ice::Byte*>(0)); + if(sz > 0) + { + r.first = reinterpret_cast<Ice::Byte*>(PyBytes_AS_STRING(arg)); + r.second = r.first + sz; + } +#else + if(!PyBuffer_Check(arg)) + { + ostringstream ostr; + ostr << "invalid return value for operation `ice_invoke'"; + string str = ostr.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); + throw Ice::MarshalException(__FILE__, __LINE__); + } - arg = PyTuple_GET_ITEM(args, 1); + char* charBuf = 0; + Py_ssize_t sz = arg->ob_type->tp_as_buffer->bf_getcharbuffer(arg, 0, &charBuf); + const Ice::Byte* mem = reinterpret_cast<const Ice::Byte*>(charBuf); + const pair<const ::Ice::Byte*, const ::Ice::Byte*> r(mem, mem + sz); +#endif -#if PY_VERSION_HEX >= 0x03000000 - if(!PyBytes_Check(arg)) - { - ostringstream ostr; - ostr << "invalid return value for operation `ice_invoke'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + _callback->ice_response(isTrue, r); } - - Py_ssize_t sz = PyBytes_GET_SIZE(arg); - pair<const ::Ice::Byte*, const ::Ice::Byte*> r(static_cast<const Ice::Byte*>(0),static_cast<const Ice::Byte*>(0)); - if(sz > 0) + catch(const AbortMarshaling&) { - r.first = reinterpret_cast<Ice::Byte*>(PyBytes_AS_STRING(arg)); - r.second = r.first + sz; + try + { + throwPythonException(); + } + catch(const Ice::Exception& ex) + { + exception(ex); + } } -#else - if(!PyBuffer_Check(arg)) + catch(const Ice::Exception& ex) { - ostringstream ostr; - ostr << "invalid return value for operation `ice_invoke'"; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); + exception(ex); } - - char* charBuf = 0; - Py_ssize_t sz = arg->ob_type->tp_as_buffer->bf_getcharbuffer(arg, 0, &charBuf); - const Ice::Byte* mem = reinterpret_cast<const Ice::Byte*>(charBuf); - const pair<const ::Ice::Byte*, const ::Ice::Byte*> r(mem, mem + sz); -#endif - - AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_response(isTrue, r); } void -IcePy::BlobjectUpcall::exception(PyException& ex, const Ice::EncodingVersion&) +IcePy::BlobjectUpcall::exception(PyException& ex) { - if(_finished) - { - // - // An asynchronous response or exception has already been sent. We just - // raise an exception and let the C++ run time handle it. - // - ex.raise(); - } - - _finished = true; - try { // @@ -3840,11 +4051,17 @@ IcePy::BlobjectUpcall::exception(PyException& ex, const Ice::EncodingVersion&) } catch(const Ice::Exception& ex) { - AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. - _callback->ice_exception(ex); + exception(ex); } } +void +IcePy::BlobjectUpcall::exception(const Ice::Exception& ex) +{ + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + _callback->ice_exception(ex); +} + PyObject* IcePy::invokeBuiltin(PyObject* proxy, const string& builtin, PyObject* args) { @@ -3863,6 +4080,23 @@ IcePy::invokeBuiltin(PyObject* proxy, const string& builtin, PyObject* args) } PyObject* +IcePy::invokeBuiltinAsync(PyObject* proxy, const string& builtin, PyObject* args) +{ + string name = "_op_" + builtin; + PyObject* objectType = lookupType("Ice.Object"); + assert(objectType); + PyObjectHandle obj = PyObject_GetAttrString(objectType, STRCAST(name.c_str())); + assert(obj.get()); + + OperationPtr op = getOperation(obj.get()); + assert(op); + + Ice::ObjectPrx p = getProxy(proxy); + InvocationPtr i = new NewAsyncTypedInvocation(p, proxy, op); + return i->invoke(args); +} + +PyObject* IcePy::beginBuiltin(PyObject* proxy, const string& builtin, PyObject* args) { string name = "_op_" + builtin; @@ -3921,7 +4155,7 @@ PyObject* IcePy::iceInvokeAsync(PyObject* proxy, PyObject* args) { Ice::ObjectPrx p = getProxy(proxy); - InvocationPtr i = new OldAsyncBlobjectInvocation(p); + InvocationPtr i = new NewAsyncBlobjectInvocation(p, proxy); return i->invoke(args); } @@ -3963,12 +4197,9 @@ IcePy::createAsyncResult(const Ice::AsyncResultPtr& r, PyObject* proxy, PyObject return 0; } obj->result = new Ice::AsyncResultPtr(r); - obj->proxy = proxy; - Py_XINCREF(obj->proxy); - obj->connection = connection; - Py_XINCREF(obj->connection); - obj->communicator = communicator; - Py_XINCREF(obj->communicator); + obj->proxy = incRef(proxy); + obj->connection = incRef(connection); + obj->communicator = incRef(communicator); return reinterpret_cast<PyObject*>(obj); } @@ -3980,6 +4211,9 @@ IcePy::getAsyncResult(PyObject* p) return *obj->result; } +// +// FlushCallback +// IcePy::FlushCallback::FlushCallback(PyObject* ex, PyObject* sent, const string& op) : _ex(ex), _sent(sent), _op(op) { @@ -4014,6 +4248,100 @@ IcePy::FlushCallback::sent(bool sentSynchronously) } } +IcePy::FlushAsyncCallback::FlushAsyncCallback(const string& op) : + _op(op), _future(0), _sent(false), _sentSynchronously(false), _exception(0) +{ +} + +IcePy::FlushAsyncCallback::~FlushAsyncCallback() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + Py_XDECREF(_future); + Py_XDECREF(_exception); +} + +void +IcePy::FlushAsyncCallback::setFuture(PyObject* future) +{ + // + // Called with the GIL locked. + // + + // + // Check if any callbacks have been invoked already. + // + if(_exception) + { + PyObjectHandle tmp = callMethod(future, "set_exception", _exception); + PyErr_Clear(); + } + else if(_sent) + { + PyObjectHandle tmp = callMethod(future, "set_sent", _sentSynchronously ? getTrue() : getFalse()); + PyErr_Clear(); + // + // We consider the invocation complete when sent. + // + tmp = callMethod(future, "set_result", Py_None); + PyErr_Clear(); + } + else + { + _future = incRef(future); + } +} + +void +IcePy::FlushAsyncCallback::exception(const Ice::Exception& ex) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) + { + // + // The future hasn't been set yet, which means the request is still being invoked. Save the results for later. + // + _exception = convertException(ex); + return; + } + + PyObjectHandle exh = convertException(ex); + assert(exh.get()); + PyObjectHandle tmp = callMethod(_future, "set_exception", exh.get()); + PyErr_Clear(); + + Py_DECREF(_future); // Break cyclic dependency. + _future = 0; +} + +void +IcePy::FlushAsyncCallback::sent(bool sentSynchronously) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) + { + // + // The future hasn't been set yet, which means the request is still being invoked. Save the results for later. + // + _sent = true; + _sentSynchronously = sentSynchronously; + return; + } + + PyObjectHandle tmp = callMethod(_future, "set_sent", _sentSynchronously ? getTrue() : getFalse()); + PyErr_Clear(); + // + // We consider the invocation complete when sent. + // + tmp = callMethod(_future, "set_result", Py_None); + PyErr_Clear(); + + Py_DECREF(_future); // Break cyclic dependency. + _future = 0; +} + IcePy::GetConnectionCallback::GetConnectionCallback(const Ice::CommunicatorPtr& communicator, PyObject* response, PyObject* ex, const string& op) : _communicator(communicator), _response(response), _ex(ex), _op(op) @@ -4053,6 +4381,92 @@ IcePy::GetConnectionCallback::exception(const Ice::Exception& ex) callException(_ex, ex); } +IcePy::GetConnectionAsyncCallback::GetConnectionAsyncCallback(const Ice::CommunicatorPtr& communicator, + const string& op) : + _communicator(communicator), _op(op), _future(0), _exception(0) +{ +} + +IcePy::GetConnectionAsyncCallback::~GetConnectionAsyncCallback() +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + Py_XDECREF(_future); + Py_XDECREF(_exception); +} + +void +IcePy::GetConnectionAsyncCallback::setFuture(PyObject* future) +{ + // + // Called with the GIL locked. + // + + // + // Check if any callbacks have been invoked already. + // + if(_connection) + { + PyObjectHandle pyConn = createConnection(_connection, _communicator); + assert(pyConn.get()); + PyObjectHandle tmp = callMethod(future, "set_result", pyConn.get()); + PyErr_Clear(); + } + else if(_exception) + { + PyObjectHandle tmp = callMethod(future, "set_exception", _exception); + PyErr_Clear(); + } + else + { + _future = incRef(future); + } +} + +void +IcePy::GetConnectionAsyncCallback::response(const Ice::ConnectionPtr& conn) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) + { + // + // The future hasn't been set yet, which means the request is still being invoked. Save the results for later. + // + _connection = conn; + return; + } + + PyObjectHandle pyConn = createConnection(conn, _communicator); + PyObjectHandle tmp = callMethod(_future, "set_result", pyConn.get()); + PyErr_Clear(); + + Py_DECREF(_future); // Break cyclic dependency. + _future = 0; +} + +void +IcePy::GetConnectionAsyncCallback::exception(const Ice::Exception& ex) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + if(!_future) + { + // + // The future hasn't been set yet, which means the request is still being invoked. Save the results for later. + // + _exception = convertException(ex); + return; + } + + PyObjectHandle exh = convertException(ex); + PyObjectHandle tmp = callMethod(_future, "set_exception", exh.get()); + PyErr_Clear(); + + Py_DECREF(_future); // Break cyclic dependency. + _future = 0; +} + // // ServantWrapper implementation. // @@ -4172,7 +4586,7 @@ IcePy::BlobjectServantWrapper::ice_invoke_async(const Ice::AMD_Object_ice_invoke try { - UpcallPtr up = new BlobjectUpcall(_amd, cb); + UpcallPtr up = new BlobjectUpcall(cb); up->dispatch(_servant, inParams, current); } catch(const Ice::Exception& ex) @@ -4199,3 +4613,50 @@ IcePy::createServantWrapper(PyObject* servant) return new TypedServantWrapper(servant); } + +PyObject* +IcePy::createFuture() +{ + PyObject* futureType = lookupType("Ice.Future"); + assert(futureType); + PyObjectHandle args = PyTuple_New(0); + if(!args.get()) + { + return 0; + } + PyTypeObject* type = reinterpret_cast<PyTypeObject*>(futureType); + PyObject* future = type->tp_new(type, args.get(), 0); + if(!future) + { + return 0; + } + type->tp_init(future, args.get(), 0); // Call the constructor + return future; +} + +PyObject* +IcePy::createFuture(const string& operation, PyObject* asyncResult) +{ + if(!asyncResult) // Can be nil for batch invocations. + { + asyncResult = Py_None; + } + + PyObject* futureType = lookupType("Ice.InvocationFuture"); + assert(futureType); + PyObjectHandle args = PyTuple_New(2); + if(!args.get()) + { + return 0; + } + PyTuple_SET_ITEM(args.get(), 0, createString(operation)); + PyTuple_SET_ITEM(args.get(), 1, incRef(asyncResult)); + PyTypeObject* type = reinterpret_cast<PyTypeObject*>(futureType); + PyObject* future = type->tp_new(type, args.get(), 0); + if(!future) + { + return 0; + } + type->tp_init(future, args.get(), 0); // Call the constructor + return future; +} diff --git a/python/modules/IcePy/Operation.h b/python/modules/IcePy/Operation.h index cc8736f1ec7..3d0c2e44850 100644 --- a/python/modules/IcePy/Operation.h +++ b/python/modules/IcePy/Operation.h @@ -15,6 +15,8 @@ #include <Ice/Object.h> #include <Ice/AsyncResultF.h> #include <Ice/CommunicatorF.h> +#include <IceUtil/Monitor.h> +#include <Util.h> namespace IcePy { @@ -25,6 +27,7 @@ bool initOperation(PyObject*); // Builtin operations. // PyObject* invokeBuiltin(PyObject*, const std::string&, PyObject*); +PyObject* invokeBuiltinAsync(PyObject*, const std::string&, PyObject*); PyObject* beginBuiltin(PyObject*, const std::string&, PyObject*); PyObject* endBuiltin(PyObject*, const std::string&, PyObject*); @@ -63,6 +66,31 @@ protected: typedef IceUtil::Handle<GetConnectionCallback> GetConnectionCallbackPtr; // +// Used as the callback for getConnectionAsync operation. +// +class GetConnectionAsyncCallback : public IceUtil::Shared +{ +public: + + GetConnectionAsyncCallback(const Ice::CommunicatorPtr&, const std::string&); + ~GetConnectionAsyncCallback(); + + void setFuture(PyObject*); + + void response(const Ice::ConnectionPtr&); + void exception(const Ice::Exception&); + +protected: + + Ice::CommunicatorPtr _communicator; + std::string _op; + PyObject* _future; + Ice::ConnectionPtr _connection; + PyObject* _exception; +}; +typedef IceUtil::Handle<GetConnectionAsyncCallback> GetConnectionAsyncCallbackPtr; + +// // Used as the callback for the various flushBatchRequest operations. // class FlushCallback : public IceUtil::Shared @@ -84,6 +112,31 @@ protected: typedef IceUtil::Handle<FlushCallback> FlushCallbackPtr; // +// Used as the callback for the various flushBatchRequestAsync operations. +// +class FlushAsyncCallback : public IceUtil::Shared +{ +public: + + FlushAsyncCallback(const std::string&); + ~FlushAsyncCallback(); + + void setFuture(PyObject*); + + void exception(const Ice::Exception&); + void sent(bool); + +protected: + + std::string _op; + PyObject* _future; + bool _sent; + bool _sentSynchronously; + PyObject* _exception; +}; +typedef IceUtil::Handle<FlushAsyncCallback> FlushAsyncCallbackPtr; + +// // ServantWrapper handles dispatching to a Python servant. // class ServantWrapper : public Ice::BlobjectArrayAsync @@ -103,6 +156,9 @@ typedef IceUtil::Handle<ServantWrapper> ServantWrapperPtr; ServantWrapperPtr createServantWrapper(PyObject*); +PyObject* createFuture(); +PyObject* createFuture(const std::string&, PyObject*); + } #endif diff --git a/python/modules/IcePy/Proxy.cpp b/python/modules/IcePy/Proxy.cpp index 0d1c11bb082..a9fb3b09360 100644 --- a/python/modules/IcePy/Proxy.cpp +++ b/python/modules/IcePy/Proxy.cpp @@ -201,6 +201,27 @@ proxyIceIsA(ProxyObject* self, PyObject* args) extern "C" #endif static PyObject* +proxyIceIsAAsync(ProxyObject* self, PyObject* args) +{ + PyObject* type; + PyObject* ctx = Py_None; + if(!PyArg_ParseTuple(args, STRCAST("O|O!"), &type, &PyDict_Type, &ctx)) + { + return 0; + } + + // + // We need to reformat the arguments to match what is used by the generated code: ((params...), ctx|None) + // + PyObjectHandle newArgs = Py_BuildValue(STRCAST("((O), O)"), type, ctx); + + return invokeBuiltinAsync(reinterpret_cast<PyObject*>(self), "ice_isA", newArgs.get()); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceIsA(ProxyObject* self, PyObject* args, PyObject* kwds) { static char* argNames[] = @@ -265,6 +286,26 @@ proxyIcePing(ProxyObject* self, PyObject* args) extern "C" #endif static PyObject* +proxyIcePingAsync(ProxyObject* self, PyObject* args) +{ + PyObject* ctx = Py_None; + if(!PyArg_ParseTuple(args, STRCAST("|O!"), &PyDict_Type, &ctx)) + { + return 0; + } + + // + // We need to reformat the arguments to match what is used by the generated code: ((params...), ctx|None) + // + PyObjectHandle newArgs = Py_BuildValue(STRCAST("((), O)"), ctx); + + return invokeBuiltinAsync(reinterpret_cast<PyObject*>(self), "ice_ping", newArgs.get()); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIcePing(ProxyObject* self, PyObject* args, PyObject* kwds) { static char* argNames[] = @@ -327,6 +368,26 @@ proxyIceIds(ProxyObject* self, PyObject* args) extern "C" #endif static PyObject* +proxyIceIdsAsync(ProxyObject* self, PyObject* args) +{ + PyObject* ctx = Py_None; + if(!PyArg_ParseTuple(args, STRCAST("|O!"), &PyDict_Type, &ctx)) + { + return 0; + } + + // + // We need to reformat the arguments to match what is used by the generated code: ((params...), ctx|None) + // + PyObjectHandle newArgs = Py_BuildValue(STRCAST("((), O)"), ctx); + + return invokeBuiltinAsync(reinterpret_cast<PyObject*>(self), "ice_ids", newArgs.get()); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceIds(ProxyObject* self, PyObject* args, PyObject* kwds) { static char* argNames[] = @@ -389,6 +450,26 @@ proxyIceId(ProxyObject* self, PyObject* args) extern "C" #endif static PyObject* +proxyIceIdAsync(ProxyObject* self, PyObject* args) +{ + PyObject* ctx = Py_None; + if(!PyArg_ParseTuple(args, STRCAST("|O!"), &PyDict_Type, &ctx)) + { + return 0; + } + + // + // We need to reformat the arguments to match what is used by the generated code: ((params...), ctx|None) + // + PyObjectHandle newArgs = Py_BuildValue(STRCAST("((), O)"), ctx); + + return invokeBuiltinAsync(reinterpret_cast<PyObject*>(self), "ice_id", newArgs.get()); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceId(ProxyObject* self, PyObject* args, PyObject* kwds) { static char* argNames[] = @@ -1733,6 +1814,51 @@ proxyIceGetConnection(ProxyObject* self) extern "C" #endif static PyObject* +proxyIceGetConnectionAsync(ProxyObject* self, PyObject* /*args*/, PyObject* /*kwds*/) +{ + assert(self->proxy); + const string op = "ice_getConnection"; + + GetConnectionAsyncCallbackPtr d = new GetConnectionAsyncCallback(*self->communicator, op); + Ice::Callback_Object_ice_getConnectionPtr cb = + Ice::newCallback_Object_ice_getConnection(d, &GetConnectionAsyncCallback::response, + &GetConnectionAsyncCallback::exception); + + Ice::AsyncResultPtr result; + + try + { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + + result = (*self->proxy)->begin_ice_getConnection(cb); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + return 0; + } + + PyObjectHandle communicatorObj = getCommunicatorWrapper(*self->communicator); + PyObjectHandle asyncResultObj = + createAsyncResult(result, reinterpret_cast<PyObject*>(self), 0, communicatorObj.get()); + if(!asyncResultObj.get()) + { + return 0; + } + + PyObjectHandle future = createFuture(op, asyncResultObj.get()); + if(!future.get()) + { + return 0; + } + d->setFuture(future.get()); + return future.release(); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceGetConnection(ProxyObject* self, PyObject* args, PyObject* kwds) { assert(self->proxy); @@ -1894,6 +2020,50 @@ proxyIceFlushBatchRequests(ProxyObject* self) extern "C" #endif static PyObject* +proxyIceFlushBatchRequestsAsync(ProxyObject* self, PyObject* /*args*/, PyObject* /*kwds*/) +{ + assert(self->proxy); + const string op = "ice_flushBatchRequests"; + + FlushAsyncCallbackPtr d = new FlushAsyncCallback(op); + Ice::Callback_Object_ice_flushBatchRequestsPtr cb = + Ice::newCallback_Object_ice_flushBatchRequests(d, &FlushAsyncCallback::exception, &FlushAsyncCallback::sent); + + Ice::AsyncResultPtr result; + + try + { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. + + result = (*self->proxy)->begin_ice_flushBatchRequests(cb); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + return 0; + } + + PyObjectHandle communicatorObj = getCommunicatorWrapper(*self->communicator); + PyObjectHandle asyncResultObj = + createAsyncResult(result, reinterpret_cast<PyObject*>(self), 0, communicatorObj.get()); + if(!asyncResultObj.get()) + { + return 0; + } + + PyObjectHandle future = createFuture(op, asyncResultObj.get()); + if(!future.get()) + { + return 0; + } + d->setFuture(future.get()); + return future.release(); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceFlushBatchRequests(ProxyObject* self, PyObject* args, PyObject* kwds) { assert(self->proxy); @@ -2030,7 +2200,7 @@ AMI_Object_ice_flushBatchRequestsI::exception(const Ice::Exception& ex) ostringstream ostr; ostr << "AMI callback object for ice_flushBatchRequests does not define " << methodName << "()"; string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + PyErr_WarnEx(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()), 1); } else { @@ -2081,6 +2251,15 @@ proxyIceInvoke(ProxyObject* self, PyObject* args) extern "C" #endif static PyObject* +proxyIceInvokeAsync(ProxyObject* self, PyObject* args, PyObject* /*kwds*/) +{ + return iceInvokeAsync(reinterpret_cast<PyObject*>(self), args); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* proxyBeginIceInvoke(ProxyObject* self, PyObject* args, PyObject* kwds) { return beginIceInvoke(reinterpret_cast<PyObject*>(self), args, kwds); @@ -2389,24 +2568,32 @@ static PyMethodDef ProxyMethods[] = PyDoc_STR(STRCAST("ice_toString() -> string")) }, { STRCAST("ice_isA"), reinterpret_cast<PyCFunction>(proxyIceIsA), METH_VARARGS, PyDoc_STR(STRCAST("ice_isA(type, [ctx]) -> bool")) }, + { STRCAST("ice_isAAsync"), reinterpret_cast<PyCFunction>(proxyIceIsAAsync), METH_VARARGS, + PyDoc_STR(STRCAST("ice_isAAsync(type, [ctx]) -> Ice.Future")) }, { STRCAST("begin_ice_isA"), reinterpret_cast<PyCFunction>(proxyBeginIceIsA), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_isA(type[, _response][, _ex][, _sent][, _ctx]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_isA"), reinterpret_cast<PyCFunction>(proxyEndIceIsA), METH_VARARGS, PyDoc_STR(STRCAST("end_ice_isA(Ice.AsyncResult) -> bool")) }, { STRCAST("ice_ping"), reinterpret_cast<PyCFunction>(proxyIcePing), METH_VARARGS, PyDoc_STR(STRCAST("ice_ping([ctx]) -> None")) }, + { STRCAST("ice_pingAsync"), reinterpret_cast<PyCFunction>(proxyIcePingAsync), METH_VARARGS, + PyDoc_STR(STRCAST("ice_pingAsync([ctx]) -> Ice.Future")) }, { STRCAST("begin_ice_ping"), reinterpret_cast<PyCFunction>(proxyBeginIcePing), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_ping([_response][, _ex][, _sent][, _ctx]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_ping"), reinterpret_cast<PyCFunction>(proxyEndIcePing), METH_VARARGS, PyDoc_STR(STRCAST("end_ice_ping(Ice.AsyncResult) -> None")) }, { STRCAST("ice_ids"), reinterpret_cast<PyCFunction>(proxyIceIds), METH_VARARGS, PyDoc_STR(STRCAST("ice_ids([ctx]) -> list")) }, + { STRCAST("ice_idsAsync"), reinterpret_cast<PyCFunction>(proxyIceIdsAsync), METH_VARARGS, + PyDoc_STR(STRCAST("ice_idsAsync([ctx]) -> Ice.Future")) }, { STRCAST("begin_ice_ids"), reinterpret_cast<PyCFunction>(proxyBeginIceIds), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_ids([_response][, _ex][, _sent][, _ctx]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_ids"), reinterpret_cast<PyCFunction>(proxyEndIceIds), METH_VARARGS, PyDoc_STR(STRCAST("end_ice_ids(Ice.AsyncResult) -> list")) }, { STRCAST("ice_id"), reinterpret_cast<PyCFunction>(proxyIceId), METH_VARARGS, PyDoc_STR(STRCAST("ice_id([ctx]) -> string")) }, + { STRCAST("ice_idAsync"), reinterpret_cast<PyCFunction>(proxyIceIdAsync), METH_VARARGS, + PyDoc_STR(STRCAST("ice_idAsync([ctx]) -> Ice.Future")) }, { STRCAST("begin_ice_id"), reinterpret_cast<PyCFunction>(proxyBeginIceId), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_id([_response][, _ex][, _sent][, _ctx]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_id"), reinterpret_cast<PyCFunction>(proxyEndIceId), METH_VARARGS, @@ -2501,6 +2688,8 @@ static PyMethodDef ProxyMethods[] = PyDoc_STR(STRCAST("ice_connectionId(string) -> Ice.ObjectPrx")) }, { STRCAST("ice_getConnection"), reinterpret_cast<PyCFunction>(proxyIceGetConnection), METH_NOARGS, PyDoc_STR(STRCAST("ice_getConnection() -> Ice.Connection")) }, + { STRCAST("ice_getConnectionAsync"), reinterpret_cast<PyCFunction>(proxyIceGetConnectionAsync), + METH_NOARGS, PyDoc_STR(STRCAST("ice_getConnectionAsync() -> Ice.Future")) }, { STRCAST("begin_ice_getConnection"), reinterpret_cast<PyCFunction>(proxyBeginIceGetConnection), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_getConnection([_response][, _ex]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_getConnection"), reinterpret_cast<PyCFunction>(proxyEndIceGetConnection), METH_VARARGS, @@ -2509,12 +2698,16 @@ static PyMethodDef ProxyMethods[] = PyDoc_STR(STRCAST("ice_getCachedConnection() -> Ice.Connection")) }, { STRCAST("ice_flushBatchRequests"), reinterpret_cast<PyCFunction>(proxyIceFlushBatchRequests), METH_NOARGS, PyDoc_STR(STRCAST("ice_flushBatchRequests() -> void")) }, + { STRCAST("ice_flushBatchRequestsAsync"), reinterpret_cast<PyCFunction>(proxyIceFlushBatchRequestsAsync), + METH_NOARGS, PyDoc_STR(STRCAST("ice_flushBatchRequestsAsync() -> Ice.Future")) }, { STRCAST("begin_ice_flushBatchRequests"), reinterpret_cast<PyCFunction>(proxyBeginIceFlushBatchRequests), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_flushBatchRequests([_ex][, _sent]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_flushBatchRequests"), reinterpret_cast<PyCFunction>(proxyEndIceFlushBatchRequests), METH_VARARGS, PyDoc_STR(STRCAST("end_ice_flushBatchRequests(Ice.AsyncResult) -> void")) }, { STRCAST("ice_invoke"), reinterpret_cast<PyCFunction>(proxyIceInvoke), METH_VARARGS, PyDoc_STR(STRCAST("ice_invoke(operation, mode, inParams) -> bool, outParams")) }, + { STRCAST("ice_invokeAsync"), reinterpret_cast<PyCFunction>(proxyIceInvokeAsync), METH_VARARGS | METH_KEYWORDS, + PyDoc_STR(STRCAST("ice_invokeAsync(op, mode, inParams[, _ctx]) -> Ice.Future")) }, { STRCAST("begin_ice_invoke"), reinterpret_cast<PyCFunction>(proxyBeginIceInvoke), METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_ice_invoke(op, mode, inParams[, _response][, _ex][, _sent][, _ctx]) -> Ice.AsyncResult")) }, { STRCAST("end_ice_invoke"), reinterpret_cast<PyCFunction>(proxyEndIceInvoke), METH_VARARGS, diff --git a/python/modules/IcePy/Slice.cpp b/python/modules/IcePy/Slice.cpp index 1294a80194c..4581a97f45b 100644 --- a/python/modules/IcePy/Slice.cpp +++ b/python/modules/IcePy/Slice.cpp @@ -72,6 +72,7 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args) opts.addOpt("", "underscore"); opts.addOpt("", "checksum"); opts.addOpt("", "all"); + opts.addOpt("", "python3"); vector<string> files; try @@ -102,6 +103,7 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args) bool underscore = opts.isSet("underscore"); bool all = false; bool checksum = false; + bool python3 = false; if(opts.isSet("D")) { vector<string> optargs = opts.argVec("D"); @@ -129,6 +131,7 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args) debug = opts.isSet("d") || opts.isSet("debug"); all = opts.isSet("all"); checksum = opts.isSet("checksum"); + python3 = opts.isSet("python3"); bool ignoreRedefs = false; bool keepComments = true; @@ -161,11 +164,13 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args) ostringstream codeStream; IceUtilInternal::Output out(codeStream); out.setUseTab(false); + // - // Python magic comment to set the file encoding, it must be first or second line + // Emit a Python magic comment to set the file encoding. + // It must be the first or second line. // out << "# -*- coding: utf-8 -*-\n"; - generate(u, all, checksum, includePaths, out); + generate(u, all, checksum, python3, includePaths, out); u->destroy(); string code = codeStream.str(); diff --git a/python/modules/IcePy/Util.cpp b/python/modules/IcePy/Util.cpp index b40d9f3dcfb..8d0cd602aae 100644 --- a/python/modules/IcePy/Util.cpp +++ b/python/modules/IcePy/Util.cpp @@ -468,11 +468,12 @@ IcePy::PyException::getTraceback() PyObjectHandle str = createString("traceback"); PyObjectHandle mod = PyImport_Import(str.get()); assert(mod.get()); // Unable to import traceback module - Python installation error? - PyObject* d = PyModule_GetDict(mod.get()); - PyObject* func = PyDict_GetItemString(d, "format_exception"); + PyObject* func = PyDict_GetItemString(PyModule_GetDict(mod.get()), "format_exception"); assert(func); // traceback.format_exception must be present. PyObjectHandle args = Py_BuildValue("(OOO)", _type.get(), ex.get(), _tb.get()); + assert(args.get()); PyObjectHandle list = PyObject_CallObject(func, args.get()); + assert(list.get()); string result; for(Py_ssize_t i = 0; i < PyList_GET_SIZE(list.get()); ++i) @@ -1090,6 +1091,60 @@ IcePy::getEncodingVersion(PyObject* args, Ice::EncodingVersion& v) return true; } +PyObject* +IcePy::callMethod(PyObject* obj, const string& name, PyObject* arg1, PyObject* arg2) +{ + PyObjectHandle method = PyObject_GetAttrString(obj, const_cast<char*>(name.c_str())); + if(!method.get()) + { + return 0; + } + return callMethod(method.get(), arg1, arg2); +} + +PyObject* +IcePy::callMethod(PyObject* method, PyObject* arg1, PyObject* arg2) +{ + PyObjectHandle args; + if(arg1 && arg2) + { + args = PyTuple_New(2); + if(!args.get()) + { + return 0; + } + PyTuple_SET_ITEM(args.get(), 0, incRef(arg1)); + PyTuple_SET_ITEM(args.get(), 1, incRef(arg2)); + } + else if(arg1) + { + args = PyTuple_New(1); + if(!args.get()) + { + return 0; + } + PyTuple_SET_ITEM(args.get(), 0, incRef(arg1)); + } + else if(arg2) + { + args = PyTuple_New(1); + if(!args.get()) + { + return 0; + } + PyTuple_SET_ITEM(args.get(), 0, incRef(arg2)); + } + else + { + args = PyTuple_New(0); + if(!args.get()) + { + return 0; + } + } + return PyObject_Call(method, args.get(), 0); +} + extern "C" PyObject* IcePy_stringVersion(PyObject* /*self*/) diff --git a/python/modules/IcePy/Util.h b/python/modules/IcePy/Util.h index 54f1df6b21f..76035279ebe 100644 --- a/python/modules/IcePy/Util.h +++ b/python/modules/IcePy/Util.h @@ -28,6 +28,12 @@ namespace IcePy { +inline PyObject* incRef(PyObject* obj) +{ + Py_XINCREF(obj); + return obj; +} + // // This should be used instead of Py_False to avoid GCC compiler warnings. // @@ -58,16 +64,12 @@ inline PyObject* getTrue() inline PyObject* incFalse() { - PyObject* f = getFalse(); - Py_INCREF(f); - return f; + return incRef(getFalse()); } inline PyObject* incTrue() { - PyObject* t = getTrue(); - Py_INCREF(t); - return t; + return incRef(getTrue()); } // @@ -262,6 +264,12 @@ PyObject* createEncodingVersion(const Ice::EncodingVersion&); // bool getEncodingVersion(PyObject*, Ice::EncodingVersion&); +// +// Call a Python method. +// +PyObject* callMethod(PyObject*, const std::string&, PyObject* = 0, PyObject* = 0); +PyObject* callMethod(PyObject*, PyObject* = 0, PyObject* = 0); + } extern "C" PyObject* IcePy_stringVersion(PyObject*); diff --git a/python/python/Ice.py b/python/python/Ice.py index 7c06a1fec77..46218a57f6f 100644 --- a/python/python/Ice.py +++ b/python/python/Ice.py @@ -11,7 +11,7 @@ Ice module """ -import sys, string, imp, os, threading, warnings, datetime +import sys, string, imp, os, threading, warnings, datetime, logging, time, inspect # # RTTI problems can occur in C++ code unless we modify Python's dlopen flags. @@ -76,6 +76,208 @@ loadSlice = IcePy.loadSlice AsyncResult = IcePy.AsyncResult Unset = IcePy.Unset +if sys.version_info[0] > 3 or (sys.version_info[0] == 3 and sys.version_info[1] >= 5): + from IceFuture import FutureBase, wrap_future +else: + FutureBase = object + +class Future(FutureBase): + def __init__(self): + self._result = None + self._exception = None + self._condition = threading.Condition() + self._doneCallbacks = [] + self._state = Future.StateRunning + + def cancel(self): + callbacks = [] + with self._condition: + if self._state == Future.StateDone: + return False + + if self._state == Future.StateCancelled: + return True + + self._state = Future.StateCancelled + callbacks = self._doneCallbacks + self._doneCallbacks = [] + self._condition.notify_all() + + self._callCallbacks(callbacks) + + return True + + def cancelled(self): + with self._condition: + return self._state == Future.StateCancelled + + def running(self): + with self._condition: + return self._state == Future.StateRunning + + def done(self): + with self._condition: + return self._state in [Future.StateCancelled, Future.StateDone] + + def add_done_callback(self, fn): + with self._condition: + if self._state == Future.StateRunning: + self._doneCallbacks.append(fn) + return + fn(self) + + def result(self, timeout=None): + with self._condition: + if not self._wait(timeout, lambda: self._state == Future.StateRunning): + raise TimeoutException() + if self._state == Future.StateCancelled: + raise InvocationCanceledException() + elif self._exception: + raise self._exception + else: + return self._result + + def exception(self, timeout=None): + with self._condition: + if not self._wait(timeout, lambda: self._state == Future.StateRunning): + raise TimeoutException() + if self._state == Future.StateCancelled: + raise InvocationCanceledException() + else: + return self._exception + + def set_result(self, result): + callbacks = [] + with self._condition: + if self._state != Future.StateRunning: + return + self._result = result + self._state = Future.StateDone + callbacks = self._doneCallbacks + self._doneCallbacks = [] + self._condition.notify_all() + + self._callCallbacks(callbacks) + + def set_exception(self, ex): + callbacks = [] + with self._condition: + if self._state != Future.StateRunning: + return + self._exception = ex + self._state = Future.StateDone + callbacks = self._doneCallbacks + self._doneCallbacks = [] + self._condition.notify_all() + + self._callCallbacks(callbacks) + + def completed(result): + f = Future() + f.set_result(result) + return f + completed = staticmethod(completed) + + def _wait(self, timeout, testFn=None): + # Must be called with _condition acquired + + while testFn(): + if timeout: + start = time.time() + self._condition.wait(timeout) + # Subtract the elapsed time so far from the timeout + timeout -= (time.time() - start) + if timeout <= 0: + return False + else: + self._condition.wait() + + return True + + def _callCallbacks(self, callbacks): + for callback in callbacks: + try: + callback(self) + except: + logging.getLogger("Ice.Future").exception('callback raised exception') + + StateRunning = 'running' + StateCancelled = 'cancelled' + StateDone = 'done' + +class InvocationFuture(Future): + def __init__(self, operation, asyncResult): + Future.__init__(self) + self._operation = operation + self._asyncResult = asyncResult # May be None for a batch invocation. + self._sent = False + self._sentSynchronously = False + self._sentCallbacks = [] + + def cancel(self): + if self._asyncResult: + self._asyncResult.cancel() + return Future.cancel(self) + + def is_sent(self): + with self._condition: + return self._sent + + def sent_synchronously(self): + with self._condition: + return self._sentSynchronously + + def add_sent_callback(self, fn): + with self._condition: + if not self._sent: + self._sentCallbacks.append(fn) + return + if self._sentSynchronously or not self._asyncResult: + fn(self, self._sentSynchronously) + else: + self._asyncResult.callLater(lambda: fn(self, self._sentSynchronously)) + + def sent(self, timeout=None): + with self._condition: + if not self._wait(timeout, lambda: not self._sent): + raise TimeoutException() + if self._state == Future.StateCancelled: + raise InvocationCanceledException() + elif self._exception: + raise self._exception + else: + return self._sentSynchronously + + def set_sent(self, sentSynchronously): + callbacks = [] + with self._condition: + if self._sent: + return + + self._sent = True + self._sentSynchronously = sentSynchronously + callbacks = self._sentCallbacks + self._sentCallbacks = [] + self._condition.notify_all() + + for callback in callbacks: + try: + callback(self, sentSynchronously) + except Exception: + logging.getLogger("Ice.Future").exception('callback raised exception') + + def operation(self): + return self._operation + + def proxy(self): + return None if not self._asyncResult else self._asyncResult.getProxy() + + def connection(self): + return None if not self._asyncResult else self._asyncResult.getConnection() + + def communicator(self): + return None if not self._asyncResult else self._asyncResult.getCommunicator() + # # This value is used as the default value for struct types in the constructors # of user-defined types. It allows us to determine whether the application has @@ -134,11 +336,52 @@ Returns: #def ice_postUnmarshal(self): # pass -# -# LocalObject is deprecated; use the Python base 'object' type instead. -# -class LocalObject(object): - pass + def _dispatch(self, cb, method, args): + # Invoke the given servant method. Exceptions can propagate to the caller. + result = method(*args) + + # Check for a future. + if isinstance(result, Future) or callable(getattr(result, "add_done_callback", None)): + def handler(future): + try: + cb.response(future.result()) + except: + cb.exception(sys.exc_info()[1]) + result.add_done_callback(handler) + elif self._isCoroutine(result): + self._dispatchCoroutine(cb, result) + else: + cb.response(result) + + def _isCoroutine(self, coro): + # The inspect.iscoroutine() function was added in Python 3.5. + if sys.version_info[0] > 3 or (sys.version_info[0] == 3 and sys.version_info[1] >= 5): + return inspect.iscoroutine(coro) + else: + return False + + def _dispatchCoroutine(self, cb, coro, value=None, exception=None): + try: + if exception: + result = coro.throw(exception) + else: + result = coro.send(value) + + # Calling 'await <future>' will return the future. Check if we've received a future. + if isinstance(result, Future) or callable(getattr(result, "add_done_callback", None)): + def handler(future): + try: + self._dispatchCoroutine(cb, coro, value=future.result()) + except: + self._dispatchCoroutine(cb, coro, exception=sys.exc_info()[1]) + result.add_done_callback(handler) + else: + raise RuntimeError('unexpected value of type ' + str(type(result)) + ' provided by coroutine') + except StopIteration as ex: + # StopIteration is raised when the coroutine completes. + cb.response(ex.value) + except: + cb.exception(sys.exc_info()[1]) class Blobject(Object): '''Special-purpose servant base class that allows a subclass to @@ -670,6 +913,9 @@ class CommunicatorI(Communicator): def flushBatchRequests(self): self._impl.flushBatchRequests() + def flushBatchRequestsAsync(self): + return self._impl.flushBatchRequestsAsync() + def begin_flushBatchRequests(self, _ex=None, _sent=None): return self._impl.begin_flushBatchRequests(_ex, _sent) diff --git a/python/python/IceFuture.py b/python/python/IceFuture.py new file mode 100644 index 00000000000..c79c5b8d512 --- /dev/null +++ b/python/python/IceFuture.py @@ -0,0 +1,48 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +# +# This file should only be used in Python >= 3.5. +# + +import asyncio + +# +# This class defines an __await__ method so that coroutines can call 'await <future>'. +# +# Python 2.x rejects this code with a syntax error because a return statement is not allowed in a generator. +# +class FutureBase(object): + def __await__(self): + if not self.done(): + yield self + return self.result() + +def wrap_future(future, *, loop=None): + '''Wrap Ice.Future object into an asyncio.Future.''' + if isinstance(future, asyncio.Future): + return future + + assert isinstance(future, FutureBase), 'Ice.Future is expected, got {!r}'.format(future) + + if loop is None: + loop = asyncio.get_event_loop() + + af = loop.create_future() + + def callback(): + if future.cancelled(): + af.cancel() + elif future.exception(): + af.set_exception(future.exception()) + else: + af.set_result(future.result()) + + future.add_done_callback(lambda f: loop.call_soon_threadsafe(callback)) + return af diff --git a/python/test/Ice/acm/AllTests.py b/python/test/Ice/acm/AllTests.py index a82b6515db2..c10edd1de77 100644 --- a/python/test/Ice/acm/AllTests.py +++ b/python/test/Ice/acm/AllTests.py @@ -20,48 +20,33 @@ class LoggerI(Ice.Logger): self.m = threading.Lock() def start(self): - self.m.acquire() - try: + with self.m: self._started = True self.dump() - finally: - self.m.release() def _print(self, msg): - self.m.acquire() - try: + with self.m: self._messages.append(msg) if self._started: self.dump() - finally: - self.m.release() def trace(self, category, msg): - self.m.acquire() - try: + with self.m: self._messages.append("[" + category + "] " + msg) if self._started: self.dump() - finally: - self.m.release() def warning(self, msg): - self.m.acquire() - try: + with self.m: self._messages.append("warning: " + msg) if self._started: self.dump() - finally: - self.m.release() def error(self, msg): - self.m.acquire() - try: + with self.m: self._messages.append("error: " + msg) if self._started: self.dump() - finally: - self.m.release() def getPrefix(self): return "" @@ -136,18 +121,12 @@ class TestCase(threading.Thread): self._msg = "unexpected exception:\n" + traceback.format_exc() def heartbeat(self, con): - self.m.acquire() - try: + with self.m: self._heartbeat = self._heartbeat + 1 - finally: - self.m.release() def closed(self, con): - self.m.acquire() - try: + with self.m: self._closed = True - finally: - self.m.release() def runTestCase(self, adapter, proxy): test(False) @@ -175,11 +154,8 @@ def allTests(communicator): def runTestCase(self, adapter, proxy): proxy.sleep(2) - self.m.acquire() - try: + with self.m: test(self._heartbeat >= 2) - finally: - self.m.release() class InvocationHeartbeatOnHoldTest(TestCase): def __init__(self, com): @@ -197,11 +173,8 @@ def allTests(communicator): adapter.activate() proxy.interruptSleep() - self.m.acquire() - try: + with self.m: test(self._closed) - finally: - self.m.release() class InvocationNoHeartbeatTest(TestCase): def __init__(self, com): @@ -218,12 +191,9 @@ def allTests(communicator): except Ice.ConnectionTimeoutException: proxy.interruptSleep() - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(self._closed) - finally: - self.m.release() class InvocationHeartbeatCloseOnIdleTest(TestCase): def __init__(self, com): @@ -235,12 +205,9 @@ def allTests(communicator): # No close on invocation, the call should succeed this time. proxy.sleep(2) - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(not self._closed) - finally: - self.m.release() class CloseOnIdleTest(TestCase): def __init__(self, com): @@ -250,12 +217,9 @@ def allTests(communicator): def runTestCase(self, adapter, proxy): time.sleep(1.6) # Idle for 1.6 seconds - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(self._closed) - finally: - self.m.release() class CloseOnInvocationTest(TestCase): def __init__(self, com): @@ -265,12 +229,9 @@ def allTests(communicator): def runTestCase(self, adapter, proxy): time.sleep(1.5) # Idle for 1.5 seconds - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(not self._closed) - finally: - self.m.release() class CloseOnIdleAndInvocationTest(TestCase): def __init__(self, com): @@ -286,21 +247,15 @@ def allTests(communicator): adapter.hold() time.sleep(1.6) # Idle for 1.6 seconds - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(not self._closed) # Not closed yet because of graceful close. - finally: - self.m.release() adapter.activate() time.sleep(0.5) - self.m.acquire() - try: + with self.m: test(self._closed) # Connection should be closed this time. - finally: - self.m.release() class ForcefulCloseOnIdleAndInvocationTest(TestCase): def __init__(self, com): @@ -311,12 +266,9 @@ def allTests(communicator): adapter.hold() time.sleep(1.6) # Idle for 1.6 seconds - self.m.acquire() - try: + with self.m: test(self._heartbeat == 0) test(self._closed) # Connection closed forcefully by ACM. - finally: - self.m.release() class HeartbeatOnIdleTest(TestCase): def __init__(self, com): @@ -326,11 +278,8 @@ def allTests(communicator): def runTestCase(self, adapter, proxy): time.sleep(2) - self.m.acquire() - try: + with self.m: test(self._heartbeat >= 3) - finally: - self.m.release() class HeartbeatAlwaysTest(TestCase): def __init__(self, com): @@ -342,11 +291,8 @@ def allTests(communicator): proxy.ice_ping() time.sleep(0.1) - self.m.acquire() - try: + with self.m: test(self._heartbeat >= 3) - finally: - self.m.release() class SetACMTest(TestCase): def __init__(self, com): diff --git a/python/test/Ice/acm/TestI.py b/python/test/Ice/acm/TestI.py index a728dfce1b3..a54e13621bb 100644 --- a/python/test/Ice/acm/TestI.py +++ b/python/test/Ice/acm/TestI.py @@ -56,26 +56,17 @@ class TestIntfI(Test.TestIntf): self.m = threading.Condition() def sleep(self, delay, current=None): - self.m.acquire() - try: + with self.m: self.m.wait(delay) - finally: - self.m.release() def sleepAndHold(self, delay, current=None): - self.m.acquire() - try: + with self.m: current.adapter.hold() self.m.wait(delay) - finally: - self.m.release() def interruptSleep(self, delay, current=None): - self.m.acquire() - try: + with self.m: self.m.notifyAll() - finally: - self.m.release() def waitForHeartbeat(self, count, current=None): @@ -86,21 +77,15 @@ class TestIntfI(Test.TestIntf): self.count = 0 def heartbeat(self, con): - self.m.acquire() - try: + with self.m: self.count -= 1 self.m.notifyAll() - finally: - self.m.release() def waitForCount(self, count): - self.m.acquire() - self.count = count - try: + with self.m: + self.count = count while self.count > 0: self.m.wait() - finally: - self.m.release() callback = ConnectionCallbackI() current.con.setHeartbeatCallback(lambda con: callback.heartbeat(con)) diff --git a/python/test/Ice/adapterDeactivation/AllTests.py b/python/test/Ice/adapterDeactivation/AllTests.py index a8936ef5b4a..4bcdff20117 100644 --- a/python/test/Ice/adapterDeactivation/AllTests.py +++ b/python/test/Ice/adapterDeactivation/AllTests.py @@ -57,7 +57,7 @@ def allTests(communicator): initData = Ice.InitializationData(); initData.properties = communicator.getProperties().clone(); comm = Ice.initialize(initData); - comm.stringToProxy("test:default -p 12010").begin_ice_ping(); + comm.stringToProxy("test:default -p 12010").ice_pingAsync(); comm.destroy(); print("ok"); diff --git a/python/test/Ice/admin/TestI.py b/python/test/Ice/admin/TestI.py index f1e6e0b49d5..c040ffbef59 100644 --- a/python/test/Ice/admin/TestI.py +++ b/python/test/Ice/admin/TestI.py @@ -27,8 +27,7 @@ class RemoteCommunicatorI(Test.RemoteCommunicator, Ice.PropertiesAdminUpdateCall return self.communicator.getAdmin() def getChanges(self, current = None): - self.m.acquire() - try: + with self.m: # # The client calls PropertiesAdmin::setProperties() and then invokes # this operation. Since setProperties() is implemented using AMD, the @@ -42,8 +41,6 @@ class RemoteCommunicatorI(Test.RemoteCommunicator, Ice.PropertiesAdminUpdateCall self.called = False return self.changes - finally: - self.m.release() def shutdown(self, current = None): self.communicator.shutdown() @@ -59,13 +56,10 @@ class RemoteCommunicatorI(Test.RemoteCommunicator, Ice.PropertiesAdminUpdateCall self.communicator.destroy() def updated(self, changes): - self.m.acquire() - try: + with self.m: self.changes = changes self.called = True self.m.notify() - finally: - self.m.release() class RemoteCommunicatorFactoryI(Test.RemoteCommunicatorFactory): diff --git a/python/test/Ice/ami/AllTests.py b/python/test/Ice/ami/AllTests.py index e209138f9f3..5418336f12d 100644 --- a/python/test/Ice/ami/AllTests.py +++ b/python/test/Ice/ami/AllTests.py @@ -19,19 +19,15 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() def exception(self, ex): test(False) @@ -241,6 +237,86 @@ class FlushExCallback(CallbackBase): def sentWC(self, sentSynchronously, cookie): test(False) +class FutureDoneCallback(CallbackBase): + def isA(self, f): + test(f.result()) + self.called() + + def ping(self, f): + self.called() + + def id(self, f): + test(f.result() == "::Test::TestIntf") + self.called() + + def ids(self, f): + test(len(f.result()) == 2) + self.called() + + def connection(self, f): + test(f.result() != None) + self.called() + + def op(self, f): + self.called() + + def opWithResult(self, f): + test(f.result() == 15) + self.called() + + def opWithUE(self, f): + try: + f.result() + test(False) + except Test.TestIntfException: + self.called() + except: + test(False) + +class FutureExceptionCallback(CallbackBase): + def opWithUE(self, f): + test(isinstance(f.exception(), Test.TestIntfException)) + self.called() + + def ex(self, f): + test(isinstance(f.exception(), Ice.NoEndpointException)) + self.called() + + def noEx(self, f): + test(f.exception() is None) + +class FutureSentCallback(CallbackBase): + def __init__(self): + CallbackBase.__init__(self) + self._thread = threading.currentThread() + + def sent(self, f, sentSynchronously): + test((sentSynchronously and self._thread == threading.currentThread()) or \ + (not sentSynchronously and self._thread != threading.currentThread())) + self.called() + +class FutureFlushCallback(CallbackBase): + def __init__(self, cookie=None): + CallbackBase.__init__(self) + self._thread = threading.currentThread() + self._cookie = cookie + + def sent(self, f, sentSynchronously): + test((sentSynchronously and self._thread == threading.currentThread()) or \ + (not sentSynchronously and self._thread != threading.currentThread())) + self.called() + +class FutureFlushExCallback(CallbackBase): + def __init__(self, cookie=None): + CallbackBase.__init__(self) + self._cookie = cookie + + def exception(self, f): + self.called() + + def sent(self, f, sentSynchronously): + test(False) + LocalException = 0 UserException = 1 OtherException = 2 @@ -1087,4 +1163,607 @@ def allTests(communicator, collocated): print("ok") +def allTestsFuture(communicator, collocated): + sref = "test:default -p 12010" + obj = communicator.stringToProxy(sref) + test(obj) + + p = Test.TestIntfPrx.uncheckedCast(obj) + + sref = "testController:default -p 12011" + obj = communicator.stringToProxy(sref) + test(obj) + + testController = Test.TestIntfControllerPrx.uncheckedCast(obj) + + sys.stdout.write("testing future invocations... ") + sys.stdout.flush() + ctx = {} + + test(p.ice_isAAsync("::Test::TestIntf").result()) + test(p.ice_isAAsync("::Test::TestIntf", ctx).result()) + + p.ice_pingAsync().result() + p.ice_pingAsync(ctx).result() + + test(p.ice_idAsync().result() == "::Test::TestIntf") + test(p.ice_idAsync(ctx).result() == "::Test::TestIntf") + + test(len(p.ice_idsAsync().result()) == 2) + test(len(p.ice_idsAsync(ctx).result()) == 2) + + if not collocated: + test(p.ice_getConnectionAsync().result() != None) + + p.opAsync().result() + p.opAsync(ctx).result() + + test(p.opWithResultAsync().result() == 15) + test(p.opWithResultAsync(ctx).result() == 15) + + try: + p.opWithUEAsync().result() + test(False) + except Test.TestIntfException: + pass + try: + p.opWithUEAsync(ctx).result() + test(False) + except Test.TestIntfException: + pass + + print("ok") + + sys.stdout.write("testing done callback... ") + sys.stdout.flush() + + ctx = {} + cb = FutureDoneCallback() + + p.ice_isAAsync(Test.TestIntf.ice_staticId()).add_done_callback(cb.isA) + cb.check() + p.ice_isAAsync(Test.TestIntf.ice_staticId(), ctx).add_done_callback(cb.isA) + cb.check() + + p.ice_pingAsync().add_done_callback(cb.ping) + cb.check() + p.ice_pingAsync(ctx).add_done_callback(cb.ping) + cb.check() + + p.ice_idAsync().add_done_callback(cb.id) + cb.check() + p.ice_idAsync(ctx).add_done_callback(cb.id) + cb.check() + + p.ice_idsAsync().add_done_callback(cb.ids) + cb.check() + p.ice_idsAsync(ctx).add_done_callback(cb.ids) + cb.check() + + if not collocated: + p.ice_getConnectionAsync().add_done_callback(cb.connection) + cb.check() + + p.opAsync().add_done_callback(cb.op) + cb.check() + p.opAsync(ctx).add_done_callback(cb.op) + cb.check() + + p.opWithResultAsync().add_done_callback(cb.opWithResult) + cb.check() + p.opWithResultAsync(ctx).add_done_callback(cb.opWithResult) + cb.check() + + p.opWithUEAsync().add_done_callback(cb.opWithUE) + cb.check() + p.opWithUEAsync(ctx).add_done_callback(cb.opWithUE) + cb.check() + + print("ok") + + sys.stdout.write("testing local exceptions... ") + sys.stdout.flush() + + indirect = Test.TestIntfPrx.uncheckedCast(p.ice_adapterId("dummy")) + + try: + indirect.opAsync().result() + test(False) + except Ice.NoEndpointException: + pass + + try: + p.ice_oneway().opWithResultAsync().result() + test(False) + except RuntimeError: + pass + + # + # Check that CommunicatorDestroyedException is raised directly. + # + if p.ice_getConnection(): + initData = Ice.InitializationData() + initData.properties = communicator.getProperties().clone() + ic = Ice.initialize(initData) + obj = ic.stringToProxy(p.ice_toString()) + p2 = Test.TestIntfPrx.checkedCast(obj) + ic.destroy(); + + try: + p2.opAsync() + test(False) + except Ice.CommunicatorDestroyedException: + pass + + print("ok") + + sys.stdout.write("testing local exceptions with done callback... ") + sys.stdout.flush() + + i = Test.TestIntfPrx.uncheckedCast(p.ice_adapterId("dummy")) + cb = FutureExceptionCallback() + + i.ice_isAAsync(Test.TestIntf.ice_staticId()).add_done_callback(cb.ex) + cb.check() + + i.ice_pingAsync().add_done_callback(cb.ex) + cb.check() + + i.ice_idAsync().add_done_callback(cb.ex) + cb.check() + + i.ice_idsAsync().add_done_callback(cb.ex) + cb.check() + + if not collocated: + i.ice_getConnectionAsync().add_done_callback(cb.ex) + cb.check() + + i.opAsync().add_done_callback(cb.ex) + cb.check() + + print("ok") + + sys.stdout.write("testing exceptions with done callback... ") + sys.stdout.flush() + + cb = FutureExceptionCallback() + + # Ensures no exception is set when response is received. + p.ice_isAAsync(Test.TestIntf.ice_staticId()).add_done_callback(cb.noEx) + p.opAsync().add_done_callback(cb.noEx) + + # If response is a user exception, it should be received. + p.opWithUEAsync().add_done_callback(cb.opWithUE) + cb.check() + + print("ok") + + sys.stdout.write("testing sent callback... ") + sys.stdout.flush() + + cb = FutureSentCallback() + + p.ice_isAAsync("").add_sent_callback(cb.sent) + cb.check() + + p.ice_pingAsync().add_sent_callback(cb.sent) + cb.check() + + p.ice_idAsync().add_sent_callback(cb.sent) + cb.check() + + p.ice_idsAsync().add_sent_callback(cb.sent) + cb.check() + + p.opAsync().add_sent_callback(cb.sent) + cb.check() + + cbs = [] + if sys.version_info[0] == 2: + b = [chr(random.randint(0, 255)) for x in range(0, 1024)] + seq = ''.join(b) + else: + b = [random.randint(0, 255) for x in range(0, 1024)] + seq = bytes(b) + testController.holdAdapter() + try: + cb = FutureSentCallback() + while True: + f = p.opWithPayloadAsync(seq) + f.add_sent_callback(cb.sent) + cbs.append(cb) + if not f.sent_synchronously(): + break + cb = FutureSentCallback() + except Exception as ex: + testController.resumeAdapter() + raise ex + testController.resumeAdapter() + for r in cbs: + r.check() + + print("ok") + + sys.stdout.write("testing batch requests with proxy... ") + sys.stdout.flush() + + test(p.opBatchCount() == 0) + b1 = p.ice_batchOneway() + b1.opBatch() + b1.opBatch() + cb = FutureFlushCallback() + f = b1.ice_flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + test(f.is_sent()) + test(f.done()) + test(p.waitForBatch(2)) + + if p.ice_getConnection(): # No collocation optimization + test(p.opBatchCount() == 0) + b1 = p.ice_batchOneway() + b1.opBatch() + b1.ice_getConnection().close(False) + cb = FutureFlushCallback() + f = b1.ice_flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) + test(f.done()) + test(p.waitForBatch(1)) + + print("ok") + + if p.ice_getConnection(): # No collocation optimization + sys.stdout.write("testing batch requests with connection... ") + sys.stdout.flush() + + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b1.opBatch() + b1.opBatch() + cb = FutureFlushCallback() + f = b1.ice_getConnection().flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) + test(f.done()) + test(p.waitForBatch(2)) + + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b1.opBatch() + b1.ice_getConnection().close(False) + cb = FutureFlushExCallback() + f = b1.ice_getConnection().flushBatchRequestsAsync() + f.add_done_callback(cb.exception) + f.add_sent_callback(cb.sent) + cb.check() + test(not f.is_sent()) + test(f.done()) + test(p.opBatchCount() == 0) + + print("ok") + + sys.stdout.write("testing batch requests with communicator... ") + sys.stdout.flush() + + # + # 1 connection. + # + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b1.opBatch() + b1.opBatch() + cb = FutureFlushCallback() + f = communicator.flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) + test(f.done()) + test(p.waitForBatch(2)) + + # + # 1 connection. + # + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b1.opBatch() + b1.ice_getConnection().close(False) + cb = FutureFlushCallback() + f = communicator.flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) # Exceptions are ignored! + test(f.done()) + test(p.opBatchCount() == 0) + + # + # 2 connections. + # + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b2 = Test.TestIntfPrx.uncheckedCast(p.ice_connectionId("2").ice_getConnection().createProxy( + p.ice_getIdentity()).ice_batchOneway()) + b2.ice_getConnection() # Ensure connection is established. + b1.opBatch() + b1.opBatch() + b2.opBatch() + b2.opBatch() + cb = FutureFlushCallback() + f = communicator.flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) + test(f.done()) + test(p.waitForBatch(4)) + + # + # 2 connections - 1 failure. + # + # All connections should be flushed even if there are failures on some connections. + # Exceptions should not be reported. + # + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b2 = Test.TestIntfPrx.uncheckedCast(p.ice_connectionId("2").ice_getConnection().createProxy( + p.ice_getIdentity()).ice_batchOneway()) + b2.ice_getConnection() # Ensure connection is established. + b1.opBatch() + b2.opBatch() + b1.ice_getConnection().close(False) + cb = FutureFlushCallback() + f = communicator.flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) # Exceptions are ignored! + test(f.done()) + test(p.waitForBatch(1)) + + # + # 2 connections - 2 failures. + # + # The sent callback should be invoked even if all connections fail. + # + test(p.opBatchCount() == 0) + b1 = Test.TestIntfPrx.uncheckedCast(p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway()) + b2 = Test.TestIntfPrx.uncheckedCast(p.ice_connectionId("2").ice_getConnection().createProxy( + p.ice_getIdentity()).ice_batchOneway()) + b2.ice_getConnection() # Ensure connection is established. + b1.opBatch() + b2.opBatch() + b1.ice_getConnection().close(False) + b2.ice_getConnection().close(False) + cb = FutureFlushCallback() + f = communicator.flushBatchRequestsAsync() + f.add_sent_callback(cb.sent) + cb.check() + f.result() # Wait until finished. + test(f.is_sent()) # Exceptions are ignored! + test(f.done()) + test(p.opBatchCount() == 0) + + print("ok") + + sys.stdout.write("testing future operations... ") + sys.stdout.flush() + + indirect = Test.TestIntfPrx.uncheckedCast(p.ice_adapterId("dummy")) + f = indirect.opAsync() + try: + f.result() + test(False) + except Ice.NoEndpointException: + pass + + testController.holdAdapter() + f1 = None + f2 = None + try: + f1 = p.opAsync() + if sys.version_info[0] == 2: + b = [chr(random.randint(0, 255)) for x in range(0, 1024)] + seq = ''.join(b) + else: + b = [random.randint(0, 255) for x in range(0, 1024)] + seq = bytes(b) + while(True): + f2 = p.opWithPayloadAsync(seq) + if not f2.sent_synchronously(): + break + + test(f1 == f1) + test(f1 != f2) + + if p.ice_getConnection(): + test((f1.sent_synchronously() and f1.is_sent() and not f1.done()) or + (not f1.sent_synchronously() and not f1.done())) + + test(not f2.sent_synchronously() and not f2.done()) + except Exception as ex: + testController.resumeAdapter() + raise ex + testController.resumeAdapter() + + f1.sent() + test(f1.is_sent()) + + f2.sent() + test(f2.is_sent()) + + f1.result() + test(f1.done()) + + f2.result() + test(f2.done()) + + test(f1.operation() == "op") + test(f2.operation() == "opWithPayload") + + # + # Twoway + # + f = p.ice_pingAsync() + test(f.operation() == "ice_ping") + test(f.connection() == None) # Expected + test(f.communicator() == communicator) + test(f.proxy() == p) + f.result() + + # + # Oneway + # + p2 = p.ice_oneway() + f = p2.ice_pingAsync() + test(f.operation() == "ice_ping") + test(f.connection() == None) # Expected + test(f.communicator() == communicator) + test(f.proxy() == p2) + + # + # Batch request via proxy + # + p2 = p.ice_batchOneway() + p2.ice_ping() + f = p2.ice_flushBatchRequestsAsync() + test(f.connection() == None) # Expected + test(f.communicator() == communicator) + test(f.proxy() == p2) + f.result() + + if p.ice_getConnection(): + # + # Batch request via connection + # + con = p.ice_getConnection() + p2 = p.ice_batchOneway() + p2.ice_ping() + f = con.flushBatchRequestsAsync() + test(f.connection() == con) + test(f.communicator() == communicator) + test(f.proxy() == None) # Expected + f.result() + + # + # Batch request via communicator + # + p2 = p.ice_batchOneway() + p2.ice_ping() + f = communicator.flushBatchRequestsAsync() + test(f.connection() == None) # Expected + test(f.communicator() == communicator) + test(f.proxy() == None) # Expected + f.result() + + if(p.ice_getConnection()): + f1 = None + f2 = None + + if sys.version_info[0] == 2: + b = [chr(random.randint(0, 255)) for x in range(0, 10024)] + seq = ''.join(b) + else: + b = [random.randint(0, 255) for x in range(0, 10024)] + seq = bytes(b) + + testController.holdAdapter() + + for x in range(0, 200): # 2MB + f = p.opWithPayloadAsync(seq) + + test(not f.is_sent()) + + f1 = p.ice_pingAsync() + f2 = p.ice_idAsync() + f1.cancel() + f2.cancel() + try: + f1.result() + test(false) + except(Ice.InvocationCanceledException): + pass + + try: + f2.result() + test(false) + except(Ice.InvocationCanceledException): + pass + + testController.resumeAdapter() + p.ice_ping() + test(not f1.is_sent() and f1.done()) + test(not f2.is_sent() and f2.done()) + + testController.holdAdapter() + + f1 = p.opAsync() + f2 = p.ice_idAsync() + f1.sent() + f2.sent() + f1.cancel() + f2.cancel() + try: + f1.result() + test(false) + except: + pass + try: + f2.result() + test(false) + except: + pass + testController.resumeAdapter() + + print("ok") + + if p.ice_getConnection(): + sys.stdout.write("testing close connection with sending queue... ") + sys.stdout.flush() + + if sys.version_info[0] == 2: + b = [chr(random.randint(0, 255)) for x in range(0, 10*1024)] + seq = ''.join(b) + else: + b = [random.randint(0, 255) for x in range(0, 10*1024)] + seq = bytes(b) + + # + # Send multiple opWithPayload, followed by a close and followed by multiple opWithPaylod. + # The goal is to make sure that none of the opWithPayload fail even if the server closes + # the connection gracefully in between. + # + maxQueue = 2 + done = False + while not done and maxQueue < 50: + done = True + p.ice_ping() + results = [] + for i in range(0, maxQueue): + results.append(p.opWithPayloadAsync(seq)) + if not p.closeAsync(False).is_sent(): + for i in range(0, maxQueue): + f = p.opWithPayloadAsync(seq) + results.append(f) + if f.is_sent(): + done = False + maxQueue = maxQueue * 2 + break + else: + maxQueue = maxQueue * 2 + done = False + for f in results: + try: + f.result() + except Ice.LocalException: + test(False) + + print("ok") + p.shutdown() diff --git a/python/test/Ice/ami/Client.py b/python/test/Ice/ami/Client.py index 0b2c5389137..f09179c2893 100755 --- a/python/test/Ice/ami/Client.py +++ b/python/test/Ice/ami/Client.py @@ -26,6 +26,7 @@ def test(b): def run(args, communicator): AllTests.allTests(communicator, False) + AllTests.allTestsFuture(communicator, False) return True try: diff --git a/python/test/Ice/ami/TestI.py b/python/test/Ice/ami/TestI.py index 53ee490ff71..f37bd47f806 100644 --- a/python/test/Ice/ami/TestI.py +++ b/python/test/Ice/ami/TestI.py @@ -27,30 +27,21 @@ class TestIntfI(Test.TestIntf): pass def opBatch(self, current=None): - self._cond.acquire() - try: + with self._cond: self._batchCount += 1 self._cond.notify() - finally: - self._cond.release() def opBatchCount(self, current=None): - self._cond.acquire() - try: + with self._cond: return self._batchCount - finally: - self._cond.release() def waitForBatch(self, count, current=None): - self._cond.acquire() - try: + with self._cond: while self._batchCount < count: self._cond.wait(5) result = count == self._batchCount self._batchCount = 0 return result - finally: - self._cond.release() def close(self, force, current=None): current.con.close(force) diff --git a/python/test/Ice/binding/AllTests.py b/python/test/Ice/binding/AllTests.py index 1517526688a..e7b46e4f727 100644 --- a/python/test/Ice/binding/AllTests.py +++ b/python/test/Ice/binding/AllTests.py @@ -18,30 +18,23 @@ class GetAdapterNameCB: self._name = "" self._cond = threading.Condition() - def response(self, name): - self._cond.acquire() - self._name = name - self._cond.notify() - self._cond.release() - - def exception(self, ex): - test(False) + def response(self, f): + with self._cond: + self._name = f.result() + self._cond.notify() def getResult(self): - self._cond.acquire() - try: + with self._cond: while self._name == "": self._cond.wait(5.0) if self._name != "": return self._name else: return "" - finally: - self._cond.release() def getAdapterNameWithAMI(proxy): cb = GetAdapterNameCB() - proxy.begin_getAdapterName(cb.response, cb.exception) + proxy.getAdapterNameAsync().add_done_callback(cb.response) return cb.getResult() def createTestIntfPrx(adapters): diff --git a/python/test/Ice/blobject/RouterI.py b/python/test/Ice/blobject/RouterI.py index d49d7153b48..7b07b36e1da 100644 --- a/python/test/Ice/blobject/RouterI.py +++ b/python/test/Ice/blobject/RouterI.py @@ -17,43 +17,29 @@ class CallQueue(threading.Thread): self._destroy = False def add(self, call): - self._condVar.acquire() - self._queue.append(call) - self._condVar.notify() - self._condVar.release() + with self._condVar: + self._queue.append(call) + self._condVar.notify() def destroy(self): - self._condVar.acquire() - self._destroy = True - self._condVar.notify() - self._condVar.release() + with self._condVar: + self._destroy = True + self._condVar.notify() def run(self): while True: - self._condVar.acquire() - while len(self._queue) == 0 and not self._destroy: - self._condVar.wait() - if self._destroy: - self._condVar.release() - break - call = self._queue.pop() - self._condVar.release() + with self._condVar: + while len(self._queue) == 0 and not self._destroy: + self._condVar.wait() + if self._destroy: + break + call = self._queue.pop() call.execute() -class AsyncCallback(object): - def __init__(self, cb): - self._cb = cb - - def response(self, ok, results): - self._cb.ice_response(ok, results) - - def exception(self, ex): - self._cb.ice_exception(ex) - class BlobjectCall(object): - def __init__(self, proxy, amdCallback, inParams, curr): + def __init__(self, proxy, future, inParams, curr): self._proxy = proxy - self._amdCallback = amdCallback + self._future = future self._inParams = inParams self._curr = curr @@ -66,13 +52,19 @@ class BlobjectCall(object): proxy = proxy.ice_oneway() try: ok, out = proxy.ice_invoke(self._curr.operation, self._curr.mode, self._inParams, self._curr.ctx) - self._amdCallback.ice_response(ok, out) + self._future.set_result((ok, out)) except Ice.Exception as e: - self._amdCallback.ice_exception(e) + self._future.set_exception(e) else: - cb = AsyncCallback(self._amdCallback) - proxy.begin_ice_invoke(self._curr.operation, self._curr.mode, self._inParams, cb.response, cb.exception, - None, self._curr.ctx) + f = proxy.ice_invokeAsync(self._curr.operation, self._curr.mode, self._inParams, self._curr.ctx) + f.add_done_callback(self.done) + + def done(self, future): + try: + (ok, bytes) = future.result() + self._future.set_result((ok, bytes)) + except Exception as ex: + self._future.set_exception(ex) class BlobjectAsyncI(Ice.BlobjectAsync): def __init__(self): @@ -81,23 +73,22 @@ class BlobjectAsyncI(Ice.BlobjectAsync): self._objects = {} self._lock = threading.Lock() - def ice_invoke_async(self, amdCallback, inParams, curr): - self._lock.acquire() - proxy = self._objects[curr.id] - assert proxy - self._lock.release() - self._queue.add(BlobjectCall(proxy, amdCallback, inParams, curr)) + def ice_invoke(self, inParams, curr): + f = Ice.Future() + with self._lock: + proxy = self._objects[curr.id] + assert proxy + self._queue.add(BlobjectCall(proxy, f, inParams, curr)) + return f def add(self, proxy): - self._lock.acquire() - self._objects[proxy.ice_getIdentity()] = proxy.ice_facet("").ice_twoway().ice_router(None) - self._lock.release() + with self._lock: + self._objects[proxy.ice_getIdentity()] = proxy.ice_facet("").ice_twoway().ice_router(None) def destroy(self): - self._lock.acquire() - self._queue.destroy() - self._queue.join() - self._lock.release() + with self._lock: + self._queue.destroy() + self._queue.join() class BlobjectI(Ice.Blobject): def __init__(self): @@ -105,9 +96,8 @@ class BlobjectI(Ice.Blobject): self._lock = threading.Lock() def ice_invoke(self, inParams, curr): - self._lock.acquire() - proxy = self._objects[curr.id] - self._lock.release() + with self._lock: + proxy = self._objects[curr.id] if len(curr.facet) > 0: proxy = proxy.ice_facet(curr.facet) @@ -122,9 +112,8 @@ class BlobjectI(Ice.Blobject): raise def add(self, proxy): - self._lock.acquire() - self._objects[proxy.ice_getIdentity()] = proxy.ice_facet("").ice_twoway().ice_router(None) - self._lock.release() + with self._lock: + self._objects[proxy.ice_getIdentity()] = proxy.ice_facet("").ice_twoway().ice_router(None) def destroy(self): pass diff --git a/python/test/Ice/exceptions/AllTests.py b/python/test/Ice/exceptions/AllTests.py index 0f660497980..3c13e06f24c 100644 --- a/python/test/Ice/exceptions/AllTests.py +++ b/python/test/Ice/exceptions/AllTests.py @@ -35,19 +35,15 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): def __init__(self, communicator=None): @@ -598,6 +594,230 @@ def allTests(communicator): print("ok") + sys.stdout.write("catching exact types with futures... ") + sys.stdout.flush() + + try: + thrower.throwAasAAsync(1).result() + test(False) + except Test.A as ex: + test(ex.aMem == 1) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwAorDasAorDAsync(1).result() + test(False) + except Test.A as ex: + test(ex.aMem == 1) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwAorDasAorDAsync(-1).result() + test(False) + except Test.D as ex: + test(ex.dMem == -1) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwBasBAsync(1, 2).result() + test(False) + except Test.B as ex: + test(ex.aMem == 1) + test(ex.bMem == 2) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwCasCAsync(1, 2, 3).result() + test(False) + except Test.C as ex: + test(ex.aMem == 1) + test(ex.bMem == 2) + test(ex.cMem == 3) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwModAAsync(1, 2).result() + test(False) + except Test.Mod.A as ex: + test(ex.aMem == 1) + test(ex.a2Mem == 2) + except Ice.OperationNotExistException: + # + # This operation is not supported in Java. + # + pass + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching derived types with futures... ") + sys.stdout.flush() + + try: + thrower.throwBasAAsync(1, 2).result() + test(False) + except Test.B as ex: + test(ex.aMem == 1) + test(ex.bMem == 2) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwCasAAsync(1, 2, 3).result() + test(False) + except Test.C as ex: + test(ex.aMem == 1) + test(ex.bMem == 2) + test(ex.cMem == 3) + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwCasBAsync(1, 2, 3).result() + test(False) + except Test.C as ex: + test(ex.aMem == 1) + test(ex.bMem == 2) + test(ex.cMem == 3) + except: + print(sys.exc_info()) + test(False) + + print("ok") + + if thrower.supportsUndeclaredExceptions(): + sys.stdout.write("catching unknown user exception with futures... ") + sys.stdout.flush() + + try: + thrower.throwUndeclaredAAsync(1).result() + test(False) + except Ice.UnknownUserException: + pass + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwUndeclaredBAsync(1, 2).result() + test(False) + except Ice.UnknownUserException: + pass + except: + print(sys.exc_info()) + test(False) + + try: + thrower.throwUndeclaredCAsync(1, 2, 3).result() + test(False) + except Ice.UnknownUserException: + pass + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching object not exist exception with futures... ") + sys.stdout.flush() + + id = Ice.stringToIdentity("does not exist") + try: + thrower2 = Test.ThrowerPrx.uncheckedCast(thrower.ice_identity(id)) + thrower2.throwAasAAsync(1).result() +# thrower2.ice_ping() + test(False) + except Ice.ObjectNotExistException as ex: + test(ex.id == id) + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching facet not exist exception with futures... ") + sys.stdout.flush() + + try: + thrower2 = Test.ThrowerPrx.uncheckedCast(thrower, "no such facet") + try: + thrower2.ice_pingAsync().result() + test(False) + except Ice.FacetNotExistException as ex: + test(ex.facet == "no such facet") + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching operation not exist exception with futures... ") + sys.stdout.flush() + + try: + thrower2 = Test.WrongOperationPrx.uncheckedCast(thrower) + thrower2.noSuchOperationAsync().result() + test(False) + except Ice.OperationNotExistException as ex: + test(ex.operation == "noSuchOperation") + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching unknown local exception with futures... ") + sys.stdout.flush() + + try: + thrower.throwLocalExceptionAsync().result() + test(False) + except Ice.UnknownLocalException: + pass + except: + print(sys.exc_info()) + test(False) + try: + thrower.throwLocalExceptionIdempotentAsync().result() + test(False) + except Ice.UnknownLocalException: + pass + except Ice.OperationNotExistException: + pass + except: + print(sys.exc_info()) + test(False) + + print("ok") + + sys.stdout.write("catching unknown non-Ice exception with futures... ") + sys.stdout.flush() + + try: + thrower.throwNonIceExceptionAsync().result() + test(False) + except Ice.UnknownException: + pass + except: + print(sys.exc_info()) + test(False) + + print("ok") + sys.stdout.write("catching exact types with AMI mapping... ") sys.stdout.flush() diff --git a/python/test/Ice/exceptions/ServerAMD.py b/python/test/Ice/exceptions/ServerAMD.py index ae11c454596..ef4511a383b 100755 --- a/python/test/Ice/exceptions/ServerAMD.py +++ b/python/test/Ice/exceptions/ServerAMD.py @@ -24,120 +24,131 @@ def test(b): raise RuntimeError('test assertion failed') class ThrowerI(Test.Thrower): - def shutdown_async(self, cb, current=None): + def shutdown(self, current=None): current.adapter.getCommunicator().shutdown() - cb.ice_response() - def supportsUndeclaredExceptions_async(self, cb, current=None): - cb.ice_response(True) + def supportsUndeclaredExceptions(self, current=None): + return True - def supportsAssertException_async(self, cb, current=None): - cb.ice_response(False) + def supportsAssertException(self, current=None): + return False - def throwAasA_async(self, cb, a, current=None): + def throwAasA(self, a, current=None): ex = Test.A() ex.aMem = a - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwAorDasAorD_async(self, cb, a, current=None): + def throwAorDasAorD(self, a, current=None): + f = Ice.Future() if a > 0: ex = Test.A() ex.aMem = a - cb.ice_exception(ex) + f.set_exception(ex) else: ex = Test.D() ex.dMem = a - cb.ice_exception(ex) + f.set_exception(ex) + return f - def throwBasA_async(self, cb, a, b, current=None): + def throwBasA(self, a, b, current=None): ex = Test.B() ex.aMem = a ex.bMem = b raise ex - #cb.ice_exception(ex) - def throwCasA_async(self, cb, a, b, c, current=None): + def throwCasA(self, a, b, c, current=None): ex = Test.C() ex.aMem = a ex.bMem = b ex.cMem = c - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwBasB_async(self, cb, a, b, current=None): + def throwBasB(self, a, b, current=None): ex = Test.B() ex.aMem = a ex.bMem = b raise ex - #cb.ice_exception(ex) - def throwCasB_async(self, cb, a, b, c, current=None): + def throwCasB(self, a, b, c, current=None): ex = Test.C() ex.aMem = a ex.bMem = b ex.cMem = c - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwCasC_async(self, cb, a, b, c, current=None): + def throwCasC(self, a, b, c, current=None): ex = Test.C() ex.aMem = a ex.bMem = b ex.cMem = c - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwModA_async(self, cb, a, a2, current=None): + def throwModA(self, a, a2, current=None): ex = Test.Mod.A() ex.aMem = a ex.a2Mem = a2 raise ex - def throwUndeclaredA_async(self, cb, a, current=None): + def throwUndeclaredA(self, a, current=None): ex = Test.A() ex.aMem = a - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwUndeclaredB_async(self, cb, a, b, current=None): + def throwUndeclaredB(self, a, b, current=None): ex = Test.B() ex.aMem = a ex.bMem = b raise ex - #cb.ice_exception(ex) - def throwUndeclaredC_async(self, cb, a, b, c, current=None): + def throwUndeclaredC(self, a, b, c, current=None): ex = Test.C() ex.aMem = a ex.bMem = b ex.cMem = c - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def throwLocalException_async(self, cb, current=None): - cb.ice_exception(Ice.TimeoutException()) + def throwLocalException(self, current=None): + f = Ice.Future() + f.set_exception(Ice.TimeoutException()) + return f - def throwNonIceException_async(self, cb, current=None): - # Python-specific: make sure the argument is validated. - try: - cb.ice_exception('foo') - test(False) - except TypeError: - pass + def throwNonIceException(self, current=None): + f = Ice.Future() + f.set_exception(RuntimeError("12345")) + return f - cb.ice_exception(RuntimeError("12345")) - - def throwAssertException_async(self, cb, current=None): + def throwAssertException(self, current=None): raise RuntimeError("operation `throwAssertException' not supported") - def throwMemoryLimitException_async(self, cb, seq, current=None): - cb.ice_response(bytearray(20 * 1024)) + def throwMemoryLimitException(self, seq, current=None): + return Ice.Future.completed(bytearray(20 * 1024)) - def throwLocalExceptionIdempotent_async(self, cb, current=None): - cb.ice_exception(Ice.TimeoutException()) + def throwLocalExceptionIdempotent(self, current=None): + f = Ice.Future() + f.set_exception(Ice.TimeoutException()) + return f - def throwAfterResponse_async(self, cb, current=None): - cb.ice_response() - raise RuntimeError("12345") + def throwAfterResponse(self, current=None): + # Cannot be implemented with Futures + return None - def throwAfterException_async(self, cb, current=None): - cb.ice_exception(Test.A()) - raise RuntimeError("12345") + def throwAfterException(self, current=None): + # Cannot be implemented with Futures + f = Ice.Future() + f.set_exception(Test.A()) + return f def run(args, communicator): adapter = communicator.createObjectAdapter("TestAdapter") diff --git a/python/test/Ice/faultTolerance/AllTests.py b/python/test/Ice/faultTolerance/AllTests.py index 94263cf1602..c55c3a138da 100644 --- a/python/test/Ice/faultTolerance/AllTests.py +++ b/python/test/Ice/faultTolerance/AllTests.py @@ -22,37 +22,32 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): - def response(self): - test(False) - - def exception(self, ex): - test(False) - - def opPidI(self, pid): - self._pid = pid - self.called() + def opPidI(self, f): + try: + self._pid = f.result() + self.called() + except: + test(False) - def opShutdownI(self): + def opShutdownI(self, f): + test(f.exception() is None) self.called() - def exceptAbortI(self, ex): + def exceptAbortI(self, f): + test(f.exception() is not None) try: - raise ex + f.result() except Ice.ConnectionLostException: pass except Ice.ConnectFailedException: @@ -102,7 +97,7 @@ def allTests(communicator, ports): sys.stdout.write("testing server #%d with AMI... " % i) sys.stdout.flush() cb = Callback() - obj.begin_pid(cb.opPidI, cb.exception) + obj.pidAsync().add_done_callback(cb.opPidI) cb.check() pid = cb.pid() test(pid != oldPid) @@ -119,7 +114,7 @@ def allTests(communicator, ports): sys.stdout.write("shutting down server #%d with AMI... " % i) sys.stdout.flush() cb = Callback() - obj.begin_shutdown(cb.opShutdownI, cb.exception) + obj.shutdownAsync().add_done_callback(cb.opShutdownI) cb.check() print("ok") elif j == 1 or i + 1 > len(ports): @@ -137,7 +132,7 @@ def allTests(communicator, ports): sys.stdout.write("aborting server #%d with AMI... " % i) sys.stdout.flush() cb = Callback() - obj.begin_abort(cb.response, cb.exceptAbortI) + obj.abortAsync().add_done_callback(cb.exceptAbortI) cb.check() print("ok") elif j == 2 or j == 3: @@ -155,7 +150,7 @@ def allTests(communicator, ports): sys.stdout.write("aborting server #%d and #%d with idempotent AMI call... " % (i, i + 1)) sys.stdout.flush() cb = Callback() - obj.begin_idempotentAbort(cb.response, cb.exceptAbortI) + obj.idempotentAbortAsync().add_done_callback(cb.exceptAbortI) cb.check() print("ok") diff --git a/python/test/Ice/location/Server.py b/python/test/Ice/location/Server.py index 24cd82df2d8..debd8d06d28 100755 --- a/python/test/Ice/location/Server.py +++ b/python/test/Ice/location/Server.py @@ -24,24 +24,24 @@ class ServerLocatorRegistry(Test.TestLocatorRegistry): self._adapters = {} self._objects = {} - def setAdapterDirectProxy_async(self, cb, adapter, obj, current=None): + def setAdapterDirectProxy(self, adapter, obj, current=None): if obj: self._adapters[adapter] = obj else: self._adapters.pop(adapter) - cb.ice_response() + return None - def setReplicatedAdapterDirectProxy_async(self, cb, adapter, replica, obj, current=None): + def setReplicatedAdapterDirectProxy(self, adapter, replica, obj, current=None): if obj: self._adapters[adapter] = obj self._adapters[replica] = obj else: self._adapters.pop(adapter) self._adapters.pop(replica) - cb.ice_response() + return None - def setServerProcessProxy_async(self, id, proxy, current=None): - cb.ice_response() + def setServerProcessProxy(self, id, proxy, current=None): + return None def addObject(self, obj, current=None): self._objects[obj.ice_getIdentity()] = obj @@ -63,13 +63,13 @@ class ServerLocator(Test.TestLocator): self._registryPrx = registryPrx self._requestCount = 0 - def findObjectById_async(self, response, id, current=None): + def findObjectById(self, id, current=None): self._requestCount += 1 - response.ice_response(self._registry.getObject(id)) + return Ice.Future.completed(self._registry.getObject(id)) - def findAdapterById_async(self, response, id, current=None): + def findAdapterById(self, id, current=None): self._requestCount += 1 - response.ice_response(self._registry.getAdapter(id)) + return Ice.Future.completed(self._registry.getAdapter(id)) def getRegistry(self, current=None): return self._registryPrx diff --git a/python/test/Ice/objects/AllTests.py b/python/test/Ice/objects/AllTests.py index bedb4d6c437..8f129218307 100644 --- a/python/test/Ice/objects/AllTests.py +++ b/python/test/Ice/objects/AllTests.py @@ -113,7 +113,7 @@ def allTests(communicator): sys.stdout.write("getting D1... ") sys.stdout.flush() - d1 = initial.getD1(Test.D1(Test.A1("a1"), Test.A1("a2"), Test.A1("a3"), Test.A1("a4"))); + d1 = initial.getD1(Test.D1(Test.A1("a1"), Test.A1("a2"), Test.A1("a3"), Test.A1("a4"))) test(d1.a1.name == "a1") test(d1.a2.name == "a2") test(d1.a3.name == "a3") @@ -225,9 +225,9 @@ def allTests(communicator): sys.stdout.write("testing marshaled results...") sys.stdout.flush() b1 = initial.getMB() - test(b1 != None and b1.theB == b1); - b1 = initial.end_getAMDMB(initial.begin_getAMDMB()); - test(b1 != None and b1.theB == b1); + test(b1 != None and b1.theB == b1) + b1 = initial.getAMDMBAsync().result() + test(b1 != None and b1.theB == b1) print("ok") # Don't run this test with collocation, this should work with collocation diff --git a/python/test/Ice/objects/TestI.py b/python/test/Ice/objects/TestI.py index 8b0df2c1594..7c0be3ae8dd 100644 --- a/python/test/Ice/objects/TestI.py +++ b/python/test/Ice/objects/TestI.py @@ -124,10 +124,10 @@ class InitialI(Test.Initial): return self._f def getMB(self, current): - return self._b1; + return self._b1 - def getAMDMB_async(self, cb, current): - cb.ice_response(self._b1); + def getAMDMB(self, current): + return Ice.Future.completed(self._b1) def getAll(self, current=None): self._b1.preMarshalInvoked = False diff --git a/python/test/Ice/operations/AllTests.py b/python/test/Ice/operations/AllTests.py index 02a6480de4c..27a70ab62e2 100644 --- a/python/test/Ice/operations/AllTests.py +++ b/python/test/Ice/operations/AllTests.py @@ -7,8 +7,8 @@ # # ********************************************************************** -import Ice, Test, Twoways, TwowaysAMI, Oneways, OnewaysAMI, BatchOneways, sys -import BatchOnewaysAMI +import Ice, Test, Twoways, TwowaysFuture, TwowaysAMI, Oneways, OnewaysFuture, OnewaysAMI, BatchOneways, sys +import BatchOnewaysAMI, BatchOnewaysFuture def test(b): if not b: @@ -32,23 +32,39 @@ def allTests(communicator): Oneways.oneways(communicator, cl) print("ok") + sys.stdout.write("testing twoway operations with futures... ") + sys.stdout.flush() + TwowaysFuture.twowaysFuture(communicator, cl) + print("ok") + sys.stdout.write("testing twoway operations with AMI... ") sys.stdout.flush() TwowaysAMI.twowaysAMI(communicator, cl) print("ok") - + + sys.stdout.write("testing oneway operations with futures... ") + sys.stdout.flush() + OnewaysFuture.onewaysFuture(communicator, cl) + print("ok") + sys.stdout.write("testing oneway operations with AMI... ") sys.stdout.flush() OnewaysAMI.onewaysAMI(communicator, cl) print("ok") - + sys.stdout.write("testing batch oneway operations... ") sys.stdout.flush() BatchOneways.batchOneways(cl) BatchOneways.batchOneways(derived) print("ok") - - sys.stdout.write("testing batch AMI oneway operations... ") + + sys.stdout.write("testing batch oneway operations with futures... ") + sys.stdout.flush() + BatchOnewaysFuture.batchOneways(cl) + BatchOnewaysFuture.batchOneways(derived) + print("ok") + + sys.stdout.write("testing batch oneway operations with AMI... ") sys.stdout.flush() BatchOnewaysAMI.batchOneways(cl) BatchOnewaysAMI.batchOneways(derived) diff --git a/python/test/Ice/operations/BatchOnewaysAMI.py b/python/test/Ice/operations/BatchOnewaysAMI.py index 5515185d572..cd53ee94470 100644 --- a/python/test/Ice/operations/BatchOnewaysAMI.py +++ b/python/test/Ice/operations/BatchOnewaysAMI.py @@ -19,19 +19,15 @@ class Callback: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() def batchOneways(p): diff --git a/python/test/Ice/operations/BatchOnewaysFuture.py b/python/test/Ice/operations/BatchOnewaysFuture.py new file mode 100644 index 00000000000..e03bddbcfd0 --- /dev/null +++ b/python/test/Ice/operations/BatchOnewaysFuture.py @@ -0,0 +1,88 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import Ice, Test, array, sys, threading, time + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +class Callback: + def __init__(self): + self._called = False + self._cond = threading.Condition() + + def check(self): + with self._cond: + while not self._called: + self._cond.wait() + self._called = False + + def called(self): + with self._cond: + self._called = True + self._cond.notify() + +def batchOneways(p): + + if sys.version_info[0] == 2: + bs1 = [] + bs1[0:10 * 1024] = range(0, 10 * 1024) # add 100,000 entries. + bs1 = ['\x00' for x in bs1] # set them all to \x00 + bs1 = ''.join(bs1) # make into a byte array + else: + bs1 = bytes([0 for x in range(0, 10 * 1024)]) + batch = Test.MyClassPrx.uncheckedCast(p.ice_batchOneway()) + + f = batch.ice_flushBatchRequestsAsync() # Empty flush + f.result() + + test(batch.ice_flushBatchRequestsAsync().is_sent()) # Empty flush + test(batch.ice_flushBatchRequestsAsync().done()) # Empty flush + test(batch.ice_flushBatchRequestsAsync().sent_synchronously()) # Empty flush + + for i in range(30): + batch.opByteSOnewayAsync(bs1) + + count = 0 + while count < 27: # 3 * 9 requests auto-flushed. + count += p.opByteSOnewayCallCount() + time.sleep(0.01) + + if p.ice_getConnection(): + + batch1 = Test.MyClassPrx.uncheckedCast(p.ice_batchOneway()) + batch2 = Test.MyClassPrx.uncheckedCast(p.ice_batchOneway()) + + batch1.ice_pingAsync() + batch2.ice_pingAsync() + batch1.ice_flushBatchRequestsAsync().result() + batch1.ice_getConnection().close(False) + batch1.ice_pingAsync() + batch2.ice_pingAsync() + + batch1.ice_getConnection() + batch2.ice_getConnection() + + batch1.ice_getConnection().close(False) + + test(not batch1.ice_pingAsync().done()) + test(not batch2.ice_pingAsync().done()) + + identity = Ice.Identity() + identity.name = "invalid"; + batch3 = batch.ice_identity(identity) + batch3.ice_ping() + batch3.ice_flushBatchRequestsAsync().result() + + # Make sure that a bogus batch request doesn't cause troubles to other ones. + batch3.ice_ping() + batch.ice_ping() + batch.ice_flushBatchRequestsAsync().result() + batch.ice_ping() diff --git a/python/test/Ice/operations/OnewaysAMI.py b/python/test/Ice/operations/OnewaysAMI.py index e0e1fac0cca..4c08b60f52f 100644 --- a/python/test/Ice/operations/OnewaysAMI.py +++ b/python/test/Ice/operations/OnewaysAMI.py @@ -19,19 +19,15 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): def sent(self, sentSynchronously): diff --git a/python/test/Ice/operations/OnewaysFuture.py b/python/test/Ice/operations/OnewaysFuture.py new file mode 100644 index 00000000000..ea5e6f06b90 --- /dev/null +++ b/python/test/Ice/operations/OnewaysFuture.py @@ -0,0 +1,54 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import Ice, Test + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +def onewaysFuture(communicator, proxy): + + p = Test.MyClassPrx.uncheckedCast(proxy.ice_oneway()) + + f = p.ice_pingAsync() + f.sent() + + try: + p.ice_isAAsync(Test.MyClass.ice_staticId()) + test(False) + except RuntimeError: + pass + + try: + p.ice_idAsync() + test(False) + except RuntimeError: + pass + + try: + p.ice_idsAsync() + test(False) + except RuntimeError: + pass + + f = p.opVoidAsync() + f.sent() + + f = p.opIdempotentAsync() + f.sent() + + f = p.opNonmutatingAsync() + f.sent() + + try: + p.opByteAsync(0xff, 0x0f) + test(False) + except RuntimeError: + pass diff --git a/python/test/Ice/operations/ServerAMD.py b/python/test/Ice/operations/ServerAMD.py index 05777bad2d7..3204be386dc 100755 --- a/python/test/Ice/operations/ServerAMD.py +++ b/python/test/Ice/operations/ServerAMD.py @@ -8,7 +8,11 @@ # # ********************************************************************** -import os, sys, traceback, threading +import os, sys, traceback, threading, time + +haveConcurrentFuture = sys.version_info.major > 3 or (sys.version_info.major == 3 and sys.version_info.minor >= 5) +if haveConcurrentFuture: + import concurrent.futures import Ice slice_dir = Ice.getSliceDir() @@ -23,18 +27,20 @@ def test(b): if not b: raise RuntimeError('test assertion failed') -class Thread_opVoid(threading.Thread): - def __init__(self, cb): +class FutureThread(threading.Thread): + def __init__(self, f, r): threading.Thread.__init__(self) - self.cb = cb + self.future = f + self.result = r def run(self): - self.cb.ice_response() + time.sleep(0.01) + self.future.set_result(self.result) class MyDerivedClassI(Test.MyDerivedClass): def __init__(self): - self.opVoidThread = None - self.opVoidThreadLock = threading.Lock() + self.threads = [] + self.threadLock = threading.Lock() self.lock = threading.Lock() self.opByteSOnewayCount = 0 @@ -54,56 +60,63 @@ class MyDerivedClassI(Test.MyDerivedClass): test(current.mode == Ice.OperationMode.Nonmutating) return Test.MyDerivedClass.ice_id(self, current) - def shutdown_async(self, cb, current=None): - self.opVoidThreadLock.acquire() - if self.opVoidThread: - self.opVoidThread.join() - self.opVoidThread = None - self.opVoidThreadLock.release() + def shutdown(self, current=None): + with self.threadLock: + for thread in self.threads: + thread.join() + self.threads = [] current.adapter.getCommunicator().shutdown() - cb.ice_response() - def opVoid_async(self, cb, current=None): + def opVoid(self, current=None): test(current.mode == Ice.OperationMode.Normal) - self.opVoidThreadLock.acquire() - if self.opVoidThread: - self.opVoidThread.join() - self.opVoidThread = None + f = Ice.Future() + + with self.threadLock: + thread = FutureThread(f, None) + self.threads.append(thread) + thread.start() - self.opVoidThread = Thread_opVoid(cb) - self.opVoidThread.start() - self.opVoidThreadLock.release() + return f - def opByte_async(self, cb, p1, p2, current=None): - cb.ice_response(p1, p1 ^ p2) + def opByte(self, p1, p2, current=None): + # Test the ability to use another Future type + if haveConcurrentFuture: + f = concurrent.futures.Future() + with self.threadLock: + thread = FutureThread(f, (p1, p1 ^ p2)) + self.threads.append(thread) + thread.start() + else: + f = Ice.Future.completed((p1, p1 ^ p2)) + return f - def opBool_async(self, cb, p1, p2, current=None): - cb.ice_response(p2, p1) + def opBool(self, p1, p2, current=None): + return Ice.Future.completed((p2, p1)) - def opShortIntLong_async(self, cb, p1, p2, p3, current=None): - cb.ice_response(p3, p1, p2, p3) + def opShortIntLong(self, p1, p2, p3, current=None): + return Ice.Future.completed((p3, p1, p2, p3)) - def opFloatDouble_async(self, cb, p1, p2, current=None): - cb.ice_response(p2, p1, p2) + def opFloatDouble(self, p1, p2, current=None): + return Ice.Future.completed((p2, p1, p2)) - def opString_async(self, cb, p1, p2, current=None): - cb.ice_response(p1 + " " + p2, p2 + " " + p1) + def opString(self, p1, p2, current=None): + return Ice.Future.completed((p1 + " " + p2, p2 + " " + p1)) - def opMyEnum_async(self, cb, p1, current=None): - cb.ice_response(Test.MyEnum.enum3, p1) + def opMyEnum(self, p1, current=None): + return Ice.Future.completed((Test.MyEnum.enum3, p1)) - def opMyClass_async(self, cb, p1, current=None): + def opMyClass(self, p1, current=None): p2 = p1 p3 = Test.MyClassPrx.uncheckedCast(current.adapter.createProxy(Ice.stringToIdentity("noSuchIdentity"))) - cb.ice_response(Test.MyClassPrx.uncheckedCast(current.adapter.createProxy(current.id)), p2, p3) + return Ice.Future.completed((Test.MyClassPrx.uncheckedCast(current.adapter.createProxy(current.id)), p2, p3)) - def opStruct_async(self, cb, p1, p2, current=None): + def opStruct(self, p1, p2, current=None): p1.s.s = "a new string" - cb.ice_response(p2, p1) + return Ice.Future.completed((p2, p1)) - def opByteS_async(self, cb, p1, p2, current=None): + def opByteS(self, p1, p2, current=None): if sys.version_info[0] == 2: # By default sequence<byte> maps to a string. p3 = map(ord, p1) @@ -113,323 +126,322 @@ class MyDerivedClassI(Test.MyDerivedClass): else: p3 = bytes(reversed(p1)) r = p1 + p2 - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opBoolS_async(self, cb, p1, p2, current=None): + def opBoolS(self, p1, p2, current=None): p3 = p1[0:] p3.extend(p2) r = p1[0:] r.reverse(); - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opShortIntLongS_async(self, cb, p1, p2, p3, current=None): + def opShortIntLongS(self, p1, p2, p3, current=None): p4 = p1[0:] p5 = p2[0:] p5.reverse() p6 = p3[0:] p6.extend(p3) - cb.ice_response(p3, p4, p5, p6) + return Ice.Future.completed((p3, p4, p5, p6)) - def opFloatDoubleS_async(self, cb, p1, p2, current=None): + def opFloatDoubleS(self, p1, p2, current=None): p3 = p1[0:] p4 = p2[0:] p4.reverse() r = p2[0:] r.extend(p1) - cb.ice_response(r, p3, p4) + return Ice.Future.completed((r, p3, p4)) - def opStringS_async(self, cb, p1, p2, current=None): + def opStringS(self, p1, p2, current=None): p3 = p1[0:] p3.extend(p2) r = p1[0:] r.reverse() - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opByteSS_async(self, cb, p1, p2, current=None): + def opByteSS(self, p1, p2, current=None): p3 = p1[0:] p3.reverse() r = p1[0:] r.extend(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opBoolSS_async(self, cb, p1, p2, current=None): + def opBoolSS(self, p1, p2, current=None): p3 = p1[0:] p3.extend(p2) r = p1[0:] r.reverse() - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opShortIntLongSS_async(self, cb, p1, p2, p3, current=None): + def opShortIntLongSS(self, p1, p2, p3, current=None): p4 = p1[0:] p5 = p2[0:] p5.reverse() p6 = p3[0:] p6.extend(p3) - cb.ice_response(p3, p4, p5, p6) + return Ice.Future.completed((p3, p4, p5, p6)) - def opFloatDoubleSS_async(self, cb, p1, p2, current=None): + def opFloatDoubleSS(self, p1, p2, current=None): p3 = p1[0:] p4 = p2[0:] p4.reverse() r = p2[0:] r.extend(p2) - cb.ice_response(r, p3, p4) + return Ice.Future.completed((r, p3, p4)) - def opStringSS_async(self, cb, p1, p2, current=None): + def opStringSS(self, p1, p2, current=None): p3 = p1[0:] p3.extend(p2) r = p2[0:] r.reverse() - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringSSS_async(self, cb, p1, p2, current=None): + def opStringSSS(self, p1, p2, current=None): p3 = p1[0:] p3.extend(p2) r = p2[0:] r.reverse() - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opByteBoolD_async(self, cb, p1, p2, current=None): + def opByteBoolD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opShortIntD_async(self, cb, p1, p2, current=None): + def opShortIntD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opLongFloatD_async(self, cb, p1, p2, current=None): + def opLongFloatD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringStringD_async(self, cb, p1, p2, current=None): + def opStringStringD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringMyEnumD_async(self, cb, p1, p2, current=None): + def opStringMyEnumD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opMyEnumStringD_async(self, cb, p1, p2, current=None): + def opMyEnumStringD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opMyStructMyEnumD_async(self, cb, p1, p2, current=None): + def opMyStructMyEnumD(self, p1, p2, current=None): p3 = p1.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opByteBoolDS_async(self, cb, p1, p2, current=None): + def opByteBoolDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opShortIntDS_async(self, cb, p1, p2, current=None): + def opShortIntDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opLongFloatDS_async(self, cb, p1, p2, current=None): + def opLongFloatDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringStringDS_async(self, cb, p1, p2, current=None): + def opStringStringDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringMyEnumDS_async(self, cb, p1, p2, current=None): + def opStringMyEnumDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opMyEnumStringDS_async(self, cb, p1, p2, current=None): + def opMyEnumStringDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opMyStructMyEnumDS_async(self, cb, p1, p2, current=None): + def opMyStructMyEnumDS(self, p1, p2, current=None): p3 = p2[0:] p3.extend(p1) r = p1[::-1] - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opByteByteSD_async(self, cb, p1, p2, current=None): + def opByteByteSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opBoolBoolSD_async(self, cb, p1, p2, current=None): + def opBoolBoolSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opShortShortSD_async(self, cb, p1, p2, current=None): + def opShortShortSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opIntIntSD_async(self, cb, p1, p2, current=None): + def opIntIntSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opLongLongSD_async(self, cb, p1, p2, current=None): + def opLongLongSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringFloatSD_async(self, cb, p1, p2, current=None): + def opStringFloatSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringDoubleSD_async(self, cb, p1, p2, current=None): + def opStringDoubleSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opStringStringSD_async(self, cb, p1, p2, current=None): + def opStringStringSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opMyEnumMyEnumSD_async(self, cb, p1, p2, current=None): + def opMyEnumMyEnumSD(self, p1, p2, current=None): p3 = p2.copy() r = p1.copy() r.update(p2) - cb.ice_response(r, p3) + return Ice.Future.completed((r, p3)) - def opIntS_async(self, cb, s, current=None): - cb.ice_response([-x for x in s]) + def opIntS(self, s, current=None): + return Ice.Future.completed([-x for x in s]) - def opByteSOneway_async(self, cb, s, current=None): - self.lock.acquire() - self.opByteSOnewayCount += 1 - self.lock.release() - cb.ice_response() + def opByteSOneway(self, s, current=None): + with self.lock: + self.opByteSOnewayCount += 1 + return Ice.Future.completed(None) - def opByteSOnewayCallCount_async(self, cb, current=None): - self.lock.acquire() - count = self.opByteSOnewayCount - self.opByteSOnewayCount = 0 - self.lock.release() - cb.ice_response(count) + def opByteSOnewayCallCount(self, current=None): + with self.lock: + count = self.opByteSOnewayCount + self.opByteSOnewayCount = 0 + return Ice.Future.completed(count) - def opDoubleMarshaling_async(self, cb, p1, p2, current=None): + def opDoubleMarshaling(self, p1, p2, current=None): d = 1278312346.0 / 13.0; test(p1 == d) for i in p2: test(i == d) - cb.ice_response() + return Ice.Future.completed(None) - def opContext_async(self, cb, current=None): - cb.ice_response(current.ctx) + def opContext(self, current=None): + return Ice.Future.completed(current.ctx) - def opIdempotent_async(self, cb, current=None): + def opIdempotent(self, current=None): test(current.mode == Ice.OperationMode.Idempotent) - cb.ice_response() + return Ice.Future.completed(None) - def opNonmutating_async(self, cb, current=None): + def opNonmutating(self, current=None): test(current.mode == Ice.OperationMode.Nonmutating) - cb.ice_response() + return Ice.Future.completed(None) - def opDerived_async(self, cb, current=None): - cb.ice_response() + def opDerived(self, current=None): + return Ice.Future.completed(None) - def opByte1_async(self, cb, value, current=None): - cb.ice_response(value) + def opByte1(self, value, current=None): + return Ice.Future.completed(value) - def opShort1_async(self, cb, value, current=None): - cb.ice_response(value) + def opShort1(self, value, current=None): + return Ice.Future.completed(value) - def opInt1_async(self, cb, value, current=None): - cb.ice_response(value) + def opInt1(self, value, current=None): + return Ice.Future.completed(value) - def opLong1_async(self, cb, value, current=None): - cb.ice_response(value) + def opLong1(self, value, current=None): + return Ice.Future.completed(value) - def opFloat1_async(self, cb, value, current=None): - cb.ice_response(value) + def opFloat1(self, value, current=None): + return Ice.Future.completed(value) - def opDouble1_async(self, cb, value, current=None): - cb.ice_response(value) + def opDouble1(self, value, current=None): + return Ice.Future.completed(value) - def opString1_async(self, cb, value, current=None): - cb.ice_response(value) + def opString1(self, value, current=None): + return Ice.Future.completed(value) - def opStringS1_async(self, cb, value, current=None): - cb.ice_response(value) + def opStringS1(self, value, current=None): + return Ice.Future.completed(value) - def opByteBoolD1_async(self, cb, value, current=None): - cb.ice_response(value) + def opByteBoolD1(self, value, current=None): + return Ice.Future.completed(value) - def opStringS2_async(self, cb, value, current=None): - cb.ice_response(value) + def opStringS2(self, value, current=None): + return Ice.Future.completed(value) - def opByteBoolD2_async(self, cb, value, current=None): - cb.ice_response(value) + def opByteBoolD2(self, value, current=None): + return Ice.Future.completed(value) - def opMyClass1_async(self, cb, value, current=None): - return cb.ice_response(value) + def opMyClass1(self, value, current=None): + return Ice.Future.completed(value) - def opMyStruct1_async(self, cb, value, current=None): - return cb.ice_response(value) + def opMyStruct1(self, value, current=None): + return Ice.Future.completed(value) - def opStringLiterals_async(self, cb, current=None): - return cb.ice_response([ + def opStringLiterals(self, current=None): + return Ice.Future.completed([ Test.s0, Test.s1, Test.s2, Test.s3, Test.s4, Test.s5, Test.s6, Test.s7, Test.s8, Test.s9, Test.s10, - Test.sw0, Test.sw1, Test.sw2, Test.sw3, Test.sw4, Test.sw5, Test.sw6, Test.sw7, Test.sw8, Test.sw9, Test.sw10, + Test.sw0, Test.sw1, Test.sw2, Test.sw3, Test.sw4, Test.sw5, Test.sw6, Test.sw7, Test.sw8, Test.sw9, + Test.sw10, Test.ss0, Test.ss1, Test.ss2, Test.ss3, Test.ss4, Test.ss5, Test.su0, Test.su1, Test.su2]) - def opWStringLiterals_async(self, cb, current=None): - return self.opStringLiterals_async(cb, current) + def opWStringLiterals(self, current=None): + return self.opStringLiterals(current) - def opMStruct1_async(self, cb, current): - cb.ice_response(Test.Structure()) + def opMStruct1(self, current): + return Ice.Future.completed(Test.Structure()) - def opMStruct2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMStruct2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def opMSeq1_async(self, cb, current): - cb.ice_response([]) + def opMSeq1(self, current): + return Ice.Future.completed([]) - def opMSeq2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMSeq2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def opMDict1_async(self, cb, current): - cb.ice_response({}) + def opMDict1(self, current): + return Ice.Future.completed({}) - def opMDict2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMDict2(self, p1, current): + return Ice.Future.completed((p1, p1)) def run(args, communicator): communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010:udp") diff --git a/python/test/Ice/operations/TestI.py b/python/test/Ice/operations/TestI.py index 2901b2796ae..87b1e0b21bc 100644 --- a/python/test/Ice/operations/TestI.py +++ b/python/test/Ice/operations/TestI.py @@ -294,15 +294,13 @@ class MyDerivedClassI(Test.MyDerivedClass): return [-x for x in s] def opByteSOneway(self, s, current=None): - self.lock.acquire() - self.opByteSOnewayCount += 1 - self.lock.release() + with self.lock: + self.opByteSOnewayCount += 1 def opByteSOnewayCallCount(self, current=None): - self.lock.acquire() - count = self.opByteSOnewayCount - self.opByteSOnewayCount = 0 - self.lock.release() + with self.lock: + count = self.opByteSOnewayCount + self.opByteSOnewayCount = 0 return count def opContext(self, current=None): diff --git a/python/test/Ice/operations/TwowaysAMI.py b/python/test/Ice/operations/TwowaysAMI.py index cb356b3177f..a1cbc7642d4 100644 --- a/python/test/Ice/operations/TwowaysAMI.py +++ b/python/test/Ice/operations/TwowaysAMI.py @@ -19,19 +19,15 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): def __init__(self, communicator=None): diff --git a/python/test/Ice/operations/TwowaysFuture.py b/python/test/Ice/operations/TwowaysFuture.py new file mode 100644 index 00000000000..45720916adc --- /dev/null +++ b/python/test/Ice/operations/TwowaysFuture.py @@ -0,0 +1,1354 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import Ice, Test, math, sys, threading + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +class CallbackBase: + def __init__(self): + self._called = False + self._cond = threading.Condition() + + def check(self): + with self._cond: + while not self._called: + self._cond.wait() + self._called = False + + def called(self): + with self._cond: + self._called = True + self._cond.notify() + +class Callback(CallbackBase): + def __init__(self, communicator=None): + CallbackBase.__init__(self) + self._communicator = communicator + + def opByte(self, f): + try: + (r, b) = f.result() + test(b == 0xf0) + test(r == 0xff) + self.called() + except: + test(False) + + def opBool(self, f): + try: + (r, b) = f.result() + test(b) + test(not r) + self.called() + except: + test(False) + + def opShortIntLong(self, f): + try: + (r, s, i, l) = f.result() + test(s == 10) + test(i == 11) + test(l == 12) + test(r == 12) + self.called() + except: + test(False) + + def opFloatDouble(self, fut): + try: + (r, f, d) = fut.result() + test(f - 3.14 < 0.001) + test(d == 1.1E10) + test(r == 1.1E10) + self.called() + except: + test(False) + + def opString(self, f): + try: + (r, s) = f.result() + test(s == "world hello") + test(r == "hello world") + self.called() + except: + test(False) + + def opMyEnum(self, f): + try: + (r, e) = f.result() + test(e == Test.MyEnum.enum2) + test(r == Test.MyEnum.enum3) + self.called() + except: + test(False) + + def opMyClass(self, f): + try: + (r, c1, c2) = f.result() + test(c1.ice_getIdentity() == Ice.stringToIdentity("test")) + test(c2.ice_getIdentity() == Ice.stringToIdentity("noSuchIdentity")) + test(r.ice_getIdentity() == Ice.stringToIdentity("test")) + # We can't do the callbacks below in serialize mode + if self._communicator.getProperties().getPropertyAsInt("Ice.Client.ThreadPool.Serialize") == 0: + r.opVoid() + c1.opVoid() + try: + c2.opVoid() + test(False) + except Ice.ObjectNotExistException: + pass + self.called() + except: + test(False) + + def opStruct(self, f): + try: + (rso, so) = f.result() + test(rso.p == None) + test(rso.e == Test.MyEnum.enum2) + test(rso.s.s == "def") + test(so.e == Test.MyEnum.enum3) + test(so.s.s == "a new string") + # We can't do the callbacks below in serialize mode. + if self._communicator.getProperties().getPropertyAsInt("Ice.ThreadPool.Client.Serialize") == 0: + so.p.opVoid() + self.called() + except: + test(False) + + def opByteS(self, f): + try: + (rso, bso) = f.result() + test(len(bso) == 4) + test(len(rso) == 8) + if sys.version_info[0] == 2: + test(bso[0] == '\x22') + test(bso[1] == '\x12') + test(bso[2] == '\x11') + test(bso[3] == '\x01') + test(rso[0] == '\x01') + test(rso[1] == '\x11') + test(rso[2] == '\x12') + test(rso[3] == '\x22') + test(rso[4] == '\xf1') + test(rso[5] == '\xf2') + test(rso[6] == '\xf3') + test(rso[7] == '\xf4') + else: + test(bso[0] == 0x22) + test(bso[1] == 0x12) + test(bso[2] == 0x11) + test(bso[3] == 0x01) + test(rso[0] == 0x01) + test(rso[1] == 0x11) + test(rso[2] == 0x12) + test(rso[3] == 0x22) + test(rso[4] == 0xf1) + test(rso[5] == 0xf2) + test(rso[6] == 0xf3) + test(rso[7] == 0xf4) + self.called() + except: + test(False) + + def opBoolS(self, f): + try: + (rso, bso) = f.result() + test(len(bso) == 4) + test(bso[0]) + test(bso[1]) + test(not bso[2]) + test(not bso[3]) + test(len(rso) == 3) + test(not rso[0]) + test(rso[1]) + test(rso[2]) + self.called() + except: + test(False) + + def opShortIntLongS(self, f): + try: + (rso, sso, iso, lso) = f.result() + test(len(sso) == 3) + test(sso[0] == 1) + test(sso[1] == 2) + test(sso[2] == 3) + test(len(iso) == 4) + test(iso[0] == 8) + test(iso[1] == 7) + test(iso[2] == 6) + test(iso[3] == 5) + test(len(lso) == 6) + test(lso[0] == 10) + test(lso[1] == 30) + test(lso[2] == 20) + test(lso[3] == 10) + test(lso[4] == 30) + test(lso[5] == 20) + test(len(rso) == 3) + test(rso[0] == 10) + test(rso[1] == 30) + test(rso[2] == 20) + self.called() + except: + test(False) + + def opFloatDoubleS(self, f): + try: + (rso, fso, dso) = f.result() + test(len(fso) == 2) + test(fso[0] - 3.14 < 0.001) + test(fso[1] - 1.11 < 0.001) + test(len(dso) == 3) + test(dso[0] == 1.3E10) + test(dso[1] == 1.2E10) + test(dso[2] == 1.1E10) + test(len(rso) == 5) + test(rso[0] == 1.1E10) + test(rso[1] == 1.2E10) + test(rso[2] == 1.3E10) + test(rso[3] - 3.14 < 0.001) + test(rso[4] - 1.11 < 0.001) + self.called() + except: + test(False) + + def opStringS(self, f): + try: + (rso, sso) = f.result() + test(len(sso) == 4) + test(sso[0] == "abc") + test(sso[1] == "de") + test(sso[2] == "fghi") + test(sso[3] == "xyz") + test(len(rso) == 3) + test(rso[0] == "fghi") + test(rso[1] == "de") + test(rso[2] == "abc") + self.called() + except: + test(False) + + def opByteSS(self, f): + try: + (rso, bso) = f.result() + test(len(bso) == 2) + test(len(bso[0]) == 1) + test(len(bso[1]) == 3) + test(len(rso) == 4) + test(len(rso[0]) == 3) + test(len(rso[1]) == 1) + test(len(rso[2]) == 1) + test(len(rso[3]) == 2) + if sys.version_info[0] == 2: + test(bso[0][0] == '\xff') + test(bso[1][0] == '\x01') + test(bso[1][1] == '\x11') + test(bso[1][2] == '\x12') + test(rso[0][0] == '\x01') + test(rso[0][1] == '\x11') + test(rso[0][2] == '\x12') + test(rso[1][0] == '\xff') + test(rso[2][0] == '\x0e') + test(rso[3][0] == '\xf2') + test(rso[3][1] == '\xf1') + else: + test(bso[0][0] == 0xff) + test(bso[1][0] == 0x01) + test(bso[1][1] == 0x11) + test(bso[1][2] == 0x12) + test(rso[0][0] == 0x01) + test(rso[0][1] == 0x11) + test(rso[0][2] == 0x12) + test(rso[1][0] == 0xff) + test(rso[2][0] == 0x0e) + test(rso[3][0] == 0xf2) + test(rso[3][1] == 0xf1) + self.called() + except: + test(False) + + def opBoolSS(self, f): + try: + (rso, bso) = f.result() + test(len(bso) == 4); + test(len(bso[0]) == 1); + test(bso[0][0]); + test(len(bso[1]) == 1); + test(not bso[1][0]); + test(len(bso[2]) == 2); + test(bso[2][0]); + test(bso[2][1]); + test(len(bso[3]) == 3); + test(not bso[3][0]); + test(not bso[3][1]); + test(bso[3][2]); + test(len(rso) == 3); + test(len(rso[0]) == 2); + test(rso[0][0]); + test(rso[0][1]); + test(len(rso[1]) == 1); + test(not rso[1][0]); + test(len(rso[2]) == 1); + test(rso[2][0]); + self.called(); + except: + test(False) + + def opShortIntLongSS(self, f): + try: + (rso, sso, iso, lso) = f.result() + test(len(rso) == 1); + test(len(rso[0]) == 2); + test(rso[0][0] == 496); + test(rso[0][1] == 1729); + test(len(sso) == 3); + test(len(sso[0]) == 3); + test(sso[0][0] == 1); + test(sso[0][1] == 2); + test(sso[0][2] == 5); + test(len(sso[1]) == 1); + test(sso[1][0] == 13); + test(len(sso[2]) == 0); + test(len(iso) == 2); + test(len(iso[0]) == 1); + test(iso[0][0] == 42); + test(len(iso[1]) == 2); + test(iso[1][0] == 24); + test(iso[1][1] == 98); + test(len(lso) == 2); + test(len(lso[0]) == 2); + test(lso[0][0] == 496); + test(lso[0][1] == 1729); + test(len(lso[1]) == 2); + test(lso[1][0] == 496); + test(lso[1][1] == 1729); + self.called(); + except: + test(False) + + def opFloatDoubleSS(self, f): + try: + (rso, fso, dso) = f.result() + test(len(fso) == 3) + test(len(fso[0]) == 1) + test(fso[0][0] - 3.14 < 0.001) + test(len(fso[1]) == 1) + test(fso[1][0] - 1.11 < 0.001) + test(len(fso[2]) == 0) + test(len(dso) == 1) + test(len(dso[0]) == 3) + test(dso[0][0] == 1.1E10) + test(dso[0][1] == 1.2E10) + test(dso[0][2] == 1.3E10) + test(len(rso) == 2) + test(len(rso[0]) == 3) + test(rso[0][0] == 1.1E10) + test(rso[0][1] == 1.2E10) + test(rso[0][2] == 1.3E10) + test(len(rso[1]) == 3) + test(rso[1][0] == 1.1E10) + test(rso[1][1] == 1.2E10) + test(rso[1][2] == 1.3E10) + self.called() + except: + test(False) + + def opStringSS(self, f): + try: + (rso, sso) = f.result() + test(len(sso) == 5) + test(len(sso[0]) == 1) + test(sso[0][0] == "abc") + test(len(sso[1]) == 2) + test(sso[1][0] == "de") + test(sso[1][1] == "fghi") + test(len(sso[2]) == 0) + test(len(sso[3]) == 0) + test(len(sso[4]) == 1) + test(sso[4][0] == "xyz") + test(len(rso) == 3) + test(len(rso[0]) == 1) + test(rso[0][0] == "xyz") + test(len(rso[1]) == 0) + test(len(rso[2]) == 0) + self.called() + except: + test(False) + + def opByteBoolD(self, f): + try: + (ro, do) = f.result() + di1 = {10: True, 100: False} + test(do == di1) + test(len(ro) == 4) + test(ro[10]) + test(not ro[11]) + test(not ro[100]) + test(ro[101]) + self.called() + except: + test(False) + + def opShortIntD(self, f): + try: + (ro, do) = f.result() + di1 = {110: -1, 1100: 123123} + test(do == di1) + test(len(ro) == 4) + test(ro[110] == -1) + test(ro[111] == -100) + test(ro[1100] == 123123) + test(ro[1101] == 0) + self.called() + except: + test(False) + + def opLongFloatD(self, f): + try: + (ro, do) = f.result() + di1 = {999999110: -1.1, 999999111: 123123.2} + for k in do: + test(math.fabs(do[k] - di1[k]) < 0.01) + test(len(ro) == 4) + test(ro[999999110] - -1.1 < 0.01) + test(ro[999999120] - -100.4 < 0.01) + test(ro[999999111] - 123123.2 < 0.01) + test(ro[999999130] - 0.5 < 0.01) + self.called() + except: + test(False) + + def opStringStringD(self, f): + try: + (ro, do) = f.result() + di1 = {'foo': 'abc -1.1', 'bar': 'abc 123123.2'} + test(do == di1) + test(len(ro) == 4) + test(ro["foo"] == "abc -1.1") + test(ro["FOO"] == "abc -100.4") + test(ro["bar"] == "abc 123123.2") + test(ro["BAR"] == "abc 0.5") + self.called() + except: + test(False) + + def opStringMyEnumD(self, f): + try: + (ro, do) = f.result() + di1 = {'abc': Test.MyEnum.enum1, '': Test.MyEnum.enum2} + test(do == di1) + test(len(ro) == 4) + test(ro["abc"] == Test.MyEnum.enum1) + test(ro["qwerty"] == Test.MyEnum.enum3) + test(ro[""] == Test.MyEnum.enum2) + test(ro["Hello!!"] == Test.MyEnum.enum2) + self.called() + except: + test(False) + + def opMyEnumStringD(self, f): + try: + (ro, do) = f.result() + di1 = {Test.MyEnum.enum1: 'abc'} + test(do == di1) + test(len(ro) == 3) + test(ro[Test.MyEnum.enum1] == "abc") + test(ro[Test.MyEnum.enum2] == "Hello!!") + test(ro[Test.MyEnum.enum3] == "qwerty") + self.called() + except: + test(False) + + def opMyStructMyEnumD(self, f): + try: + (ro, do) = f.result() + s11 = Test.MyStruct() + s11.i = 1 + s11.j = 1 + s12 = Test.MyStruct() + s12.i = 1 + s12.j = 2 + s22 = Test.MyStruct() + s22.i = 2 + s22.j = 2 + s23 = Test.MyStruct() + s23.i = 2 + s23.j = 3 + di1 = {s11: Test.MyEnum.enum1, s12: Test.MyEnum.enum2} + test(do == di1) + test(len(ro) == 4) + test(ro[s11] == Test.MyEnum.enum1) + test(ro[s12] == Test.MyEnum.enum2) + test(ro[s22] == Test.MyEnum.enum3) + test(ro[s23] == Test.MyEnum.enum2) + self.called() + except: + test(False) + + def opByteBoolDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0][10]) + test(not ro[0][11]) + test(ro[0][101]) + test(len(ro[1]) == 2) + test(ro[1][10]) + test(not ro[1][100]) + test(len(do) == 3) + test(len(do[0]) == 2) + test(not do[0][100]) + test(not do[0][101]) + test(len(do[1]) == 2) + test(do[1][10]) + test(not do[1][100]) + test(len(do[2]) == 3) + test(do[2][10]) + test(not do[2][11]) + test(do[2][101]) + self.called() + except: + test(False) + + def opShortIntDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0][110] == -1) + test(ro[0][111] == -100) + test(ro[0][1101] == 0) + test(len(ro[1]) == 2) + test(ro[1][110] == -1) + test(ro[1][1100] == 123123) + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0][100] == -1001) + test(len(do[1]) == 2) + test(do[1][110] == -1) + test(do[1][1100] == 123123) + test(len(do[2]) == 3) + test(do[2][110] == -1) + test(do[2][111] == -100) + test(do[2][1101] == 0) + self.called() + except: + test(False) + + def opLongFloatDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0][999999110] - -1.1 < 0.01) + test(ro[0][999999120] - -100.4 < 0.01) + test(ro[0][999999130] - 0.5 < 0.01) + test(len(ro[1]) == 2) + test(ro[1][999999110] - -1.1 < 0.01) + test(ro[1][999999111] - 123123.2 < 0.01) + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0][999999140] - 3.14 < 0.01) + test(len(do[1]) == 2) + test(do[1][999999110] - -1.1 < 0.01) + test(do[1][999999111] - 123123.2 < 0.01) + test(len(do[2]) == 3) + test(do[2][999999110] - -1.1 < 0.01) + test(do[2][999999120] - -100.4 < 0.01) + test(do[2][999999130] - 0.5 < 0.01) + self.called() + except: + test(False) + + def opStringStringDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0]["foo"] == "abc -1.1") + test(ro[0]["FOO"] == "abc -100.4") + test(ro[0]["BAR"] == "abc 0.5") + test(len(ro[1]) == 2) + test(ro[1]["foo"] == "abc -1.1") + test(ro[1]["bar"] == "abc 123123.2") + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0]["f00"] == "ABC -3.14") + test(len(do[1]) == 2) + test(do[1]["foo"] == "abc -1.1") + test(do[1]["bar"] == "abc 123123.2") + test(len(do[2]) == 3) + test(do[2]["foo"] == "abc -1.1") + test(do[2]["FOO"] == "abc -100.4") + test(do[2]["BAR"] == "abc 0.5") + self.called() + except: + test(False) + + def opStringMyEnumDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0]["abc"] == Test.MyEnum.enum1) + test(ro[0]["qwerty"] == Test.MyEnum.enum3) + test(ro[0]["Hello!!"] == Test.MyEnum.enum2) + test(len(ro[1]) == 2) + test(ro[1]["abc"] == Test.MyEnum.enum1) + test(ro[1][""] == Test.MyEnum.enum2) + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0]["Goodbye"] == Test.MyEnum.enum1) + test(len(do[1]) == 2) + test(do[1]["abc"] == Test.MyEnum.enum1) + test(do[1][""] == Test.MyEnum.enum2) + test(len(do[2]) == 3) + test(do[2]["abc"] == Test.MyEnum.enum1) + test(do[2]["qwerty"] == Test.MyEnum.enum3) + test(do[2]["Hello!!"] == Test.MyEnum.enum2) + self.called() + except: + test(False) + + def opMyEnumStringDS(self, f): + try: + (ro, do) = f.result() + test(len(ro) == 2) + test(len(ro[0]) == 2) + test(ro[0][Test.MyEnum.enum2] == "Hello!!") + test(ro[0][Test.MyEnum.enum3] == "qwerty") + test(len(ro[1]) == 1) + test(ro[1][Test.MyEnum.enum1] == "abc") + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0][Test.MyEnum.enum1] == "Goodbye") + test(len(do[1]) == 1) + test(do[1][Test.MyEnum.enum1] == "abc") + test(len(do[2]) == 2) + test(do[2][Test.MyEnum.enum2] == "Hello!!") + test(do[2][Test.MyEnum.enum3] == "qwerty") + self.called() + except: + test(False) + + def opMyStructMyEnumDS(self, f): + try: + (ro, do) = f.result() + s11 = Test.MyStruct(1, 1) + s12 = Test.MyStruct(1, 2) + s22 = Test.MyStruct(2, 2) + s23 = Test.MyStruct(2, 3) + test(len(ro) == 2) + test(len(ro[0]) == 3) + test(ro[0][s11] == Test.MyEnum.enum1) + test(ro[0][s22] == Test.MyEnum.enum3) + test(ro[0][s23] == Test.MyEnum.enum2) + test(len(ro[1]) == 2) + test(ro[1][s11] == Test.MyEnum.enum1) + test(ro[1][s12] == Test.MyEnum.enum2) + test(len(do) == 3) + test(len(do[0]) == 1) + test(do[0][s23] == Test.MyEnum.enum3) + test(len(do[1]) == 2) + test(do[1][s11] == Test.MyEnum.enum1) + test(do[1][s12] == Test.MyEnum.enum2) + test(len(do[2]) == 3) + test(do[2][s11] == Test.MyEnum.enum1) + test(do[2][s22] == Test.MyEnum.enum3) + test(do[2][s23] == Test.MyEnum.enum2) + self.called() + except: + test(False) + + def opByteByteSD(self, f): + try: + (ro, do) = f.result() + if sys.version_info[0] == 2: + test(len(do) == 1) + test(len(do[0xf1]) == 2) + test(do[0xf1][0] == '\xf2') + test(do[0xf1][1] == '\xf3') + test(len(ro) == 3) + test(len(ro[0x01]) == 2) + test(ro[0x01][0] == '\x01') + test(ro[0x01][1] == '\x11') + test(len(ro[0x22]) == 1) + test(ro[0x22][0] == '\x12') + test(len(ro[0xf1]) == 2) + test(ro[0xf1][0] == '\xf2') + test(ro[0xf1][1] == '\xf3') + else: + test(len(do) == 1) + test(len(do[0xf1]) == 2) + test(do[0xf1][0] == 0xf2) + test(do[0xf1][1] == 0xf3) + test(len(ro) == 3) + test(len(ro[0x01]) == 2) + test(ro[0x01][0] == 0x01) + test(ro[0x01][1] == 0x11) + test(len(ro[0x22]) == 1) + test(ro[0x22][0] == 0x12) + test(len(ro[0xf1]) == 2) + test(ro[0xf1][0] == 0xf2) + test(ro[0xf1][1] == 0xf3) + self.called() + except: + test(False) + + def opBoolBoolSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[False]) == 2) + test(do[False][0]) + test(not do[False][1]) + test(len(ro) == 2) + test(len(ro[False]) == 2) + test(ro[False][0]) + test(not ro[False][1]) + test(len(ro[True]) == 3) + test(not ro[True][0]) + test(ro[True][1]) + test(ro[True][2]) + self.called() + except: + test(False) + + def opShortShortSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[4]) == 2) + test(do[4][0] == 6) + test(do[4][1] == 7) + test(len(ro) == 3) + test(len(ro[1]) == 3) + test(ro[1][0] == 1) + test(ro[1][1] == 2) + test(ro[1][2] == 3) + test(len(ro[2]) == 2) + test(ro[2][0] == 4) + test(ro[2][1] == 5) + test(len(ro[4]) == 2) + test(ro[4][0] == 6) + test(ro[4][1] == 7) + self.called() + except: + test(False) + + def opIntIntSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[400]) == 2) + test(do[400][0] == 600) + test(do[400][1] == 700) + test(len(ro) == 3) + test(len(ro[100]) == 3) + test(ro[100][0] == 100) + test(ro[100][1] == 200) + test(ro[100][2] == 300) + test(len(ro[200]) == 2) + test(ro[200][0] == 400) + test(ro[200][1] == 500) + test(len(ro[400]) == 2) + test(ro[400][0] == 600) + test(ro[400][1] == 700) + self.called() + except: + test(False) + + def opLongLongSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[999999992]) == 2) + test(do[999999992][0] == 999999110) + test(do[999999992][1] == 999999120) + test(len(ro) == 3) + test(len(ro[999999990]) == 3) + test(ro[999999990][0] == 999999110) + test(ro[999999990][1] == 999999111) + test(ro[999999990][2] == 999999110) + test(len(ro[999999991]) == 2) + test(ro[999999991][0] == 999999120) + test(ro[999999991][1] == 999999130) + test(len(ro[999999992]) == 2) + test(ro[999999992][0] == 999999110) + test(ro[999999992][1] == 999999120) + self.called() + except: + test(False) + + def opStringFloatSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do["aBc"]) == 2) + test(do["aBc"][0] - -3.14 < 0.10) + test(do["aBc"][1] - 3.14 < 0.10) + test(len(ro) == 3) + test(len(ro["abc"]) == 3) + test(ro["abc"][0] - -1.1 < 0.10) + test(ro["abc"][1] - 123123.2 < 0.10) + test(ro["abc"][2] - 100.0 < 0.10) + test(len(ro["ABC"]) == 2) + test(ro["ABC"][0] - 42.24 < 0.10) + test(ro["ABC"][1] - -1.61 < 0.10) + test(len(ro["aBc"]) == 2) + test(ro["aBc"][0] - -3.14 < 0.10) + test(ro["aBc"][1] - 3.14 < 0.10) + self.called() + except: + test(False) + + def opStringDoubleSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[""]) == 2) + test(do[""][0] == 1.6E10) + test(do[""][1] == 1.7E10) + test(len(ro) == 3) + test(len(ro["Hello!!"]) == 3) + test(ro["Hello!!"][0] == 1.1E10) + test(ro["Hello!!"][1] == 1.2E10) + test(ro["Hello!!"][2] == 1.3E10) + test(len(ro["Goodbye"]) == 2) + test(ro["Goodbye"][0] == 1.4E10) + test(ro["Goodbye"][1] == 1.5E10) + test(len(ro[""]) == 2) + test(ro[""][0] == 1.6E10) + test(ro[""][1] == 1.7E10) + self.called() + except: + test(False) + + def opStringStringSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do["ghi"]) == 2) + test(do["ghi"][0] == "and") + test(do["ghi"][1] == "xor") + test(len(ro) == 3) + test(len(ro["abc"]) == 3) + test(ro["abc"][0] == "abc") + test(ro["abc"][1] == "de") + test(ro["abc"][2] == "fghi") + test(len(ro["def"]) == 2) + test(ro["def"][0] == "xyz") + test(ro["def"][1] == "or") + test(len(ro["ghi"]) == 2) + test(ro["ghi"][0] == "and") + test(ro["ghi"][1] == "xor") + self.called() + except: + test(False) + + def opMyEnumMyEnumSD(self, f): + try: + (ro, do) = f.result() + test(len(do) == 1) + test(len(do[Test.MyEnum.enum1]) == 2) + test(do[Test.MyEnum.enum1][0] == Test.MyEnum.enum3) + test(do[Test.MyEnum.enum1][1] == Test.MyEnum.enum3) + test(len(ro) == 3) + test(len(ro[Test.MyEnum.enum3]) == 3) + test(ro[Test.MyEnum.enum3][0] == Test.MyEnum.enum1) + test(ro[Test.MyEnum.enum3][1] == Test.MyEnum.enum1) + test(ro[Test.MyEnum.enum3][2] == Test.MyEnum.enum2) + test(len(ro[Test.MyEnum.enum2]) == 2) + test(ro[Test.MyEnum.enum2][0] == Test.MyEnum.enum1) + test(ro[Test.MyEnum.enum2][1] == Test.MyEnum.enum2) + test(len(ro[Test.MyEnum.enum1]) == 2) + test(ro[Test.MyEnum.enum1][0] == Test.MyEnum.enum3) + test(ro[Test.MyEnum.enum1][1] == Test.MyEnum.enum3) + self.called() + except: + test(False) + + def opIntS(self, f): + try: + r = f.result() + for j in range(0, len(r)): + test(r[j] == -j) + self.called() + except: + test(False) + + def opIdempotent(self, f): + self.called() + + def opNonmutating(self, f): + self.called() + + def opDerived(self, f): + self.called() + +def twowaysFuture(communicator, p): + f = p.ice_pingAsync() + test(f.result() is None) + + f = p.ice_isAAsync(Test.MyClass.ice_staticId()) + test(f.result()) + + f = p.ice_idAsync() + test(f.result() == "::Test::MyDerivedClass") + + f = p.ice_idsAsync() + test(len(f.result()) == 3) + + f = p.opVoidAsync() + test(f.result() is None) + + cb = Callback() + p.opVoidAsync().add_done_callback(lambda f: cb.called()) + cb.check() + + f = p.opByteAsync(0xff, 0x0f) + (ret, p3) = f.result() + test(p3 == 0xf0) + test(ret == 0xff) + + cb = Callback() + p.opByteAsync(0xff, 0x0f).add_done_callback(cb.opByte) + cb.check() + + cb = Callback() + p.opBoolAsync(True, False).add_done_callback(cb.opBool) + cb.check() + + cb = Callback() + p.opShortIntLongAsync(10, 11, 12).add_done_callback(cb.opShortIntLong) + cb.check() + + cb = Callback() + p.opFloatDoubleAsync(3.14, 1.1E10).add_done_callback(cb.opFloatDouble) + cb.check() + + cb = Callback() + p.opStringAsync("hello", "world").add_done_callback(cb.opString) + cb.check() + + cb = Callback() + p.opMyEnumAsync(Test.MyEnum.enum2).add_done_callback(cb.opMyEnum) + cb.check() + + cb = Callback(communicator) + p.opMyClassAsync(p).add_done_callback(cb.opMyClass) + cb.check() + + si1 = Test.Structure() + si1.p = p + si1.e = Test.MyEnum.enum3 + si1.s = Test.AnotherStruct() + si1.s.s = "abc" + si2 = Test.Structure() + si2.p = None + si2.e = Test.MyEnum.enum2 + si2.s = Test.AnotherStruct() + si2.s.s = "def" + + cb = Callback(communicator) + p.opStructAsync(si1, si2).add_done_callback(cb.opStruct) + cb.check() + + bsi1 = (0x01, 0x11, 0x12, 0x22) + bsi2 = (0xf1, 0xf2, 0xf3, 0xf4) + + cb = Callback() + p.opByteSAsync(bsi1, bsi2).add_done_callback(cb.opByteS) + cb.check() + + bsi1 = (True, True, False) + bsi2 = (False,) + + cb = Callback() + p.opBoolSAsync(bsi1, bsi2).add_done_callback(cb.opBoolS) + cb.check() + + ssi = (1, 2, 3) + isi = (5, 6, 7, 8) + lsi = (10, 30, 20) + + cb = Callback() + p.opShortIntLongSAsync(ssi, isi, lsi).add_done_callback(cb.opShortIntLongS) + cb.check() + + fsi = (3.14, 1.11) + dsi = (1.1E10, 1.2E10, 1.3E10) + + cb = Callback() + p.opFloatDoubleSAsync(fsi, dsi).add_done_callback(cb.opFloatDoubleS) + cb.check() + + ssi1 = ('abc', 'de', 'fghi') + ssi2 = ('xyz',) + + cb = Callback() + p.opStringSAsync(ssi1, ssi2).add_done_callback(cb.opStringS) + cb.check() + + bsi1 = ((0x01, 0x11, 0x12), (0xff,)) + bsi2 = ((0x0e,), (0xf2, 0xf1)) + + cb = Callback() + p.opByteSSAsync(bsi1, bsi2).add_done_callback(cb.opByteSS) + cb.check() + + bsi1 = ((True,), (False,), (True, True),) + bsi2 = ((False, False, True),) + + cb = Callback() + p.opBoolSSAsync(bsi1, bsi2).add_done_callback(cb.opBoolSS) + cb.check(); + + ssi = ((1,2,5), (13,), ()) + isi = ((24, 98), (42,)) + lsi = ((496, 1729),) + + cb = Callback() + p.opShortIntLongSSAsync(ssi, isi, lsi).add_done_callback(cb.opShortIntLongSS) + cb.check() + + fsi = ((3.14,), (1.11,), ()) + dsi = ((1.1E10, 1.2E10, 1.3E10),) + + cb = Callback() + p.opFloatDoubleSSAsync(fsi, dsi).add_done_callback(cb.opFloatDoubleSS) + cb.check() + + ssi1 = (('abc',), ('de', 'fghi')) + ssi2 = ((), (), ('xyz',)) + + cb = Callback() + p.opStringSSAsync(ssi1, ssi2).add_done_callback(cb.opStringSS) + cb.check() + + di1 = {10: True, 100: False} + di2 = {10: True, 11: False, 101: True} + + cb = Callback() + p.opByteBoolDAsync(di1, di2).add_done_callback(cb.opByteBoolD) + cb.check() + + di1 = {110: -1, 1100: 123123} + di2 = {110: -1, 111: -100, 1101: 0} + + cb = Callback() + p.opShortIntDAsync(di1, di2).add_done_callback(cb.opShortIntD) + cb.check() + + di1 = {999999110: -1.1, 999999111: 123123.2} + di2 = {999999110: -1.1, 999999120: -100.4, 999999130: 0.5} + + cb = Callback() + p.opLongFloatDAsync(di1, di2).add_done_callback(cb.opLongFloatD) + cb.check() + + di1 = {'foo': 'abc -1.1', 'bar': 'abc 123123.2'} + di2 = {'foo': 'abc -1.1', 'FOO': 'abc -100.4', 'BAR': 'abc 0.5'} + + cb = Callback() + p.opStringStringDAsync(di1, di2).add_done_callback(cb.opStringStringD) + cb.check() + + di1 = {'abc': Test.MyEnum.enum1, '': Test.MyEnum.enum2} + di2 = {'abc': Test.MyEnum.enum1, 'qwerty': Test.MyEnum.enum3, 'Hello!!': Test.MyEnum.enum2} + + cb = Callback() + p.opStringMyEnumDAsync(di1, di2).add_done_callback(cb.opStringMyEnumD) + cb.check() + + di1 = {Test.MyEnum.enum1: 'abc'} + di2 = {Test.MyEnum.enum2: 'Hello!!', Test.MyEnum.enum3: 'qwerty'} + + cb = Callback() + p.opMyEnumStringDAsync(di1, di2).add_done_callback(cb.opMyEnumStringD) + cb.check() + + s11 = Test.MyStruct() + s11.i = 1 + s11.j = 1 + s12 = Test.MyStruct() + s12.i = 1 + s12.j = 2 + s22 = Test.MyStruct() + s22.i = 2 + s22.j = 2 + s23 = Test.MyStruct() + s23.i = 2 + s23.j = 3 + di1 = {s11: Test.MyEnum.enum1, s12: Test.MyEnum.enum2} + di2 = {s11: Test.MyEnum.enum1, s22: Test.MyEnum.enum3, s23: Test.MyEnum.enum2} + + cb = Callback() + p.opMyStructMyEnumDAsync(di1, di2).add_done_callback(cb.opMyStructMyEnumD) + cb.check() + + dsi1 = ({ 10: True, 100: False }, { 10: True, 11: False, 101: True }) + dsi2 = ({ 100: False, 101: False },) + + cb = Callback() + p.opByteBoolDSAsync(dsi1, dsi2).add_done_callback(cb.opByteBoolDS) + cb.check() + + dsi1 = ({ 110: -1, 1100: 123123 }, { 110: -1, 111: -100, 1101: 0 }) + dsi2 = ({ 100: -1001 },) + + cb = Callback() + p.opShortIntDSAsync(dsi1, dsi2).add_done_callback(cb.opShortIntDS) + cb.called() + + dsi1 = ({ 999999110: -1.1, 999999111: 123123.2 }, { 999999110: -1.1, 999999120: -100.4, 999999130: 0.5 }) + dsi2 = ({ 999999140: 3.14 },) + + cb = Callback() + p.opLongFloatDSAsync(dsi1, dsi2).add_done_callback(cb.opLongFloatDS) + cb.called() + + dsi1 = ({ "foo": "abc -1.1", "bar": "abc 123123.2" }, { "foo": "abc -1.1", "FOO": "abc -100.4", "BAR": "abc 0.5" }) + dsi2 = ({ "f00": "ABC -3.14" },) + + cb = Callback() + p.opStringStringDSAsync(dsi1, dsi2).add_done_callback(cb.opStringStringDS) + cb.called() + + dsi1 = ( + { "abc": Test.MyEnum.enum1, "": Test.MyEnum.enum2 }, + { "abc": Test.MyEnum.enum1, "qwerty": Test.MyEnum.enum3, "Hello!!": Test.MyEnum.enum2 } + ) + + dsi2 = ({ "Goodbye": Test.MyEnum.enum1 },) + + cb = Callback() + p.opStringMyEnumDSAsync(dsi1, dsi2).add_done_callback(cb.opStringMyEnumDS) + cb.called() + + dsi1 = ({ Test.MyEnum.enum1: 'abc' }, { Test.MyEnum.enum2: 'Hello!!', Test.MyEnum.enum3: 'qwerty'}) + dsi2 = ({ Test.MyEnum.enum1: 'Goodbye' },) + + cb = Callback() + p.opMyEnumStringDSAsync(dsi1, dsi2).add_done_callback(cb.opMyEnumStringDS) + cb.called() + + s11 = Test.MyStruct(1, 1) + s12 = Test.MyStruct(1, 2) + + s22 = Test.MyStruct(2, 2) + s23 = Test.MyStruct(2, 3) + + dsi1 = ( + { s11: Test.MyEnum.enum1, s12: Test.MyEnum.enum2 }, + { s11: Test.MyEnum.enum1, s22: Test.MyEnum.enum3, s23: Test.MyEnum.enum2 } + ) + dsi2 = ({ s23: Test.MyEnum.enum3 },) + + cb = Callback() + p.opMyStructMyEnumDSAsync(dsi1, dsi2).add_done_callback(cb.opMyStructMyEnumDS) + cb.called() + + sdi1 = { 0x01: (0x01, 0x11), 0x22: (0x12,) } + sdi2 = { 0xf1: (0xf2, 0xf3) } + + cb = Callback() + p.opByteByteSDAsync(sdi1, sdi2).add_done_callback(cb.opByteByteSD) + cb.called() + + sdi1 = { False: (True, False), True: (False, True, True) } + sdi2 = { False: (True, False) } + + cb = Callback() + p.opBoolBoolSDAsync(sdi1, sdi2).add_done_callback(cb.opBoolBoolSD) + cb.called() + + sdi1 = { 1: (1, 2, 3), 2: (4, 5) } + sdi2 = { 4: (6, 7) } + + cb = Callback() + p.opShortShortSDAsync(sdi1, sdi2).add_done_callback(cb.opShortShortSD) + cb.called() + + sdi1 = { 100: (100, 200, 300), 200: (400, 500) } + sdi2 = { 400: (600, 700) } + + cb = Callback() + p.opIntIntSDAsync(sdi1, sdi2).add_done_callback(cb.opIntIntSD) + cb.called() + + sdi1 = { 999999990: (999999110, 999999111, 999999110), 999999991: (999999120, 999999130) } + sdi2 = { 999999992: (999999110, 999999120) } + + cb = Callback() + p.opLongLongSDAsync(sdi1, sdi2).add_done_callback(cb.opLongLongSD) + cb.called() + + sdi1 = { "abc": (-1.1, 123123.2, 100.0), "ABC": (42.24, -1.61) } + sdi2 = { "aBc": (-3.14, 3.14) } + + cb = Callback() + p.opStringFloatSDAsync(sdi1, sdi2).add_done_callback(cb.opStringFloatSD) + cb.called() + + sdi1 = { "Hello!!": (1.1E10, 1.2E10, 1.3E10), "Goodbye": (1.4E10, 1.5E10) } + sdi2 = { "": (1.6E10, 1.7E10) } + + cb = Callback() + p.opStringDoubleSDAsync(sdi1, sdi2).add_done_callback(cb.opStringDoubleSD) + cb.called() + + sdi1 = { "abc": ("abc", "de", "fghi") , "def": ("xyz", "or") } + sdi2 = { "ghi": ("and", "xor") } + + cb = Callback() + p.opStringStringSDAsync(sdi1, sdi2).add_done_callback(cb.opStringStringSD) + cb.called() + + sdi1 = { + Test.MyEnum.enum3: (Test.MyEnum.enum1, Test.MyEnum.enum1, Test.MyEnum.enum2), + Test.MyEnum.enum2: (Test.MyEnum.enum1, Test.MyEnum.enum2) + } + sdi2 = { Test.MyEnum.enum1: (Test.MyEnum.enum3, Test.MyEnum.enum3) } + + cb = Callback() + p.opMyEnumMyEnumSDAsync(sdi1, sdi2).add_done_callback(cb.opMyEnumMyEnumSD) + cb.called() + + lengths = ( 0, 1, 2, 126, 127, 128, 129, 253, 254, 255, 256, 257, 1000 ) + for l in lengths: + s = [] + for i in range(l): + s.append(i) + cb = Callback(l) + p.opIntSAsync(s).add_done_callback(cb.opIntS) + cb.check() + + ctx = {'one': 'ONE', 'two': 'TWO', 'three': 'THREE'} + + test(len(p.ice_getContext()) == 0) + f = p.opContextAsync() + c = f.result() + test(c != ctx) + + test(len(p.ice_getContext()) == 0) + f = p.opContextAsync(_ctx=ctx) + c = f.result() + test(c == ctx) + + p2 = Test.MyClassPrx.checkedCast(p.ice_context(ctx)) + test(p2.ice_getContext() == ctx) + f = p2.opContextAsync() + c = f.result() + test(c == ctx) + + f = p2.opContextAsync(_ctx=ctx) + c = f.result() + test(c == ctx) + + # + # Test implicit context propagation + # + if p.ice_getConnection(): + impls = ( 'Shared', 'PerThread' ) + for i in impls: + initData = Ice.InitializationData() + initData.properties = communicator.getProperties().clone() + initData.properties.setProperty('Ice.ImplicitContext', i) + ic = Ice.initialize(data=initData) + + ctx = {'one': 'ONE', 'two': 'TWO', 'three': 'THREE'} + + p3 = Test.MyClassPrx.uncheckedCast(ic.stringToProxy("test:default -p 12010")) + + ic.getImplicitContext().setContext(ctx) + test(ic.getImplicitContext().getContext() == ctx) + f = p3.opContextAsync() + c = f.result() + test(c == ctx) + + ic.getImplicitContext().put('zero', 'ZERO') + + ctx = ic.getImplicitContext().getContext() + f = p3.opContextAsync() + c = f.result() + test(c == ctx) + + prxContext = {'one': 'UN', 'four': 'QUATRE'} + + combined = {} + combined.update(ctx) + combined.update(prxContext) + test(combined['one'] == 'UN') + + p3 = Test.MyClassPrx.uncheckedCast(p3.ice_context(prxContext)) + ic.getImplicitContext().setContext({}) + f = p3.opContextAsync() + c = f.result() + test(c == prxContext) + + ic.getImplicitContext().setContext(ctx) + f = p3.opContextAsync() + c = f.result() + test(c == combined) + + ic.destroy() + + cb = Callback() + p.opIdempotentAsync().add_done_callback(cb.opIdempotent) + cb.check() + + cb = Callback() + p.opNonmutatingAsync().add_done_callback(cb.opNonmutating) + cb.check() + + derived = Test.MyDerivedClassPrx.checkedCast(p) + test(derived) + cb = Callback() + derived.opDerivedAsync().add_done_callback(cb.opDerived) + cb.check() + + f = p.opByte1Async(0xFF) + test(f.result() == 0xFF) + + f = p.opShort1Async(0x7FFF) + test(f.result() == 0x7FFF) + + f = p.opInt1Async(0x7FFFFFFF) + test(f.result() == 0x7FFFFFFF) + + f = p.opLong1Async(0x7FFFFFFFFFFFFFFF) + test(f.result() == 0x7FFFFFFFFFFFFFFF) + + f = p.opFloat1Async(1.0) + test(f.result() == 1.0) + + f = p.opDouble1Async(1.0) + test(f.result() == 1.0) + + f = p.opString1Async("opString1") + test(f.result() == "opString1") + + f = p.opStringS1Async(None) + test(len(f.result()) == 0) + + f = p.opByteBoolD1Async(None) + test(len(f.result()) == 0) + + f = p.opStringS2Async(None) + test(len(f.result()) == 0) + + f = p.opByteBoolD2Async(None) + test(len(f.result()) == 0) diff --git a/python/test/Ice/optional/AllTests.py b/python/test/Ice/optional/AllTests.py index 6f2a610e8f3..8219fe6f428 100644 --- a/python/test/Ice/optional/AllTests.py +++ b/python/test/Ice/optional/AllTests.py @@ -456,72 +456,72 @@ def allTests(communicator): test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opByte(56) test(p2 == 56 and p3 == 56) - r = initial.begin_opByte(56) - (p2, p3) = initial.end_opByte(r) + f = initial.opByteAsync(56) + (p2, p3) = f.result() test(p2 == 56 and p3 == 56) (p2, p3) = initial.opBool(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opBool(True) test(p2 == True and p3 == True) - r = initial.begin_opBool(True) - (p2, p3) = initial.end_opBool(r) + f = initial.opBoolAsync(True) + (p2, p3) = f.result() test(p2 == True and p3 == True) (p2, p3) = initial.opShort(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opShort(56) test(p2 == 56 and p3 == 56) - r = initial.begin_opShort(56) - (p2, p3) = initial.end_opShort(r) + f = initial.opShortAsync(56) + (p2, p3) = f.result() test(p2 == 56 and p3 == 56) (p2, p3) = initial.opInt(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opInt(56) test(p2 == 56 and p3 == 56) - r = initial.begin_opInt(56) - (p2, p3) = initial.end_opInt(r) + f = initial.opIntAsync(56) + (p2, p3) = f.result() test(p2 == 56 and p3 == 56) (p2, p3) = initial.opLong(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opLong(56) test(p2 == 56 and p3 == 56) - r = initial.begin_opLong(56) - (p2, p3) = initial.end_opLong(r) + f = initial.opLongAsync(56) + (p2, p3) = f.result() test(p2 == 56 and p3 == 56) (p2, p3) = initial.opFloat(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opFloat(1.0) test(p2 == 1.0 and p3 == 1.0) - r = initial.begin_opFloat(1.0) - (p2, p3) = initial.end_opFloat(r) + f = initial.opFloatAsync(1.0) + (p2, p3) = f.result() test(p2 == 1.0 and p3 == 1.0) (p2, p3) = initial.opDouble(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opDouble(1.0) test(p2 == 1.0 and p3 == 1.0) - r = initial.begin_opDouble(1.0) - (p2, p3) = initial.end_opDouble(r) + f = initial.opDoubleAsync(1.0) + (p2, p3) = f.result() test(p2 == 1.0 and p3 == 1.0) (p2, p3) = initial.opString(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opString("test") test(p2 == "test" and p3 == "test") - r = initial.begin_opString("test") - (p2, p3) = initial.end_opString(r) + f = initial.opStringAsync("test") + (p2, p3) = f.result() test(p2 == "test" and p3 == "test") (p2, p3) = initial.opMyEnum(Ice.Unset) test(p2 is Ice.Unset and p3 is Ice.Unset) (p2, p3) = initial.opMyEnum(Test.MyEnum.MyEnumMember) test(p2 == Test.MyEnum.MyEnumMember and p3 == Test.MyEnum.MyEnumMember) - r = initial.begin_opMyEnum(Test.MyEnum.MyEnumMember) - (p2, p3) = initial.end_opMyEnum(r) + f = initial.opMyEnumAsync(Test.MyEnum.MyEnumMember) + (p2, p3) = f.result() test(p2 == Test.MyEnum.MyEnumMember and p3 == Test.MyEnum.MyEnumMember) (p2, p3) = initial.opSmallStruct(Ice.Unset) @@ -531,8 +531,8 @@ def allTests(communicator): test(p2 == p1 and p3 == p1) (p2, p3) = initial.opSmallStruct(None) # Test null struct test(p2.m == 0 and p3.m == 0) - r = initial.begin_opSmallStruct(p1) - (p2, p3) = initial.end_opSmallStruct(r) + f = initial.opSmallStructAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opFixedStruct(Ice.Unset) @@ -540,8 +540,8 @@ def allTests(communicator): p1 = Test.FixedStruct(56) (p2, p3) = initial.opFixedStruct(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opFixedStruct(p1) - (p2, p3) = initial.end_opFixedStruct(r) + f = initial.opFixedStructAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opVarStruct(Ice.Unset) @@ -549,8 +549,8 @@ def allTests(communicator): p1 = Test.VarStruct("test") (p2, p3) = initial.opVarStruct(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opVarStruct(p1) - (p2, p3) = initial.end_opVarStruct(r) + f = initial.opVarStructAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opOneOptional(Ice.Unset) @@ -558,8 +558,8 @@ def allTests(communicator): p1 = Test.OneOptional(58) (p2, p3) = initial.opOneOptional(p1) test(p2.a == p1.a and p3.a == p1.a) - r = initial.begin_opOneOptional(p1) - (p2, p3) = initial.end_opOneOptional(r) + f = initial.opOneOptionalAsync(p1) + (p2, p3) = f.result() test(p2.a == p1.a and p3.a == p1.a) (p2, p3) = initial.opOneOptionalProxy(Ice.Unset) @@ -567,8 +567,8 @@ def allTests(communicator): p1 = Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test")) (p2, p3) = initial.opOneOptionalProxy(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opOneOptionalProxy(p1) - (p2, p3) = initial.end_opOneOptionalProxy(r) + f = initial.opOneOptionalProxyAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opByteSeq(Ice.Unset) @@ -582,8 +582,8 @@ def allTests(communicator): else: test(p2[0] == 0x38) test(p3[0] == 0x38) - r = initial.begin_opByteSeq(p1) - (p2, p3) = initial.end_opByteSeq(r) + f = initial.opByteSeqAsync(p1) + (p2, p3) = f.result() test(len(p2) == len(p1) and len(p3) == len(p1)) if sys.version_info[0] == 2: test(p2[0] == '\x38') @@ -597,8 +597,8 @@ def allTests(communicator): p1 = [True for x in range(100)] (p2, p3) = initial.opBoolSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opBoolSeq(p1) - (p2, p3) = initial.end_opBoolSeq(r) + f = initial.opBoolSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opShortSeq(Ice.Unset) @@ -606,8 +606,8 @@ def allTests(communicator): p1 = [56 for x in range(100)] (p2, p3) = initial.opShortSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opShortSeq(p1) - (p2, p3) = initial.end_opShortSeq(r) + f = initial.opShortSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opIntSeq(Ice.Unset) @@ -615,8 +615,8 @@ def allTests(communicator): p1 = [56 for x in range(100)] (p2, p3) = initial.opIntSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opIntSeq(p1) - (p2, p3) = initial.end_opIntSeq(r) + f = initial.opIntSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opLongSeq(Ice.Unset) @@ -624,8 +624,8 @@ def allTests(communicator): p1 = [56 for x in range(100)] (p2, p3) = initial.opLongSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opLongSeq(p1) - (p2, p3) = initial.end_opLongSeq(r) + f = initial.opLongSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opFloatSeq(Ice.Unset) @@ -633,8 +633,8 @@ def allTests(communicator): p1 = [1.0 for x in range(100)] (p2, p3) = initial.opFloatSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opFloatSeq(p1) - (p2, p3) = initial.end_opFloatSeq(r) + f = initial.opFloatSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opDoubleSeq(Ice.Unset) @@ -642,8 +642,8 @@ def allTests(communicator): p1 = [1.0 for x in range(100)] (p2, p3) = initial.opDoubleSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opDoubleSeq(p1) - (p2, p3) = initial.end_opDoubleSeq(r) + f = initial.opDoubleSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opStringSeq(Ice.Unset) @@ -651,8 +651,8 @@ def allTests(communicator): p1 = ["test1" for x in range(100)] (p2, p3) = initial.opStringSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opStringSeq(p1) - (p2, p3) = initial.end_opStringSeq(r) + f = initial.opStringSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opSmallStructSeq(Ice.Unset) @@ -660,8 +660,8 @@ def allTests(communicator): p1 = [Test.SmallStruct(1) for x in range(10)] (p2, p3) = initial.opSmallStructSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opSmallStructSeq(p1) - (p2, p3) = initial.end_opSmallStructSeq(r) + f = initial.opSmallStructSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opSmallStructList(Ice.Unset) @@ -669,8 +669,8 @@ def allTests(communicator): p1 = tuple([Test.SmallStruct(1) for x in range(10)]) (p2, p3) = initial.opSmallStructList(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opSmallStructList(p1) - (p2, p3) = initial.end_opSmallStructList(r) + f = initial.opSmallStructListAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opFixedStructSeq(Ice.Unset) @@ -678,8 +678,8 @@ def allTests(communicator): p1 = [Test.FixedStruct(1) for x in range(10)] (p2, p3) = initial.opFixedStructSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opFixedStructSeq(p1) - (p2, p3) = initial.end_opFixedStructSeq(r) + f = initial.opFixedStructSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opFixedStructList(Ice.Unset) @@ -687,8 +687,8 @@ def allTests(communicator): p1 = tuple([Test.FixedStruct(1) for x in range(10)]) (p2, p3) = initial.opFixedStructList(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opFixedStructList(p1) - (p2, p3) = initial.end_opFixedStructList(r) + f = initial.opFixedStructListAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opVarStructSeq(Ice.Unset) @@ -696,8 +696,8 @@ def allTests(communicator): p1 = [Test.VarStruct("test") for x in range(10)] (p2, p3) = initial.opVarStructSeq(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opVarStructSeq(p1) - (p2, p3) = initial.end_opVarStructSeq(r) + f = initial.opVarStructSeqAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opIntIntDict(Ice.Unset) @@ -705,8 +705,8 @@ def allTests(communicator): p1 = {1:2, 2:3} (p2, p3) = initial.opIntIntDict(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opIntIntDict(p1) - (p2, p3) = initial.end_opIntIntDict(r) + f = initial.opIntIntDictAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opStringIntDict(Ice.Unset) @@ -714,8 +714,8 @@ def allTests(communicator): p1 = {"1":2, "2":3} (p2, p3) = initial.opStringIntDict(p1) test(p2 == p1 and p3 == p1) - r = initial.begin_opStringIntDict(p1) - (p2, p3) = initial.end_opStringIntDict(r) + f = initial.opStringIntDictAsync(p1) + (p2, p3) = f.result() test(p2 == p1 and p3 == p1) (p2, p3) = initial.opIntOneOptionalDict(Ice.Unset) @@ -723,8 +723,8 @@ def allTests(communicator): p1 = {1:Test.OneOptional(58), 2:Test.OneOptional(59)} (p2, p3) = initial.opIntOneOptionalDict(p1) test(p2[1].a == 58 and p3[1].a == 58); - r = initial.begin_opIntOneOptionalDict(p1) - (p2, p3) = initial.end_opIntOneOptionalDict(r) + f = initial.opIntOneOptionalDictAsync(p1) + (p2, p3) = f.result() test(p2[1].a == 58 and p3[1].a == 58); print("ok") diff --git a/python/test/Ice/optional/ServerAMD.py b/python/test/Ice/optional/ServerAMD.py index 15f4ca42867..a9bbda70c9b 100755 --- a/python/test/Ice/optional/ServerAMD.py +++ b/python/test/Ice/optional/ServerAMD.py @@ -16,20 +16,23 @@ import Test class InitialI(Test.Initial): - def shutdown_async(self, cb, current=None): + def shutdown(self, current=None): current.adapter.getCommunicator().shutdown() - cb.ice_response() - def pingPong_async(self, cb, o, current=None): - cb.ice_response(o) + def pingPong(self, o, current=None): + return Ice.Future.completed(o) - def opOptionalException_async(self, cb, a, b, o, current=None): - cb.ice_exception(Test.OptionalException(False, a, b, o)) + def opOptionalException(self, a, b, o, current=None): + f = Ice.Future() + f.set_exception(Test.OptionalException(False, a, b, o)) + return f - def opDerivedException_async(self, cb, a, b, o, current=None): - cb.ice_exception(Test.DerivedException(False, a, b, o, b, o)) + def opDerivedException(self, a, b, o, current=None): + f = Ice.Future() + f.set_exception(Test.DerivedException(False, a, b, o, b, o)) + return f - def opRequiredException_async(self, cb, a, b, o, current=None): + def opRequiredException(self, a, b, o, current=None): e = Test.RequiredException() e.a = a e.b = b @@ -38,154 +41,156 @@ class InitialI(Test.Initial): e.ss = b if o is not Ice.Unset: e.o2 = o - cb.ice_exception(e) + f = Ice.Future() + f.set_exception(e) + return f - def opByte_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opByte(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opBool_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opBool(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opShort_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opShort(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opInt_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opInt(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opLong_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opLong(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opFloat_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opFloat(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opDouble_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opDouble(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opString_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opString(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opMyEnum_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opMyEnum(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opSmallStruct_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opSmallStruct(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opFixedStruct_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opFixedStruct(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opVarStruct_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opVarStruct(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opOneOptional_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opOneOptional(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opOneOptionalProxy_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opOneOptionalProxy(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opByteSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opByteSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opBoolSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opBoolSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opShortSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opShortSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opIntSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opIntSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opLongSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opLongSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opFloatSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opFloatSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opDoubleSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opDoubleSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opStringSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opStringSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opSmallStructSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opSmallStructSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opSmallStructList_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opSmallStructList(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opFixedStructSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opFixedStructSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opFixedStructList_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opFixedStructList(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opVarStructSeq_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opVarStructSeq(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opSerializable_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opSerializable(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opIntIntDict_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opIntIntDict(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opStringIntDict_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opStringIntDict(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opIntOneOptionalDict_async(self, cb, p1, current=None): - cb.ice_response(p1, p1) + def opIntOneOptionalDict(self, p1, current=None): + return Ice.Future.completed((p1, p1)) - def opClassAndUnknownOptional_async(self, cb, p, current=None): - cb.ice_response() + def opClassAndUnknownOptional(self, p, current=None): + return Ice.Future.completed(None) - def sendOptionalClass_async(self, cb, req, o, current=None): - cb.ice_response() + def sendOptionalClass(self, req, o, current=None): + return Ice.Future.completed(None) - def returnOptionalClass_async(self, cb, req, current=None): - cb.ice_response(Test.OneOptional(53)) + def returnOptionalClass(self, req, current=None): + return Ice.Future.completed(Test.OneOptional(53)) - def opG_async(self, cb, g, current=None): - cb.ice_response(g) + def opG(self, g, current=None): + return Ice.Future.completed(g) - def opVoid_async(self, cb, current=None): - cb.ice_response() + def opVoid(self, current=None): + return Ice.Future.completed(None) - def opMStruct1_async(self, cb, current): - cb.ice_response(Test.SmallStruct()) + def opMStruct1(self, current): + return Ice.Future.completed(Test.SmallStruct()) - def opMStruct2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMStruct2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def opMSeq1_async(self, cb, current): - cb.ice_response([]) + def opMSeq1(self, current): + return Ice.Future.completed([]) - def opMSeq2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMSeq2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def opMDict1_async(self, cb, current): - cb.ice_response({}) + def opMDict1(self, current): + return Ice.Future.completed({}) - def opMDict2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMDict2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def opMG1_async(self, cb, current): - cb.ice_response(Test.G()) + def opMG1(self, current): + return Ice.Future.completed(Test.G()) - def opMG2_async(self, cb, p1, current): - cb.ice_response(p1, p1) + def opMG2(self, p1, current): + return Ice.Future.completed((p1, p1)) - def supportsRequiredParams_async(self, cb, current=None): - cb.ice_response(False) + def supportsRequiredParams(self, current=None): + return Ice.Future.completed(False) - def supportsJavaSerializable_async(self, cb, current=None): - cb.ice_response(True) + def supportsJavaSerializable(self, current=None): + return Ice.Future.completed(True) - def supportsCsharpSerializable_async(self, cb, current=None): - cb.ice_response(False) + def supportsCsharpSerializable(self, current=None): + return Ice.Future.completed(False) - def supportsCppStringView_async(self, cb, current=None): - cb.ice_response(False) + def supportsCppStringView(self, current=None): + return Ice.Future.completed(False) - def supportsNullOptional_async(self, cb, current=None): - cb.ice_response(True) + def supportsNullOptional(self, current=None): + return Ice.Future.completed(True) def run(args, communicator): communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010:udp") diff --git a/python/test/Ice/proxy/ServerAMD.py b/python/test/Ice/proxy/ServerAMD.py index 35804df3068..218e8f7d596 100755 --- a/python/test/Ice/proxy/ServerAMD.py +++ b/python/test/Ice/proxy/ServerAMD.py @@ -23,15 +23,14 @@ class MyDerivedClassI(Test.MyDerivedClass): def __init__(self): self.ctx = None - def shutdown_async(self, cb, current=None): + def shutdown(self, current=None): current.adapter.getCommunicator().shutdown() - cb.ice_response() - def getContext_async(self, cb, current): - return cb.ice_response(self.ctx) + def getContext(self, current): + return Ice.Future.completed(self.ctx) - def echo_async(self, cb, obj, current): - return cb.ice_response(obj) + def echo(self, obj, current): + return Ice.Future.completed(obj) def ice_isA(self, s, current): self.ctx = current.ctx diff --git a/python/test/Ice/servantLocator/TestAMDI.py b/python/test/Ice/servantLocator/TestAMDI.py index 22d87341375..219ce7f3ebc 100644 --- a/python/test/Ice/servantLocator/TestAMDI.py +++ b/python/test/Ice/servantLocator/TestAMDI.py @@ -16,61 +16,74 @@ def test(b): class TestI(Test.TestIntf): - def requestFailedException_async(self, cb, current=None): - cb.ice_response() + def requestFailedException(self, current=None): + return None - def unknownUserException_async(self, cb, current=None): - cb.ice_response() + def unknownUserException(self, current=None): + return None - def unknownLocalException_async(self, cb, current=None): - cb.ice_response() + def unknownLocalException(self, current=None): + return None - def unknownException_async(self, cb, current=None): - cb.ice_response() + def unknownException(self, current=None): + return None - def localException_async(self, cb, current=None): - cb.ice_response() + def localException(self, current=None): + return None - def userException_async(self, cb, current=None): - cb.ice_response() + def userException(self, current=None): + return None - def pythonException_async(self, cb, current=None): - cb.ice_response() + def pythonException(self, current=None): + return None - def unknownExceptionWithServantException_async(self, cb, current=None): - cb.ice_exception(Ice.ObjectNotExistException()) + def unknownExceptionWithServantException(self, current=None): + f = Ice.Future() + f.set_exception(Ice.ObjectNotExistException()) + return f - def impossibleException_async(self, cb, throw, current=None): + def impossibleException(self, throw, current=None): + f = Ice.Future() if throw: - cb.ice_exception(Test.TestImpossibleException()) + f.set_exception(Test.TestImpossibleException()) else: # # Return a value so we can be sure that the stream position # is reset correctly if finished() throws. # - cb.ice_response("Hello") + f.set_result("Hello") + return f - def intfUserException_async(self, cb, throw, current=None): + def intfUserException(self, throw, current=None): + f = Ice.Future() if throw: - cb.ice_exception(Test.TestIntfUserException()) + f.set_exception(Test.TestIntfUserException()) else: # # Return a value so we can be sure that the stream position # is reset correctly if finished() throws. # - cb.ice_response("Hello") + f.set_result("Hello") + return f - def asyncResponse_async(self, cb, current=None): - cb.ice_response() + def asyncResponse(self, current=None): + # + # We can't do this with futures. + # + #return Ice.Future.completed(None) raise Ice.ObjectNotExistException() - def asyncException_async(self, cb, current=None): - cb.ice_exception(Test.TestIntfUserException()) + def asyncException(self, current=None): + # + # We can't do this with futures. + # + #f = Ice.Future() + #f.set_exception(Test.TestIntfUserException()) + #return f raise Ice.ObjectNotExistException() - def shutdown_async(self, cb, current=None): + def shutdown(self, current=None): current.adapter.deactivate() - cb.ice_response() class CookieI(Test.Cookie): def message(self): diff --git a/python/test/Ice/slicing/exceptions/AllTests.py b/python/test/Ice/slicing/exceptions/AllTests.py index b3fa67dd502..5419f08e33e 100644 --- a/python/test/Ice/slicing/exceptions/AllTests.py +++ b/python/test/Ice/slicing/exceptions/AllTests.py @@ -23,27 +23,21 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): - def response(self): - test(False) - - def exception_baseAsBase(self, exc): + def exception_baseAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.Base as b: test(b.b == "Base.b") test(b.ice_id() == "::Test::Base") @@ -51,9 +45,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_unknownDerivedAsBase(self, exc): + def exception_unknownDerivedAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.Base as b: test(b.b == "UnknownDerived.b") test(b.ice_id() == "::Test::Base") @@ -61,9 +56,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownDerivedAsBase(self, exc): + def exception_knownDerivedAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.KnownDerived as k: test(k.b == "KnownDerived.b") test(k.kd == "KnownDerived.kd") @@ -72,9 +68,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownDerivedAsKnownDerived(self, exc): + def exception_knownDerivedAsKnownDerived(self, f): try: - raise exc + f.result() + test(False) except Test.KnownDerived as k: test(k.b == "KnownDerived.b") test(k.kd == "KnownDerived.kd") @@ -83,9 +80,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_unknownIntermediateAsBase(self, exc): + def exception_unknownIntermediateAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.Base as b: test(b.b == "UnknownIntermediate.b") test(b.ice_id() == "::Test::Base") @@ -93,9 +91,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownIntermediateAsBase(self, exc): + def exception_knownIntermediateAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.KnownIntermediate as ki: test(ki.b == "KnownIntermediate.b") test(ki.ki == "KnownIntermediate.ki") @@ -104,9 +103,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownMostDerivedAsBase(self, exc): + def exception_knownMostDerivedAsBase(self, f): try: - raise exc + f.result() + test(False) except Test.KnownMostDerived as kmd: test(kmd.b == "KnownMostDerived.b") test(kmd.ki == "KnownMostDerived.ki") @@ -116,9 +116,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownIntermediateAsKnownIntermediate(self, exc): + def exception_knownIntermediateAsKnownIntermediate(self, f): try: - raise exc + f.result() + test(False) except Test.KnownIntermediate as ki: test(ki.b == "KnownIntermediate.b") test(ki.ki == "KnownIntermediate.ki") @@ -127,9 +128,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownMostDerivedAsKnownMostDerived(self, exc): + def exception_knownMostDerivedAsKnownMostDerived(self, f): try: - raise exc + f.result() + test(False) except Test.KnownMostDerived as kmd: test(kmd.b == "KnownMostDerived.b") test(kmd.ki == "KnownMostDerived.ki") @@ -139,9 +141,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_knownMostDerivedAsKnownIntermediate(self, exc): + def exception_knownMostDerivedAsKnownIntermediate(self, f): try: - raise exc + f.result() + test(False) except Test.KnownMostDerived as kmd: test(kmd.b == "KnownMostDerived.b") test(kmd.ki == "KnownMostDerived.ki") @@ -151,9 +154,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_unknownMostDerived1AsBase(self, exc): + def exception_unknownMostDerived1AsBase(self, f): try: - raise exc + f.result() + test(False) except Test.KnownIntermediate as ki: test(ki.b == "UnknownMostDerived1.b") test(ki.ki == "UnknownMostDerived1.ki") @@ -162,9 +166,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_unknownMostDerived1AsKnownIntermediate(self, exc): + def exception_unknownMostDerived1AsKnownIntermediate(self, f): try: - raise exc + f.result() + test(False) except Test.KnownIntermediate as ki: test(ki.b == "UnknownMostDerived1.b") test(ki.ki == "UnknownMostDerived1.ki") @@ -173,9 +178,10 @@ class Callback(CallbackBase): test(False) self.called() - def exception_unknownMostDerived2AsBase(self, exc): + def exception_unknownMostDerived2AsBase(self, f): try: - raise exc + f.result() + test(False) except Test.Base as b: test(b.b == "UnknownMostDerived2.b") test(b.ice_id() == "::Test::Base") @@ -235,7 +241,7 @@ def allTests(communicator): sys.stdout.write("base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_baseAsBase(cb.response, cb.exception_baseAsBase) + t.baseAsBaseAsync().add_done_callback(cb.exception_baseAsBase) cb.check() print("ok") @@ -254,7 +260,7 @@ def allTests(communicator): sys.stdout.write("slicing of unknown derived (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_unknownDerivedAsBase(cb.response, cb.exception_unknownDerivedAsBase) + t.unknownDerivedAsBaseAsync().add_done_callback(cb.exception_unknownDerivedAsBase) cb.check() print("ok") @@ -274,7 +280,7 @@ def allTests(communicator): sys.stdout.write("non-slicing of known derived as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownDerivedAsBase(cb.response, cb.exception_knownDerivedAsBase) + t.knownDerivedAsBaseAsync().add_done_callback(cb.exception_knownDerivedAsBase) cb.check() print("ok") @@ -294,7 +300,7 @@ def allTests(communicator): sys.stdout.write("non-slicing of known derived as derived (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownDerivedAsKnownDerived(cb.response, cb.exception_knownDerivedAsKnownDerived) + t.knownDerivedAsKnownDerivedAsync().add_done_callback(cb.exception_knownDerivedAsKnownDerived) cb.check() print("ok") @@ -313,7 +319,7 @@ def allTests(communicator): sys.stdout.write("slicing of unknown intermediate as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_unknownIntermediateAsBase(cb.response, cb.exception_unknownIntermediateAsBase) + t.unknownIntermediateAsBaseAsync().add_done_callback(cb.exception_unknownIntermediateAsBase) cb.check() print("ok") @@ -333,7 +339,7 @@ def allTests(communicator): sys.stdout.write("slicing of known intermediate as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownIntermediateAsBase(cb.response, cb.exception_knownIntermediateAsBase) + t.knownIntermediateAsBaseAsync().add_done_callback(cb.exception_knownIntermediateAsBase) cb.check() print("ok") @@ -354,7 +360,7 @@ def allTests(communicator): sys.stdout.write("slicing of known most derived as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownMostDerivedAsBase(cb.response, cb.exception_knownMostDerivedAsBase) + t.knownMostDerivedAsBaseAsync().add_done_callback(cb.exception_knownMostDerivedAsBase) cb.check() print("ok") @@ -374,7 +380,7 @@ def allTests(communicator): sys.stdout.write("non-slicing of known intermediate as intermediate (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownIntermediateAsKnownIntermediate(cb.response, cb.exception_knownIntermediateAsKnownIntermediate) + t.knownIntermediateAsKnownIntermediateAsync().add_done_callback(cb.exception_knownIntermediateAsKnownIntermediate) cb.check() print("ok") @@ -395,7 +401,7 @@ def allTests(communicator): sys.stdout.write("non-slicing of known most derived as intermediate (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownMostDerivedAsKnownIntermediate(cb.response, cb.exception_knownMostDerivedAsKnownIntermediate) + t.knownMostDerivedAsKnownIntermediateAsync().add_done_callback(cb.exception_knownMostDerivedAsKnownIntermediate) cb.check() print("ok") @@ -416,7 +422,7 @@ def allTests(communicator): sys.stdout.write("non-slicing of known most derived as most derived (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_knownMostDerivedAsKnownMostDerived(cb.response, cb.exception_knownMostDerivedAsKnownMostDerived) + t.knownMostDerivedAsKnownMostDerivedAsync().add_done_callback(cb.exception_knownMostDerivedAsKnownMostDerived) cb.check() print("ok") @@ -436,7 +442,7 @@ def allTests(communicator): sys.stdout.write("slicing of unknown most derived, known intermediate as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_unknownMostDerived1AsBase(cb.response, cb.exception_unknownMostDerived1AsBase) + t.unknownMostDerived1AsBaseAsync().add_done_callback(cb.exception_unknownMostDerived1AsBase) cb.check() print("ok") @@ -456,7 +462,8 @@ def allTests(communicator): sys.stdout.write("slicing of unknown most derived, known intermediate as intermediate (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_unknownMostDerived1AsKnownIntermediate(cb.response, cb.exception_unknownMostDerived1AsKnownIntermediate) + t.unknownMostDerived1AsKnownIntermediateAsync().add_done_callback( + cb.exception_unknownMostDerived1AsKnownIntermediate) cb.check() print("ok") @@ -475,7 +482,7 @@ def allTests(communicator): sys.stdout.write("slicing of unknown most derived, unknown intermediate as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_unknownMostDerived2AsBase(cb.response, cb.exception_unknownMostDerived2AsBase) + t.unknownMostDerived2AsBaseAsync().add_done_callback(cb.exception_unknownMostDerived2AsBase) cb.check() print("ok") diff --git a/python/test/Ice/slicing/exceptions/ServerAMD.py b/python/test/Ice/slicing/exceptions/ServerAMD.py index 9b3004e1d6e..5dd7386d670 100755 --- a/python/test/Ice/slicing/exceptions/ServerAMD.py +++ b/python/test/Ice/slicing/exceptions/ServerAMD.py @@ -15,159 +15,202 @@ Ice.loadSlice('-I. --all ServerPrivateAMD.ice') import Test class TestI(Test.TestIntf): - def shutdown_async(self, cb, current=None): + def shutdown(self, current=None): current.adapter.getCommunicator().shutdown() - cb.ice_response() - def baseAsBase_async(self, cb, current=None): + def baseAsBase(self, current=None): b = Test.Base() b.b = "Base.b" - cb.ice_exception(b) + f = Ice.Future() + f.set_exception(b) + return f - def unknownDerivedAsBase_async(self, cb, current=None): + def unknownDerivedAsBase(self, current=None): d = Test.UnknownDerived() d.b = "UnknownDerived.b" d.ud = "UnknownDerived.ud" - cb.ice_exception(d) + f = Ice.Future() + f.set_exception(d) + return f - def knownDerivedAsBase_async(self, cb, current=None): + def knownDerivedAsBase(self, current=None): d = Test.KnownDerived() d.b = "KnownDerived.b" d.kd = "KnownDerived.kd" - cb.ice_exception(d) + f = Ice.Future() + f.set_exception(d) + return f - def knownDerivedAsKnownDerived_async(self, cb, current=None): + def knownDerivedAsKnownDerived(self, current=None): d = Test.KnownDerived() d.b = "KnownDerived.b" d.kd = "KnownDerived.kd" - cb.ice_exception(d) + f = Ice.Future() + f.set_exception(d) + return f - def unknownIntermediateAsBase_async(self, cb, current=None): + def unknownIntermediateAsBase(self, current=None): ui = Test.UnknownIntermediate() ui.b = "UnknownIntermediate.b" ui.ui = "UnknownIntermediate.ui" - cb.ice_exception(ui) + f = Ice.Future() + f.set_exception(ui) + return f - def knownIntermediateAsBase_async(self, cb, current=None): + def knownIntermediateAsBase(self, current=None): ki = Test.KnownIntermediate() ki.b = "KnownIntermediate.b" ki.ki = "KnownIntermediate.ki" - cb.ice_exception(ki) + f = Ice.Future() + f.set_exception(ki) + return f - def knownMostDerivedAsBase_async(self, cb, current=None): + def knownMostDerivedAsBase(self, current=None): kmd = Test.KnownMostDerived() kmd.b = "KnownMostDerived.b" kmd.ki = "KnownMostDerived.ki" kmd.kmd = "KnownMostDerived.kmd" - cb.ice_exception(kmd) + f = Ice.Future() + f.set_exception(kmd) + return f - def knownIntermediateAsKnownIntermediate_async(self, cb, current=None): + def knownIntermediateAsKnownIntermediate(self, current=None): ki = Test.KnownIntermediate() ki.b = "KnownIntermediate.b" ki.ki = "KnownIntermediate.ki" - cb.ice_exception(ki) + f = Ice.Future() + f.set_exception(ki) + return f - def knownMostDerivedAsKnownIntermediate_async(self, cb, current=None): + def knownMostDerivedAsKnownIntermediate(self, current=None): kmd = Test.KnownMostDerived() kmd.b = "KnownMostDerived.b" kmd.ki = "KnownMostDerived.ki" kmd.kmd = "KnownMostDerived.kmd" - cb.ice_exception(kmd) + f = Ice.Future() + f.set_exception(kmd) + return f - def knownMostDerivedAsKnownMostDerived_async(self, cb, current=None): + def knownMostDerivedAsKnownMostDerived(self, current=None): kmd = Test.KnownMostDerived() kmd.b = "KnownMostDerived.b" kmd.ki = "KnownMostDerived.ki" kmd.kmd = "KnownMostDerived.kmd" - cb.ice_exception(kmd) + f = Ice.Future() + f.set_exception(kmd) + return f - def unknownMostDerived1AsBase_async(self, cb, current=None): + def unknownMostDerived1AsBase(self, current=None): umd1 = Test.UnknownMostDerived1() umd1.b = "UnknownMostDerived1.b" umd1.ki = "UnknownMostDerived1.ki" umd1.umd1 = "UnknownMostDerived1.umd1" - cb.ice_exception(umd1) + f = Ice.Future() + f.set_exception(umd1) + return f - def unknownMostDerived1AsKnownIntermediate_async(self, cb, current=None): + def unknownMostDerived1AsKnownIntermediate(self, current=None): umd1 = Test.UnknownMostDerived1() umd1.b = "UnknownMostDerived1.b" umd1.ki = "UnknownMostDerived1.ki" umd1.umd1 = "UnknownMostDerived1.umd1" - cb.ice_exception(umd1) + f = Ice.Future() + f.set_exception(umd1) + return f - def unknownMostDerived2AsBase_async(self, cb, current=None): + def unknownMostDerived2AsBase(self, current=None): umd2 = Test.UnknownMostDerived2() umd2.b = "UnknownMostDerived2.b" umd2.ui = "UnknownMostDerived2.ui" umd2.umd2 = "UnknownMostDerived2.umd2" - cb.ice_exception(umd2) + f = Ice.Future() + f.set_exception(umd2) + return f - def unknownMostDerived2AsBaseCompact_async(self, cb, current=None): + def unknownMostDerived2AsBaseCompact(self, current=None): umd2 = Test.UnknownMostDerived2() umd2.b = "UnknownMostDerived2.b" umd2.ui = "UnknownMostDerived2.ui" umd2.umd2 = "UnknownMostDerived2.umd2" - cb.ice_exception(umd2) + f = Ice.Future() + f.set_exception(umd2) + return f - def knownPreservedAsBase_async(self, cb, r, current=None): + def knownPreservedAsBase(self, r, current=None): ex = Test.KnownPreservedDerived() ex.b = "base" ex.kp = "preserved" ex.kpd = "derived" - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def knownPreservedAsKnownPreserved_async(self, cb, r, current=None): + def knownPreservedAsKnownPreserved(self, r, current=None): ex = Test.KnownPreservedDerived() ex.b = "base" ex.kp = "preserved" ex.kpd = "derived" - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def relayKnownPreservedAsBase_async(self, cb, r, current=None): + def relayKnownPreservedAsBase(self, r, current=None): + f = Ice.Future() try: r.knownPreservedAsBase() test(False) except Ice.Exception as ex: - cb.ice_exception(ex) + f.set_exception(ex) + return f - def relayKnownPreservedAsKnownPreserved_async(self, cb, r, current=None): + def relayKnownPreservedAsKnownPreserved(self, r, current=None): + f = Ice.Future() try: r.knownPreservedAsKnownPreserved() test(False) except Ice.Exception as ex: - cb.ice_exception(ex) + f.set_exception(ex) + return f - def unknownPreservedAsBase_async(self, cb, r, current=None): + def unknownPreservedAsBase(self, r, current=None): ex = Test.SPreserved2() ex.b = "base" ex.kp = "preserved" ex.kpd = "derived" ex.p1 = Test.SPreservedClass("bc", "spc") ex.p2 = ex.p1 - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def unknownPreservedAsKnownPreserved_async(self, cb, r, current=None): + def unknownPreservedAsKnownPreserved(self, r, current=None): ex = Test.SPreserved2() ex.b = "base" ex.kp = "preserved" ex.kpd = "derived" ex.p1 = Test.SPreservedClass("bc", "spc") ex.p2 = ex.p1 - cb.ice_exception(ex) + f = Ice.Future() + f.set_exception(ex) + return f - def relayUnknownPreservedAsBase_async(self, cb, r, current=None): + def relayUnknownPreservedAsBase(self, r, current=None): + f = Ice.Future() try: r.unknownPreservedAsBase() test(False) except Ice.Exception as ex: - cb.ice_exception(ex) + f.set_exception(ex) + return f - def relayUnknownPreservedAsKnownPreserved_async(self, cb, r, current=None): + def relayUnknownPreservedAsKnownPreserved(self, r, current=None): + f = Ice.Future() try: r.unknownPreservedAsKnownPreserved() test(False) except Ice.Exception as ex: - cb.ice_exception(ex) + f.set_exception(ex) + return f def run(args, communicator): properties = communicator.getProperties() diff --git a/python/test/Ice/slicing/objects/AllTests.py b/python/test/Ice/slicing/objects/AllTests.py index 44cd9af1665..cc3a321d5fd 100644 --- a/python/test/Ice/slicing/objects/AllTests.py +++ b/python/test/Ice/slicing/objects/AllTests.py @@ -23,22 +23,19 @@ class CallbackBase: self._cond = threading.Condition() def check(self): - self._cond.acquire() - try: + with self._cond: while not self._called: self._cond.wait() self._called = False - finally: - self._cond.release() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() class Callback(CallbackBase): - def response_SBaseAsObject(self, o): + def response_SBaseAsObject(self, f): + o = f.result() test(o) test(o.ice_id() == "::Test::SBase") sb = o @@ -46,54 +43,53 @@ class Callback(CallbackBase): test(sb.sb == "SBase.sb") self.called() - def response_SBaseAsSBase(self, sb): + def response_SBaseAsSBase(self, f): + sb = f.result() test(sb.sb == "SBase.sb") self.called() - def response_SBSKnownDerivedAsSBase(self, sb): - sbskd = sb + def response_SBSKnownDerivedAsSBase(self, f): + sbskd = f.result() test(isinstance(sbskd, Test.SBSKnownDerived)) test(sbskd.sbskd == "SBSKnownDerived.sbskd") self.called() - def response_SBSKnownDerivedAsSBSKnownDerived(self, sbskd): + def response_SBSKnownDerivedAsSBSKnownDerived(self, f): + sbskd = f.result() test(sbskd.sbskd == "SBSKnownDerived.sbskd") self.called() - def response_SBSUnknownDerivedAsSBase(self, sb): + def response_SBSUnknownDerivedAsSBase(self, f): + sb = f.result() test(sb.sb == "SBSUnknownDerived.sb") self.called() - def response_SBSUnknownDerivedAsSBaseCompact(self, sb): - test(False) - - def exception_SBSUnknownDerivedAsSBaseCompact(self, ex): - test(isinstance(ex, Ice.NoValueFactoryException)) + def exception_SBSUnknownDerivedAsSBaseCompact(self, f): + test(f.exception() is not None) + test(isinstance(f.exception(), Ice.NoValueFactoryException)) self.called() - def response_SUnknownAsObject10(self, o): - test(False) - - def exception_SUnknownAsObject10(self, exc): - test(exc.ice_id() == "::Ice::NoValueFactoryException") + def exception_SUnknownAsObject10(self, f): + test(f.exception() is not None) + test(f.exception().ice_id() == "::Ice::NoValueFactoryException") self.called() - def response_SUnknownAsObject11(self, o): + def response_SUnknownAsObject11(self, f): + o = f.result() test(isinstance(o, Ice.UnknownSlicedObject)) test(o.unknownTypeId == "::Test::SUnknown") self.called() - def exception_SUnknownAsObject11(self, exc): - test(False) - - def response_oneElementCycle(self, b): + def response_oneElementCycle(self, f): + b = f.result() test(b) test(b.ice_id() == "::Test::B") test(b.sb == "B1.sb") test(b.pb == b) self.called() - def response_twoElementCycle(self, b1): + def response_twoElementCycle(self, f): + b1 = f.result() test(b1) test(b1.ice_id() == "::Test::B") test(b1.sb == "B1.sb") @@ -105,7 +101,8 @@ class Callback(CallbackBase): test(b2.pb == b1) self.called() - def response_D1AsB(self, b1): + def response_D1AsB(self, f): + b1 = f.result() test(b1) test(b1.ice_id() == "::Test::D1") test(b1.sb == "D1.sb") @@ -125,7 +122,8 @@ class Callback(CallbackBase): test(b2.ice_id() == "::Test::B") self.called() - def response_D1AsD1(self, d1): + def response_D1AsD1(self, f): + d1 = f.result() test(d1) test(d1.ice_id() == "::Test::D1") test(d1.sb == "D1.sb") @@ -139,7 +137,8 @@ class Callback(CallbackBase): test(b2.pb == d1) self.called() - def response_D2AsB(self, b2): + def response_D2AsB(self, f): + b2 = f.result() test(b2) test(b2.ice_id() == "::Test::B") test(b2.sb == "D2.sb") @@ -157,7 +156,8 @@ class Callback(CallbackBase): test(d1.pd1 == b2) self.called() - def response_paramTest1(self, b1, b2): + def response_paramTest1(self, f): + (b1, b2) = f.result() test(b1) test(b1.ice_id() == "::Test::D1") test(b1.sb == "D1.sb") @@ -173,19 +173,23 @@ class Callback(CallbackBase): test(b2.pb == b1) self.called() - def response_returnTest1(self, r, p1, p2): + def response_returnTest1(self, f): + (r, p1, p2) = f.result() test(r == p1) self.called() - def response_returnTest2(self, r, p1, p2): + def response_returnTest2(self, f): + (r, p1, p2) = f.result() test(r == p1) self.called() - def response_returnTest3(self, b): + def response_returnTest3(self, f): + b = f.result() self.r = b self.called() - def response_paramTest3(self, ret, p1, p2): + def response_paramTest3(self, f): + (ret, p1, p2) = f.result() test(p1) test(p1.sb == "D2.sb (p1 1)") test(p1.pb == None) @@ -202,7 +206,8 @@ class Callback(CallbackBase): test(ret.ice_id() == "::Test::D1") self.called() - def response_paramTest4(self, ret, b): + def response_paramTest4(self, f): + (ret, b) = f.result() test(b) test(b.sb == "D4.sb (1)") test(b.pb == None) @@ -214,16 +219,20 @@ class Callback(CallbackBase): test(ret.ice_id() == "::Test::B") self.called() - def response_sequenceTest(self, ss): + def response_sequenceTest(self, f): + ss = f.result() self.r = ss self.called() - def response_dictionaryTest(self, r, bout): + def response_dictionaryTest(self, f): + (r, bout) = f.result() self.r = r self.bout = bout self.called() - def exception_throwBaseAsBase(self, ex): + def exception_throwBaseAsBase(self, f): + ex = f.exception() + test(ex is not None) test(ex.ice_id() == "::Test::BaseException") e = ex test(isinstance(e, Test.BaseException)) @@ -233,7 +242,9 @@ class Callback(CallbackBase): test(e.pb.pb == e.pb) self.called() - def exception_throwDerivedAsBase(self, ex): + def exception_throwDerivedAsBase(self, f): + ex = f.exception() + test(ex is not None) test(ex.ice_id() == "::Test::DerivedException") e = ex test(isinstance(e, Test.DerivedException)) @@ -249,7 +260,9 @@ class Callback(CallbackBase): test(e.pd1.pd1 == e.pd1) self.called() - def exception_throwDerivedAsDerived(self, ex): + def exception_throwDerivedAsDerived(self, f): + ex = f.exception() + test(ex is not None) test(ex.ice_id() == "::Test::DerivedException") e = ex test(isinstance(e, Test.DerivedException)) @@ -265,7 +278,9 @@ class Callback(CallbackBase): test(e.pd1.pd1 == e.pd1) self.called() - def exception_throwUnknownDerivedAsBase(self, ex): + def exception_throwUnknownDerivedAsBase(self, f): + ex = f.exception() + test(ex is not None) test(ex.ice_id() == "::Test::BaseException") e = ex test(isinstance(e, Test.BaseException)) @@ -276,10 +291,12 @@ class Callback(CallbackBase): self.called() def response_useForward(self, f): - test(f) + fwd = f.result() + test(fwd) self.called() - def response_preserved1(self, r): + def response_preserved1(self, f): + r = f.result() test(r) test(isinstance(r, Test.PDerived)) test(r.pi == 3) @@ -287,30 +304,34 @@ class Callback(CallbackBase): test(r.pb == r) self.called() - def response_preserved2(self, r): + def response_preserved2(self, f): + r = f.result() test(r) test(not isinstance(r, Test.PCUnknown)) test(r.pi == 3) self.called() - def response_preserved3(self, r): + def response_preserved3(self, f): # # Encoding 1.0 # + r = f.result() test(not isinstance(r, Test.PCDerived)) test(r.pi == 3) self.called() - def response_preserved4(self, r): + def response_preserved4(self, f): # # Encoding > 1.0 # + r = f.result() test(isinstance(r, Test.PCDerived)) test(r.pi == 3) test(r.pbs[0] == r) self.called() - def response_preserved5(self, r): + def response_preserved5(self, f): + r = f.result() test(isinstance(r, Test.PCDerived3)) test(r.pi == 3) for i in range(0, 300): @@ -324,32 +345,25 @@ class Callback(CallbackBase): test(r.pcd3 == r.pbs[10]) self.called() - def response_compactPreserved1(self, r): + def response_compactPreserved1(self, f): # # Encoding 1.0 # + r = f.result() test(not isinstance(r, Test.CompactPCDerived)) test(r.pi == 3) self.called() - def response_compactPreserved2(self, r): + def response_compactPreserved2(self, f): # # Encoding > 1.0 # + r = f.result() test(isinstance(r, Test.CompactPCDerived)) test(r.pi == 3) test(r.pbs[0] == r) self.called() - def response(self): - test(False) - - def exception(self, exc): - if(isinstance(exc, Ice.OperationNotExistException)): - self.called() - return - test(False) - class PNodeI(Test.PNode): counter = 0 @@ -400,7 +414,7 @@ def allTests(communicator): sys.stdout.write("base as Object (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_SBaseAsObject(cb.response_SBaseAsObject, cb.exception) + t.SBaseAsObjectAsync().add_done_callback(cb.response_SBaseAsObject) cb.check() print("ok") @@ -416,7 +430,7 @@ def allTests(communicator): sys.stdout.write("base as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_SBaseAsSBase(cb.response_SBaseAsSBase, cb.exception) + t.SBaseAsSBaseAsync().add_done_callback(cb.response_SBaseAsSBase) cb.check() print("ok") @@ -436,7 +450,7 @@ def allTests(communicator): sys.stdout.write("base with known derived as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_SBSKnownDerivedAsSBase(cb.response_SBSKnownDerivedAsSBase, cb.exception) + t.SBSKnownDerivedAsSBaseAsync().add_done_callback(cb.response_SBSKnownDerivedAsSBase) cb.check() print("ok") @@ -452,7 +466,7 @@ def allTests(communicator): sys.stdout.write("base with known derived as known derived (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_SBSKnownDerivedAsSBSKnownDerived(cb.response_SBSKnownDerivedAsSBSKnownDerived, cb.exception) + t.SBSKnownDerivedAsSBSKnownDerivedAsync().add_done_callback(cb.response_SBSKnownDerivedAsSBSKnownDerived) cb.check() print("ok") @@ -494,14 +508,14 @@ def allTests(communicator): sys.stdout.write("base with unknown derived as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_SBSUnknownDerivedAsSBase(cb.response_SBSUnknownDerivedAsSBase, cb.exception) + t.SBSUnknownDerivedAsSBaseAsync().add_done_callback(cb.response_SBSUnknownDerivedAsSBase) cb.check() if t.ice_getEncodingVersion() == Ice.Encoding_1_0: # # This test succeeds for the 1.0 encoding. # cb = Callback() - t.begin_SBSUnknownDerivedAsSBaseCompact(cb.response_SBSUnknownDerivedAsSBase, cb.exception) + t.SBSUnknownDerivedAsSBaseCompactAsync().add_done_callback(cb.response_SBSUnknownDerivedAsSBase) cb.check() else: # @@ -509,8 +523,7 @@ def allTests(communicator): # be sliced to a known type. # cb = Callback() - t.begin_SBSUnknownDerivedAsSBaseCompact(cb.response_SBSUnknownDerivedAsSBaseCompact, - cb.exception_SBSUnknownDerivedAsSBaseCompact) + t.SBSUnknownDerivedAsSBaseCompactAsync().add_done_callback(cb.exception_SBSUnknownDerivedAsSBaseCompact) cb.check() print("ok") @@ -533,9 +546,9 @@ def allTests(communicator): try: cb = Callback() if t.ice_getEncodingVersion() == Ice.Encoding_1_0: - t.begin_SUnknownAsObject(cb.response_SUnknownAsObject10, cb.exception_SUnknownAsObject10) + t.SUnknownAsObjectAsync().add_done_callback(cb.exception_SUnknownAsObject10) else: - t.begin_SUnknownAsObject(cb.response_SUnknownAsObject11, cb.exception_SUnknownAsObject11) + t.SUnknownAsObjectAsync().add_done_callback(cb.response_SUnknownAsObject11) cb.check() except Ice.Exception: test(False) @@ -556,7 +569,7 @@ def allTests(communicator): sys.stdout.write("one-element cycle (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_oneElementCycle(cb.response_oneElementCycle, cb.exception) + t.oneElementCycleAsync().add_done_callback(cb.response_oneElementCycle) cb.check() print("ok") @@ -580,7 +593,7 @@ def allTests(communicator): sys.stdout.write("two-element cycle (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_twoElementCycle(cb.response_twoElementCycle, cb.exception) + t.twoElementCycleAsync().add_done_callback(cb.response_twoElementCycle) cb.check() print("ok") @@ -612,7 +625,7 @@ def allTests(communicator): sys.stdout.write("known derived pointer slicing as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_D1AsB(cb.response_D1AsB, cb.exception) + t.D1AsBAsync().add_done_callback(cb.response_D1AsB) cb.check() print("ok") @@ -638,7 +651,7 @@ def allTests(communicator): sys.stdout.write("known derived pointer slicing as derived (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_D1AsD1(cb.response_D1AsD1, cb.exception) + t.D1AsD1Async().add_done_callback(cb.response_D1AsD1) cb.check() print("ok") @@ -668,7 +681,7 @@ def allTests(communicator): sys.stdout.write("unknown derived pointer slicing as base (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_D2AsB(cb.response_D2AsB, cb.exception) + t.D2AsBAsync().add_done_callback(cb.response_D2AsB) cb.check() print("ok") @@ -697,7 +710,7 @@ def allTests(communicator): sys.stdout.write("param ptr slicing with known first (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_paramTest1(cb.response_paramTest1, cb.exception) + t.paramTest1Async().add_done_callback(cb.response_paramTest1) cb.check() print("ok") @@ -735,7 +748,7 @@ def allTests(communicator): sys.stdout.write("return value identity with known first (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_returnTest1(cb.response_returnTest1, cb.exception) + t.returnTest1Async().add_done_callback(cb.response_returnTest1) cb.check() print("ok") @@ -751,7 +764,7 @@ def allTests(communicator): sys.stdout.write("return value identity with unknown first (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_returnTest2(cb.response_returnTest2, cb.exception) + t.returnTest2Async().add_done_callback(cb.response_returnTest2) cb.check() print("ok") @@ -810,7 +823,7 @@ def allTests(communicator): d1.pd1 = d3 cb = Callback() - t.begin_returnTest3(d1, d3, cb.response_returnTest3, cb.exception) + t.returnTest3Async(d1, d3).add_done_callback(cb.response_returnTest3) cb.check() b1 = cb.r @@ -893,7 +906,7 @@ def allTests(communicator): d1.pd1 = d3 cb = Callback() - t.begin_returnTest3(d3, d1, cb.response_returnTest3, cb.exception) + t.returnTest3Async(d3, d1).add_done_callback(cb.response_returnTest3) cb.check() b1 = cb.r @@ -947,7 +960,7 @@ def allTests(communicator): sys.stdout.write("remainder unmarshaling (3 instances) (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_paramTest3(cb.response_paramTest3, cb.exception) + t.paramTest3Async().add_done_callback(cb.response_paramTest3) cb.check() print("ok") @@ -972,7 +985,7 @@ def allTests(communicator): sys.stdout.write("remainder unmarshaling (4 instances) (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_paramTest4(cb.response_paramTest4, cb.exception) + t.paramTest4Async().add_done_callback(cb.response_paramTest4) cb.check() print("ok") @@ -1021,7 +1034,7 @@ def allTests(communicator): b2.pb = b1 cb = Callback() - t.begin_returnTest3(d3, b2, cb.response_returnTest3, cb.exception) + t.returnTest3Async(d3, b2).add_done_callback(cb.response_returnTest3) cb.check() r = cb.r @@ -1085,7 +1098,7 @@ def allTests(communicator): d12.pd1 = d11 cb = Callback() - t.begin_returnTest3(d3, d12, cb.response_returnTest3, cb.exception) + t.returnTest3Async(d3, d12).add_done_callback(cb.response_returnTest3) cb.check() r = cb.r @@ -1218,7 +1231,7 @@ def allTests(communicator): ss2.s = (ss2b, ss2d1, ss2d3) cb = Callback() - t.begin_sequenceTest(ss1, ss2, cb.response_sequenceTest, cb.exception) + t.sequenceTestAsync(ss1, ss2).add_done_callback(cb.response_sequenceTest) cb.check() ss = cb.r @@ -1310,7 +1323,7 @@ def allTests(communicator): bin[i] = d1 cb = Callback() - t.begin_dictionaryTest(bin, cb.response_dictionaryTest, cb.exception) + t.dictionaryTestAsync(bin).add_done_callback(cb.response_dictionaryTest) cb.check() bout = cb.bout r = cb.r @@ -1362,7 +1375,7 @@ def allTests(communicator): sys.stdout.write("base exception thrown as base exception (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_throwBaseAsBase(cb.response, cb.exception_throwBaseAsBase) + t.throwBaseAsBaseAsync().add_done_callback(cb.exception_throwBaseAsBase) cb.check() print("ok") @@ -1390,7 +1403,7 @@ def allTests(communicator): sys.stdout.write("derived exception thrown as base exception (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_throwDerivedAsBase(cb.response, cb.exception_throwDerivedAsBase) + t.throwDerivedAsBaseAsync().add_done_callback(cb.exception_throwDerivedAsBase) cb.check() print("ok") @@ -1418,7 +1431,7 @@ def allTests(communicator): sys.stdout.write("derived exception thrown as derived exception (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_throwDerivedAsDerived(cb.response, cb.exception_throwDerivedAsDerived) + t.throwDerivedAsDerivedAsync().add_done_callback(cb.exception_throwDerivedAsDerived) cb.check() print("ok") @@ -1440,7 +1453,7 @@ def allTests(communicator): sys.stdout.write("unknown derived exception thrown as base exception (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_throwUnknownDerivedAsBase(cb.response, cb.exception_throwUnknownDerivedAsBase) + t.throwUnknownDerivedAsBaseAsync().add_done_callback(cb.exception_throwUnknownDerivedAsBase) cb.check() print("ok") @@ -1456,7 +1469,7 @@ def allTests(communicator): sys.stdout.write("forward-declared class (AMI)... ") sys.stdout.flush() cb = Callback() - t.begin_useForward(cb.response_useForward, cb.exception) + t.useForwardAsync().add_done_callback(cb.response_useForward) cb.check() print("ok") @@ -1586,7 +1599,7 @@ def allTests(communicator): pd.pb = pd cb = Callback() - t.begin_exchangePBase(pd, cb.response_preserved1, cb.exception) + t.exchangePBaseAsync(pd).add_done_callback(cb.response_preserved1) cb.check() # @@ -1597,7 +1610,7 @@ def allTests(communicator): pu.pu = "preserved" cb = Callback() - t.begin_exchangePBase(pu, cb.response_preserved2, cb.exception) + t.exchangePBaseAsync(pu).add_done_callback(cb.response_preserved2) cb.check() # @@ -1610,9 +1623,9 @@ def allTests(communicator): cb = Callback() if t.ice_getEncodingVersion() == Ice.Encoding_1_0: - t.begin_exchangePBase(pcd, cb.response_preserved3, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_preserved3) else: - t.begin_exchangePBase(pcd, cb.response_preserved4, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_preserved4) cb.check() # @@ -1625,9 +1638,9 @@ def allTests(communicator): cb = Callback() if t.ice_getEncodingVersion() == Ice.Encoding_1_0: - t.begin_exchangePBase(pcd, cb.response_compactPreserved1, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_compactPreserved1) else: - t.begin_exchangePBase(pcd, cb.response_compactPreserved2, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_compactPreserved2) cb.check() # @@ -1651,9 +1664,9 @@ def allTests(communicator): cb = Callback() if t.ice_getEncodingVersion() == Ice.Encoding_1_0: - t.begin_exchangePBase(pcd, cb.response_preserved3, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_preserved3) else: - t.begin_exchangePBase(pcd, cb.response_preserved5, cb.exception) + t.exchangePBaseAsync(pcd).add_done_callback(cb.response_preserved5) cb.check() print("ok") diff --git a/python/test/Ice/slicing/objects/Server.py b/python/test/Ice/slicing/objects/Server.py index e785fe0f8ab..53b522a6462 100755 --- a/python/test/Ice/slicing/objects/Server.py +++ b/python/test/Ice/slicing/objects/Server.py @@ -244,7 +244,7 @@ class TestI(Test.TestIntf): test(p.psu == "unknown") test(not p.graph) - def PBSUnknownAsPreservedWithGraph_async(self, cb, current=None): + def PBSUnknownAsPreservedWithGraph(self, current=None): r = Test.PSUnknown() r.pi = 5 r.ps = "preserved" @@ -253,8 +253,8 @@ class TestI(Test.TestIntf): r.graph.next = Test.PNode() r.graph.next.next = Test.PNode() r.graph.next.next.next = r.graph - cb.ice_response(r) - r.graph.next.next.next = None # Break the cycle. + return Ice.Future.completed(r) + #r.graph.next.next.next = None # Break the cycle. def checkPBSUnknownWithGraph(self, p, current=None): if current.encoding == Ice.Encoding_1_0: @@ -271,13 +271,13 @@ class TestI(Test.TestIntf): test(p.graph.next.next.next == p.graph) p.graph.next.next.next = None # Break the cycle. - def PBSUnknown2AsPreservedWithGraph_async(self, cb, current=None): + def PBSUnknown2AsPreservedWithGraph(self, current=None): r = Test.PSUnknown2() r.pi = 5 r.ps = "preserved" r.pb = r - cb.ice_response(r) - r.pb = None # Break the cycle. + return Ice.Future.completed(r) + #r.pb = None # Break the cycle. def checkPBSUnknown2WithGraph(self, p, current=None): if current.encoding == Ice.Encoding_1_0: @@ -344,14 +344,16 @@ class TestI(Test.TestIntf): ude.pd2 = d2 raise ude - def throwPreservedException_async(self, cb, current=None): + def throwPreservedException(self, current=None): ue = Test.PSUnknownException() ue.p = Test.PSUnknown2() ue.p.pi = 5 ue.p.ps = "preserved" ue.p.pb = ue.p - cb.ice_exception(ue) - ue.p.pb = None # Break the cycle. + f = Ice.Future() + f.set_exception(ue) + return f + #ue.p.pb = None # Break the cycle. def useForward(self, current=None): f = Test.Forward() diff --git a/python/test/Ice/slicing/objects/ServerAMD.py b/python/test/Ice/slicing/objects/ServerAMD.py index d42a174b213..fc5f63ca732 100755 --- a/python/test/Ice/slicing/objects/ServerAMD.py +++ b/python/test/Ice/slicing/objects/ServerAMD.py @@ -19,69 +19,69 @@ def test(b): raise RuntimeError('test assertion failed') class TestI(Test.TestIntf): - def SBaseAsObject_async(self, cb, current=None): + def SBaseAsObject(self, current=None): sb = Test.SBase() sb.sb = "SBase.sb" - cb.ice_response(sb) + return Ice.Future.completed(sb) - def SBaseAsSBase_async(self, cb, current=None): + def SBaseAsSBase(self, current=None): sb = Test.SBase() sb.sb = "SBase.sb" - cb.ice_response(sb) + return Ice.Future.completed(sb) - def SBSKnownDerivedAsSBase_async(self, cb, current=None): + def SBSKnownDerivedAsSBase(self, current=None): sbskd = Test.SBSKnownDerived() sbskd.sb = "SBSKnownDerived.sb" sbskd.sbskd = "SBSKnownDerived.sbskd" - cb.ice_response(sbskd) + return Ice.Future.completed(sbskd) - def SBSKnownDerivedAsSBSKnownDerived_async(self, cb, current=None): + def SBSKnownDerivedAsSBSKnownDerived(self, current=None): sbskd = Test.SBSKnownDerived() sbskd.sb = "SBSKnownDerived.sb" sbskd.sbskd = "SBSKnownDerived.sbskd" - cb.ice_response(sbskd) + return Ice.Future.completed(sbskd) - def SBSUnknownDerivedAsSBase_async(self, cb, current=None): + def SBSUnknownDerivedAsSBase(self, current=None): sbsud = Test.SBSUnknownDerived() sbsud.sb = "SBSUnknownDerived.sb" sbsud.sbsud = "SBSUnknownDerived.sbsud" - cb.ice_response(sbsud) + return Ice.Future.completed(sbsud) - def SBSUnknownDerivedAsSBaseCompact_async(self, cb, current=None): + def SBSUnknownDerivedAsSBaseCompact(self, current=None): sbsud = Test.SBSUnknownDerived() sbsud.sb = "SBSUnknownDerived.sb" sbsud.sbsud = "SBSUnknownDerived.sbsud" - cb.ice_response(sbsud) + return Ice.Future.completed(sbsud) - def SUnknownAsObject_async(self, cb, current=None): + def SUnknownAsObject(self, current=None): su = Test.SUnknown() su.su = "SUnknown.su" - cb.ice_response(su) + return Ice.Future.completed(su) - def checkSUnknown_async(self, cb, obj, current=None): + def checkSUnknown(self, obj, current=None): if current.encoding == Ice.Encoding_1_0: test(not isinstance(obj, Test.SUnknown)) else: test(isinstance(obj, Test.SUnknown)) test(obj.su == "SUnknown.su") - cb.ice_response() + return Ice.Future.completed(None) - def oneElementCycle_async(self, cb, current=None): + def oneElementCycle(self, current=None): b = Test.B() b.sb = "B1.sb" b.pb = b - cb.ice_response(b) + return Ice.Future.completed(b) - def twoElementCycle_async(self, cb, current=None): + def twoElementCycle(self, current=None): b1 = Test.B() b1.sb = "B1.sb" b2 = Test.B() b2.sb = "B2.sb" b2.pb = b1 b1.pb = b2 - cb.ice_response(b1) + return Ice.Future.completed(b1) - def D1AsB_async(self, cb, current=None): + def D1AsB(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -92,9 +92,9 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d1) + return Ice.Future.completed(d1) - def D1AsD1_async(self, cb, current=None): + def D1AsD1(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -105,9 +105,9 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d1) + return Ice.Future.completed(d1) - def D2AsB_async(self, cb, current=None): + def D2AsB(self, current=None): d2 = Test.D2() d2.sb = "D2.sb" d2.sd2 = "D2.sd2" @@ -118,9 +118,9 @@ class TestI(Test.TestIntf): d1.pd1 = d2 d2.pb = d1 d2.pd2 = d1 - cb.ice_response(d2) + return Ice.Future.completed(d2) - def paramTest1_async(self, cb, current=None): + def paramTest1(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -131,9 +131,9 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d1, d2) + return Ice.Future.completed((d1, d2)) - def paramTest2_async(self, cb, current=None): + def paramTest2(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -144,9 +144,9 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d2, d1) + return Ice.Future.completed((d2, d1)) - def paramTest3_async(self, cb, current=None): + def paramTest3(self, current=None): d2 = Test.D2() d2.sb = "D2.sb (p1 1)" d2.pb = None @@ -171,9 +171,9 @@ class TestI(Test.TestIntf): d3.pd1 = None d4.pd2 = d3 - cb.ice_response(d3, d2, d4) + return Ice.Future.completed((d3, d2, d4)) - def paramTest4_async(self, cb, current=None): + def paramTest4(self, current=None): d4 = Test.D4() d4.sb = "D4.sb (1)" d4.pb = None @@ -183,9 +183,9 @@ class TestI(Test.TestIntf): d4.p2 = Test.B() d4.p2.sb = "B.sb (2)" d4.p2.pb = None - cb.ice_response(d4.p2, d4) + return Ice.Future.completed((d4.p2, d4)) - def returnTest1_async(self, cb, current=None): + def returnTest1(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -196,9 +196,9 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d2, d2, d1) + return Ice.Future.completed((d2, d2, d1)) - def returnTest2_async(self, cb, current=None): + def returnTest2(self, current=None): d1 = Test.D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" @@ -209,18 +209,18 @@ class TestI(Test.TestIntf): d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 - cb.ice_response(d1, d1, d2) + return Ice.Future.completed((d1, d1, d2)) - def returnTest3_async(self, cb, p1, p2, current=None): - cb.ice_response(p1) + def returnTest3(self, p1, p2, current=None): + return Ice.Future.completed(p1) - def sequenceTest_async(self, cb, p1, p2, current=None): + def sequenceTest(self, p1, p2, current=None): ss = Test.SS3() ss.c1 = p1 ss.c2 = p2 - cb.ice_response(ss) + return Ice.Future.completed(ss) - def dictionaryTest_async(self, cb, bin, current=None): + def dictionaryTest(self, bin, current=None): bout = {} for i in range(0, 10): b = bin[i] @@ -244,20 +244,20 @@ class TestI(Test.TestIntf): d1.pd1 = d1 r[i * 20] = d1 - cb.ice_response(r, bout) + return Ice.Future.completed((r, bout)) - def exchangePBase_async(self, cb, pb, current=None): - cb.ice_response(pb) + def exchangePBase(self, pb, current=None): + return Ice.Future.completed(pb) - def PBSUnknownAsPreserved_async(self, cb, current=None): + def PBSUnknownAsPreserved(self, current=None): r = Test.PSUnknown() r.pi = 5 r.ps = "preserved" r.psu = "unknown" r.graph = None - cb.ice_response(r) + return Ice.Future.completed(r) - def checkPBSUnknown_async(self, cb, p, current=None): + def checkPBSUnknown(self, p, current=None): if current.encoding == Ice.Encoding_1_0: test(not isinstance(p, Test.PSUnknown)) test(p.pi == 5) @@ -268,9 +268,9 @@ class TestI(Test.TestIntf): test(p.ps == "preserved") test(p.psu == "unknown") test(not p.graph) - cb.ice_response() + return Ice.Future.completed(None) - def PBSUnknownAsPreservedWithGraph_async(self, cb, current=None): + def PBSUnknownAsPreservedWithGraph(self, current=None): r = Test.PSUnknown() r.pi = 5 r.ps = "preserved" @@ -279,10 +279,10 @@ class TestI(Test.TestIntf): r.graph.next = Test.PNode() r.graph.next.next = Test.PNode() r.graph.next.next.next = r.graph - cb.ice_response(r) - r.graph.next.next.next = None # Break the cycle. + return Ice.Future.completed(r) + #r.graph.next.next.next = None # Break the cycle. - def checkPBSUnknownWithGraph_async(self, cb, p, current=None): + def checkPBSUnknownWithGraph(self, p, current=None): if current.encoding == Ice.Encoding_1_0: test(not isinstance(p, Test.PSUnknown)) test(p.pi == 5) @@ -296,17 +296,17 @@ class TestI(Test.TestIntf): test(p.graph.next != p.graph.next.next) test(p.graph.next.next.next == p.graph) p.graph.next.next.next = None # Break the cycle. - cb.ice_response() + return Ice.Future.completed(None) - def PBSUnknown2AsPreservedWithGraph_async(self, cb, current=None): + def PBSUnknown2AsPreservedWithGraph(self, current=None): r = Test.PSUnknown2() r.pi = 5 r.ps = "preserved" r.pb = r - cb.ice_response(r) - r.pb = None # Break the cycle. + return Ice.Future.completed(r) + #r.pb = None # Break the cycle. - def checkPBSUnknown2WithGraph_async(self, cb, p, current=None): + def checkPBSUnknown2WithGraph(self, p, current=None): if current.encoding == Ice.Encoding_1_0: test(not isinstance(p, Test.PSUnknown2)) test(p.pi == 5) @@ -317,20 +317,22 @@ class TestI(Test.TestIntf): test(p.ps == "preserved") test(p.pb == p) p.pb = None # Break the cycle. - cb.ice_response() + return Ice.Future.completed(None) - def exchangePNode_async(self, cb, pn, current=None): - cb.ice_response(pn) + def exchangePNode(self, pn, current=None): + return Ice.Future.completed(pn) - def throwBaseAsBase_async(self, cb, current=None): + def throwBaseAsBase(self, current=None): be = Test.BaseException() be.sbe = "sbe" be.pb = Test.B() be.pb.sb = "sb" be.pb.pb = be.pb - cb.ice_exception(be) + f = Ice.Future() + f.set_exception(be) + return f - def throwDerivedAsBase_async(self, cb, current=None): + def throwDerivedAsBase(self, current=None): de = Test.DerivedException() de.sbe = "sbe" de.pb = Test.B() @@ -342,9 +344,11 @@ class TestI(Test.TestIntf): de.pd1.pb = de.pd1 de.pd1.sd1 = "sd2" de.pd1.pd1 = de.pd1 - cb.ice_exception(de) + f = Ice.Future() + f.set_exception(de) + return f - def throwDerivedAsDerived_async(self, cb, current=None): + def throwDerivedAsDerived(self, current=None): de = Test.DerivedException() de.sbe = "sbe" de.pb = Test.B() @@ -356,9 +360,11 @@ class TestI(Test.TestIntf): de.pd1.pb = de.pd1 de.pd1.sd1 = "sd2" de.pd1.pd1 = de.pd1 - cb.ice_exception(de) + f = Ice.Future() + f.set_exception(de) + return f - def throwUnknownDerivedAsBase_async(self, cb, current=None): + def throwUnknownDerivedAsBase(self, current=None): d2 = Test.D2() d2.sb = "sb d2" d2.pb = d2 @@ -370,26 +376,29 @@ class TestI(Test.TestIntf): ude.pb = d2 ude.sude = "sude" ude.pd2 = d2 - cb.ice_exception(ude) + f = Ice.Future() + f.set_exception(ude) + return f - def throwPreservedException_async(self, cb, current=None): + def throwPreservedException(self, current=None): ue = Test.PSUnknownException() ue.p = Test.PSUnknown2() ue.p.pi = 5 ue.p.ps = "preserved" ue.p.pb = ue.p - cb.ice_exception(ue) - ue.p.pb = None # Break the cycle. - - def useForward_async(self, cb, current=None): - f = Test.Forward() - f.h = Test.Hidden() - f.h.f = f - cb.ice_response(f) - - def shutdown_async(self, cb, current=None): + f = Ice.Future() + f.set_exception(ue) + return f + #ue.p.pb = None # Break the cycle. + + def useForward(self, current=None): + fwd = Test.Forward() + fwd.h = Test.Hidden() + fwd.h.f = fwd + return Ice.Future.completed(fwd) + + def shutdown(self, current=None): current.adapter.getCommunicator().shutdown() - cb.ice_response() def run(args, communicator): properties = communicator.getProperties() diff --git a/python/test/Ice/timeout/AllTests.py b/python/test/Ice/timeout/AllTests.py index fd90bdad679..16d3d0484f8 100644 --- a/python/test/Ice/timeout/AllTests.py +++ b/python/test/Ice/timeout/AllTests.py @@ -19,17 +19,16 @@ class CallbackBase: self._cond = threading.Condition() def called(self): - self._cond.acquire() - self._called = True - self._cond.notify() - self._cond.release() + with self._cond: + self._called = True + self._cond.notify() def check(self): - self._cond.acquire() - while not self._called: - self._cond.wait() - self._called = False - return True + with self._cond: + while not self._called: + self._cond.wait() + self._called = False + return True class Callback(CallbackBase): def response(self): diff --git a/python/test/Slice/keyword/Client.py b/python/test/Slice/keyword/Client.py index a81722b544d..4bbb984634f 100755 --- a/python/test/Slice/keyword/Client.py +++ b/python/test/Slice/keyword/Client.py @@ -23,7 +23,7 @@ Ice.loadSlice('Key.ice') import _and class delI(_and._del): - def _elif_async(self, _cb, _else, current=None): + def _elifAsync(self, _else, current=None): pass class execI(_and._exec): @@ -35,7 +35,7 @@ class forI(_and._for): pass class ifI(_and._if): - def _elif_async(self, _cb, _else, current=None): + def _elifAsync(self, _else, current=None): pass def _finally(self, current=None): pass |