From 158f874dae612edca13d056d131f5732aa172ba1 Mon Sep 17 00:00:00 2001 From: Kay Hayen Date: Mon, 22 Mar 2021 11:51:51 +0100 Subject: [PATCH 6/6] Nuitka: Detect compiled methods as receivers too --- sources/pyside6/PySide6/glue/qtcore.cpp | 34 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp index 354dfa389..cf7bb90d3 100644 --- a/sources/pyside6/PySide6/glue/qtcore.cpp +++ b/sources/pyside6/PySide6/glue/qtcore.cpp @@ -316,13 +316,34 @@ PyModule_AddStringConstant(module, "__version__", qVersion()); // @snippet qt-version // @snippet qobject-connect -static bool isDecorator(PyObject *method, PyObject *self) +static bool isMethodDecorator(PyObject *method, bool is_pymethod, PyObject *self) { Shiboken::AutoDecRef methodName(PyObject_GetAttr(method, Shiboken::PyMagicName::name())); if (!PyObject_HasAttr(self, methodName)) return true; Shiboken::AutoDecRef otherMethod(PyObject_GetAttr(self, methodName)); - return PyMethod_GET_FUNCTION(otherMethod.object()) != PyMethod_GET_FUNCTION(method); + + PyObject *function1, *function2; + + // PYSIDE-1523: Each could be a compiled method or a normal method here, for the + // compiled ones we can use the attributes. + if (PyMethod_Check(otherMethod.object())) { + function1 = PyMethod_GET_FUNCTION(otherMethod.object()); + } else { + function1 = PyObject_GetAttrString(otherMethod.object(), "im_func"); + Py_DECREF(function1); + // Not retaining a reference inline with what PyMethod_GET_FUNCTION does. + } + + if (is_pymethod) { + function2 = PyMethod_GET_FUNCTION(method); + } else { + function2 = PyObject_GetAttrString(method, "im_func"); + Py_DECREF(function2); + // Not retaining a reference inline with what PyMethod_GET_FUNCTION does. + } + + return function1 != function2; } static bool getReceiver(QObject *source, const char *signal, PyObject *callback, QObject **receiver, PyObject **self, QByteArray *callbackSig) @@ -332,11 +353,18 @@ static bool getReceiver(QObject *source, const char *signal, PyObject *callback, *self = PyMethod_GET_SELF(callback); if (%CHECKTYPE[QObject *](*self)) *receiver = %CONVERTTOCPP[QObject *](*self); - forceGlobalReceiver = isDecorator(callback, *self); + forceGlobalReceiver = isMethodDecorator(callback, true, *self); } else if (PyCFunction_Check(callback)) { *self = PyCFunction_GET_SELF(callback); if (*self && %CHECKTYPE[QObject *](*self)) *receiver = %CONVERTTOCPP[QObject *](*self); + } else if (PyObject_HasAttrString(callback, "im_func") && PyObject_HasAttrString(callback, "im_self")) { + *self = PyObject_GetAttrString(callback, "im_self"); + Py_DECREF(*self); + + if (%CHECKTYPE[QObject *](*self)) + *receiver = %CONVERTTOCPP[QObject *](*self); + forceGlobalReceiver = isMethodDecorator(callback, false, *self); } else if (PyCallable_Check(callback)) { // Ok, just a callable object *receiver = nullptr; -- 2.30.0.windows.2