From 91b62d3742754c2a366841938219e06c93d44aa9 2012-09-05 07:03:47 From: florianlink Date: 2012-09-05 07:03:47 Subject: [PATCH] added support for kwargs on call() methods git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@230 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index e8b72b9..6dadb66 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -1007,21 +1007,21 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type) return results; } -QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args) +QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args, const QVariantMap& kwargs) { PythonQtObjectPtr callable = lookupCallable(object, name); if (callable) { - return call(callable, args); + return call(callable, args, kwargs); } else { return QVariant(); } } -QVariant PythonQt::call(PyObject* callable, const QVariantList& args) +QVariant PythonQt::call(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs) { QVariant r; PythonQtObjectPtr result; - result.setNewRef(callAndReturnPyObject(callable, args)); + result.setNewRef(callAndReturnPyObject(callable, args, kwargs)); if (result) { r = PythonQtConv::PyObjToQVariant(result); } else { @@ -1030,31 +1030,54 @@ QVariant PythonQt::call(PyObject* callable, const QVariantList& args) return r; } -PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args) +PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs) { PyObject* result = NULL; if (callable) { + bool err = false; PythonQtObjectPtr pargs; int count = args.size(); - if (count>0) { + if ((count > 0) || (kwargs.count() > 0)) { // create empty tuple if kwargs are given pargs.setNewRef(PyTuple_New(count)); - } - bool err = false; - // transform QVariants to Python - for (int i = 0; i < count; i++) { - PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i)); - if (arg) { - // steals reference, no unref - PyTuple_SetItem(pargs, i,arg); - } else { - err = true; - break; + + // transform QVariant arguments to Python + for (int i = 0; i < count; i++) { + PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i)); + if (arg) { + // steals reference, no unref + PyTuple_SetItem(pargs, i,arg); + } else { + err = true; + break; + } } } - if (!err) { - PyErr_Clear(); - result = PyObject_CallObject(callable, pargs); + if (kwargs.isEmpty()) { + // do a direct call if we have no keyword arguments + PyErr_Clear(); + result = PyObject_CallObject(callable, pargs); + } else { + // convert keyword arguments to Python + PythonQtObjectPtr pkwargs; + pkwargs.setNewRef(PyDict_New()); + QMapIterator it(kwargs); + while (it.hasNext()) { + it.next(); + PyObject* arg = PythonQtConv::QVariantToPyObject(it.value()); + if (arg) { + PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg); + } else { + err = true; + break; + } + } + if (!err) { + // call with arguments and keyword arguments + PyErr_Clear(); + result = PyObject_Call(callable, pargs, pkwargs); + } + } } } return result; diff --git a/src/PythonQt.h b/src/PythonQt.h index 0224f0e..278ee81 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -356,13 +356,13 @@ public: //@{ //! call the given python \c callable in the scope of object, returns the result converted to a QVariant - QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList()); + QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap()); //! call the given python object, returns the result converted to a QVariant - QVariant call(PyObject* callable, const QVariantList& args = QVariantList()); + QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap()); //! call the given python object, returns the result as new PyObject - PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList()); + PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap()); //@} diff --git a/src/PythonQtObjectPtr.cpp b/src/PythonQtObjectPtr.cpp index f5518f0..c26664f 100644 --- a/src/PythonQtObjectPtr.cpp +++ b/src/PythonQtObjectPtr.cpp @@ -96,14 +96,14 @@ QVariant PythonQtObjectPtr::getVariable(const QString& name) } -QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args) +QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args, const QVariantMap& kwargs) { - return PythonQt::self()->call(_object, callable, args); + return PythonQt::self()->call(_object, callable, args, kwargs); } -QVariant PythonQtObjectPtr::call(const QVariantList& args) +QVariant PythonQtObjectPtr::call(const QVariantList& args, const QVariantMap& kwargs) { - return PythonQt::self()->call(_object, args); + return PythonQt::self()->call(_object, args, kwargs); } bool PythonQtObjectPtr::fromVariant(const QVariant& variant) diff --git a/src/PythonQtObjectPtr.h b/src/PythonQtObjectPtr.h index 6fcc53f..c4b7611 100644 --- a/src/PythonQtObjectPtr.h +++ b/src/PythonQtObjectPtr.h @@ -47,6 +47,7 @@ #include "PythonQtSystem.h" #include #include +#include //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically class PYTHONQT_EXPORT PythonQtObjectPtr @@ -142,10 +143,10 @@ public: QVariant getVariable(const QString& name); //! call the given python object (in the scope of the current object), returns the result converted to a QVariant - QVariant call(const QString& callable, const QVariantList& args = QVariantList()); + QVariant call(const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap()); //! call the contained python object directly, returns the result converted to a QVariant - QVariant call(const QVariantList& args = QVariantList()); + QVariant call(const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap()); protected: