From fe4c536104dbc6a10a33e1177bf2a2c1f9a4903c Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Tue, 2 Sep 2025 15:49:49 -0400 Subject: [PATCH] fix(PythonQt): Explicitly support immortals introduced in Python >= 3.12 This commit switches to using the `Py_RETURN_*` macros which expand to the expected constructs. This helps avoid a no-op (and misleading) call to `Py_INCREF()` when building against Python >= 3.12. - `Py_RETURN_NOTIMPLEMENTED` was introduced in Python 3.3 through python/cpython@7d2f9e13424 ("Add Py_RETURN_NOTIMPLEMENTED macro. Fixes #12724.", 2011-08-10) - `Py_RETURN_TRUE`, `Py_RETURN_FALSE` and `Py_RETURN_NONE` were introduced in Python 2.4 through python/cpython@d05235ec49d ("Defined macros Py_RETURN_(TRUE|FALSE|NONE) as helper functions for returning the specified value. All three Py_INCREF the singleton and then return it.", 2003-10-19) References: * https://docs.python.org/3/glossary.html#term-immortal * https://peps.python.org/pep-0683/ --- src/PythonQt.cpp | 6 ++---- src/PythonQtClassWrapper.cpp | 3 +-- src/PythonQtConversion.cpp | 21 +++++++-------------- src/PythonQtImporter.cpp | 12 ++++-------- src/PythonQtInstanceWrapper.cpp | 18 ++++++------------ src/PythonQtProperty.cpp | 3 +-- src/PythonQtSignal.cpp | 3 +-- src/PythonQtStdOut.cpp | 3 +-- 8 files changed, 23 insertions(+), 46 deletions(-) diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 8b80a3343..f6c0e05c4 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -622,8 +622,7 @@ void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const PyObject* PythonQtPrivate::wrapQObject(QObject* obj) { if (!obj) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj); if (wrap && wrap->_wrappedPtr) { @@ -652,8 +651,7 @@ PyObject* PythonQtPrivate::wrapQObject(QObject* obj) PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name, bool passOwnership) { if (!ptr) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr); diff --git a/src/PythonQtClassWrapper.cpp b/src/PythonQtClassWrapper.cpp index aaa6d84f4..b64fea24f 100644 --- a/src/PythonQtClassWrapper.cpp +++ b/src/PythonQtClassWrapper.cpp @@ -449,8 +449,7 @@ static PyObject* PythonQtClassWrapper_getDummyInstanceForProperty(PythonQtClassW if (info) { return (PyObject*)PythonQt::priv()->createNewPythonQtInstanceWrapper(nullptr, info); } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index 455a0d2dc..5e8cc5bb0 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -83,22 +83,19 @@ PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::Paramet return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data)); } else { // we do not support pointers to enums (who needs them?) - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } if (info.typeId == QMetaType::Void) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) { // a char ptr will probably be a null terminated string, so we support that: char* charPtr = *((char**)data); if (charPtr) { return PyString_FromString(charPtr); } else { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) && info.isQList && (info.innerNamePointerCount == 1)) { @@ -151,15 +148,13 @@ PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::Paramet } } } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PyObject* PythonQtConv::convertQtValueToPythonInternal(int type, const void* data) { switch (type) { case QMetaType::Void: - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; case QMetaType::Char: return PyInt_FromLong(*((char*)data)); case QMetaType::UChar: @@ -232,8 +227,7 @@ PyObject* PythonQtConv::convertQtValueToPythonInternal(int type, const void* dat } } } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info, PythonQtArgumentFrame* frame) { @@ -1389,8 +1383,7 @@ PyObject* PythonQtConv::QStringListToPyList(const QStringList& list) PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v) { if (!v.isValid()) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PyObject* obj = nullptr; if (v.userType() >= QMetaType::User && !PythonQt::priv()->isPythonQtAnyObjectPtrMetaId(v.userType())) { diff --git a/src/PythonQtImporter.cpp b/src/PythonQtImporter.cpp index 0855a29f9..aef4b1dfb 100644 --- a/src/PythonQtImporter.cpp +++ b/src/PythonQtImporter.cpp @@ -191,8 +191,7 @@ PythonQtImporter_find_module(PyObject *obj, PyObject *args) Py_INCREF(self); return (PyObject *)self; } else { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } @@ -625,16 +624,14 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ if (size <= 9) { PySys_WriteStderr("# %s has bad pyc data\n", QStringToPythonConstCharPointer(path)); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) { if (Py_VerboseFlag) PySys_WriteStderr("# %s has bad magic\n", QStringToPythonConstCharPointer(path)); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } if (mtime != 0) { @@ -644,8 +641,7 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ if (Py_VerboseFlag) PySys_WriteStderr("# %s has bad mtime\n", QStringToPythonConstCharPointer(path)); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } diff --git a/src/PythonQtInstanceWrapper.cpp b/src/PythonQtInstanceWrapper.cpp index 11ca09d64..d45b627f5 100644 --- a/src/PythonQtInstanceWrapper.cpp +++ b/src/PythonQtInstanceWrapper.cpp @@ -253,8 +253,7 @@ static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wr } else if (validPtrs && code == Py_NE) { return PythonQtConv::GetPyBool(!areSamePtrs); } - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } QByteArray memberName; @@ -313,19 +312,16 @@ static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wr // special handling of EQ and NE, if call fails we just return EQ == false / NE == true. if (code == Py_EQ) { PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; + Py_RETURN_FALSE; } else if (code == Py_NE) { PyErr_Clear(); - Py_INCREF(Py_True); - return Py_True; + Py_RETURN_TRUE; } } return result; } else { // not implemented, let python try something else! - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } } @@ -359,8 +355,7 @@ PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self) } else { PythonQtInstanceWrapper_deleteObject(self, true); } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } @@ -509,8 +504,7 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) return value; } else { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } else { QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object"; diff --git a/src/PythonQtProperty.cpp b/src/PythonQtProperty.cpp index b63ebe3bc..9b036070b 100644 --- a/src/PythonQtProperty.cpp +++ b/src/PythonQtProperty.cpp @@ -179,8 +179,7 @@ static PyObject *PythonQtProperty_get_doc(PythonQtProperty* self, void * /*closu return self->data->doc; } else { //TODO: we could get the doc string from the fget method if no doc string is given... - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } diff --git a/src/PythonQtSignal.cpp b/src/PythonQtSignal.cpp index 04e19fee2..eafacca50 100644 --- a/src/PythonQtSignal.cpp +++ b/src/PythonQtSignal.cpp @@ -116,8 +116,7 @@ meth_dealloc(PyObject *o) static PyObject * meth_get__doc__(PythonQtSignalFunctionObject * /*m*/, void * /*closure*/) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * diff --git a/src/PythonQtStdOut.cpp b/src/PythonQtStdOut.cpp index 4069bd8ea..685a61a3f 100644 --- a/src/PythonQtStdOut.cpp +++ b/src/PythonQtStdOut.cpp @@ -102,8 +102,7 @@ static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /* static PyObject *PythonQtStdOutRedirect_isatty(PyObject * /*self*/, PyObject * /*args*/) { - Py_INCREF(Py_False); - return Py_False; + Py_RETURN_FALSE; } static PyMethodDef PythonQtStdOutRedirect_methods[] = {