Merge pull request #20379 from chennes/baseEliminatePy_GetPath

Replace it with a piece of code that replicates the functionality. Also eliminate the round-trip through char * that this function was using (the final variable is stored as a std::string anyway).
This commit is contained in:
Kacper Donat
2025-03-29 18:13:08 +01:00
committed by GitHub
5 changed files with 38 additions and 10 deletions

View File

@@ -2636,8 +2636,8 @@ void Application::initConfig(int argc, char ** argv)
Py_DECREF(pyModule);
}
const char* pythonpath = Base::Interpreter().init(argc,argv);
if (pythonpath)
std::string pythonpath = Base::Interpreter().init(argc,argv);
if (!pythonpath.empty())
mConfig["PythonSearchPath"] = pythonpath;
else
Base::Console().Warning("Encoding of Python paths failed\n");

View File

@@ -538,8 +538,36 @@ void InterpreterSingleton::addPythonPath(const char* Path)
list.append(Py::String(Path));
}
std::string InterpreterSingleton::getPythonPath()
{
// Construct something that looks like the output of the now-deprecated Py_GetPath
PyGILStateLocker lock;
PyObject* path = PySys_GetObject("path");
std::string result;
const char* separator = ":"; // Use ":" on Unix-like systems, ";" on Windows
#ifdef FC_OS_WIN32
separator = ";";
#endif
Py_ssize_t length = PyList_Size(path);
for (Py_ssize_t i = 0; i < length; ++i) {
PyObject* item = PyList_GetItem(path, i); // Borrowed reference
if (!item) {
throw Base::RuntimeError("Failed to retrieve item from path");
}
const char* item_str = PyUnicode_AsUTF8(item);
if (!item_str) {
throw Base::RuntimeError("Failed to convert path item to UTF-8 string");
}
if (!result.empty()) {
result += separator;
}
result += item_str;
}
return result;
}
#if PY_VERSION_HEX < 0x030b0000
const char* InterpreterSingleton::init(int argc, char* argv[])
std::string InterpreterSingleton::init(int argc, char* argv[])
{
if (!Py_IsInitialized()) {
Py_SetProgramName(Py_DecodeLocale(argv[0], nullptr));
@@ -617,7 +645,7 @@ void initInterpreter(int argc, char* argv[])
Py_Initialize();
}
} // namespace
const char* InterpreterSingleton::init(int argc, char* argv[])
std::string InterpreterSingleton::init(int argc, char* argv[])
{
try {
if (!Py_IsInitialized()) {
@@ -626,9 +654,7 @@ const char* InterpreterSingleton::init(int argc, char* argv[])
PythonStdOutput::init_type();
this->_global = PyEval_SaveThread();
}
PyGILStateLocker lock;
return Py_EncodeLocale(Py_GetPath(), nullptr);
return getPythonPath();
}
catch (const Base::Exception& e) {
e.ReportException();

View File

@@ -285,6 +285,8 @@ public:
bool loadModule(const char* psModName);
/// Add an additional python path
void addPythonPath(const char* Path);
/// Get the path (replaces the deprecated Py_GetPath method)
std::string getPythonPath();
static void addType(PyTypeObject* Type, PyObject* Module, const char* Name);
/// Add a module and return a PyObject to it
PyObject* addModule(Py::ExtensionModuleBase*);
@@ -313,7 +315,7 @@ public:
*/
//@{
/// init the interpreter and returns the module search path
const char* init(int argc, char* argv[]);
std::string init(int argc, char* argv[]);
int runCommandLine(const char* prompt);
void replaceStdOutput();
static InterpreterSingleton& Instance();

View File

@@ -100,7 +100,7 @@ int main(int argc, char** argv)
msg << "While initializing " << appName << " the following exception occurred: '"
<< e.what() << "'\n\n";
msg << "Python is searching for its runtime files in the following directories:\n"
<< Py_EncodeLocale(Py_GetPath(), nullptr) << "\n\n";
<< Base::Interpreter().getPythonPath() << "\n\n";
msg << "Python version information:\n" << Py_GetVersion() << "\n";
const char* pythonhome = getenv("PYTHONHOME");
if (pythonhome) {

View File

@@ -266,7 +266,7 @@ int main(int argc, char** argv)
"Python version information:\n%4\n")
.arg(appName,
QString::fromUtf8(e.what()),
QString::fromUtf8(Py_EncodeLocale(Py_GetPath(), nullptr)),
QString::fromStdString(Base::Interpreter().getPythonPath()),
QString::fromLatin1(Py_GetVersion()));
const char* pythonhome = getenv("PYTHONHOME");
if (pythonhome) {