mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
GH-110109: pathlib ABCs: do not vary path syntax by host OS. (#113219)
Change the value of `pathlib._abc.PurePathBase.pathmod` from `os.path` to `posixpath`. User subclasses of `PurePathBase` and `PathBase` previously used the host OS's path syntax, e.g. backslashes as separators on Windows. This is wrong in most use cases, and likely to catch developers out unless they test on both Windows and non-Windows machines. In this patch we change the default to POSIX syntax, regardless of OS. This is somewhat arguable (why not make all aspects of syntax abstract and individually configurable?) but an improvement all the same. This change has no effect on `PurePath`, `Path`, nor their subclasses. Only private APIs are affected.
This commit is contained in:
parent
ff5e131df5
commit
a0d3d3ec9d
4 changed files with 87 additions and 60 deletions
|
@ -2,8 +2,10 @@ import io
|
|||
import os
|
||||
import sys
|
||||
import errno
|
||||
import ntpath
|
||||
import pathlib
|
||||
import pickle
|
||||
import posixpath
|
||||
import socket
|
||||
import stat
|
||||
import tempfile
|
||||
|
@ -39,6 +41,50 @@ if hasattr(os, 'geteuid'):
|
|||
class PurePathTest(test_pathlib_abc.DummyPurePathTest):
|
||||
cls = pathlib.PurePath
|
||||
|
||||
# Make sure any symbolic links in the base test path are resolved.
|
||||
base = os.path.realpath(TESTFN)
|
||||
|
||||
def test_concrete_class(self):
|
||||
if self.cls is pathlib.PurePath:
|
||||
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
|
||||
else:
|
||||
expected = self.cls
|
||||
p = self.cls('a')
|
||||
self.assertIs(type(p), expected)
|
||||
|
||||
def test_concrete_pathmod(self):
|
||||
if self.cls is pathlib.PurePosixPath:
|
||||
expected = posixpath
|
||||
elif self.cls is pathlib.PureWindowsPath:
|
||||
expected = ntpath
|
||||
else:
|
||||
expected = os.path
|
||||
p = self.cls('a')
|
||||
self.assertIs(p.pathmod, expected)
|
||||
|
||||
def test_different_pathmods_unequal(self):
|
||||
p = self.cls('a')
|
||||
if p.pathmod is posixpath:
|
||||
q = pathlib.PureWindowsPath('a')
|
||||
else:
|
||||
q = pathlib.PurePosixPath('a')
|
||||
self.assertNotEqual(p, q)
|
||||
|
||||
def test_different_pathmods_unordered(self):
|
||||
p = self.cls('a')
|
||||
if p.pathmod is posixpath:
|
||||
q = pathlib.PureWindowsPath('a')
|
||||
else:
|
||||
q = pathlib.PurePosixPath('a')
|
||||
with self.assertRaises(TypeError):
|
||||
p < q
|
||||
with self.assertRaises(TypeError):
|
||||
p <= q
|
||||
with self.assertRaises(TypeError):
|
||||
p > q
|
||||
with self.assertRaises(TypeError):
|
||||
p >= q
|
||||
|
||||
def test_constructor_nested(self):
|
||||
P = self.cls
|
||||
P(FakePath("a/b/c"))
|
||||
|
@ -958,6 +1004,19 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
|
|||
self.addCleanup(os_helper.rmtree, d)
|
||||
return d
|
||||
|
||||
def test_matches_pathbase_api(self):
|
||||
our_names = {name for name in dir(self.cls) if name[0] != '_'}
|
||||
path_names = {name for name in dir(pathlib._abc.PathBase) if name[0] != '_'}
|
||||
self.assertEqual(our_names, path_names)
|
||||
for attr_name in our_names:
|
||||
if attr_name == 'pathmod':
|
||||
# On Windows, Path.pathmod is ntpath, but PathBase.pathmod is
|
||||
# posixpath, and so their docstrings differ.
|
||||
continue
|
||||
our_attr = getattr(self.cls, attr_name)
|
||||
path_attr = getattr(pathlib._abc.PathBase, attr_name)
|
||||
self.assertEqual(our_attr.__doc__, path_attr.__doc__)
|
||||
|
||||
def test_concrete_class(self):
|
||||
if self.cls is pathlib.Path:
|
||||
expected = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue