Skip to content

Commit 01b1f82

Browse files
committed
Implement realpath for Windows
1 parent 8987eeb commit 01b1f82

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

Modules/getpath.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,45 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args)
502502
PyMem_Free((void *)path);
503503
PyMem_Free((void *)narrow);
504504
return r;
505+
#elif defined(MS_WINDOWS)
506+
HANDLE hFile;
507+
wchar_t resolved[MAXPATHLEN+1];
508+
int len = 0, err;
509+
PyObject *result;
510+
511+
wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
512+
if (!path) {
513+
return NULL;
514+
}
515+
516+
Py_BEGIN_ALLOW_THREADS
517+
hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
518+
if (hFile != INVALID_HANDLE_VALUE) {
519+
len = GetFinalPathNameByHandleW(hFile, resolved, MAXPATHLEN, VOLUME_NAME_DOS);
520+
err = len ? 0 : GetLastError();
521+
CloseHandle(hFile);
522+
} else {
523+
err = GetLastError();
524+
}
525+
Py_END_ALLOW_THREADS
526+
527+
if (err) {
528+
return PyErr_SetFromWindowsErr(GetLastError());
529+
}
530+
if (len <= MAXPATHLEN) {
531+
const wchar_t *p = resolved;
532+
if (0 == wcsncmp(p, L"\\\\?\\", 4)) {
533+
if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) {
534+
p += 4;
535+
len -= 4;
536+
}
537+
}
538+
result = PyUnicode_FromWideChar(p, len);
539+
} else {
540+
result = Py_NewRef(pathobj);
541+
}
542+
PyMem_Free(path);
543+
return result;
505544
#endif
506545

507546
return Py_NewRef(pathobj);
@@ -898,7 +937,7 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
898937
!library_to_dict(dict, "library") ||
899938
!wchar_to_dict(dict, "executable_dir", NULL) ||
900939
!wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) ||
901-
!funcs_to_dict(dict, 1) || //config->pathconfig_warnings) ||
940+
!funcs_to_dict(dict, config->pathconfig_warnings) ||
902941
#ifndef MS_WINDOWS
903942
PyDict_SetItemString(dict, "winreg", Py_None) < 0 ||
904943
#endif

Modules/getpath.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,6 @@ def search_up(prefix, *landmarks, test=isfile):
358358
venv_prefix = None
359359
pyvenvcfg = []
360360

361-
warn(f"{base_executable=} {venv_prefix=}")
362361
for line in pyvenvcfg:
363362
key, had_equ, value = line.partition('=')
364363
if had_equ and key.strip().lower() == 'home':
@@ -368,7 +367,6 @@ def search_up(prefix, *landmarks, test=isfile):
368367
# more accurate than assuming the executable in 'home'.
369368
try:
370369
base_executable = realpath(executable)
371-
warn(f"{base_executable=} {executable=}")
372370
if base_executable == executable:
373371
# No change, so probably not a link. Clear it and fall back
374372
base_executable = ''

0 commit comments

Comments
 (0)