EZ added the comment:
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)
--
nosy: +Zim -45757
versions: +Python 3.9
___
Python tracker
<https://bugs.python.org/issue39090>
___
___
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com