https://github.com/python/cpython/commit/ce96dd68589f4cff54aa7bb7bb0991c1ef7d2f4b
commit: ce96dd68589f4cff54aa7bb7bb0991c1ef7d2f4b
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-07-07T18:28:05+02:00
summary:

On Unix, avoid a conversion to wchar_t in getpath.c (#153230)

* Replace _Py_wstat() with _Py_stat() in isfile() and isxfile().
* Replace _Py_wfopen() with Py_fopen() in readlines().

files:
M Modules/getpath.c
M Python/fileutils.c

diff --git a/Modules/getpath.c b/Modules/getpath.c
index 0c80678a678dc8..ed41536acbcc81 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -198,57 +198,67 @@ getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args)
 static PyObject *
 getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args)
 {
-    PyObject *r = NULL;
     PyObject *pathobj;
-    const wchar_t *path;
     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         return NULL;
     }
-    path = PyUnicode_AsWideCharString(pathobj, NULL);
-    if (path) {
+
+    int isfile;
 #ifdef MS_WINDOWS
-        DWORD attr = GetFileAttributesW(path);
-        r = (attr != INVALID_FILE_ATTRIBUTES) &&
-            !(attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False;
+    wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
+    if (path == NULL) {
+        return NULL;
+    }
+
+    DWORD attr = GetFileAttributesW(path);
+    PyMem_Free(path);
+    isfile = ((attr != INVALID_FILE_ATTRIBUTES)
+               && !(attr & FILE_ATTRIBUTE_DIRECTORY));
 #else
-        struct stat st;
-        r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : 
Py_False;
-#endif
-        PyMem_Free((void *)path);
+    struct stat st;
+    int res = _Py_stat(pathobj, &st);
+    if (res == -2) {
+        return NULL;
     }
-    return Py_XNewRef(r);
+    isfile = ((res == 0) && S_ISREG(st.st_mode));
+#endif
+    return PyBool_FromLong(isfile);
 }
 
 
 static PyObject *
 getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args)
 {
-    PyObject *r = NULL;
     PyObject *pathobj;
-    const wchar_t *path;
-    Py_ssize_t cchPath;
     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         return NULL;
     }
-    path = PyUnicode_AsWideCharString(pathobj, &cchPath);
-    if (path) {
+
+    int isxfile;
 #ifdef MS_WINDOWS
-        DWORD attr = GetFileAttributesW(path);
-        r = (attr != INVALID_FILE_ATTRIBUTES) &&
-            !(attr & FILE_ATTRIBUTE_DIRECTORY) &&
-            (cchPath >= 4) &&
-            (CompareStringOrdinal(path + cchPath - 4, -1, L".exe", -1, 1 /* 
ignore case */) == CSTR_EQUAL)
-            ? Py_True : Py_False;
+    Py_ssize_t cchPath;
+    wchar_t *path = PyUnicode_AsWideCharString(pathobj, &cchPath);
+    if (path == NULL) {
+        return NULL;
+    }
+
+    DWORD attr = GetFileAttributesW(path);
+    PyMem_Free(path);
+    isxfile = (attr != INVALID_FILE_ATTRIBUTES) &&
+              !(attr & FILE_ATTRIBUTE_DIRECTORY) &&
+              (cchPath >= 4) &&
+              (CompareStringOrdinal(path + cchPath - 4, -1, L".exe", -1, 1 /* 
ignore case */) == CSTR_EQUAL);
 #else
-        struct stat st;
-        r = (_Py_wstat(path, &st) == 0) &&
-            S_ISREG(st.st_mode) &&
-            (st.st_mode & 0111)
-            ? Py_True : Py_False;
-#endif
-        PyMem_Free((void *)path);
+    struct stat st;
+    int res = _Py_stat(pathobj, &st);
+    if (res == -2) {
+        return NULL;
     }
-    return Py_XNewRef(r);
+    isxfile = ((res == 0)
+               && S_ISREG(st.st_mode)
+               && (st.st_mode & 0111));
+#endif
+    return PyBool_FromLong(isxfile);
 }
 
 
@@ -340,25 +350,16 @@ getpath_joinpath(PyObject *Py_UNUSED(self), PyObject 
*args)
 static PyObject *
 getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args)
 {
-    PyObject *r = NULL;
     PyObject *pathobj;
-    const wchar_t *path;
     if (!PyArg_ParseTuple(args, "U", &pathobj)) {
         return NULL;
     }
-    path = PyUnicode_AsWideCharString(pathobj, NULL);
-    if (!path) {
-        return NULL;
-    }
-    FILE *fp = _Py_wfopen(path, L"rb");
+    FILE *fp = Py_fopen(pathobj, "rb");
     if (!fp) {
-        PyErr_SetFromErrno(PyExc_OSError);
-        PyMem_Free((void *)path);
         return NULL;
     }
-    PyMem_Free((void *)path);
 
-    r = PyList_New(0);
+    PyObject *r = PyList_New(0);
     if (!r) {
         fclose(fp);
         return NULL;
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 0c1766b8804500..98ed66eff94ee1 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1368,22 +1368,21 @@ _Py_stat(PyObject *path, struct stat *statbuf)
     PyMem_Free(wpath);
     return err;
 #else
-    int ret;
-    PyObject *bytes;
-    char *cpath;
-
-    bytes = PyUnicode_EncodeFSDefault(path);
-    if (bytes == NULL)
+    PyObject *bytes = PyUnicode_EncodeFSDefault(path);
+    if (bytes == NULL) {
         return -2;
+    }
 
     /* check for embedded null bytes */
+    char *cpath;
     if (PyBytes_AsStringAndSize(bytes, &cpath, NULL) == -1) {
         Py_DECREF(bytes);
         return -2;
     }
 
-    ret = stat(cpath, statbuf);
+    int ret = stat(cpath, statbuf);
     Py_DECREF(bytes);
+    assert(ret == 0 || ret == -1);
     return ret;
 #endif
 }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to