Skip to content

Commit eb0e942

Browse files
bpo-38523: ignore_dangling_symlinks does not apply recursively (GH-22937)
(cherry picked from commit 5ff81da) Co-authored-by: Zackery Spytz <[email protected]>
1 parent ea2316a commit eb0e942

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

Lib/shutil.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,13 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
487487
# otherwise let the copy occur. copy2 will raise an error
488488
if srcentry.is_dir():
489489
copytree(srcobj, dstname, symlinks, ignore,
490-
copy_function, dirs_exist_ok=dirs_exist_ok)
490+
copy_function, ignore_dangling_symlinks,
491+
dirs_exist_ok)
491492
else:
492493
copy_function(srcobj, dstname)
493494
elif srcentry.is_dir():
494495
copytree(srcobj, dstname, symlinks, ignore, copy_function,
495-
dirs_exist_ok=dirs_exist_ok)
496+
ignore_dangling_symlinks, dirs_exist_ok)
496497
else:
497498
# Will raise a SpecialFileError for unsupported file types
498499
copy_function(srcobj, dstname)

Lib/test/test_shutil.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -731,18 +731,25 @@ def _copy(src, dst):
731731

732732
@os_helper.skip_unless_symlink
733733
def test_copytree_dangling_symlinks(self):
734-
# a dangling symlink raises an error at the end
735734
src_dir = self.mkdtemp()
735+
valid_file = os.path.join(src_dir, 'test.txt')
736+
write_file(valid_file, 'abc')
737+
dir_a = os.path.join(src_dir, 'dir_a')
738+
os.mkdir(dir_a)
739+
for d in src_dir, dir_a:
740+
os.symlink('IDONTEXIST', os.path.join(d, 'broken'))
741+
os.symlink(valid_file, os.path.join(d, 'valid'))
742+
743+
# A dangling symlink should raise an error.
736744
dst_dir = os.path.join(self.mkdtemp(), 'destination')
737-
os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
738-
os.mkdir(os.path.join(src_dir, 'test_dir'))
739-
write_file((src_dir, 'test_dir', 'test.txt'), '456')
740745
self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
741746

742-
# a dangling symlink is ignored with the proper flag
747+
# Dangling symlinks should be ignored with the proper flag.
743748
dst_dir = os.path.join(self.mkdtemp(), 'destination2')
744749
shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
745-
self.assertNotIn('test.txt', os.listdir(dst_dir))
750+
for root, dirs, files in os.walk(dst_dir):
751+
self.assertNotIn('broken', files)
752+
self.assertIn('valid', files)
746753

747754
# a dangling symlink is copied if symlinks=True
748755
dst_dir = os.path.join(self.mkdtemp(), 'destination3')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`shutil.copytree` now applies the *ignore_dangling_symlinks* argument
2+
recursively.

0 commit comments

Comments
 (0)