This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Zim
Recipients 4-launchpad-kalvdans-no-ip-org, ChrisBarker, John-Hennig, Zim, brett.cannon, docs@python, florisla, paul.moore, veky
Date 2022-03-31.23:03:08
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1648767788.61.0.384549326508.issue39090@roundup.psfhosted.org>
In-reply-to
Content
First, I hope we all agree:
'C:\Windows' and '/usr/bin' == absolute path
'Windows' and 'bin' == relative path
'C:\Program Files' and '/bin' == absolute path
'C:\Windows\..\Program Files' and '/usr/../bin' == relative path

It is very confusing between these two, but despite claims otherwise, absolute() does not work as expected. However, to sum up the findings below: 
* absolute() fails to resolve paths with relative steps (esp "..") but will always add the dir structure even if the file doesn't exist.
* resolve() will always give an absolute path.
** unless the file doesn't exist -- 
** unless unless the path includes a '..'! 
* There's also a related problem with is_absolute() being incorrect with relative paths (such as '..'), which usually results in it saying absolute().is_absolute() is True when it is obviously False.

Done on Windows 10, python 3.9.5

>>> ini
WindowsPath('desktop.ini/..')
>>> ini.resolve().is_absolute()
True
>>> ini.absolute()
WindowsPath('C:/Users/zim/Downloads/desktop.ini/..')
>>> ini.absolute().is_absolute()
True

This second should not be True, there is a trailing '..' not resolved by absolute()

Now let's create a truly messy path:
>>> ini.resolve()
WindowsPath('C:/Users/zim/Downloads')
>>> ini = ini / "ntuser.ini"
>>> ini.exists()
False
>>> ini.resolve()
WindowsPath('C:/Users/zim/Downloads/ntuser.ini')
>>> ini = ini / "../ntuser.ini"
>>> ini.exists()
False
>>> ini.resolve()
WindowsPath('C:/Users/zim/Downloads/ntuser.ini')
>>> ini = ini / "../../ntuser.ini"
>>> ini.resolve()
WindowsPath('C:/Users/zim/ntuser.ini')
>>> ini.exists()
True
>>> ini.absolute()
WindowsPath('C:/Users/zim/Downloads/desktop.ini/../ntuser.ini/../ntuser.ini/../../ntuser.ini')
>>> ini.absolute().is_absolute()
True

absolute() not only doesn't give an absolute path, but is_absolute() is somehow ok with that.

Now a file that doesn't exist:
>>> mike = Path("palin.jpg")
>>> mike.resolve()
WindowsPath('palin.jpg')
>>> mike.resolve().is_absolute()
False
>>> mike.absolute()
WindowsPath('C:/Users/zim/Downloads/palin.jpg')
>>> mike.absolute().is_absolute()
True

Finally, absolute() is right about the right thing, but resolve() is not terribly wrong. is_absolute() is correctly False here (for once). 

The problem is that the after a resolve() call, a Path object can still be used to create a file (good), but if resolve() is used before file creation, then the full path will not be there as should be expected (bad). This seems like a bug with resolve()

What if a file is non existent AND relative? Things get more confusing.

>>> badrel = Path('../circus.jpg')
>>> badrel
WindowsPath('../circus.jpg')
>>> badrel.absolute()
WindowsPath('C:/Users/zim/Downloads/../circus.jpg')
>>> badrel.resolve()
WindowsPath('C:/Users/zim/circus.jpg')
>>> badrel.exists()
False

So, absolute() still acts like the normal trash fire it is with relative paths, but what's this, resolve() actually gives an absolute path?!

I should note resolve() only behaves unpredictably on Windows. It correctly resolves non-existent files no matter what on macOS and Linux (caveat: my linux test was done with python 3.6). However, absolute() always fails to distill paths with relative steps regardless of OS.

So, it seems clear:
Bug 1: resolve() should work the same with non-existent files with incomplete paths on Windows as it does on *nix platforms, as it does on Windows when handling existent files and non-existent ones with parent path notation.
Bug 2: Obviously if absolute() is supposed to be in the lib, it should be documented, and it likely should be distinct from resolve(), but most of all: it should return actual absolute paths! If these cannot be fulfilled, it should be set to be deprecated (after resolve() is fixed, hopefully)
Bug 3: is_absolute() should actually detect absolute paths, instead it seems to report True if the path contains a root starting point, but ignores relative changes in between. (this issue exists on all three major OSs)
History
Date User Action Args
2022-03-31 23:03:08Zimsetrecipients: + Zim, brett.cannon, paul.moore, docs@python, veky, ChrisBarker, 4-launchpad-kalvdans-no-ip-org, florisla, John-Hennig
2022-03-31 23:03:08Zimsetmessageid: <1648767788.61.0.384549326508.issue39090@roundup.psfhosted.org>
2022-03-31 23:03:08Zimlinkissue39090 messages
2022-03-31 23:03:08Zimcreate