-
-
Notifications
You must be signed in to change notification settings - Fork 30.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PurePosixPath no longer correctly parses PureWindowsPath #103631
Comments
If constructing a POSIX path directly from a Windows path is supported, it won't be implemented by adding backslash as an alternate path separator for POSIX paths. Backslash is a normal name character in POSIX, not a reserved path separator. As a workaround, you can get a POSIX path before passing the path to the >>> pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c").as_posix())
PurePosixPath('a/b/c') |
Only for relative paths. If you try to pass an absolute path, things quickly go south: barney@acorn ~ $ python3.8
Python 3.8.10 (default, Mar 13 2023, 10:26:41)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> pathlib.PurePosixPath(pathlib.PureWindowsPath(r"c:\a\b\c"))
PurePosixPath('c:\\/a/b/c')
>>> pathlib.PurePosixPath(pathlib.PureWindowsPath(r"\\server\share\a\b\c"))
PurePosixPath('\\\\server\\share\\/a/b/c') |
FYI, the behaviour was changed in #101667 and #102454 in order to fix this bug: As a result, these all do the same thing: >>> from pathlib import PurePosixPath, PureWindowsPath
>>> from os import fspath
>>> PurePosixPath(r"c:\a\b\c")
PurePosixPath('c:\\a\\b\\c')
>>> PurePosixPath(PureWindowsPath(r"c:\a\b\c"))
PurePosixPath('c:\\a\\b\\c')
>>> PurePosixPath(fspath(PureWindowsPath(r"c:\a\b\c")))
PurePosixPath('c:\\a\\b\\c') We tweaked the docs slightly to make clear that all diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst
index c8a734ecad8e..8e91936680fa 100644
--- a/Doc/library/pathlib.rst
+++ b/Doc/library/pathlib.rst
@@ -105,8 +105,9 @@ we also call *flavours*:
PurePosixPath('setup.py')
Each element of *pathsegments* can be either a string representing a
- path segment, an object implementing the :class:`os.PathLike` interface
- which returns a string, or another path object::
+ path segment, or an object implementing the :class:`os.PathLike` interface
+ where the :meth:`~os.PathLike.__fspath__` method returns a string,
+ such as another path object::
>>> PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar') Eryk's suggestion looks ideal to me, and clearly signals intentions. |
The problem with this is it means your code has to be system-aware. The case I've run across this, just figuring out it was broken now, uses a |
Hm! Backslashes can appear in Posix filenames. How would I specify such a path in your file of pathnames? Or is that not a problem because you create all these paths from within your program? |
For your use case, would this work? pathlib.Path(pathlib.PureWindowsPath(yourpath).as_posix())
Alternatively: pathlib.Path(yourpath.replace('\\', '/')) |
The usecase is more specifically a list of tests to run (cmdline or from a file), and we know we're not creating tests with particularly "odd" names, so it's a (somewhat) controlled namespace. We've wanted to display the names the way they were entered if they were on Windows, so if someone actually typed |
Gotcha.
|
…handling For backwards compatibility, accept backslashes as path separators in `PurePosixPath` if an instance of `PureWindowsPath` is supplied.
Upon further consideration I don't think this is worth the backwards-compatibility break. PR up: #104949 |
…ng (GH-104949) For backwards compatibility, accept backslashes as path separators in `PurePosixPath` if an instance of `PureWindowsPath` is supplied. This restores behaviour from Python 3.11. Co-authored-by: Gregory P. Smith <greg@krypto.org>
…handling (pythonGH-104949) For backwards compatibility, accept backslashes as path separators in `PurePosixPath` if an instance of `PureWindowsPath` is supplied. This restores behaviour from Python 3.11. (cherry picked from commit 328422c) Co-authored-by: Barney Gale <barney.gale@gmail.com> Co-authored-by: Gregory P. Smith <greg@krypto.org>
… handling (GH-104949) (GH-104991) For backwards compatibility, accept backslashes as path separators in `PurePosixPath` if an instance of `PureWindowsPath` is supplied. This restores behaviour from Python 3.11. (cherry picked from commit 328422c) Co-authored-by: Barney Gale <barney.gale@gmail.com> Co-authored-by: Gregory P. Smith <greg@krypto.org>
Thanks for reporting + discussing, all. This is fixed in:
3.12 beta 2 should contain the fix. |
Bug report
In
pathlib
prior to Python 3.12, passing aPureWindowsPath
to aPurePosixPath
resulted in the Windows separator (\
) being converted to the POSIX separator (/
). However, in the current main branch the backslashes are preserved in thePurePosixPath
object.Here is an example which illustrates this:
(The behaviour is the same if using
PosixPath
orWindowsPath
on the relevant platform; it's not specific to the "pure" variants.)Before the recent refactoring of the module, passing one
Path
orPurePath
object to another resulted in the_parts
attribute being inspected. This was a list of the individual path elements (e.g.['a', 'b', 'c']
for the patha\b\c
). The_parts
attribute was removed in GH-102476 and replaced with_tail
, but with slightly different semantics.The current code replaces any
os.altsep
in the path withos.sep
, which forWindowsPath
replaces/
with\
but forPosixPath
does nothing as there is no alternative separator. However, the following will produce a correct result:Thus I think the problem can be isolated to these lines here:
cpython/Lib/pathlib.py
Lines 316 to 324 in da2273f
Your environment
Linked PRs
PurePosixPath(PureWindowsPath(...))
separator handling #104949PurePosixPath(PureWindowsPath(...))
separator handling (GH-104949) #104991The text was updated successfully, but these errors were encountered: