Windows documents that symlinks can target root-relative paths, for example \Target.
Python abides, and if the symlink is C:\Path\Symlink to \Target then C:\Target is used by os.stat and just about every built-in function and module.
The problem is that in reality, in Windows 10 and I think since a long time ago, the shell treats all relative paths the same.
Basically, they normalize C:\Path\Symlink\..\Target which in Windows is purely lexical and .. just removes the previous name.
The actual behavior in Windows Explorer and if you open the symlink’s properties is that it resolves to C:\Path\Target and not C:\Target.
What should take precedence, the documentation or the longstanding behavior?
Should Python at least use the OS version to match the actual end-user experience when reading symlinks, which I think is all versions?
Should it just fail on any root-relative symlink due to ambiguity and not end up in the wrong location?
I wish I could. GetFinalPathNameByHandleA is very convenient, but it does have bugs related to root-relative paths.
In C, if I could do it, I would resolve DOS paths walking the path like POSIX, applying symlinks encountered, and at the end calling GetFinalPathNameByHandleA to get the case-sensitive value.
But I wonder if it could be addressed at the Python level, when using os.realpath.
If you use os.readlink, you either get an absolute path, or a relative one, but relative to what?
It’s not relative to the CWD but relative to the symlink’s path, so there’s code path applies ntpath.join to it.
Should it just apply .. to relative symlinks?
Also it is not appropiate to impose the Posix rules on a Windows system.
To clarify, I did not mean to impose the rules, just meant iterating through each component kinda like ntpath.realpath does, but in C, if there’s no C/C++ APIs that treat the symlinks as Windows Explorer.
I suppose you mean not for dot and dot-dot components, and trailing slashes.
My view (not a core dev) is that python must use the Win32 API under the os module.
I think that’s perfectly valid. I’d be interesing for me to get opinions about this Win32 API bug, reported here.
The API, exposed with nt._getfullpathname, can make paths with a single leading slash into UNC paths. That’s without following symlinks, but it’s the same behavior as GetFinalPathNameByHandleW.
That’s clearly wrong.
If it was an open-sourced API then it be better to report or contribute to that project and it would hopefully trickle down to OS distributions. Could the same be said about a Win32 API?
Would it be better for Python to develop its own C functions that replace or wrap GetFullPathNameW and GetFinalPathNameByHandleW so it has control over it’s bugs?