mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
GH-130614: pathlib ABCs: revise test suite for readable paths (#131018)
Test `pathlib.types._ReadablePath` in a dedicated test module. These tests cover `ReadableZipPath`, `ReadableLocalPath` and `Path`, where the former two classes are implementations of `_ReadablePath` for use in tests.
This commit is contained in:
parent
24070492cf
commit
ad90c5fabc
5 changed files with 759 additions and 268 deletions
|
@ -314,76 +314,6 @@ class ReadablePathTest(JoinablePathTest):
|
|||
normcase = self.parser.normcase
|
||||
self.assertEqual(normcase(path_a), normcase(path_b))
|
||||
|
||||
def test_is_readable(self):
|
||||
p = self.cls(self.base)
|
||||
self.assertIsInstance(p, _ReadablePath)
|
||||
|
||||
def test_magic_open(self):
|
||||
p = self.cls(self.base)
|
||||
with magic_open(p / 'fileA', 'r') as f:
|
||||
self.assertIsInstance(f, io.TextIOBase)
|
||||
self.assertEqual(f.read(), "this is file A\n")
|
||||
with magic_open(p / 'fileA', 'rb') as f:
|
||||
self.assertIsInstance(f, io.BufferedIOBase)
|
||||
self.assertEqual(f.read().strip(), b"this is file A")
|
||||
|
||||
def test_iterdir(self):
|
||||
P = self.cls
|
||||
p = P(self.base)
|
||||
it = p.iterdir()
|
||||
paths = set(it)
|
||||
expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
|
||||
if self.can_symlink:
|
||||
expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop']
|
||||
self.assertEqual(paths, { P(self.base, q) for q in expected })
|
||||
|
||||
def test_iterdir_nodir(self):
|
||||
# __iter__ on something that is not a directory.
|
||||
p = self.cls(self.base, 'fileA')
|
||||
with self.assertRaises(OSError) as cm:
|
||||
p.iterdir()
|
||||
# ENOENT or EINVAL under Windows, ENOTDIR otherwise
|
||||
# (see issue #12802).
|
||||
self.assertIn(cm.exception.errno, (errno.ENOTDIR,
|
||||
errno.ENOENT, errno.EINVAL))
|
||||
|
||||
def test_iterdir_info(self):
|
||||
p = self.cls(self.base)
|
||||
for child in p.iterdir():
|
||||
self.assertIsInstance(child.info, PathInfo)
|
||||
self.assertTrue(child.info.exists(follow_symlinks=False))
|
||||
|
||||
def test_glob_common(self):
|
||||
def _check(glob, expected):
|
||||
self.assertEqual(set(glob), { P(self.base, q) for q in expected })
|
||||
P = self.cls
|
||||
p = P(self.base)
|
||||
it = p.glob("fileA")
|
||||
self.assertIsInstance(it, collections.abc.Iterator)
|
||||
_check(it, ["fileA"])
|
||||
_check(p.glob("fileB"), [])
|
||||
_check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"])
|
||||
if not self.can_symlink:
|
||||
_check(p.glob("*A"), ['dirA', 'fileA'])
|
||||
else:
|
||||
_check(p.glob("*A"), ['dirA', 'fileA', 'linkA'])
|
||||
if not self.can_symlink:
|
||||
_check(p.glob("*B/*"), ['dirB/fileB'])
|
||||
else:
|
||||
_check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD',
|
||||
'linkB/fileB', 'linkB/linkD'])
|
||||
if not self.can_symlink:
|
||||
_check(p.glob("*/fileB"), ['dirB/fileB'])
|
||||
else:
|
||||
_check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB'])
|
||||
if self.can_symlink:
|
||||
_check(p.glob("brokenLink"), ['brokenLink'])
|
||||
|
||||
if not self.can_symlink:
|
||||
_check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/"])
|
||||
else:
|
||||
_check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"])
|
||||
|
||||
@needs_posix
|
||||
def test_glob_posix(self):
|
||||
P = self.cls
|
||||
|
@ -402,123 +332,6 @@ class ReadablePathTest(JoinablePathTest):
|
|||
self.assertEqual(set(p.glob("*a\\")), { P(self.base, "dirA/") })
|
||||
self.assertEqual(set(p.glob("F*a")), { P(self.base, "fileA") })
|
||||
|
||||
def test_glob_empty_pattern(self):
|
||||
P = self.cls
|
||||
p = P(self.base)
|
||||
self.assertEqual(list(p.glob("")), [p.joinpath("")])
|
||||
|
||||
def test_info_exists(self):
|
||||
p = self.cls(self.base)
|
||||
self.assertTrue(p.info.exists())
|
||||
self.assertTrue((p / 'dirA').info.exists())
|
||||
self.assertTrue((p / 'dirA').info.exists(follow_symlinks=False))
|
||||
self.assertTrue((p / 'fileA').info.exists())
|
||||
self.assertTrue((p / 'fileA').info.exists(follow_symlinks=False))
|
||||
self.assertFalse((p / 'non-existing').info.exists())
|
||||
self.assertFalse((p / 'non-existing').info.exists(follow_symlinks=False))
|
||||
if self.can_symlink:
|
||||
self.assertTrue((p / 'linkA').info.exists())
|
||||
self.assertTrue((p / 'linkA').info.exists(follow_symlinks=False))
|
||||
self.assertTrue((p / 'linkB').info.exists())
|
||||
self.assertTrue((p / 'linkB').info.exists(follow_symlinks=True))
|
||||
self.assertFalse((p / 'brokenLink').info.exists())
|
||||
self.assertTrue((p / 'brokenLink').info.exists(follow_symlinks=False))
|
||||
self.assertFalse((p / 'brokenLinkLoop').info.exists())
|
||||
self.assertTrue((p / 'brokenLinkLoop').info.exists(follow_symlinks=False))
|
||||
self.assertFalse((p / 'fileA\udfff').info.exists())
|
||||
self.assertFalse((p / 'fileA\udfff').info.exists(follow_symlinks=False))
|
||||
self.assertFalse((p / 'fileA\x00').info.exists())
|
||||
self.assertFalse((p / 'fileA\x00').info.exists(follow_symlinks=False))
|
||||
|
||||
def test_info_exists_caching(self):
|
||||
p = self.cls(self.base)
|
||||
q = p / 'myfile'
|
||||
self.assertFalse(q.info.exists())
|
||||
self.assertFalse(q.info.exists(follow_symlinks=False))
|
||||
if isinstance(self.cls, _WritablePath):
|
||||
q.write_text('hullo')
|
||||
self.assertFalse(q.info.exists())
|
||||
self.assertFalse(q.info.exists(follow_symlinks=False))
|
||||
|
||||
def test_info_is_dir(self):
|
||||
p = self.cls(self.base)
|
||||
self.assertTrue((p / 'dirA').info.is_dir())
|
||||
self.assertTrue((p / 'dirA').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'fileA').info.is_dir())
|
||||
self.assertFalse((p / 'fileA').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'non-existing').info.is_dir())
|
||||
self.assertFalse((p / 'non-existing').info.is_dir(follow_symlinks=False))
|
||||
if self.can_symlink:
|
||||
self.assertFalse((p / 'linkA').info.is_dir())
|
||||
self.assertFalse((p / 'linkA').info.is_dir(follow_symlinks=False))
|
||||
self.assertTrue((p / 'linkB').info.is_dir())
|
||||
self.assertFalse((p / 'linkB').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'brokenLink').info.is_dir())
|
||||
self.assertFalse((p / 'brokenLink').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'brokenLinkLoop').info.is_dir())
|
||||
self.assertFalse((p / 'brokenLinkLoop').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'dirA\udfff').info.is_dir())
|
||||
self.assertFalse((p / 'dirA\udfff').info.is_dir(follow_symlinks=False))
|
||||
self.assertFalse((p / 'dirA\x00').info.is_dir())
|
||||
self.assertFalse((p / 'dirA\x00').info.is_dir(follow_symlinks=False))
|
||||
|
||||
def test_info_is_dir_caching(self):
|
||||
p = self.cls(self.base)
|
||||
q = p / 'mydir'
|
||||
self.assertFalse(q.info.is_dir())
|
||||
self.assertFalse(q.info.is_dir(follow_symlinks=False))
|
||||
if isinstance(self.cls, _WritablePath):
|
||||
q.mkdir()
|
||||
self.assertFalse(q.info.is_dir())
|
||||
self.assertFalse(q.info.is_dir(follow_symlinks=False))
|
||||
|
||||
def test_info_is_file(self):
|
||||
p = self.cls(self.base)
|
||||
self.assertTrue((p / 'fileA').info.is_file())
|
||||
self.assertTrue((p / 'fileA').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'dirA').info.is_file())
|
||||
self.assertFalse((p / 'dirA').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'non-existing').info.is_file())
|
||||
self.assertFalse((p / 'non-existing').info.is_file(follow_symlinks=False))
|
||||
if self.can_symlink:
|
||||
self.assertTrue((p / 'linkA').info.is_file())
|
||||
self.assertFalse((p / 'linkA').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'linkB').info.is_file())
|
||||
self.assertFalse((p / 'linkB').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'brokenLink').info.is_file())
|
||||
self.assertFalse((p / 'brokenLink').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'brokenLinkLoop').info.is_file())
|
||||
self.assertFalse((p / 'brokenLinkLoop').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'fileA\udfff').info.is_file())
|
||||
self.assertFalse((p / 'fileA\udfff').info.is_file(follow_symlinks=False))
|
||||
self.assertFalse((p / 'fileA\x00').info.is_file())
|
||||
self.assertFalse((p / 'fileA\x00').info.is_file(follow_symlinks=False))
|
||||
|
||||
def test_info_is_file_caching(self):
|
||||
p = self.cls(self.base)
|
||||
q = p / 'myfile'
|
||||
self.assertFalse(q.info.is_file())
|
||||
self.assertFalse(q.info.is_file(follow_symlinks=False))
|
||||
if isinstance(self.cls, _WritablePath):
|
||||
q.write_text('hullo')
|
||||
self.assertFalse(q.info.is_file())
|
||||
self.assertFalse(q.info.is_file(follow_symlinks=False))
|
||||
|
||||
def test_info_is_symlink(self):
|
||||
p = self.cls(self.base)
|
||||
self.assertFalse((p / 'fileA').info.is_symlink())
|
||||
self.assertFalse((p / 'dirA').info.is_symlink())
|
||||
self.assertFalse((p / 'non-existing').info.is_symlink())
|
||||
if self.can_symlink:
|
||||
self.assertTrue((p / 'linkA').info.is_symlink())
|
||||
self.assertTrue((p / 'linkB').info.is_symlink())
|
||||
self.assertTrue((p / 'brokenLink').info.is_symlink())
|
||||
self.assertFalse((p / 'linkA\udfff').info.is_symlink())
|
||||
self.assertFalse((p / 'linkA\x00').info.is_symlink())
|
||||
self.assertTrue((p / 'brokenLinkLoop').info.is_symlink())
|
||||
self.assertFalse((p / 'fileA\udfff').info.is_symlink())
|
||||
self.assertFalse((p / 'fileA\x00').info.is_symlink())
|
||||
|
||||
|
||||
class WritablePathTest(JoinablePathTest):
|
||||
cls = DummyWritablePath
|
||||
|
@ -553,21 +366,6 @@ class RWPathTest(WritablePathTest, ReadablePathTest):
|
|||
self.assertRaises(TypeError, (p / 'fileA').write_text, b'somebytes')
|
||||
self.assertEqual((p / 'fileA').read_text(encoding='latin-1'), 'äbcdefg')
|
||||
|
||||
def test_read_text_with_newlines(self):
|
||||
p = self.cls(self.base)
|
||||
# Check that `\n` character change nothing
|
||||
(p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq')
|
||||
self.assertEqual((p / 'fileA').read_text(newline='\n'),
|
||||
'abcde\r\nfghlk\n\rmnopq')
|
||||
# Check that `\r` character replaces `\n`
|
||||
(p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq')
|
||||
self.assertEqual((p / 'fileA').read_text(newline='\r'),
|
||||
'abcde\r\nfghlk\n\rmnopq')
|
||||
# Check that `\r\n` character replaces `\n`
|
||||
(p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq')
|
||||
self.assertEqual((p / 'fileA').read_text(newline='\r\n'),
|
||||
'abcde\r\nfghlk\n\rmnopq')
|
||||
|
||||
def test_write_text_with_newlines(self):
|
||||
p = self.cls(self.base)
|
||||
# Check that `\n` character change nothing
|
||||
|
@ -763,72 +561,6 @@ class ReadablePathWalkTest(unittest.TestCase):
|
|||
cls._files.clear()
|
||||
cls._directories.clear()
|
||||
|
||||
def test_walk_topdown(self):
|
||||
walker = self.walk_path.walk()
|
||||
entry = next(walker)
|
||||
entry[1].sort() # Ensure we visit SUB1 before SUB2
|
||||
self.assertEqual(entry, (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
|
||||
entry = next(walker)
|
||||
self.assertEqual(entry, (self.sub1_path, ["SUB11"], ["tmp2"]))
|
||||
entry = next(walker)
|
||||
self.assertEqual(entry, (self.sub11_path, [], []))
|
||||
entry = next(walker)
|
||||
entry[1].sort()
|
||||
entry[2].sort()
|
||||
self.assertEqual(entry, self.sub2_tree)
|
||||
with self.assertRaises(StopIteration):
|
||||
next(walker)
|
||||
|
||||
def test_walk_prune(self):
|
||||
# Prune the search.
|
||||
all = []
|
||||
for root, dirs, files in self.walk_path.walk():
|
||||
all.append((root, dirs, files))
|
||||
if 'SUB1' in dirs:
|
||||
# Note that this also mutates the dirs we appended to all!
|
||||
dirs.remove('SUB1')
|
||||
|
||||
self.assertEqual(len(all), 2)
|
||||
self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"]))
|
||||
|
||||
all[1][-1].sort()
|
||||
all[1][1].sort()
|
||||
self.assertEqual(all[1], self.sub2_tree)
|
||||
|
||||
def test_walk_bottom_up(self):
|
||||
seen_testfn = seen_sub1 = seen_sub11 = seen_sub2 = False
|
||||
for path, dirnames, filenames in self.walk_path.walk(top_down=False):
|
||||
if path == self.walk_path:
|
||||
self.assertFalse(seen_testfn)
|
||||
self.assertTrue(seen_sub1)
|
||||
self.assertTrue(seen_sub2)
|
||||
self.assertEqual(sorted(dirnames), ["SUB1", "SUB2"])
|
||||
self.assertEqual(filenames, ["tmp1"])
|
||||
seen_testfn = True
|
||||
elif path == self.sub1_path:
|
||||
self.assertFalse(seen_testfn)
|
||||
self.assertFalse(seen_sub1)
|
||||
self.assertTrue(seen_sub11)
|
||||
self.assertEqual(dirnames, ["SUB11"])
|
||||
self.assertEqual(filenames, ["tmp2"])
|
||||
seen_sub1 = True
|
||||
elif path == self.sub11_path:
|
||||
self.assertFalse(seen_sub1)
|
||||
self.assertFalse(seen_sub11)
|
||||
self.assertEqual(dirnames, [])
|
||||
self.assertEqual(filenames, [])
|
||||
seen_sub11 = True
|
||||
elif path == self.sub2_path:
|
||||
self.assertFalse(seen_testfn)
|
||||
self.assertFalse(seen_sub2)
|
||||
self.assertEqual(sorted(dirnames), sorted(self.sub2_tree[1]))
|
||||
self.assertEqual(sorted(filenames), sorted(self.sub2_tree[2]))
|
||||
seen_sub2 = True
|
||||
else:
|
||||
raise AssertionError(f"Unexpected path: {path}")
|
||||
self.assertTrue(seen_testfn)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue