cext: use sys.executable instead of deprecated Py_GetProgramFullPath
Fix warning with Python 3.13:
mercurial/cext/parsers.c: In function 'check_python_version':
mercurial/cext/parsers.c:1243:30: warning: 'Py_GetProgramFullPath' is deprecated [-Wdeprecated-declarations]
1243 | Py_GetProgramFullPath());
| ^~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/python3.13/Python.h:119,
from mercurial/cext/parsers.c:11:
/usr/include/python3.13/pylifecycle.h:43:43: note: declared here
43 | Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
| ^~~~~~~~~~~~~~~~~~~~~
At this point in time, the PyConfig struct memory has been released and the PyConfig API can't be used.
https://docs.python.org/3.13/c-api/init.html#c.Py_GetProgramFullPath recommands
using sys.executable instead. Let's assume that will work in all versions.
It would perhaps be better to use PySys_GetObject, but I prefer to stay
consistent with how the same function is retrieving sys.hexversion.
--- a/mercurial/cext/parsers.c Thu Jan 11 21:58:55 2024 +0100
+++ b/mercurial/cext/parsers.c Thu Jan 11 20:32:07 2024 +0100
@@ -1232,6 +1232,15 @@
* should only occur in unusual circumstances (e.g. if sys.hexversion
* is manually set to an invalid value). */
if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
+ PyObject *sys = PyImport_ImportModule("sys"), *executable;
+ if (!sys) {
+ return -1;
+ }
+ executable = PyObject_GetAttrString(sys, "executable");
+ Py_DECREF(sys);
+ if (!executable) {
+ return -1;
+ }
PyErr_Format(PyExc_ImportError,
"%s: The Mercurial extension "
"modules were compiled with Python " PY_VERSION
@@ -1240,7 +1249,8 @@
"sys.hexversion=%ld: "
"Python %s\n at: %s",
versionerrortext, hexversion, Py_GetVersion(),
- Py_GetProgramFullPath());
+ PyUnicode_AsUTF8(executable));
+ Py_DECREF(executable);
return -1;
}
return 0;