From 3487676ffa3bb94587e21231e5bbaa1f54d71ba8 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 27 Jun 2025 06:07:48 -0400 Subject: [PATCH 1/2] chore(importer): read `sys.flags` (verbose/optimize) on Python >= 3.12; fallback to legacy globals Python 3.12 deprecates direct use of global flags (`Py_VerboseFlag`, `Py_OptimizeFlag`). Query `sys.flags.verbose` / `sys.flags.optimize` at runtime (via a small helper) when building against 3.12+, and fall back to the legacy globals on older versions. No functional change intended. Co-authored-by: Jean-Christophe Fillion-Robin --- src/PythonQtImporter.cpp | 67 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/src/PythonQtImporter.cpp b/src/PythonQtImporter.cpp index beb414c88..97953a777 100644 --- a/src/PythonQtImporter.cpp +++ b/src/PythonQtImporter.cpp @@ -80,6 +80,26 @@ struct st_mlab_searchorder { extern PyTypeObject PythonQtImporter_Type; PyObject *PythonQtImportError; +namespace +{ +int getSysFlag(const char* flag_name) +{ + PyObject* flags = PySys_GetObject("flags"); + if (!flags) { + return false; + } + PyObject* flag = PyObject_GetAttrString(flags, flag_name); + if (!flag) { + PyErr_Clear(); return false; + } + int flag_value = (int)PyLong_AsLong(flag); + Py_DECREF(flag); + if (PyErr_Occurred()) { PyErr_Clear(); return 0; }; + return flag_value; +} + +} + QString PythonQtImport::getSubName(const QString& str) { int idx = str.lastIndexOf('.'); @@ -308,7 +328,11 @@ PythonQtImporter_load_module(PyObject *obj, PyObject *args) } Py_DECREF(code); +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else if (Py_VerboseFlag) { +#endif PySys_WriteStderr("import %s # loaded from %s\n", fullname, QStringToPythonConstCharPointer(fullPath)); } @@ -555,9 +579,14 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena } fp = open_exclusive(filename); if (fp == nullptr) { - if (Py_VerboseFlag) +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else + if (Py_VerboseFlag) { +#endif PySys_WriteStderr( "# can't create %s\n", QStringToPythonConstCharPointer(filename)); + } return; } PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION); @@ -566,8 +595,13 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena PyMarshal_WriteLongToFile(sourceSize, fp, Py_MARSHAL_VERSION); PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); if (ferror(fp)) { - if (Py_VerboseFlag) +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else + if (Py_VerboseFlag) { +#endif PySys_WriteStderr("# can't write %s\n", QStringToPythonConstCharPointer(filename)); + } /* Don't keep partial file */ fclose(fp); QFile::remove(filename); @@ -578,7 +612,11 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION); fflush(fp); fclose(fp); +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else if (Py_VerboseFlag) { +#endif PySys_WriteStderr("# wrote %s\n", QStringToPythonConstCharPointer(filename)); } } @@ -603,9 +641,14 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ } if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) { - if (Py_VerboseFlag) +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else + if (Py_VerboseFlag) { +#endif PySys_WriteStderr("# %s has bad magic\n", QStringToPythonConstCharPointer(path)); + } Py_RETURN_NONE; } @@ -613,9 +656,14 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime; if (timeDiff<0) { timeDiff = -timeDiff; } if (timeDiff > 1) { - if (Py_VerboseFlag) +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose")) { +#else + if (Py_VerboseFlag) { +#endif PySys_WriteStderr("# %s has bad mtime\n", QStringToPythonConstCharPointer(path)); + } Py_RETURN_NONE; } } @@ -751,9 +799,14 @@ PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QStr PyObject *code = nullptr; test = path + zso->suffix; - if (Py_VerboseFlag > 1) +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("verbose") > 1) { +#else + if (Py_VerboseFlag > 1) { +#endif PySys_WriteStderr("# trying %s\n", QStringToPythonConstCharPointer(test)); + } if (PythonQt::importInterface()->exists(test)) { time_t mtime = 0; int ispackage = zso->type & IS_PACKAGE; @@ -860,7 +913,11 @@ void PythonQtImport::init() mlab_searchorder[0].suffix[0] = SEP; mlab_searchorder[1].suffix[0] = SEP; mlab_searchorder[2].suffix[0] = SEP; +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + if (getSysFlag("optimize")) { +#else if (Py_OptimizeFlag) { +#endif /* Reverse *.pyc and *.pyo */ struct st_mlab_searchorder tmp; tmp = mlab_searchorder[0]; From c4c4aed795f8d346f75b7ea69885af2ecd9de9ea Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Fri, 26 Sep 2025 02:17:02 -0400 Subject: [PATCH 2/2] chore(importer): add helpers for runtime flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce getSysVerbose() and getSysOptimizationLevel() to read verbosity/optimization in a version-safe way: On Python ≥ 3.12: query sys.flags.verbose / sys.flags.optimize. On older Pythons: fall back to Py_VerboseFlag / Py_OptimizeFlag. --- src/PythonQtImporter.cpp | 69 +++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/src/PythonQtImporter.cpp b/src/PythonQtImporter.cpp index 97953a777..cd3c064ef 100644 --- a/src/PythonQtImporter.cpp +++ b/src/PythonQtImporter.cpp @@ -82,6 +82,8 @@ PyObject *PythonQtImportError; namespace { + +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 int getSysFlag(const char* flag_name) { PyObject* flags = PySys_GetObject("flags"); @@ -97,6 +99,25 @@ int getSysFlag(const char* flag_name) if (PyErr_Occurred()) { PyErr_Clear(); return 0; }; return flag_value; } +#endif + +int getSysVerbose() +{ +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + return getSysFlag("verbose"); +#else + return Py_VerboseFlag; +#endif +} + +int getSysOptimizationLevel() +{ +#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 + return getSysFlag("optimize"); +#else + return Py_OptimizeFlag; +#endif +} } @@ -328,11 +349,7 @@ PythonQtImporter_load_module(PyObject *obj, PyObject *args) } Py_DECREF(code); -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr("import %s # loaded from %s\n", fullname, QStringToPythonConstCharPointer(fullPath)); } @@ -579,11 +596,7 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena } fp = open_exclusive(filename); if (fp == nullptr) { -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr( "# can't create %s\n", QStringToPythonConstCharPointer(filename)); } @@ -595,11 +608,7 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena PyMarshal_WriteLongToFile(sourceSize, fp, Py_MARSHAL_VERSION); PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); if (ferror(fp)) { -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr("# can't write %s\n", QStringToPythonConstCharPointer(filename)); } /* Don't keep partial file */ @@ -612,11 +621,7 @@ void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filena PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION); fflush(fp); fclose(fp); -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr("# wrote %s\n", QStringToPythonConstCharPointer(filename)); } } @@ -641,11 +646,7 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ } if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) { -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr("# %s has bad magic\n", QStringToPythonConstCharPointer(path)); } @@ -656,11 +657,7 @@ PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_ time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime; if (timeDiff<0) { timeDiff = -timeDiff; } if (timeDiff > 1) { -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose")) { -#else - if (Py_VerboseFlag) { -#endif + if (getSysVerbose()) { PySys_WriteStderr("# %s has bad mtime\n", QStringToPythonConstCharPointer(path)); } @@ -799,11 +796,7 @@ PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QStr PyObject *code = nullptr; test = path + zso->suffix; -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("verbose") > 1) { -#else - if (Py_VerboseFlag > 1) { -#endif + if (getSysVerbose() > 1) { PySys_WriteStderr("# trying %s\n", QStringToPythonConstCharPointer(test)); } @@ -913,11 +906,7 @@ void PythonQtImport::init() mlab_searchorder[0].suffix[0] = SEP; mlab_searchorder[1].suffix[0] = SEP; mlab_searchorder[2].suffix[0] = SEP; -#if PY_VERSION_HEX >= 0x030C0000 // Python >= 3.12 - if (getSysFlag("optimize")) { -#else - if (Py_OptimizeFlag) { -#endif + if (getSysOptimizationLevel()) { /* Reverse *.pyc and *.pyo */ struct st_mlab_searchorder tmp; tmp = mlab_searchorder[0];