pathlib tests: move walk() tests into their own classes (GH-126651)

Move tests for Path.walk() into a new PathWalkTest class, and apply a similar change in tests for the ABCs. This allows us to properly tear down the walk test hierarchy in tearDown(), rather than leaving it to os_helper.rmtree().
This commit is contained in:
Barney Gale 2024-11-24 02:31:00 +00:00 committed by GitHub
parent dbd23790db
commit 4ea71278ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 107 additions and 84 deletions

View File

@ -1425,84 +1425,6 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
with self.assertRaises(TypeError):
self.cls(foo="bar")
def setUpWalk(self):
super().setUpWalk()
sub21_path= self.sub2_path / "SUB21"
tmp5_path = sub21_path / "tmp3"
broken_link3_path = self.sub2_path / "broken_link3"
os.makedirs(sub21_path)
tmp5_path.write_text("I am tmp5, blame test_pathlib.")
if self.can_symlink:
os.symlink(tmp5_path, broken_link3_path)
self.sub2_tree[2].append('broken_link3')
self.sub2_tree[2].sort()
if not is_emscripten:
# Emscripten fails with inaccessible directories.
os.chmod(sub21_path, 0)
try:
os.listdir(sub21_path)
except PermissionError:
self.sub2_tree[1].append('SUB21')
else:
os.chmod(sub21_path, stat.S_IRWXU)
os.unlink(tmp5_path)
os.rmdir(sub21_path)
def test_walk_bad_dir(self):
self.setUpWalk()
errors = []
walk_it = self.walk_path.walk(on_error=errors.append)
root, dirs, files = next(walk_it)
self.assertEqual(errors, [])
dir1 = 'SUB1'
path1 = root / dir1
path1new = (root / dir1).with_suffix(".new")
path1.rename(path1new)
try:
roots = [r for r, _, _ in walk_it]
self.assertTrue(errors)
self.assertNotIn(path1, roots)
self.assertNotIn(path1new, roots)
for dir2 in dirs:
if dir2 != dir1:
self.assertIn(root / dir2, roots)
finally:
path1new.rename(path1)
def test_walk_many_open_files(self):
depth = 30
base = self.cls(self.base, 'deep')
path = self.cls(base, *(['d']*depth))
path.mkdir(parents=True)
iters = [base.walk(top_down=False) for _ in range(100)]
for i in range(depth + 1):
expected = (path, ['d'] if i else [], [])
for it in iters:
self.assertEqual(next(it), expected)
path = path.parent
iters = [base.walk(top_down=True) for _ in range(100)]
path = base
for i in range(depth + 1):
expected = (path, ['d'] if i < depth else [], [])
for it in iters:
self.assertEqual(next(it), expected)
path = path / 'd'
def test_walk_above_recursion_limit(self):
recursion_limit = 40
# directory_depth > recursion_limit
directory_depth = recursion_limit + 10
base = self.cls(self.base, 'deep')
path = base.joinpath(*(['d'] * directory_depth))
path.mkdir(parents=True)
with infinite_recursion(recursion_limit):
list(base.walk())
list(base.walk(top_down=False))
def test_glob_empty_pattern(self):
p = self.cls('')
with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
@ -1886,6 +1808,94 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
P('c:/').group()
class PathWalkTest(test_pathlib_abc.DummyPathWalkTest):
cls = pathlib.Path
base = PathTest.base
can_symlink = PathTest.can_symlink
def setUp(self):
super().setUp()
sub21_path= self.sub2_path / "SUB21"
tmp5_path = sub21_path / "tmp3"
broken_link3_path = self.sub2_path / "broken_link3"
os.makedirs(sub21_path)
tmp5_path.write_text("I am tmp5, blame test_pathlib.")
if self.can_symlink:
os.symlink(tmp5_path, broken_link3_path)
self.sub2_tree[2].append('broken_link3')
self.sub2_tree[2].sort()
if not is_emscripten:
# Emscripten fails with inaccessible directories.
os.chmod(sub21_path, 0)
try:
os.listdir(sub21_path)
except PermissionError:
self.sub2_tree[1].append('SUB21')
else:
os.chmod(sub21_path, stat.S_IRWXU)
os.unlink(tmp5_path)
os.rmdir(sub21_path)
def tearDown(self):
if 'SUB21' in self.sub2_tree[1]:
os.chmod(self.sub2_path / "SUB21", stat.S_IRWXU)
super().tearDown()
def test_walk_bad_dir(self):
errors = []
walk_it = self.walk_path.walk(on_error=errors.append)
root, dirs, files = next(walk_it)
self.assertEqual(errors, [])
dir1 = 'SUB1'
path1 = root / dir1
path1new = (root / dir1).with_suffix(".new")
path1.rename(path1new)
try:
roots = [r for r, _, _ in walk_it]
self.assertTrue(errors)
self.assertNotIn(path1, roots)
self.assertNotIn(path1new, roots)
for dir2 in dirs:
if dir2 != dir1:
self.assertIn(root / dir2, roots)
finally:
path1new.rename(path1)
def test_walk_many_open_files(self):
depth = 30
base = self.cls(self.base, 'deep')
path = self.cls(base, *(['d']*depth))
path.mkdir(parents=True)
iters = [base.walk(top_down=False) for _ in range(100)]
for i in range(depth + 1):
expected = (path, ['d'] if i else [], [])
for it in iters:
self.assertEqual(next(it), expected)
path = path.parent
iters = [base.walk(top_down=True) for _ in range(100)]
path = base
for i in range(depth + 1):
expected = (path, ['d'] if i < depth else [], [])
for it in iters:
self.assertEqual(next(it), expected)
path = path / 'd'
def test_walk_above_recursion_limit(self):
recursion_limit = 40
# directory_depth > recursion_limit
directory_depth = recursion_limit + 10
base = self.cls(self.base, 'deep')
path = base.joinpath(*(['d'] * directory_depth))
path.mkdir(parents=True)
with infinite_recursion(recursion_limit):
list(base.walk())
list(base.walk(top_down=False))
@unittest.skipIf(os.name == 'nt', 'test requires a POSIX-compatible system')
class PosixPathTest(PathTest, PurePosixPathTest):
cls = pathlib.PosixPath

