@@ -341,68 +341,114 @@ PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self,
341
341
342
342
PyObject *PythonQtSlotFunction_CallImpl (PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * kw, void * firstArg, void ** directReturnValuePointer, PythonQtPassThisOwnershipType* passThisOwnershipToCPP)
343
343
{
344
- if (kw != NULL && PyDict_Check (kw) && (PyDict_Size (kw) > 0 )) {
345
- QString e = QString (" Calling C++ functions with Python keywords is not supported! Function: " ) + info->fullSignature (true ) + " Keywords: " + PythonQtConv::PyObjGetString (kw);
346
- PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
347
- return NULL ;
348
- }
349
-
350
344
int argc = args?PyTuple_Size (args):0 ;
345
+
351
346
if (passThisOwnershipToCPP) {
352
347
*passThisOwnershipToCPP = IgnoreOwnership;
353
348
}
354
349
355
- #ifdef PYTHONQT_DEBUG
356
- std::cout << " called " << info->metaMethod ()->typeName () << " " << info->signature () << std::endl;
357
- #endif
358
-
359
350
PyObject* r = NULL ;
360
351
bool ok = false ;
352
+
361
353
if (directReturnValuePointer) {
362
354
*directReturnValuePointer = NULL ;
363
355
}
364
- if (info->nextInfo ()) {
365
- // overloaded slot call, try on all slots with strict conversion first
366
- bool strict = true ;
367
- PythonQtSlotInfo* i = info;
368
- while (i) {
369
- bool skipFirst = i->isInstanceDecorator ();
370
- if (i->parameterCount ()-1 -(skipFirst?1 :0 ) == argc) {
371
- PyErr_Clear ();
372
- ok = PythonQtCallSlot (classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer, passThisOwnershipToCPP);
373
- if (PyErr_Occurred () || ok) break ;
356
+
357
+ if ( (kw != NULL && PyDict_Check (kw) && (PyDict_Size (kw) > 0 )) ) {
358
+ // -------------------keyword args slot call -------------------------
359
+
360
+ // keyword arguments are given as dict, must be mapped to arguments in correct order
361
+ // very complicated, so call them only on a slot with last variable name kwargs
362
+ // slot must be implemented as
363
+ // <type> <name>(any number of positional arguments, QVariantMap kwargs)
364
+ int numCombinedArgs = argc + 1 ;
365
+ PyObject* combinedArgs = PyTuple_New (numCombinedArgs);
366
+
367
+ for (int i = 0 ; i<argc; i++) {
368
+ PyObject* p = PyTuple_GetItem (args,i);
369
+ Py_INCREF (p);
370
+ PyTuple_SetItem (combinedArgs,i,p);
371
+ }
372
+
373
+ Py_INCREF (kw);
374
+ PyTuple_SetItem (combinedArgs, numCombinedArgs - 1 , kw);
375
+
376
+ bool kwSlotFound = false ;
377
+
378
+ QList<QByteArray> parameterNames;
379
+ PythonQtSlotInfo* slotInfo = info;
380
+ static QByteArray kwargs = " kwargs" ;
381
+ while (slotInfo) {
382
+ parameterNames = slotInfo->metaMethod ()->parameterNames ();
383
+ if (!parameterNames.isEmpty () && (parameterNames.last ().constData () == kwargs)) {
384
+ kwSlotFound = true ;
385
+ break ;
374
386
}
375
- i = i->nextInfo ();
376
- if (!i) {
377
- if (strict) {
378
- // one more run without being strict
379
- strict = false ;
380
- i = info;
381
- }
387
+ }
388
+ if (kwSlotFound) {
389
+ #ifdef PYTHONQT_DEBUG
390
+ std::cout << " called " << slotInfo->metaMethod ()->typeName () << " " << slotInfo->signature ().constData () << std::endl;
391
+ #endif
392
+
393
+ ok = PythonQtCallSlot (classInfo, objectToCall, combinedArgs, false , slotInfo, firstArg, &r, directReturnValuePointer, passThisOwnershipToCPP);
394
+ if (!ok && !PyErr_Occurred ()) {
395
+ QString e = QString (" Called " ) + info->fullSignature () + " with wrong arguments: " + PythonQtConv::PyObjGetString (args);
396
+ PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
382
397
}
398
+ } else {
399
+ QString e = QString (" Called " ) + info->fullSignature () + " with keyword arguments, but called slot does not support kwargs." ;
400
+ PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
383
401
}
384
- if (!ok && !PyErr_Occurred ()) {
385
- QString e = QString (" Could not find matching overload for given arguments:\n " + PythonQtConv::PyObjGetString (args) + " \n The following slots are available:\n " );
402
+
403
+ Py_DECREF (combinedArgs);
404
+ } else {
405
+ // -------------------Normal slot call -------------------------
406
+ if (info->nextInfo ()) {
407
+ // overloaded slot call, try on all slots with strict conversion first
408
+ bool strict = true ;
386
409
PythonQtSlotInfo* i = info;
387
410
while (i) {
388
- e += QString (i->fullSignature ()) + " \n " ;
411
+ bool skipFirst = i->isInstanceDecorator ();
412
+ if (i->parameterCount ()-1 -(skipFirst?1 :0 ) == argc) {
413
+ PyErr_Clear ();
414
+ ok = PythonQtCallSlot (classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer, passThisOwnershipToCPP);
415
+ if (PyErr_Occurred () || ok) break ;
416
+ }
389
417
i = i->nextInfo ();
418
+ if (!i) {
419
+ if (strict) {
420
+ // one more run without being strict
421
+ strict = false ;
422
+ i = info;
423
+ }
424
+ }
390
425
}
391
- PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
392
- }
393
- } else {
394
- // simple (non-overloaded) slot call
395
- bool skipFirst = info->isInstanceDecorator ();
396
- if (info->parameterCount ()-1 -(skipFirst?1 :0 ) == argc) {
397
- PyErr_Clear ();
398
- ok = PythonQtCallSlot (classInfo, objectToCall, args, false , info, firstArg, &r, directReturnValuePointer, passThisOwnershipToCPP);
399
426
if (!ok && !PyErr_Occurred ()) {
400
- QString e = QString (" Called " ) + info->fullSignature () + " with wrong arguments: " + PythonQtConv::PyObjGetString (args);
427
+ QString e = QString (" Could not find matching overload for given arguments:\n " + PythonQtConv::PyObjGetString (args) + " \n The following slots are available:\n " );
428
+ PythonQtSlotInfo* i = info;
429
+ while (i) {
430
+ e += QString (i->fullSignature ()) + " \n " ;
431
+ i = i->nextInfo ();
432
+ }
401
433
PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
402
434
}
403
435
} else {
404
- QString e = QString (" Called " ) + info->fullSignature () + " with wrong number of arguments: " + PythonQtConv::PyObjGetString (args);
405
- PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
436
+ // simple (non-overloaded) slot call
437
+ bool skipFirst = info->isInstanceDecorator ();
438
+ if (info->parameterCount ()-1 -(skipFirst?1 :0 ) == argc) {
439
+ PyErr_Clear ();
440
+ #ifdef PYTHONQT_DEBUG
441
+ std::cout << " called " << info->metaMethod ()->typeName () << " " << info->signature ().constData () << std::endl;
442
+ #endif
443
+ ok = PythonQtCallSlot (classInfo, objectToCall, args, false , info, firstArg, &r, directReturnValuePointer, passThisOwnershipToCPP);
444
+ if (!ok && !PyErr_Occurred ()) {
445
+ QString e = QString (" Called " ) + info->fullSignature () + " with wrong arguments: " + PythonQtConv::PyObjGetString (args);
446
+ PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
447
+ }
448
+ } else {
449
+ QString e = QString (" Called " ) + info->fullSignature () + " with wrong number of arguments: " + PythonQtConv::PyObjGetString (args);
450
+ PyErr_SetString (PyExc_ValueError, e.toLatin1 ().data ());
451
+ }
406
452
}
407
453
}
408
454
@@ -734,7 +780,7 @@ static PyObject*
734
780
meth_richcompare (PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b, int op)
735
781
{
736
782
int x = meth_compare (a, b);
737
- bool r;
783
+ bool r = false ;
738
784
if (op == Py_LT)
739
785
r = x < 0 ;
740
786
else if (op == Py_LE)
0 commit comments