Dangerous design of Path, from pathlib

Hi,

I just spent fifteen minutes debugging a problem in my code, it boils down to the fact that when you concate nate two paths, if the latter has a leading slash, the concatenation is not done and the latter path is taken, i.e.

>>>
>>> from pathlib import Path
>>>
>>> a = Path('/x/y/z')
>>> b = Path('p/q/r')
>>>
>>> a / b
PosixPath('/x/y/z/p/q/r')
>>>
>>>
>>> b = Path('/p/q/r')
>>>
>>> a / b
PosixPath('/p/q/r')
>>>

I think this should not happen and the path should just eliminate the leading slash in the next path, or at least I would rais an exception.

Cheers.

3 Likes

It agrees with interpreting the operation / as “standing at a, follow b”.
Because b is absolute, it doesn’t matter what a was.

If one reads the parts of a path as telling directions of where to go, this would be the concatenation of the sequences of directions.

1 Like

When I replicated your test, I observed something slightly different. Perhaps this is OS dependent?

In Windows that b is not absolute. If you try something like r'C:\p\q\r', it should keep b.

Another case to take into account is a being a PosixPath and b being an absolute PureWindowsPath. In that case a/b also doesn’t just keep b. I think because it first interprets b as a path of the same type as a, and there it is not absolute.

PosixPath('/x/y/z') / PureWindowsPath(r'C:\p\q\r')  # = PosixPath('/x/y/z/C:/p/q/r')

PureWindowsPath('/x/y/z') / PureWindowsPath('C:/p/q/r')  # = PureWindowsPath('C:/p/q/r')
1 Like

Yes, exactly. Moreover, the behavior is documented, so people can legitimately rely on this feature.

/ is the root on Posix. Shouldn’t appending /foo to another path error, or does Windows need to do that for some cursed reason?

Regardless, eliminating leading slashes is a bad idea - that’s not a redundant os.sep, that’s a crucial piece of information.

Path.joinpath behaves the same. I’m not suggesting a breaking change should be made.

Is there demand for a safe method (or optional args to joinpath) that doesn’t discard the leading slash and errors? Or for a way to append a root path ignoring its root, always producing a child path? I realise I’m interchanging path to mean both pathlib.Path and ‘string of a posix file path’.

The second b doesn’t start with /

Everything to do with Windows paths is cursed, so, yes, it is. The path "C:/spam" is absolute; the path "C:spam" is not, and the path "/spam" is not. Or rather, they’re partly absolute. Awesome, isn’t it?

2 Likes

I’ve been bitten by Windows Paths being case insensitive before, and keeping their original name even when renamed to switch the case of a few characters.