cpython/Lib/test/test_pathlib/test_read.py

322 lines
14 KiB
Python

"""
Tests for pathlib.types._ReadablePath
"""
import collections.abc
import io
import unittest
from .support import is_pypi
from .support.local_path import ReadableLocalPath, LocalPathGround
from .support.zip_path import ReadableZipPath, ZipPathGround
if is_pypi:
from pathlib_abc import PathInfo, _ReadablePath
from pathlib_abc._os import magic_open
else:
from pathlib.types import PathInfo, _ReadablePath
from pathlib._os import magic_open
class ReadTestBase:
def setUp(self):
self.root = self.ground.setup()
self.ground.create_hierarchy(self.root)
def tearDown(self):
self.ground.teardown(self.root)
def test_is_readable(self):
self.assertIsInstance(self.root, _ReadablePath)
def test_open_r(self):
p = self.root / 'fileA'
with magic_open(p, 'r') as f:
self.assertIsInstance(f, io.TextIOBase)
self.assertEqual(f.read(), 'this is file A\n')
def test_open_rb(self):
p = self.root / 'fileA'
with magic_open(p, 'rb') as f:
self.assertEqual(f.read(), b'this is file A\n')
self.assertRaises(ValueError, magic_open, p, 'rb', encoding='utf8')
self.assertRaises(ValueError, magic_open, p, 'rb', errors='strict')
self.assertRaises(ValueError, magic_open, p, 'rb', newline='')
def test_read_bytes(self):
p = self.root / 'fileA'
self.assertEqual(p.read_bytes(), b'this is file A\n')
def test_read_text(self):
p = self.root / 'fileA'
self.assertEqual(p.read_text(), 'this is file A\n')
q = self.root / 'abc'
self.ground.create_file(q, b'\xe4bcdefg')
self.assertEqual(q.read_text(encoding='latin-1'), 'äbcdefg')
self.assertEqual(q.read_text(encoding='utf-8', errors='ignore'), 'bcdefg')
def test_read_text_with_newlines(self):
p = self.root / 'abc'
self.ground.create_file(p, b'abcde\r\nfghlk\n\rmnopq')
# Check that `\n` character change nothing
self.assertEqual(p.read_text(newline='\n'), 'abcde\r\nfghlk\n\rmnopq')
# Check that `\r` character replaces `\n`
self.assertEqual(p.read_text(newline='\r'), 'abcde\r\nfghlk\n\rmnopq')
# Check that `\r\n` character replaces `\n`
self.assertEqual(p.read_text(newline='\r\n'), 'abcde\r\nfghlk\n\rmnopq')
def test_iterdir(self):
expected = ['dirA', 'dirB', 'dirC', 'fileA']
if self.ground.can_symlink:
expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop']
expected = {self.root.joinpath(name) for name in expected}
actual = set(self.root.iterdir())
self.assertEqual(actual, expected)
def test_iterdir_nodir(self):
p = self.root / 'fileA'
self.assertRaises(OSError, p.iterdir)
def test_iterdir_info(self):
for child in self.root.iterdir():
self.assertIsInstance(child.info, PathInfo)
self.assertTrue(child.info.exists(follow_symlinks=False))
def test_glob(self):
if not self.ground.can_symlink:
self.skipTest("requires symlinks")
p = self.root
sep = self.root.parser.sep
altsep = self.root.parser.altsep
def check(pattern, expected):
if altsep:
expected = {name.replace(altsep, sep) for name in expected}
expected = {p.joinpath(name) for name in expected}
actual = set(p.glob(pattern, recurse_symlinks=True))
self.assertEqual(actual, expected)
it = p.glob("fileA")
self.assertIsInstance(it, collections.abc.Iterator)
self.assertEqual(list(it), [p.joinpath("fileA")])
check("*A", ["dirA", "fileA", "linkA"])
check("*A", ['dirA', 'fileA', 'linkA'])
check("*B/*", ["dirB/fileB", "linkB/fileB"])
check("*B/*", ['dirB/fileB', 'linkB/fileB'])
check("brokenLink", ['brokenLink'])
check("brokenLinkLoop", ['brokenLinkLoop'])
check("**/", ["", "dirA/", "dirA/linkC/", "dirB/", "dirC/", "dirC/dirD/", "linkB/"])
check("**/*/", ["dirA/", "dirA/linkC/", "dirB/", "dirC/", "dirC/dirD/", "linkB/"])
check("*/", ["dirA/", "dirB/", "dirC/", "linkB/"])
check("*/dirD/**/", ["dirC/dirD/"])
check("*/dirD/**", ["dirC/dirD/", "dirC/dirD/fileD"])
check("dir*/**", ["dirA/", "dirA/linkC", "dirA/linkC/fileB", "dirB/", "dirB/fileB", "dirC/",
"dirC/fileC", "dirC/dirD", "dirC/dirD/fileD", "dirC/novel.txt"])
check("dir*/**/", ["dirA/", "dirA/linkC/", "dirB/", "dirC/", "dirC/dirD/"])
check("dir*/**/..", ["dirA/..", "dirA/linkC/..", "dirB/..", "dirC/..", "dirC/dirD/.."])
check("dir*/*/**", ["dirA/linkC/", "dirA/linkC/fileB", "dirC/dirD/", "dirC/dirD/fileD"])
check("dir*/*/**/", ["dirA/linkC/", "dirC/dirD/"])
check("dir*/*/**/..", ["dirA/linkC/..", "dirC/dirD/.."])
check("dir*/*/..", ["dirC/dirD/..", "dirA/linkC/.."])
check("dir*/*/../dirD/**/", ["dirC/dirD/../dirD/"])
check("dir*/**/fileC", ["dirC/fileC"])
check("dir*/file*", ["dirB/fileB", "dirC/fileC"])
check("**/*/fileA", [])
check("fileB", [])
check("**/*/fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"])
check("**/fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"])
check("*/fileB", ["dirB/fileB", "linkB/fileB"])
check("*/fileB", ['dirB/fileB', 'linkB/fileB'])
check("**/file*",
["fileA", "dirA/linkC/fileB", "dirB/fileB", "dirC/fileC", "dirC/dirD/fileD",
"linkB/fileB"])
with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
list(p.glob(''))
def test_walk_top_down(self):
it = self.root.walk()
path, dirnames, filenames = next(it)
dirnames.sort()
filenames.sort()
self.assertEqual(path, self.root)
self.assertEqual(dirnames, ['dirA', 'dirB', 'dirC'])
self.assertEqual(filenames, ['brokenLink', 'brokenLinkLoop', 'fileA', 'linkA', 'linkB']
if self.ground.can_symlink else ['fileA'])
path, dirnames, filenames = next(it)
self.assertEqual(path, self.root / 'dirA')
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['linkC'] if self.ground.can_symlink else [])
path, dirnames, filenames = next(it)
self.assertEqual(path, self.root / 'dirB')
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['fileB'])
path, dirnames, filenames = next(it)
filenames.sort()
self.assertEqual(path, self.root / 'dirC')
self.assertEqual(dirnames, ['dirD'])
self.assertEqual(filenames, ['fileC', 'novel.txt'])
path, dirnames, filenames = next(it)
self.assertEqual(path, self.root / 'dirC' / 'dirD')
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['fileD'])
self.assertRaises(StopIteration, next, it)
def test_walk_prune(self):
expected = {self.root, self.root / 'dirA', self.root / 'dirC', self.root / 'dirC' / 'dirD'}
actual = set()
for path, dirnames, filenames in self.root.walk():
actual.add(path)
if path == self.root:
dirnames.remove('dirB')
self.assertEqual(actual, expected)
def test_walk_bottom_up(self):
seen_root = seen_dira = seen_dirb = seen_dirc = seen_dird = False
for path, dirnames, filenames in self.root.walk(top_down=False):
if path == self.root:
self.assertFalse(seen_root)
self.assertTrue(seen_dira)
self.assertTrue(seen_dirb)
self.assertTrue(seen_dirc)
self.assertEqual(sorted(dirnames), ['dirA', 'dirB', 'dirC'])
self.assertEqual(sorted(filenames),
['brokenLink', 'brokenLinkLoop', 'fileA', 'linkA', 'linkB']
if self.ground.can_symlink else ['fileA'])
seen_root = True
elif path == self.root / 'dirA':
self.assertFalse(seen_root)
self.assertFalse(seen_dira)
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['linkC'] if self.ground.can_symlink else [])
seen_dira = True
elif path == self.root / 'dirB':
self.assertFalse(seen_root)
self.assertFalse(seen_dirb)
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['fileB'])
seen_dirb = True
elif path == self.root / 'dirC':
self.assertFalse(seen_root)
self.assertFalse(seen_dirc)
self.assertTrue(seen_dird)
self.assertEqual(dirnames, ['dirD'])
self.assertEqual(sorted(filenames), ['fileC', 'novel.txt'])
seen_dirc = True
elif path == self.root / 'dirC' / 'dirD':
self.assertFalse(seen_root)
self.assertFalse(seen_dirc)
self.assertFalse(seen_dird)
self.assertEqual(dirnames, [])
self.assertEqual(filenames, ['fileD'])
seen_dird = True
else:
raise AssertionError(f"Unexpected path: {path}")
self.assertTrue(seen_root)
def test_info_exists(self):
p = self.root
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.ground.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_is_dir(self):
p = self.root
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.ground.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_file(self):
p = self.root
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.ground.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_symlink(self):
p = self.root
self.assertFalse((p / 'fileA').info.is_symlink())
self.assertFalse((p / 'dirA').info.is_symlink())
self.assertFalse((p / 'non-existing').info.is_symlink())
if self.ground.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 ZipPathReadTest(ReadTestBase, unittest.TestCase):
ground = ZipPathGround(ReadableZipPath)
class LocalPathReadTest(ReadTestBase, unittest.TestCase):
ground = LocalPathGround(ReadableLocalPath)
if not is_pypi:
from pathlib import Path
class PathReadTest(ReadTestBase, unittest.TestCase):
ground = LocalPathGround(Path)
if __name__ == "__main__":
unittest.main()