Skip to content

Commit 002259f

Browse files
committed
pythonGH-112675: Move path joining tests into test_posixpath and test_ntpath
In `test_pathlib`, the `check_drive_root_parts` test methods evaluated both joining and parsing/normalisation of paths. This dates from a time when pathlib implemented both functions itself, but nowadays path joining is done with `posixpath.join()` and `ntpath.join()`. This commit moves the joining-related test cases into `test_posixpath` and `test_ntpath`.
1 parent 09505c5 commit 002259f

File tree

3 files changed

+96
-106
lines changed

3 files changed

+96
-106
lines changed

Lib/test/test_ntpath.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ def test_join(self):
256256
tester('ntpath.join("a", "b", "c")', 'a\\b\\c')
257257
tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c')
258258
tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c')
259+
tester('ntpath.join("a", "b", "c\\")', 'a\\b\\c\\')
259260
tester('ntpath.join("a", "b", "\\c")', '\\c')
260261
tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep')
261262
tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b')
@@ -313,6 +314,16 @@ def test_join(self):
313314
tester("ntpath.join('\\\\computer\\', 'share')", '\\\\computer\\share')
314315
tester("ntpath.join('\\\\computer\\share\\', 'a')", '\\\\computer\\share\\a')
315316
tester("ntpath.join('\\\\computer\\share\\a\\', 'b')", '\\\\computer\\share\\a\\b')
317+
# Second part is anchored, so that the first part is ignored.
318+
tester("ntpath.join('a', 'Z:b', 'c')", 'Z:b\\c')
319+
tester("ntpath.join('a', 'Z:\\b', 'c')", 'Z:\\b\\c')
320+
tester("ntpath.join('a', '\\\\b\\c', 'd')", '\\\\b\\c\\d')
321+
# Second part has a root but not drive.
322+
tester("ntpath.join('a', '\\b', 'c')", '\\b\\c')
323+
tester("ntpath.join('Z:/a', '/b', 'c')", 'Z:\\b\\c')
324+
tester("ntpath.join('//?/Z:/a', '/b', 'c')", '\\\\?\\Z:\\b\\c')
325+
tester("ntpath.join('D:a', './c:b')", 'D:a\\.\\c:b')
326+
tester("ntpath.join('D:/a', './c:b')", 'D:\\a\\.\\c:b')
316327

317328
def test_normpath(self):
318329
tester("ntpath.normpath('A//////././//.//B')", r'A\B')

Lib/test/test_pathlib.py

Lines changed: 65 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -157,45 +157,30 @@ def with_segments(self, *pathsegments):
157157
for parent in p.parents:
158158
self.assertEqual(42, parent.session_id)
159159

160-
def _get_drive_root_parts(self, parts):
161-
path = self.cls(*parts)
162-
return path.drive, path.root, path.parts
163-
164-
def _check_drive_root_parts(self, arg, *expected):
160+
def _check_parse_path(self, raw_path, *expected):
165161
sep = self.pathmod.sep
166-
actual = self._get_drive_root_parts([x.replace('/', sep) for x in arg])
162+
actual = self.cls._parse_path(raw_path.replace('/', sep))
167163
self.assertEqual(actual, expected)
168164
if altsep := self.pathmod.altsep:
169-
actual = self._get_drive_root_parts([x.replace('/', altsep) for x in arg])
165+
actual = self.cls._parse_path(raw_path.replace('/', altsep))
170166
self.assertEqual(actual, expected)
171167

172-
def test_drive_root_parts_common(self):
173-
check = self._check_drive_root_parts
168+
def test_parse_path_common(self):
169+
check = self._check_parse_path
174170
sep = self.pathmod.sep
175-
# Unanchored parts.
176-
check((), '', '', ())
177-
check(('a',), '', '', ('a',))
178-
check(('a/',), '', '', ('a',))
179-
check(('a', 'b'), '', '', ('a', 'b'))
180-
# Expansion.
181-
check(('a/b',), '', '', ('a', 'b'))
182-
check(('a/b/',), '', '', ('a', 'b'))
183-
check(('a', 'b/c', 'd'), '', '', ('a', 'b', 'c', 'd'))
184-
# Collapsing and stripping excess slashes.
185-
check(('a', 'b//c', 'd'), '', '', ('a', 'b', 'c', 'd'))
186-
check(('a', 'b/c/', 'd'), '', '', ('a', 'b', 'c', 'd'))
187-
# Eliminating standalone dots.
188-
check(('.',), '', '', ())
189-
check(('.', '.', 'b'), '', '', ('b',))
190-
check(('a', '.', 'b'), '', '', ('a', 'b'))
191-
check(('a', '.', '.'), '', '', ('a',))
192-
# The first part is anchored.
193-
check(('/a/b',), '', sep, (sep, 'a', 'b'))
194-
check(('/a', 'b'), '', sep, (sep, 'a', 'b'))
195-
check(('/a/', 'b'), '', sep, (sep, 'a', 'b'))
196-
# Ignoring parts before an anchored part.
197-
check(('a', '/b', 'c'), '', sep, (sep, 'b', 'c'))
198-
check(('a', '/b', '/c'), '', sep, (sep, 'c'))
171+
check('', '', '', [])
172+
check('a', '', '', ['a'])
173+
check('a/', '', '', ['a'])
174+
check('a/b', '', '', ['a', 'b'])
175+
check('a/b/', '', '', ['a', 'b'])
176+
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
177+
check('a/b//c/d', '', '', ['a', 'b', 'c', 'd'])
178+
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
179+
check('.', '', '', [])
180+
check('././b', '', '', ['b'])
181+
check('a/./b', '', '', ['a', 'b'])
182+
check('a/./.', '', '', ['a'])
183+
check('/a/b', '', sep, ['a', 'b'])
199184

200185
def test_join_common(self):
201186
P = self.cls
@@ -789,17 +774,17 @@ def test_repr_roundtrips(self):
789774
class PurePosixPathTest(PurePathTest):
790775
cls = pathlib.PurePosixPath
791776

792-
def test_drive_root_parts(self):
793-
check = self._check_drive_root_parts
777+
def test_parse_path(self):
778+
check = self._check_parse_path
794779
# Collapsing of excess leading slashes, except for the double-slash
795780
# special case.
796-
check(('//a', 'b'), '', '//', ('//', 'a', 'b'))
797-
check(('///a', 'b'), '', '/', ('/', 'a', 'b'))
798-
check(('////a', 'b'), '', '/', ('/', 'a', 'b'))
781+
check('//a/b', '', '//', ['a', 'b'])
782+
check('///a/b', '', '/', ['a', 'b'])
783+
check('////a/b', '', '/', ['a', 'b'])
799784
# Paths which look like NT paths aren't treated specially.
800-
check(('c:a',), '', '', ('c:a',))
801-
check(('c:\\a',), '', '', ('c:\\a',))
802-
check(('\\a',), '', '', ('\\a',))
785+
check('c:a', '', '', ['c:a',])
786+
check('c:\\a', '', '', ['c:\\a',])
787+
check('\\a', '', '', ['\\a',])
803788

804789
def test_root(self):
805790
P = self.cls
@@ -897,67 +882,53 @@ class PureWindowsPathTest(PurePathTest):
897882
],
898883
})
899884

900-
def test_drive_root_parts(self):
901-
check = self._check_drive_root_parts
885+
def test_parse_path(self):
886+
check = self._check_parse_path
902887
# First part is anchored.
903-
check(('c:',), 'c:', '', ('c:',))
904-
check(('c:/',), 'c:', '\\', ('c:\\',))
905-
check(('/',), '', '\\', ('\\',))
906-
check(('c:a',), 'c:', '', ('c:', 'a'))
907-
check(('c:/a',), 'c:', '\\', ('c:\\', 'a'))
908-
check(('/a',), '', '\\', ('\\', 'a'))
909-
# UNC paths.
910-
check(('//',), '\\\\', '', ('\\\\',))
911-
check(('//a',), '\\\\a', '', ('\\\\a',))
912-
check(('//a/',), '\\\\a\\', '', ('\\\\a\\',))
913-
check(('//a/b',), '\\\\a\\b', '\\', ('\\\\a\\b\\',))
914-
check(('//a/b/',), '\\\\a\\b', '\\', ('\\\\a\\b\\',))
915-
check(('//a/b/c',), '\\\\a\\b', '\\', ('\\\\a\\b\\', 'c'))
916-
# Second part is anchored, so that the first part is ignored.
917-
check(('a', 'Z:b', 'c'), 'Z:', '', ('Z:', 'b', 'c'))
918-
check(('a', 'Z:/b', 'c'), 'Z:', '\\', ('Z:\\', 'b', 'c'))
888+
check('c:', 'c:', '', [])
889+
check('c:/', 'c:', '\\', [])
890+
check('/', '', '\\', [])
891+
check('c:a', 'c:', '', ['a'])
892+
check('c:/a', 'c:', '\\', ['a'])
893+
check('/a', '', '\\', ['a'])
919894
# UNC paths.
920-
check(('a', '//b/c', 'd'), '\\\\b\\c', '\\', ('\\\\b\\c\\', 'd'))
895+
check('//', '\\\\', '', [])
896+
check('//a', '\\\\a', '', [])
897+
check('//a/', '\\\\a\\', '', [])
898+
check('//a/b', '\\\\a\\b', '\\', [])
899+
check('//a/b/', '\\\\a\\b', '\\', [])
900+
check('//a/b/c', '\\\\a\\b', '\\', ['c'])
921901
# Collapsing and stripping excess slashes.
922-
check(('a', 'Z://b//c/', 'd/'), 'Z:', '\\', ('Z:\\', 'b', 'c', 'd'))
902+
check('Z://b//c/d/', 'Z:', '\\', ['b', 'c', 'd'])
923903
# UNC paths.
924-
check(('a', '//b/c//', 'd'), '\\\\b\\c', '\\', ('\\\\b\\c\\', 'd'))
904+
check('//b/c//d', '\\\\b\\c', '\\', ['d'])
925905
# Extended paths.
926-
check(('//./c:',), '\\\\.\\c:', '', ('\\\\.\\c:',))
927-
check(('//?/c:/',), '\\\\?\\c:', '\\', ('\\\\?\\c:\\',))
928-
check(('//?/c:/a',), '\\\\?\\c:', '\\', ('\\\\?\\c:\\', 'a'))
929-
check(('//?/c:/a', '/b'), '\\\\?\\c:', '\\', ('\\\\?\\c:\\', 'b'))
906+
check('//./c:', '\\\\.\\c:', '', [])
907+
check('//?/c:/', '\\\\?\\c:', '\\', [])
908+
check('//?/c:/a', '\\\\?\\c:', '\\', ['a'])
930909
# Extended UNC paths (format is "\\?\UNC\server\share").
931-
check(('//?',), '\\\\?', '', ('\\\\?',))
932-
check(('//?/',), '\\\\?\\', '', ('\\\\?\\',))
933-
check(('//?/UNC',), '\\\\?\\UNC', '', ('\\\\?\\UNC',))
934-
check(('//?/UNC/',), '\\\\?\\UNC\\', '', ('\\\\?\\UNC\\',))
935-
check(('//?/UNC/b',), '\\\\?\\UNC\\b', '', ('\\\\?\\UNC\\b',))
936-
check(('//?/UNC/b/',), '\\\\?\\UNC\\b\\', '', ('\\\\?\\UNC\\b\\',))
937-
check(('//?/UNC/b/c',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\',))
938-
check(('//?/UNC/b/c/',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\',))
939-
check(('//?/UNC/b/c/d',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\', 'd'))
910+
check('//?', '\\\\?', '', [])
911+
check('//?/', '\\\\?\\', '', [])
912+
check('//?/UNC', '\\\\?\\UNC', '', [])
913+
check('//?/UNC/', '\\\\?\\UNC\\', '', [])
914+
check('//?/UNC/b', '\\\\?\\UNC\\b', '', [])
915+
check('//?/UNC/b/', '\\\\?\\UNC\\b\\', '', [])
916+
check('//?/UNC/b/c', '\\\\?\\UNC\\b\\c', '\\', [])
917+
check('//?/UNC/b/c/', '\\\\?\\UNC\\b\\c', '\\', [])
918+
check('//?/UNC/b/c/d', '\\\\?\\UNC\\b\\c', '\\', ['d'])
940919
# UNC device paths
941-
check(('//./BootPartition/',), '\\\\.\\BootPartition', '\\', ('\\\\.\\BootPartition\\',))
942-
check(('//?/BootPartition/',), '\\\\?\\BootPartition', '\\', ('\\\\?\\BootPartition\\',))
943-
check(('//./PhysicalDrive0',), '\\\\.\\PhysicalDrive0', '', ('\\\\.\\PhysicalDrive0',))
944-
check(('//?/Volume{}/',), '\\\\?\\Volume{}', '\\', ('\\\\?\\Volume{}\\',))
945-
check(('//./nul',), '\\\\.\\nul', '', ('\\\\.\\nul',))
946-
# Second part has a root but not drive.
947-
check(('a', '/b', 'c'), '', '\\', ('\\', 'b', 'c'))
948-
check(('Z:/a', '/b', 'c'), 'Z:', '\\', ('Z:\\', 'b', 'c'))
949-
check(('//?/Z:/a', '/b', 'c'), '\\\\?\\Z:', '\\', ('\\\\?\\Z:\\', 'b', 'c'))
950-
# Joining with the same drive => the first path is appended to if
951-
# the second path is relative.
952-
check(('c:/a/b', 'c:x/y'), 'c:', '\\', ('c:\\', 'a', 'b', 'x', 'y'))
953-
check(('c:/a/b', 'c:/x/y'), 'c:', '\\', ('c:\\', 'x', 'y'))
920+
check('//./BootPartition/', '\\\\.\\BootPartition', '\\', [])
921+
check('//?/BootPartition/', '\\\\?\\BootPartition', '\\', [])
922+
check('//./PhysicalDrive0', '\\\\.\\PhysicalDrive0', '', [])
923+
check('//?/Volume{}/', '\\\\?\\Volume{}', '\\', [])
924+
check('//./nul', '\\\\.\\nul', '', [])
954925
# Paths to files with NTFS alternate data streams
955-
check(('./c:s',), '', '', ('c:s',))
956-
check(('cc:s',), '', '', ('cc:s',))
957-
check(('C:c:s',), 'C:', '', ('C:', 'c:s'))
958-
check(('C:/c:s',), 'C:', '\\', ('C:\\', 'c:s'))
959-
check(('D:a', './c:b'), 'D:', '', ('D:', 'a', 'c:b'))
960-
check(('D:/a', './c:b'), 'D:', '\\', ('D:\\', 'a', 'c:b'))
926+
check('./c:s', '', '', ['c:s'])
927+
check('cc:s', '', '', ['cc:s'])
928+
check('C:c:s', 'C:', '', ['c:s'])
929+
check('C:/c:s', 'C:', '\\', ['c:s'])
930+
check('D:a/c:b', 'D:', '', ['a', 'c:b'])
931+
check('D:/a/c:b', 'D:', '\\', ['a', 'c:b'])
961932

962933
def test_str(self):
963934
p = self.cls('a/b/c')

Lib/test/test_posixpath.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,26 @@ def tearDown(self):
4747
safe_rmdir(os_helper.TESTFN + suffix)
4848

4949
def test_join(self):
50-
self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
51-
"/bar/baz")
52-
self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
53-
self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
54-
"/foo/bar/baz/")
55-
56-
self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
57-
b"/bar/baz")
58-
self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
59-
b"/foo/bar/baz")
60-
self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
61-
b"/foo/bar/baz/")
50+
fn = posixpath.join
51+
self.assertEqual(fn("/foo", "bar", "/bar", "baz"), "/bar/baz")
52+
self.assertEqual(fn("/foo", "bar", "baz"), "/foo/bar/baz")
53+
self.assertEqual(fn("/foo/", "bar/", "baz/"), "/foo/bar/baz/")
54+
55+
self.assertEqual(fn(b"/foo", b"bar", b"/bar", b"baz"), b"/bar/baz")
56+
self.assertEqual(fn(b"/foo", b"bar", b"baz"), b"/foo/bar/baz")
57+
self.assertEqual(fn(b"/foo/", b"bar/", b"baz/"), b"/foo/bar/baz/")
58+
59+
self.assertEqual(fn("a", "b"), "a/b")
60+
self.assertEqual(fn("a", "b/"), "a/b/")
61+
self.assertEqual(fn("a/", "b"), "a/b")
62+
self.assertEqual(fn("a/", "b/"), "a/b/")
63+
self.assertEqual(fn("a", "b/c", "d"), "a/b/c/d")
64+
self.assertEqual(fn("a", "b//c", "d"), "a/b//c/d")
65+
self.assertEqual(fn("a", "b/c/", "d"), "a/b/c/d")
66+
self.assertEqual(fn("/a", "b"), "/a/b")
67+
self.assertEqual(fn("/a/", "b"), "/a/b")
68+
self.assertEqual(fn("a", "/b", "c"), "/b/c")
69+
self.assertEqual(fn("a", "/b", "/c"), "/c")
6270

6371
def test_split(self):
6472
self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))

0 commit comments

Comments
 (0)