Package: src:pyqt5 Version: 5.15.11+dfsg-5 User: [email protected] Usertags: python3.15 Tags: patch
Hi! While rebuilding the python related packages against the python version 3.15rc1 we found that pyqt5 fails to build from source[1]. This is due to the removal of PyWeakref_GetObject which was deprecated in python 3.13. I'm attaching a patch that's almost identical to the one needed for pyqt6. Please consider applying this or a similar patch in your next upload. Happy hacking, [1]: https://debusine.debian.net/debian/r-python-python3.15/work-request/1017822/ -- "Can you imagine what I would do if I could do all I can?" -- Sun Tzu Saludos /\/\ /\ >< `/
Description: Fix build against Python 3.15 by using PyWeakref_GetRef PyWeakref_GetObject was deprecated in Python 3.13 and removed in Python 3.15. Replace its usage with PyWeakref_GetRef, properly handling strong references and providing a compatibility fallback for older Python versions and limited API. Author: Maximiliano Curia <[email protected]> Forwarded: no Last-Update: 2026-08-19 Index: pyqt5/qpy/QtCore/qpycore_pyqtslot.cpp =================================================================== --- pyqt5.orig/qpy/QtCore/qpycore_pyqtslot.cpp +++ pyqt5/qpy/QtCore/qpycore_pyqtslot.cpp @@ -24,6 +24,40 @@ #include "qpycore_pyqtslot.h" +#if PY_VERSION_HEX < 0x030D0000 +static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj) +{ + PyObject *obj; + + if (ref != NULL && !PyWeakref_Check(ref)) + { + *pobj = NULL; + PyErr_SetString(PyExc_TypeError, "expected a weakref"); + return -1; + } + + obj = PyWeakref_GetObject(ref); + if (obj == NULL) + { + *pobj = NULL; + return -1; + } + + if (obj == Py_None) + { + *pobj = NULL; + return 0; + } + + Py_INCREF(obj); + *pobj = obj; + return 1; +} +#elif defined(Py_LIMITED_API) && Py_LIMITED_API < 0x030D0000 +extern "C" PyAPI_FUNC(int) PyWeakref_GetRef(PyObject *ref, PyObject **pobj); +#endif + + // Create the slot for an unbound method. PyQtSlot::PyQtSlot(PyObject *method, PyObject *type, const Chimera::Signature *slot_signature) @@ -54,6 +88,8 @@ PyQtSlot::PyQtSlot(PyObject *callable, c // Try and create a weak reference to the instance object. mself_wr = PyWeakref_NewRef(mself, 0); + if (!mself_wr) + PyErr_Clear(); } else { @@ -100,9 +136,11 @@ PyQtSlot::Result PyQtSlot::invoke(void * } else { + PyObject *self_ref = 0; + // Use the value we have if one wasn't supplied. if (!self) - self = instance(); + self = self_ref = instance(); // If self is NULL then we didn't have a method in the first place. // Instead we had a callable that has been cleared during garbage @@ -112,12 +150,18 @@ PyQtSlot::Result PyQtSlot::invoke(void * // See if the instance has gone (which isn't an error). if (self == Py_None) + { + Py_XDECREF(self_ref); return PyQtSlot::Ignored; + } // If the receiver wraps a C++ object then ignore the call if it no // longer exists. if (!no_receiver_check && PyObject_TypeCheck(self, sipSimpleWrapper_Type) && !sipGetAddress((sipSimpleWrapper *)self)) + { + Py_XDECREF(self_ref); return PyQtSlot::Ignored; + } sipMethodDef callable_m; @@ -128,6 +172,8 @@ PyQtSlot::Result PyQtSlot::invoke(void * #endif callable = sipFromMethod(&callable_m); + + Py_XDECREF(self_ref); } // Convert the C++ arguments to Python objects. @@ -188,12 +234,17 @@ bool PyQtSlot::operator==(PyObject *call if (other) return false; - return (mfunc == callable_m.pm_function - && instance() == callable_m.pm_self + PyObject *self = instance(); + bool match = (mfunc == callable_m.pm_function + && self == callable_m.pm_self #if PY_MAJOR_VERSION < 3 && mclass == callable_m.pm_class #endif ); + + Py_XDECREF(self); + + return match; } if (!other) @@ -219,8 +270,19 @@ PyObject *PyQtSlot::instance() const { // Use the weak reference if possible. if (mself_wr) - return PyWeakref_GetObject(mself_wr); + { + PyObject *obj = 0; + + if (PyWeakref_GetRef(mself_wr, &obj) < 0) + { + PyErr_Clear(); + return 0; + } + + return obj; + } + Py_XINCREF(mself); return mself; }