View File

@ -2922,7 +2922,16 @@ class DummyPathTest(DummyPurePathTest):
filename = tmp / 'foo'
self.assertRaises(FileNotFoundError, filename._delete)
def setUpWalk(self):
class DummyPathWalkTest(unittest.TestCase):
cls = DummyPath
base = DummyPathTest.base
can_symlink = False
def setUp(self):
name = self.id().split('.')[-1]
if name in _tests_needing_symlinks and not self.can_symlink:
self.skipTest('requires symlinks')
# Build:
# TESTFN/
# TEST1/ a file kid and two directory kids
@ -2966,8 +2975,11 @@ class DummyPathTest(DummyPurePathTest):
else:
self.sub2_tree = (self.sub2_path, [], ["tmp3"])
def tearDown(self):
base = self.cls(self.base)
base._rmtree()
def test_walk_topdown(self):
self.setUpWalk()
walker = self.walk_path.walk()
entry = next(walker)
entry[1].sort() # Ensure we visit SUB1 before SUB2
@ -2984,7 +2996,6 @@ class DummyPathTest(DummyPurePathTest):
next(walker)
def test_walk_prune(self):
self.setUpWalk()
# Prune the search.
all = []
for root, dirs, files in self.walk_path.walk():
@ -3001,7 +3012,6 @@ class DummyPathTest(DummyPurePathTest):
self.assertEqual(all[1], self.sub2_tree)
def test_walk_bottom_up(self):
self.setUpWalk()
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:
@ -3036,7 +3046,6 @@ class DummyPathTest(DummyPurePathTest):
@needs_symlinks
def test_walk_follow_symlinks(self):
self.setUpWalk()
walk_it = self.walk_path.walk(follow_symlinks=True)
for root, dirs, files in walk_it:
if root == self.link_path:
@ -3048,7 +3057,6 @@ class DummyPathTest(DummyPurePathTest):
@needs_symlinks
def test_walk_symlink_location(self):
self.setUpWalk()
# Tests whether symlinks end up in filenames or dirnames depending
# on the `follow_symlinks` argument.
walk_it = self.walk_path.walk(follow_symlinks=False)
@ -3097,5 +3105,10 @@ class DummyPathWithSymlinksTest(DummyPathTest):
can_symlink = True
class DummyPathWithSymlinksWalkTest(DummyPathWalkTest):
cls = DummyPathWithSymlinks
can_symlink = True
if __name__ == "__main__":
unittest.main()