Eryk Sun <eryk...@gmail.com> added the comment:

Paul, I agree that joining Path(".") and Path("c:a") should yield Path("c:a"). 
However, I disagree that we should always be able to construct Path("a/b") from 
components Path("a") and Path("b"). It doesn't apply to Path("./c:a"). There's 
no way to split it up as the joining of two pathlib paths because there is no 
way to represent "c:a" by itself as anything other than a drive-relative path. 
The name "./c:a" has to be taken as a unit, which is fundamentally different 
from "c:a". pathlib agrees:

    >>> p1 = Path('./c:a')
    >>> p1
    WindowsPath('c:a')
    >>> [p1.drive, p1.root, p1.parts]
    ['', '', ('c:a',)]

    >>> p2 = Path('.') / Path('c:a')
    >>> p2
    WindowsPath('c:a')
    >>> [p2.drive, p2.root, p2.parts]
    ['c:', '', ('c:', 'a')]

Path('./c:a') is correctly parsed as a relative filename (no root and no 
drive). So, if it helps any, on the PR I wasn't requesting to change how it's 
parsed. The ambiguity is due to the way pathlib always collapses all "." 
components. I would like it to retain an initial "." component. That way the 
string representation will come out correctly as ".\\c:a" as opposed to the 
drive-relative path "c:a". 

Some Windows API and runtime library functions behave differently depending 
whether a relative path has a leading "." or ".." component. We're at a 
disadvantage if we throw this information away. For example, "./spam/eggs.ext" 
and "spam/eggs.ext" can yield different results when searching for the file via 
SearchPathW, CreateProcessW (if using lpCommandLine, not lpApplicationName), or 
LoadLibraryExW (data/image DLL loading, not normal module loading). 
"./spam/eggs.ext" will be resolved relative to the process working directory, 
but "spam/eggs.ext" will be tried against every directory in the default file, 
executable, or library search path, which may not even include the working 
directory. (The latter behavior is unique to Windows. POSIX never searches for 
a name with a slash in it.)

The CreateProcessW case is a generalization of the case that we're used to 
across various platforms, in which, for the sake of security, the "." entry is 
excluded from PATH. In this case, the only way to run an executable in the 
working directory is to reference it explicitly. For example (in Linux):

    >>> p = Path('./test.sh')
    >>> open(p, 'w').write('#!/bin/sh\necho spam\n')
    20
    >>> os.chmod(p, 0o700)
    >>> subprocess.call(['./test.sh'])
    spam
    0
    >>> try: subprocess.call([str(p)])
    ... except FileNotFoundError: print('eggs')
    ... 
    eggs
    >>> str(p)
    'test.sh'

This would work if pathlib kept the initial "." component.

An example where we currently retain information that's not obviously needed is 
with ".." components. Even Path.absolute() retains ".." components. It's 
important in POSIX. For example, "spam/../eggs" shouldn't be reduced to "eggs" 
because "spam" might be a symlink. This doesn't generally matter in Windows, 
since it normalizes paths in user mode as strings before they're passed to the 
kernel, but we still don't throw the information away because it could be 
useful to code that implements POSIX-like behavior.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36305>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to