From ca4b741daa0feb0aa65cef886a0de629fe584d78 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 3 Feb 2025 14:02:13 +0000 Subject: [PATCH] gh-12933: fix import error over nfs on Windows On Windows, realpath uses `GetFinalPathNameByHandleW` to resolve paths. This returns paths starting with a `\\?\` prefix, which is usually not what we want. This change attempts to remove the prefix for \\?\UNC\ paths. A similar thing was already done for drive paths such as \\?\C:\. --- Misc/ACKS | 1 + ...-02-01-01-30-10.gh-issue-129333.tnKrqz.rst | 1 + Modules/getpath.c | 21 +++++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2025-02-01-01-30-10.gh-issue-129333.tnKrqz.rst diff --git a/Misc/ACKS b/Misc/ACKS index 47c8d2b40aafb7..deb437b99000eb 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -439,6 +439,7 @@ Erik Demaine Jeroen Demeyer Martin Dengler John Dennis +Chris Denton L. Peter Deutsch Roger Dev Philippe Devalkeneer diff --git a/Misc/NEWS.d/next/Windows/2025-02-01-01-30-10.gh-issue-129333.tnKrqz.rst b/Misc/NEWS.d/next/Windows/2025-02-01-01-30-10.gh-issue-129333.tnKrqz.rst new file mode 100644 index 00000000000000..3d4dd1e27f460c --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2025-02-01-01-30-10.gh-issue-129333.tnKrqz.rst @@ -0,0 +1 @@ +Fixes import error when running Python from a network drive diff --git a/Modules/getpath.c b/Modules/getpath.c index e2478da021f511..f22bad9a304954 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -540,11 +540,24 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args) PyErr_SetFromWindowsErr(err); result = NULL; } else if (len <= MAXPATHLEN) { - const wchar_t *p = resolved; + wchar_t *p = resolved; if (0 == wcsncmp(p, L"\\\\?\\", 4)) { - if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) { - p += 4; - len -= 4; + if (0 == wcsncmp(&p[4], L"UNC\\", 4)) { + // A \\?\UNC\ path. Try converting to a \\ path. + p[6] = L'\\'; + if (GetFileAttributesW(&p[6]) != INVALID_FILE_ATTRIBUTES) { + p += 6; + len -= 6; + } else { + // Change back to a \\?\UNC\ path. + p[6] = L'C'; + } + } else { + // Maybe a drive path like \\?\C:\. Try stripping the prefix. + if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) { + p += 4; + len -= 4; + } } } if (CompareStringOrdinal(path, (int)pathlen, p, len, TRUE) == CSTR_EQUAL) {