diff --git a/Lib/os.py b/Lib/os.py index b4c651d24d2..011285e74bd 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -537,13 +537,13 @@ if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd: dirs.append(name) else: nondirs.append(name) - except FileNotFoundError: + except OSError: try: # Add dangling symlinks, ignore disappeared files if st.S_ISLNK(stat(name, dir_fd=topfd, follow_symlinks=False) .st_mode): nondirs.append(name) - except FileNotFoundError: + except OSError: continue if topdown: diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 97202109ee3..ac53e1b2441 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -830,39 +830,53 @@ class WalkTests(unittest.TestCase): # SUB11/ no kids # SUB2/ a file kid and a dirsymlink kid # tmp3 + # SUB21/ not readable + # tmp5 # link/ a symlink to TESTFN.2 # broken_link + # broken_link2 + # broken_link3 # TEST2/ # tmp4 a lone file self.walk_path = join(support.TESTFN, "TEST1") self.sub1_path = join(self.walk_path, "SUB1") self.sub11_path = join(self.sub1_path, "SUB11") sub2_path = join(self.walk_path, "SUB2") + self.sub21_path = join(sub2_path, "SUB21") tmp1_path = join(self.walk_path, "tmp1") tmp2_path = join(self.sub1_path, "tmp2") tmp3_path = join(sub2_path, "tmp3") + tmp5_path = join(self.sub21_path, "tmp3") self.link_path = join(sub2_path, "link") t2_path = join(support.TESTFN, "TEST2") tmp4_path = join(support.TESTFN, "TEST2", "tmp4") broken_link_path = join(sub2_path, "broken_link") + broken_link2_path = join(sub2_path, "broken_link2") + broken_link3_path = join(sub2_path, "broken_link3") # Create stuff. os.makedirs(self.sub11_path) os.makedirs(sub2_path) + os.makedirs(self.sub21_path) os.makedirs(t2_path) - for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path: - f = open(path, "w") - f.write("I'm " + path + " and proud of it. Blame test_os.\n") - f.close() + for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path: + with open(path, "x") as f: + f.write("I'm " + path + " and proud of it. Blame test_os.\n") if support.can_symlink(): os.symlink(os.path.abspath(t2_path), self.link_path) os.symlink('broken', broken_link_path, True) - self.sub2_tree = (sub2_path, ["link"], ["broken_link", "tmp3"]) + os.symlink(join('tmp3', 'broken'), broken_link2_path, True) + os.symlink(join('SUB21', 'tmp5'), broken_link3_path, True) + self.sub2_tree = (sub2_path, ["link", "SUB21"], + ["broken_link", "broken_link2", "broken_link3", + "tmp3"]) else: self.sub2_tree = (sub2_path, [], ["tmp3"]) + os.chmod(self.sub21_path, 0) + def test_walk_topdown(self): # Walk top-down. all = list(self.walk(self.walk_path)) @@ -935,6 +949,7 @@ class WalkTests(unittest.TestCase): # Windows, which doesn't have a recursive delete command. The # (not so) subtlety is that rmdir will fail unless the dir's # kids are removed first, so bottom up is essential. + os.chmod(self.sub21_path, stat.S_IRWXU) for root, dirs, files in os.walk(support.TESTFN, topdown=False): for name in files: os.remove(os.path.join(root, name)) @@ -1030,6 +1045,7 @@ class FwalkTests(WalkTests): def tearDown(self): # cleanup + os.chmod(self.sub21_path, stat.S_IRWXU) for root, dirs, files, rootfd in os.fwalk(support.TESTFN, topdown=False): for name in files: os.unlink(name, dir_fd=rootfd) diff --git a/Misc/NEWS b/Misc/NEWS index ff6025c4795..ea90cbb9da6 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -113,6 +113,8 @@ Core and Builtins Library ------- +- Issue #28353: os.fwalk() no longer fails on broken links. + - Issue #25464: Fixed HList.header_exists() in tkinter.tix module by addin a workaround to Tix library bug.