From 0f43ec3158225092f6a02422eb90c56421326570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert-Andr=C3=A9=20Mauchin?= Date: Tue, 18 Jun 2024 22:05:34 +0200 Subject: [PATCH] Changes to build pykrita with Python 3.13 Python 3.11 deprecated Py_SetPath() in 2022 and Python 3.13 removed it. Instead one needs to use the new PyConfig API (PEP 587) added to Python 3.8. Fix: #488680 --- .../extensions/pykrita/plugin/utilities.cpp | 61 +++++++++++++++++-- plugins/extensions/pykrita/plugin/utilities.h | 4 +- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/plugins/extensions/pykrita/plugin/utilities.cpp b/plugins/extensions/pykrita/plugin/utilities.cpp index 4f58183238..1e497b2681 100644 --- a/plugins/extensions/pykrita/plugin/utilities.cpp +++ b/plugins/extensions/pykrita/plugin/utilities.cpp @@ -19,8 +19,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -412,18 +414,65 @@ bool Python::setPath(const QStringList& scriptPaths) joinedPaths = joinedPaths + pathSeparator + originalPath; } dbgScript << "Setting python paths:" << joinedPaths; + #ifdef Q_OS_WIN - QVector joinedPathsWChars(joinedPaths.size() + 1, 0); - joinedPaths.toWCharArray(joinedPathsWChars.data()); - Py_SetPath(joinedPathsWChars.data()); + PyStatus status; + PyConfig config; + PyConfig_InitPythonConfig(&config); + + for (const QString& path : joinedPaths.split(pathSeparator)) { + status = PyWideStringList_Append(&config.module_search_paths, path.toStdWString().c_str()); + if (PyStatus_Exception(status)) { + qDebug() << "Error appending to PyWideStringList:" << status.err_msg; + dbgScript << "Error appending to PyWideStringList"; + return false; + } + } + + config.module_search_paths_set = true; + qDebug() << "Set module_search_paths"; + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + qDebug() << "Cannot initialize Py_InitializeFromConfig:" << status.err_msg; + Py_ExitStatusException(status); + PyConfig_Clear(&config); + dbgScript << "Cannot initialize Py_InitializeFromConfig config"; + return false; + } + + PyConfig_Clear(&config); #else if (runningInBundle) { - QVector joinedPathsWChars(joinedPaths.size() + 1, 0); - joinedPaths.toWCharArray(joinedPathsWChars.data()); - Py_SetPath(joinedPathsWChars.data()); + PyStatus status; + PyConfig config; + PyConfig_InitPythonConfig(&config); + + for (const QString& path : joinedPaths.split(pathSeparator)) { + status = PyWideStringList_Append(&config.module_search_paths, path.toStdWString().c_str()); + if (PyStatus_Exception(status)) { + qDebug() << "Error appending to PyWideStringList:" << status.err_msg; + dbgScript << "Error appending to PyWideStringList"; + return false; + } + } + + config.module_search_paths_set = true; + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + qDebug() << "Cannot initialize Py_InitializeFromConfig 2:" << status.err_msg; + PyConfig_Clear(&config); + dbgScript << "Cannot initialize Py_InitializeFromConfig config"; + return false; + } + + PyConfig_Clear(&config); } else { qputenv("PYTHONPATH", joinedPaths.toLocal8Bit()); + qDebug() << "Set PYTHONPATH environment variable"; } #endif isPythonPathSet = true; diff --git a/plugins/extensions/pykrita/plugin/utilities.h b/plugins/extensions/pykrita/plugin/utilities.h index fb309bd0b8..aec47da239 100644 --- a/plugins/extensions/pykrita/plugin/utilities.h +++ b/plugins/extensions/pykrita/plugin/utilities.h @@ -81,8 +81,8 @@ public: static bool libraryLoad(); /** - * Set the Python paths by calling Py_SetPath. This should be called before - * initialization to ensure the proper libraries get loaded. + * Set the Python paths by calling Py_InitializeFromConfig. This should be + * called before initialization to ensure the proper libraries get loaded. */ static bool setPath(const QStringList& scriptPaths); -- 2.45.2