Bug report
In pathlib prior to Python 3.12, passing a PureWindowsPath to a PurePosixPath resulted in the Windows separator (\) being converted to the POSIX separator (/). However, in the current main branch the backslashes are preserved in the PurePosixPath object.
Here is an example which illustrates this:
Python 3.12.0a7 (tags/v3.12.0a7:b861ba4, Apr 6 2023, 16:09:18) [Clang 10.0.0 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> print(pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c")))
a\b\c
>>> print(pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c")).as_posix())
a\b\c
Python 3.11.2 (tags/v3.11.2:878ead1, Mar 9 2023, 16:26:59) [Clang 10.0.0 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> print(pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c")))
a/b/c
>>> print(pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c")).as_posix())
a/b/c
(The behaviour is the same if using PosixPath or WindowsPath on the relevant platform; it's not specific to the "pure" variants.)
Before the recent refactoring of the module, passing one Path or PurePath 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 path a\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 with os.sep, which for WindowsPath replaces / with \ but for PosixPath does nothing as there is no alternative separator. However, the following will produce a correct result:
Python 3.12.0a7+ (heads/main:bd2ed06, Apr 19 2023, 15:27:47) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> pathlib.PurePosixPath._flavour.altsep = "\\"
>>> pathlib.PurePosixPath(pathlib.PureWindowsPath(r"a\b\c")).as_posix()
'a/b/c'
Thus I think the problem can be isolated to these lines here:
|
@classmethod |
|
def _parse_path(cls, path): |
|
if not path: |
|
return '', '', [] |
|
sep = cls._flavour.sep |
|
altsep = cls._flavour.altsep |
|
if altsep: |
|
path = path.replace(altsep, sep) |
|
drv, root, rel = cls._flavour.splitroot(path) |
Your environment
- CPython versions tested on: 3.8, 3.11 and 3.12 (alpha 7 and HEAD)
- Operating system and architecture: Ubuntu 20.04 and Windows 10
Linked PRs
Bug report
In
pathlibprior to Python 3.12, passing aPureWindowsPathto aPurePosixPathresulted in the Windows separator (\) being converted to the POSIX separator (/). However, in the current main branch the backslashes are preserved in thePurePosixPathobject.Here is an example which illustrates this:
(The behaviour is the same if using
PosixPathorWindowsPathon the relevant platform; it's not specific to the "pure" variants.)Before the recent refactoring of the module, passing one
PathorPurePathobject to another resulted in the_partsattribute being inspected. This was a list of the individual path elements (e.g.['a', 'b', 'c']for the patha\b\c). The_partsattribute was removed in GH-102476 and replaced with_tail, but with slightly different semantics.The current code replaces any
os.altsepin the path withos.sep, which forWindowsPathreplaces/with\but forPosixPathdoes 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) #104991