classification
Title: Pathlib resolve() resolves non-existent ".." components with strict=False
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: andrei.avk, eamanu, eryksun, john.engelke, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2020-11-25 16:07 by john.engelke, last changed 2021-07-08 14:30 by andrei.avk.

Files
File name Uploaded Description Edit
do_not_resolve_dotdot_nonexistent.patch andrei.avk, 2021-07-08 13:12
Messages (5)
msg381844 - (view) Author: John Engelke (john.engelke) Date: 2020-11-25 16:07
The below snippet results in the symlink "/home" resolving as expected. However, documentation at https://docs.python.org/3.7/library/pathlib.html#pathlib.Path.resolve suggests, "If strict is False, the path is resolved as far as possible and any remainder is appended without checking whether it exists."

>>> from pathlib import Path
>>> host_path_str = "/home/somewhere/there/../nowhere"
>>> host_path = Path(host_path_str)
>>> host_path
PosixPath('/home/somewhere/there/../nowhere')
>>> host_path.resolve()
PosixPath('/System/Volumes/Data/home/somewhere/nowhere')

Expected results (based on the wording above): 

>>> host_path.resolve()
PosixPath('/System/Volumes/Data/home/somewhere/there/../nowhere')

Right now the ".." pieces are universally removed. I'm not exactly sure exactly how symlinks resolve, but this might create unexpected results. 

No part of the path component "somewhere/there/../nowhere" exists. When strict=True this would yield an error. So when strict=False, and it doesn't resolve, documentation implies that would be re-added to the resolved section.
msg386095 - (view) Author: Emmanuel Arias (eamanu) * Date: 2021-02-01 19:42
Hi, 

I don't understand the point here. If you go back on a folder
'..', IMO has more sense remove the '..', that is a way to 
resolve it
msg386118 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021-02-01 21:53
I'd prefer to leave ".." in the path, at least with PosixPath. (It doesn't matter with WindowsPath.) The "there" component may be a symlink that's currently inaccessible. That said, Python's os.path.realpath() has a long history of naively resolving ".." components in the remainder.
msg397138 - (view) Author: Andrei Kulakov (andrei.avk) * (Python triager) Date: 2021-07-08 13:12
Adding a patch that fixes this issue, for future reference. I'm not too sure this would be the right way to solve this. The patch also causes 5 failures in test_posixpath.py that would have to be fixed (most likely all can be fixed by creating respective dirs).
msg397143 - (view) Author: Andrei Kulakov (andrei.avk) * (Python triager) Date: 2021-07-08 14:30
Another solution would be to base it on `strict` parameter:

- strict=True, subpath exists => resolve `..`
- strict=True, subpath doesn't exist => throw OSError
- strict=False => never resolve `..`

This would avoid extra `lstat()` calls but would be a much bigger change in terms of behavior.
History
Date User Action Args
2021-07-08 14:30:01andrei.avksetmessages: + msg397143
2021-07-08 13:12:56andrei.avksetfiles: + do_not_resolve_dotdot_nonexistent.patch

nosy: + andrei.avk
messages: + msg397138

keywords: + patch
2021-02-01 21:53:05eryksunsetnosy: + eryksun
messages: + msg386118
2021-02-01 19:42:59eamanusetnosy: + eamanu
messages: + msg386095
2020-11-28 20:08:22epainesetnosy: + serhiy.storchaka

versions: - Python 3.7
2020-11-25 16:07:29john.engelkecreate