From 675929762a09ad0b40cb2667918a7061c47a418c Mon Sep 17 00:00:00 2001 From: David Gobbi Date: Sat, 14 Sep 2024 08:35:21 -0600 Subject: [PATCH 1/3] Python 3.13 fix for missing dict segfault Python 3.13 removed a safety net from PyModule_Type's tp_init slot that created the module's md_dict member if it was NULL. This safety net was removed because, since Python 3.11, the md_dict is created by tp_new and is never expected to be NULL. So, in our own code, we must ensure that tp_new is called before tp_init. --- Wrapping/PythonCore/PyVTKNamespace.cxx | 6 ++++-- Wrapping/PythonCore/PyVTKTemplate.cxx | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Wrapping/PythonCore/PyVTKNamespace.cxx b/Wrapping/PythonCore/PyVTKNamespace.cxx index bed60dc47cb..c1823084086 100644 --- a/Wrapping/PythonCore/PyVTKNamespace.cxx +++ b/Wrapping/PythonCore/PyVTKNamespace.cxx @@ -112,8 +112,10 @@ PyObject* PyVTKNamespace_New(const char* name) { // make sure python has readied the type object PyType_Ready(&PyVTKNamespace_Type); - // call the allocator provided by python for this type - self = PyVTKNamespace_Type.tp_alloc(&PyVTKNamespace_Type, 0); + // call the superclass new function + PyObject* empty = PyTuple_New(0); + self = PyVTKNamespace_Type.tp_base->tp_new(&PyVTKNamespace_Type, empty, nullptr); + Py_DECREF(empty); // call the superclass init function PyObject* pyname = PyUnicode_FromString(name); PyObject* args = PyTuple_Pack(1, pyname); diff --git a/Wrapping/PythonCore/PyVTKTemplate.cxx b/Wrapping/PythonCore/PyVTKTemplate.cxx index 26421f60f07..e7780bf1007 100644 --- a/Wrapping/PythonCore/PyVTKTemplate.cxx +++ b/Wrapping/PythonCore/PyVTKTemplate.cxx @@ -761,8 +761,10 @@ PyObject* PyVTKTemplate_New(const char* name, const char* docstring) { // make sure python has readied the type object PyType_Ready(&PyVTKTemplate_Type); - // call the allocator provided by python for this type - PyObject* self = PyVTKTemplate_Type.tp_alloc(&PyVTKTemplate_Type, 0); + // call the superclass new function + PyObject* empty = PyTuple_New(0); + PyObject* self = PyVTKTemplate_Type.tp_base->tp_new(&PyVTKTemplate_Type, empty, nullptr); + Py_DECREF(empty); // call the superclass init function PyObject* pyname = PyUnicode_FromString(name); PyObject* pydoc = PyUnicode_FromString(docstring); -- GitLab From aa647dfeb453a6028ec57285b9f659426595c943 Mon Sep 17 00:00:00 2001 From: David Gobbi Date: Sat, 14 Sep 2024 11:55:31 -0600 Subject: [PATCH 2/3] Work around deprecated unittest.makeSuite The Python unittest.makeSuite() function is gone in Python 3.13, replace with unittest.TestLoader.loadTestsFromTestCase() --- Wrapping/Python/vtkmodules/test/Testing.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Wrapping/Python/vtkmodules/test/Testing.py b/Wrapping/Python/vtkmodules/test/Testing.py index 2891474a6d4..e0b8675a48b 100644 --- a/Wrapping/Python/vtkmodules/test/Testing.py +++ b/Wrapping/Python/vtkmodules/test/Testing.py @@ -515,8 +515,10 @@ def test(cases): """ # Make the test suites from the arguments. suites = [] - for case in cases: - suites.append(unittest.makeSuite(case[0], case[1])) + loader = unittest.TestLoader() + # the "name" is ignored (it was always just 'test') + for test,name in cases: + suites.append(loader.loadTestsFromTestCase(test)) test_suite = unittest.TestSuite(suites) # Now run the tests. -- GitLab From 718db8b7b95b1f75be4491c50f0ac41b58d1174a Mon Sep 17 00:00:00 2001 From: David Gobbi Date: Sat, 14 Sep 2024 16:58:26 -0600 Subject: [PATCH 3/3] Avoid use of deprecated Py_GetProgramName Py_GetProgramName() was deprecated in Python 3.13 and will be removed in Python 3.15. The same information can be retrieved from sys.executable. Note that since we stopped using Py_SetProgramName() for Python>=3.8, for consistency the #ifdef for Py_GetProgramName() also checks Python>=3.8. --- .../PythonInterpreter/vtkPythonInterpreter.cxx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx b/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx index deff95758c2..1e9b6e12145 100644 --- a/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx +++ b/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx @@ -97,6 +97,7 @@ wchar_t* vtk_Py_UTF8ToWide(const char* arg) return result; } +#if PY_VERSION_HEX < 0x03080000 std::string vtk_Py_WideToUTF8(const wchar_t* arg) { std::string result; @@ -110,6 +111,7 @@ std::string vtk_Py_WideToUTF8(const wchar_t* arg) return result; } +#endif std::vector>* GlobalInterpreters; std::vector PythonPaths; @@ -335,12 +337,21 @@ void SetupPythonPaths(bool isolated, std::string vtklib, const char* landmark) if (vtklib.empty()) { VTKPY_DEBUG_MESSAGE( - "`GetVTKVersion` library couldn't be found. Will use `Py_GetProgramName` next."); + "`GetVTKVersion` library couldn't be found. Will use `sys.executable` next."); } if (vtklib.empty()) { +#if PY_VERSION_HEX >= 0x03080000 + vtkPythonScopeGilEnsurer gilEnsurer; + PyObject* executable_path = PySys_GetObject("executable"); + if (executable_path != Py_None) + { + vtklib = PyUnicode_AsUTF8AndSize(executable_path, nullptr); + } +#else vtklib = vtk_Py_WideToUTF8(Py_GetProgramName()); +#endif } vtklib = systools::CollapseFullPath(vtklib); -- GitLab