Skip to content

Commit 5ff81da

Browse files
authored
bpo-38523: ignore_dangling_symlinks does not apply recursively (GH-22937)
1 parent cfec5b1 commit 5ff81da

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
@@ -490,12 +490,13 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
490490
# otherwise let the copy occur. copy2 will raise an error
491491
if srcentry.is_dir():
492492
copytree(srcobj, dstname, symlinks, ignore,
493-
copy_function, dirs_exist_ok=dirs_exist_ok)
493+
copy_function, ignore_dangling_symlinks,
494+
dirs_exist_ok)
494495
else:
495496
copy_function(srcobj, dstname)
496497
elif srcentry.is_dir():
497498
copytree(srcobj, dstname, symlinks, ignore, copy_function,
498-
dirs_exist_ok=dirs_exist_ok)
499+
ignore_dangling_symlinks, dirs_exist_ok)
499500
else:
500501
# Will raise a SpecialFileError for unsupported file types
501502
copy_function(srcobj, dstname)

Lib/test/test_shutil.py

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

753753
@os_helper.skip_unless_symlink
754754
def test_copytree_dangling_symlinks(self):
755-
# a dangling symlink raises an error at the end
756755
src_dir = self.mkdtemp()
756+
valid_file = os.path.join(src_dir, 'test.txt')
757+
write_file(valid_file, 'abc')
758+
dir_a = os.path.join(src_dir, 'dir_a')
759+
os.mkdir(dir_a)
760+
for d in src_dir, dir_a:
761+
os.symlink('IDONTEXIST', os.path.join(d, 'broken'))
762+
os.symlink(valid_file, os.path.join(d, 'valid'))
763+
764+
# A dangling symlink should raise an error.
757765
dst_dir = os.path.join(self.mkdtemp(), 'destination')
758-
os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
759-
os.mkdir(os.path.join(src_dir, 'test_dir'))
760-
write_file((src_dir, 'test_dir', 'test.txt'), '456')
761766
self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
762767

763-
# a dangling symlink is ignored with the proper flag
768+
# Dangling symlinks should be ignored with the proper flag.
764769
dst_dir = os.path.join(self.mkdtemp(), 'destination2')
765770
shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
766-
self.assertNotIn('test.txt', os.listdir(dst_dir))
771+
for root, dirs, files in os.walk(dst_dir):
772+
self.assertNotIn('broken', files)
773+
self.assertIn('valid', files)
767774

768775
# a dangling symlink is copied if symlinks=True
769776
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)