Eryk Sun added the comment:
ntpath.realpath() has since been implemented, and it addresses the problem by
keeping the extended (verbatim) path prefix in the result if the input argument
has it, and otherwise removing the prefix if the final path resolves correctly
without it.
--
Antoine Pitrou added the comment:
Really, the test for whether to keep or remove the prefix should be to
remove the prefix and try and resolve the path again. If it succeeds,
remove the prefix; otherwise, keep it. This can only really be done as
part of the resolve() call, which would
Steve Dower added the comment:
Another alternative is to always leave the prefix there after calling resolve()
(as opposed to the current behaviour which is to always remove it). If the
Win32 API says that the path should include the prefix, then it should. There's
no reliable way for a
Steve Dower added the comment:
Right, what the prefix actually means is treat this path as a blob and don't
do any processing. Some of the things that 'processing' includes are:
* CWD
* invalid names ('foo.' - 'foo')
* adjacent backslashes ('a\\b' - 'a\b')
* forward slashes ('a/b' - 'a\b')
*
Antoine Pitrou added the comment:
I'm a bit worried about the consequences still. If you take C: and join it
with e.g. foo, you get a drive-relative path. If you take //?/C:/ and join
it with e.g. foo, you get an absolute path (or, if you remove the drive's
trailing slash, you get something
eryksun added the comment:
If you take //?/C:/ and join it with e.g. foo, you get an
absolute path (or, if you remove the drive's trailing slash, you
get something that's invalid AFAIK).
FYI, DOS device names such as C: are NT symlinks. Win32 looks for DOS device
links in NT's \Global??
Antoine Pitrou added the comment:
Since both paths are valid and both paths refer to the same file, some
developers may find this result counterintuitive.
On the other hand the proposed solution is regular. If you input an extended
path, you get an extended path as output.
There are other
Steve Dower added the comment:
Actually, I'd be inclined to never use the prefix within pathlib and then add
it on if necessary when converting to a string. That would also solve a problem
like:
p = Path(C:\\) / ('a'*150) / ('a'*150)
p.stat()
FileNotFoundError: [WinError 3] The system
Steve Dower added the comment:
If anyone wanted to test that really long path, here's the incantation to
create it:
import os, pathlib
os.mkdir(C:\\a)
os.mkdir(C:\\a\\ + a*150)
os.rename(C:\\a, C:\\ + a*150)
p = pathlib.Path(C:\\) / (a*150) / (a*150)
--
Antoine Pitrou added the comment:
I'd be inclined to never use the prefix within pathlib and then add it on if
necessary when converting to a string
That may be very surprising when that prefix appears, though... At least with
explicit methods the user would have to invoke them, instead of
Steve Dower added the comment:
It's no less expected than having OS functions fail because the path is too
long.
Using it to maintain dots at the end of directory/file names is a little less
safe and may break some code. Maybe pathlib should strip these if there is no a
prefix? (For example,
Antoine Pitrou added the comment:
If most (or all) of the file handling functions in Python are using *W() APIs
and can support the prefix, I'd rather add it in silently if only to avoid
the long path issue.
This would only work for fully-qualified paths, right? Not relative ones.
I'm all
Steve Dower added the comment:
This would only work for fully-qualified paths, right? Not relative ones.
Correct, and I think we're most of the way there with how drives are handled.
Since the prefix only works with absolute paths, why not treat it as part of
the drive name?
--
Steve Dower added the comment:
Patch attached. (Kinda feel like this was too simple...)
--
keywords: +patch
Added file: http://bugs.python.org/file36549/22299_1.patch
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
eryksun added the comment:
It should only skip _ext_to_normal for an already extended path, i.e. a path
that starts with ext_namespace_prefix. Otherwise it needs to call
_ext_to_normal. For example:
Strip the prefix in this case:
os.path._getfinalpathname('C:\\Windows')
Steve Dower added the comment:
Ah, thought it was too simple. I didn't realise that _getfinalpathname adds the
prefix.
New patch soon.
--
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
Steve Dower added the comment:
Strips the prefix if it wasn't in the original path - otherwise, keeps it.
--
Added file: http://bugs.python.org/file36550/22299_2.patch
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
Antoine Pitrou added the comment:
As far as I can say, the patch looks fine to me. Thanks, Steve.
--
stage: needs patch - patch review
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
___
Kevin Norris added the comment:
I'm a little concerned about this fix. In particular, if I understand the
design of the patch correctly, it is intended to produce this behavior:
Path('C:/foo').resolve() != Path('//?/C:/foo').resolve()
Since both paths are valid and both paths refer to
eryksun added the comment:
Maybe for an extended path it could try _getfinalpathname without the prefix.
If it isn't a valid path or the result isn't the same as _getfinalpathname
including the prefix, then skip calling _ext_to_normal. For example:
def resolve(self, path):
s =
New submission from Kevin Norris:
Run Python as an administrator:
import pathlib
pth = pathlib.Path('//?/C:/foo.')
pth.mkdir()
pth.resolve().rmdir()
Traceback (most recent call last):
File stdin, line 1, in module
File C:\Python34\lib\pathlib.py, line 1141,
Kevin Norris added the comment:
When the directory name is '...', the error is different:
pth = pathlib.Path('//?/C:/...')
pth.mkdir()
pth.resolve().rmdir()
Traceback (most recent call last):
File stdin, line 1, in module
File C:\Python34\lib\pathlib.py, line
Changes by Terry J. Reedy tjre...@udel.edu:
--
nosy: +pitrou
stage: - test needed
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
___
___
Antoine Pitrou added the comment:
Why is it a pathological path? Can you explain?
--
nosy: +steve.dower, tim.golden, zach.ware
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
___
Steve Dower added the comment:
Is resolve() using an *A() API rather than *W()? The \\?\ prefix does not work
with *A() APIs.
Also, names that are all dots are not supported by Windows at all. I'd expect
mkdir() to fail on that, but the \\?\ prefix disables some validation, so it's
possible
Antoine Pitrou added the comment:
resolve() should use the *W APIs since it is using only functions from the os
module with str objects. Perhaps you want to double-check that, since I don't
have a Windows VM anymore.
--
___
Python tracker
eryksun added the comment:
The \\?\ extended-path prefix bypasses normal path processing. The path is
passed directly to the filesystem driver. For example, to accommodate the POSIX
namespace, NTFS allows any character except NUL and slash, so it happily
creates a directory named foo.. This
Steve Dower added the comment:
Removing the _ext_to_normal() call in resolve() looks like the right fix to me.
--
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
___
Antoine Pitrou added the comment:
Does one of you want to provide a patch? (with tests)
--
stage: test needed - needs patch
versions: +Python 3.5
___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22299
29 matches
Mail list logo