* [Buildroot] [PATCH 1/1] package/python-pyqt5: fix build with python-3.15
@ 2026-10-04 12:44 Bernd Kuhls
2026-10-10 8:26 ` Thomas Petazzoni via buildroot
0 siblings, 1 reply; 2+ messages in thread
From: Bernd Kuhls @ 2026-10-04 12:44 UTC (permalink / raw)
To: buildroot; +Cc: James Hilliard
Please note that the upstream repo is private so we used the Debian
mirror as source for patch 0003 which is marked as a cherry-pick by
upstream.
Other mirrors are not updated: https://github.com/baoboa/pyqt5/issues/76
Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
---
.../0003-Support-for-Python-v3.15.patch | 185 ++++++++++++++++++
...4-configure.py-remove-Py_LIMITED_API.patch | 37 ++++
2 files changed, 222 insertions(+)
create mode 100644 package/python-pyqt5/0003-Support-for-Python-v3.15.patch
create mode 100644 package/python-pyqt5/0004-configure.py-remove-Py_LIMITED_API.patch
diff --git a/package/python-pyqt5/0003-Support-for-Python-v3.15.patch b/package/python-pyqt5/0003-Support-for-Python-v3.15.patch
new file mode 100644
index 0000000000..ec39817b6d
--- /dev/null
+++ b/package/python-pyqt5/0003-Support-for-Python-v3.15.patch
@@ -0,0 +1,185 @@
+From: Phil Thompson <phil@riverbankcomputing.com>
+Date: Mon, 13 Jul 2026 16:38:52 +0100
+Subject: Support for Python v3.15
+
+The project can now be built with Python v3.15 (where the limited ABI
+version targeted will be v3.13).
+
+(cherry picked from commit 3aa6092c44cd17a3afcd9f8ca879c4e40d2662d1)
+
+Upstream: https://salsa.debian.org/python-team/packages/pyqt5/-/blob/1c7499d1d4d79737ae367ec263a9be71ce2b76ee/debian/patches/Support-for-Python-v3.15.patch
+
+Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
+---
+ project.py | 8 +++++++
+ qpy/QtCore/qpycore_pyqtproperty.cpp | 2 +-
+ qpy/QtCore/qpycore_pyqtslot.cpp | 44 ++++++++++++++++++++++++++--------
+ qpy/QtCore/qpycore_qobject_helpers.cpp | 11 +++++----
+ 4 files changed, 49 insertions(+), 16 deletions(-)
+
+diff --git a/project.py b/project.py
+index 9a3721f..f2143ac 100644
+--- a/project.py
++++ b/project.py
+@@ -111,6 +111,14 @@ del find_qt
+
+ return dunder_init
+
++ def get_limited_abi_version(self):
++ """ Return the version number of the limited ABI to use. """
++
++ # We use PyWeakref_GetObject() which was removed from the limited API
++ # in Python v3.15. It's replacement, PyWeakref_GetRef() was added to
++ # the limited ABI in Python v3.13.
++ return (3, 13, 0) if sys.hexversion >= 0x030f0000 else None
++
+ def get_options(self):
+ """ Return the sequence of configurable options. """
+
+diff --git a/qpy/QtCore/qpycore_pyqtproperty.cpp b/qpy/QtCore/qpycore_pyqtproperty.cpp
+index d173d51..0245134 100644
+--- a/qpy/QtCore/qpycore_pyqtproperty.cpp
++++ b/qpy/QtCore/qpycore_pyqtproperty.cpp
+@@ -575,7 +575,7 @@ static PyObject *pyqtProperty_reset(PyObject *self, PyObject *reset)
+ static qpycore_pyqtProperty *clone(qpycore_pyqtProperty *orig)
+ {
+ qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)PyType_GenericNew(
+- Py_TYPE(orig), 0, 0);
++ Py_TYPE((PyObject *)orig), 0, 0);
+
+ if (pp)
+ {
+diff --git a/qpy/QtCore/qpycore_pyqtslot.cpp b/qpy/QtCore/qpycore_pyqtslot.cpp
+index 26f4022..22a7d0c 100644
+--- a/qpy/QtCore/qpycore_pyqtslot.cpp
++++ b/qpy/QtCore/qpycore_pyqtslot.cpp
+@@ -101,7 +101,9 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
+ else
+ {
+ // Use the value we have if one wasn't supplied.
+- if (!self)
++ if (self)
++ Py_INCREF(self);
++ else
+ self = instance();
+
+ // If self is NULL then we didn't have a method in the first place.
+@@ -112,12 +114,18 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
+
+ // See if the instance has gone (which isn't an error).
+ if (self == Py_None)
++ {
++ Py_DECREF(self);
+ 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_DECREF(self);
+ return PyQtSlot::Ignored;
++ }
+
+ sipMethodDef callable_m;
+
+@@ -128,6 +136,7 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
+ #endif
+
+ callable = sipFromMethod(&callable_m);
++ Py_DECREF(self);
+ }
+
+ // Convert the C++ arguments to Python objects.
+@@ -188,12 +197,11 @@ bool PyQtSlot::operator==(PyObject *callable) const
+ if (other)
+ return false;
+
+- return (mfunc == callable_m.pm_function
+- && instance() == callable_m.pm_self
+-#if PY_MAJOR_VERSION < 3
+- && mclass == callable_m.pm_class
+-#endif
+- );
++ PyObject *instance_obj = instance();
++ bool res = (mfunc == callable_m.pm_function && instance_obj == callable_m.pm_self);
++ Py_XDECREF(instance_obj);
++
++ return res;
+ }
+
+ if (!other)
+@@ -214,14 +222,30 @@ bool PyQtSlot::operator==(PyObject *callable) const
+ }
+
+
+-// Get the instance object.
++// Get a strong reference to the instance object, otherwise return NULL or a
++// strong reference to Py_None.
+ PyObject *PyQtSlot::instance() const
+ {
++ PyObject *instance_obj;
++
+ // Use the weak reference if possible.
+ if (mself_wr)
+- return PyWeakref_GetObject(mself_wr);
++ {
++#if PY_VERSION_HEX >= 0x030f0000
++ if (PyWeakref_GetRef(mself_wr, &instance_obj) < 0)
++ instance_obj = NULL;
++#else
++ instance_obj = PyWeakref_GetObject(mself_wr);
++ Py_XINCREF(instance_obj);
++#endif
++ }
++ else
++ {
++ instance_obj = mself;
++ Py_XINCREF(instance_obj);
++ }
+
+- return mself;
++ return instance_obj;
+ }
+
+
+diff --git a/qpy/QtCore/qpycore_qobject_helpers.cpp b/qpy/QtCore/qpycore_qobject_helpers.cpp
+index f72105c..7b756ec 100644
+--- a/qpy/QtCore/qpycore_qobject_helpers.cpp
++++ b/qpy/QtCore/qpycore_qobject_helpers.cpp
+@@ -50,7 +50,7 @@ static int qt_metacall_worker(sipSimpleWrapper *pySelf, PyTypeObject *pytype,
+ const QMetaObject *qpycore_qobject_metaobject(sipSimpleWrapper *pySelf,
+ sipTypeDef *base)
+ {
+- sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE(pySelf) : 0);
++ sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE((PyObject *)pySelf) : 0);
+
+ return qpycore_get_qmetaobject(wt, base);
+ }
+@@ -64,7 +64,8 @@ int qpycore_qobject_qt_metacall(sipSimpleWrapper *pySelf, sipTypeDef *base,
+ if (!pySelf)
+ return -1;
+
+- return qt_metacall_worker(pySelf, Py_TYPE(pySelf), base, _c, _id, _a);
++ return qt_metacall_worker(pySelf, Py_TYPE((PyObject *)pySelf), base, _c,
++ _id, _a);
+ }
+
+
+@@ -236,13 +237,13 @@ bool qpycore_qobject_qt_metacast(sipSimpleWrapper *pySelf,
+
+ // We only need to look at the MRO if the object is a wrapped type (rather
+ // than a user sub-class).
+- if (base_pytype != Py_TYPE(pySelf))
++ if (base_pytype != Py_TYPE((PyObject *)pySelf))
+ {
+ PyObject *mro;
+
+ #if PY_VERSION_HEX >= 0x03040000
+- mro = PyObject_GetAttr((PyObject *)Py_TYPE(pySelf),
+- qpycore_dunder_mro);
++ mro = PyObject_GetAttr(
++ (PyObject *)Py_TYPE((PyObject *)pySelf), qpycore_dunder_mro);
+ Q_ASSERT(mro);
+ #else
+ mro = Py_TYPE(pySelf)->tp_mro;
diff --git a/package/python-pyqt5/0004-configure.py-remove-Py_LIMITED_API.patch b/package/python-pyqt5/0004-configure.py-remove-Py_LIMITED_API.patch
new file mode 100644
index 0000000000..f3af7b7fa5
--- /dev/null
+++ b/package/python-pyqt5/0004-configure.py-remove-Py_LIMITED_API.patch
@@ -0,0 +1,37 @@
+From 2fbf73d6678e956a6240a6518371ea4bde158bb6 Mon Sep 17 00:00:00 2001
+From: Bernd Kuhls <bernd@kuhls.net>
+Date: Sun, 4 Oct 2026 14:34:24 +0200
+Subject: [PATCH] configure.py: remove Py_LIMITED_API
+
+PyWeakref_GetRef is needed since python 3.15 and used by patch 0003 to
+fix build errors, but PyWeakref_GetRef is only available when
+Py_LIMITED_API+0 >= 0x030D0000:
+https://github.com/python/cpython/blob/v3.15.0rc3/Include/weakrefobject.h#L32
+
+To fix the build error we remove the define set by configure.py.
+
+Upstream: not applicable, file was removed upstream:
+https://salsa.debian.org/python-team/packages/pyqt5/-/blob/debian/5.15.11+dfsg-7/ChangeLog#L33
+
+Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
+---
+ configure.py | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/configure.py b/configure.py
+index a3450ca3..14e4e925 100644
+--- a/configure.py
++++ b/configure.py
+@@ -2673,9 +2673,6 @@ target.files = $$PY_MODULE
+
+ if metadata.qpy_lib:
+ # This is the easiest way to make sure it is set for handwritten code.
+- if not target_config.py_debug:
+- pro_lines.append('DEFINES += Py_LIMITED_API=0x03040000')
+-
+ pro_lines.append('INCLUDEPATH += %s' %
+ qmake_quote(os.path.relpath(source_path('qpy', mname), mname)))
+
+--
+2.47.3
+
--
2.47.3
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Buildroot] [PATCH 1/1] package/python-pyqt5: fix build with python-3.15
2026-10-04 12:44 [Buildroot] [PATCH 1/1] package/python-pyqt5: fix build with python-3.15 Bernd Kuhls
@ 2026-10-10 8:26 ` Thomas Petazzoni via buildroot
0 siblings, 0 replies; 2+ messages in thread
From: Thomas Petazzoni via buildroot @ 2026-10-10 8:26 UTC (permalink / raw)
To: Bernd Kuhls; +Cc: buildroot, James Hilliard
On Sun, Oct 04, 2026 at 02:44:07PM +0200, Bernd Kuhls wrote:
> Please note that the upstream repo is private so we used the Debian
> mirror as source for patch 0003 which is marked as a cherry-pick by
> upstream.
>
> Other mirrors are not updated: https://github.com/baoboa/pyqt5/issues/76
>
> Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
Applied to master, thanks!
Best regards,
Thomas Petazzoni
--
Thomas Petazzoni, co-owner and CEO, Bootlin
Embedded Linux and Kernel engineering and training
https://bootlin.com
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-13 17:57 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-04 12:44 [Buildroot] [PATCH 1/1] package/python-pyqt5: fix build with python-3.15 Bernd Kuhls
2026-10-10 8:26 ` Thomas Petazzoni via buildroot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox