mirror of https://github.com/python/cpython
GH-113528: Move a few misplaced pathlib tests (#113527)
`PurePathBase` does not define `__eq__()`, and so we have no business checking path equality in `test_eq_common` and `test_equivalences`. The tests only pass at the moment because we define the test class's `__eq__()` for use elsewhere. Also move `test_parse_path_common` into the main pathlib test suite. It exercises a private `_parse_path()` method that will be moved to `PurePath` soon. Lastly move a couple more tests concerned with optimisations and path normalisation.
This commit is contained in:
parent
aef375f56e
commit
a9df076d7d
|
@ -45,6 +45,22 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
|
||||||
# Make sure any symbolic links in the base test path are resolved.
|
# Make sure any symbolic links in the base test path are resolved.
|
||||||
base = os.path.realpath(TESTFN)
|
base = os.path.realpath(TESTFN)
|
||||||
|
|
||||||
|
# Keys are canonical paths, values are list of tuples of arguments
|
||||||
|
# supposed to produce equal paths.
|
||||||
|
equivalences = {
|
||||||
|
'a/b': [
|
||||||
|
('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'),
|
||||||
|
('a/b/',), ('a//b',), ('a//b//',),
|
||||||
|
# Empty components get removed.
|
||||||
|
('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''),
|
||||||
|
],
|
||||||
|
'/b/c/d': [
|
||||||
|
('a', '/b/c', 'd'), ('/a', '/b/c', 'd'),
|
||||||
|
# Empty components get removed.
|
||||||
|
('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
def test_concrete_class(self):
|
def test_concrete_class(self):
|
||||||
if self.cls is pathlib.PurePath:
|
if self.cls is pathlib.PurePath:
|
||||||
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
|
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
|
||||||
|
@ -95,6 +111,45 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
|
||||||
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
|
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
|
||||||
self.assertEqual(P(P('./a:b')), P('./a:b'))
|
self.assertEqual(P(P('./a:b')), P('./a:b'))
|
||||||
|
|
||||||
|
def _check_parse_path(self, raw_path, *expected):
|
||||||
|
sep = self.pathmod.sep
|
||||||
|
actual = self.cls._parse_path(raw_path.replace('/', sep))
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
if altsep := self.pathmod.altsep:
|
||||||
|
actual = self.cls._parse_path(raw_path.replace('/', altsep))
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_parse_path_common(self):
|
||||||
|
check = self._check_parse_path
|
||||||
|
sep = self.pathmod.sep
|
||||||
|
check('', '', '', [])
|
||||||
|
check('a', '', '', ['a'])
|
||||||
|
check('a/', '', '', ['a'])
|
||||||
|
check('a/b', '', '', ['a', 'b'])
|
||||||
|
check('a/b/', '', '', ['a', 'b'])
|
||||||
|
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
|
||||||
|
check('a/b//c/d', '', '', ['a', 'b', 'c', 'd'])
|
||||||
|
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
|
||||||
|
check('.', '', '', [])
|
||||||
|
check('././b', '', '', ['b'])
|
||||||
|
check('a/./b', '', '', ['a', 'b'])
|
||||||
|
check('a/./.', '', '', ['a'])
|
||||||
|
check('/a/b', '', sep, ['a', 'b'])
|
||||||
|
|
||||||
|
def test_empty_path(self):
|
||||||
|
# The empty path points to '.'
|
||||||
|
p = self.cls('')
|
||||||
|
self.assertEqual(str(p), '.')
|
||||||
|
|
||||||
|
def test_parts_interning(self):
|
||||||
|
P = self.cls
|
||||||
|
p = P('/usr/bin/foo')
|
||||||
|
q = P('/usr/local/bin')
|
||||||
|
# 'usr'
|
||||||
|
self.assertIs(p.parts[1], q.parts[1])
|
||||||
|
# 'bin'
|
||||||
|
self.assertIs(p.parts[2], q.parts[3])
|
||||||
|
|
||||||
def test_join_nested(self):
|
def test_join_nested(self):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
p = P('a/b').joinpath(P('c'))
|
p = P('a/b').joinpath(P('c'))
|
||||||
|
@ -168,6 +223,37 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b')
|
self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b')
|
||||||
|
|
||||||
|
def test_eq_common(self):
|
||||||
|
P = self.cls
|
||||||
|
self.assertEqual(P('a/b'), P('a/b'))
|
||||||
|
self.assertEqual(P('a/b'), P('a', 'b'))
|
||||||
|
self.assertNotEqual(P('a/b'), P('a'))
|
||||||
|
self.assertNotEqual(P('a/b'), P('/a/b'))
|
||||||
|
self.assertNotEqual(P('a/b'), P())
|
||||||
|
self.assertNotEqual(P('/a/b'), P('/'))
|
||||||
|
self.assertNotEqual(P(), P('/'))
|
||||||
|
self.assertNotEqual(P(), "")
|
||||||
|
self.assertNotEqual(P(), {})
|
||||||
|
self.assertNotEqual(P(), int)
|
||||||
|
|
||||||
|
def test_equivalences(self):
|
||||||
|
for k, tuples in self.equivalences.items():
|
||||||
|
canon = k.replace('/', self.sep)
|
||||||
|
posix = k.replace(self.sep, '/')
|
||||||
|
if canon != posix:
|
||||||
|
tuples = tuples + [
|
||||||
|
tuple(part.replace('/', self.sep) for part in t)
|
||||||
|
for t in tuples
|
||||||
|
]
|
||||||
|
tuples.append((posix, ))
|
||||||
|
pcanon = self.cls(canon)
|
||||||
|
for t in tuples:
|
||||||
|
p = self.cls(*t)
|
||||||
|
self.assertEqual(p, pcanon, "failed with args {}".format(t))
|
||||||
|
self.assertEqual(hash(p), hash(pcanon))
|
||||||
|
self.assertEqual(str(p), canon)
|
||||||
|
self.assertEqual(p.as_posix(), posix)
|
||||||
|
|
||||||
def test_ordering_common(self):
|
def test_ordering_common(self):
|
||||||
# Ordering is tuple-alike.
|
# Ordering is tuple-alike.
|
||||||
def assertLess(a, b):
|
def assertLess(a, b):
|
||||||
|
|
|
@ -61,22 +61,6 @@ class DummyPurePathTest(unittest.TestCase):
|
||||||
# Use a base path that's unrelated to any real filesystem path.
|
# Use a base path that's unrelated to any real filesystem path.
|
||||||
base = f'/this/path/kills/fascists/{TESTFN}'
|
base = f'/this/path/kills/fascists/{TESTFN}'
|
||||||
|
|
||||||
# Keys are canonical paths, values are list of tuples of arguments
|
|
||||||
# supposed to produce equal paths.
|
|
||||||
equivalences = {
|
|
||||||
'a/b': [
|
|
||||||
('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'),
|
|
||||||
('a/b/',), ('a//b',), ('a//b//',),
|
|
||||||
# Empty components get removed.
|
|
||||||
('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''),
|
|
||||||
],
|
|
||||||
'/b/c/d': [
|
|
||||||
('a', '/b/c', 'd'), ('/a', '/b/c', 'd'),
|
|
||||||
# Empty components get removed.
|
|
||||||
('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
p = self.cls('a')
|
p = self.cls('a')
|
||||||
self.pathmod = p.pathmod
|
self.pathmod = p.pathmod
|
||||||
|
@ -132,31 +116,6 @@ class DummyPurePathTest(unittest.TestCase):
|
||||||
for parent in p.parents:
|
for parent in p.parents:
|
||||||
self.assertEqual(42, parent.session_id)
|
self.assertEqual(42, parent.session_id)
|
||||||
|
|
||||||
def _check_parse_path(self, raw_path, *expected):
|
|
||||||
sep = self.pathmod.sep
|
|
||||||
actual = self.cls._parse_path(raw_path.replace('/', sep))
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
if altsep := self.pathmod.altsep:
|
|
||||||
actual = self.cls._parse_path(raw_path.replace('/', altsep))
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_parse_path_common(self):
|
|
||||||
check = self._check_parse_path
|
|
||||||
sep = self.pathmod.sep
|
|
||||||
check('', '', '', [])
|
|
||||||
check('a', '', '', ['a'])
|
|
||||||
check('a/', '', '', ['a'])
|
|
||||||
check('a/b', '', '', ['a', 'b'])
|
|
||||||
check('a/b/', '', '', ['a', 'b'])
|
|
||||||
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
|
|
||||||
check('a/b//c/d', '', '', ['a', 'b', 'c', 'd'])
|
|
||||||
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
|
|
||||||
check('.', '', '', [])
|
|
||||||
check('././b', '', '', ['b'])
|
|
||||||
check('a/./b', '', '', ['a', 'b'])
|
|
||||||
check('a/./.', '', '', ['a'])
|
|
||||||
check('/a/b', '', sep, ['a', 'b'])
|
|
||||||
|
|
||||||
def test_join_common(self):
|
def test_join_common(self):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
p = P('a/b')
|
p = P('a/b')
|
||||||
|
@ -202,19 +161,6 @@ class DummyPurePathTest(unittest.TestCase):
|
||||||
self.assertEqual(P(pathstr).as_posix(), pathstr)
|
self.assertEqual(P(pathstr).as_posix(), pathstr)
|
||||||
# Other tests for as_posix() are in test_equivalences().
|
# Other tests for as_posix() are in test_equivalences().
|
||||||
|
|
||||||
def test_eq_common(self):
|
|
||||||
P = self.cls
|
|
||||||
self.assertEqual(P('a/b'), P('a/b'))
|
|
||||||
self.assertEqual(P('a/b'), P('a', 'b'))
|
|
||||||
self.assertNotEqual(P('a/b'), P('a'))
|
|
||||||
self.assertNotEqual(P('a/b'), P('/a/b'))
|
|
||||||
self.assertNotEqual(P('a/b'), P())
|
|
||||||
self.assertNotEqual(P('/a/b'), P('/'))
|
|
||||||
self.assertNotEqual(P(), P('/'))
|
|
||||||
self.assertNotEqual(P(), "")
|
|
||||||
self.assertNotEqual(P(), {})
|
|
||||||
self.assertNotEqual(P(), int)
|
|
||||||
|
|
||||||
def test_match_empty(self):
|
def test_match_empty(self):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
self.assertRaises(ValueError, P('a').match, '')
|
self.assertRaises(ValueError, P('a').match, '')
|
||||||
|
@ -299,24 +245,6 @@ class DummyPurePathTest(unittest.TestCase):
|
||||||
parts = p.parts
|
parts = p.parts
|
||||||
self.assertEqual(parts, (sep, 'a', 'b'))
|
self.assertEqual(parts, (sep, 'a', 'b'))
|
||||||
|
|
||||||
def test_equivalences(self):
|
|
||||||
for k, tuples in self.equivalences.items():
|
|
||||||
canon = k.replace('/', self.sep)
|
|
||||||
posix = k.replace(self.sep, '/')
|
|
||||||
if canon != posix:
|
|
||||||
tuples = tuples + [
|
|
||||||
tuple(part.replace('/', self.sep) for part in t)
|
|
||||||
for t in tuples
|
|
||||||
]
|
|
||||||
tuples.append((posix, ))
|
|
||||||
pcanon = self.cls(canon)
|
|
||||||
for t in tuples:
|
|
||||||
p = self.cls(*t)
|
|
||||||
self.assertEqual(p, pcanon, "failed with args {}".format(t))
|
|
||||||
self.assertEqual(hash(p), hash(pcanon))
|
|
||||||
self.assertEqual(str(p), canon)
|
|
||||||
self.assertEqual(p.as_posix(), posix)
|
|
||||||
|
|
||||||
def test_parent_common(self):
|
def test_parent_common(self):
|
||||||
# Relative
|
# Relative
|
||||||
P = self.cls
|
P = self.cls
|
||||||
|
@ -918,11 +846,6 @@ class DummyPathTest(DummyPurePathTest):
|
||||||
self.assertRaises(FileNotFoundError, r.samefile, r)
|
self.assertRaises(FileNotFoundError, r.samefile, r)
|
||||||
self.assertRaises(FileNotFoundError, r.samefile, non_existent)
|
self.assertRaises(FileNotFoundError, r.samefile, non_existent)
|
||||||
|
|
||||||
def test_empty_path(self):
|
|
||||||
# The empty path points to '.'
|
|
||||||
p = self.cls('')
|
|
||||||
self.assertEqual(str(p), '.')
|
|
||||||
|
|
||||||
def test_exists(self):
|
def test_exists(self):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
p = P(self.base)
|
p = P(self.base)
|
||||||
|
@ -1598,15 +1521,6 @@ class DummyPathTest(DummyPurePathTest):
|
||||||
self.assertIs((P / 'fileA\udfff').is_char_device(), False)
|
self.assertIs((P / 'fileA\udfff').is_char_device(), False)
|
||||||
self.assertIs((P / 'fileA\x00').is_char_device(), False)
|
self.assertIs((P / 'fileA\x00').is_char_device(), False)
|
||||||
|
|
||||||
def test_parts_interning(self):
|
|
||||||
P = self.cls
|
|
||||||
p = P('/usr/bin/foo')
|
|
||||||
q = P('/usr/local/bin')
|
|
||||||
# 'usr'
|
|
||||||
self.assertIs(p.parts[1], q.parts[1])
|
|
||||||
# 'bin'
|
|
||||||
self.assertIs(p.parts[2], q.parts[3])
|
|
||||||
|
|
||||||
def _check_complex_symlinks(self, link0_target):
|
def _check_complex_symlinks(self, link0_target):
|
||||||
if not self.can_symlink:
|
if not self.can_symlink:
|
||||||
self.skipTest("symlinks required")
|
self.skipTest("symlinks required")
|
||||||
|
|
Loading…
Reference in New Issue