bpo-38523: ignore_dangling_symlinks does not apply recursively (GH-22937)

This commit is contained in:
Zackery Spytz 2022-11-07 03:45:16 -08:00 committed by GitHub
parent cfec5b18bf
commit 5ff81da6d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 8 deletions

View File

@ -490,12 +490,13 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
# otherwise let the copy occur. copy2 will raise an error
if srcentry.is_dir():
copytree(srcobj, dstname, symlinks, ignore,
copy_function, dirs_exist_ok=dirs_exist_ok)
copy_function, ignore_dangling_symlinks,
dirs_exist_ok)
else:
copy_function(srcobj, dstname)
elif srcentry.is_dir():
copytree(srcobj, dstname, symlinks, ignore, copy_function,
dirs_exist_ok=dirs_exist_ok)
ignore_dangling_symlinks, dirs_exist_ok)
else:
# Will raise a SpecialFileError for unsupported file types
copy_function(srcobj, dstname)

View File

@ -752,18 +752,25 @@ class TestCopyTree(BaseTest, unittest.TestCase):
@os_helper.skip_unless_symlink
def test_copytree_dangling_symlinks(self):
# a dangling symlink raises an error at the end
src_dir = self.mkdtemp()
valid_file = os.path.join(src_dir, 'test.txt')
write_file(valid_file, 'abc')
dir_a = os.path.join(src_dir, 'dir_a')
os.mkdir(dir_a)
for d in src_dir, dir_a:
os.symlink('IDONTEXIST', os.path.join(d, 'broken'))
os.symlink(valid_file, os.path.join(d, 'valid'))
# A dangling symlink should raise an error.
dst_dir = os.path.join(self.mkdtemp(), 'destination')
os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
os.mkdir(os.path.join(src_dir, 'test_dir'))
write_file((src_dir, 'test_dir', 'test.txt'), '456')
self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
# a dangling symlink is ignored with the proper flag
# Dangling symlinks should be ignored with the proper flag.
dst_dir = os.path.join(self.mkdtemp(), 'destination2')
shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
self.assertNotIn('test.txt', os.listdir(dst_dir))
for root, dirs, files in os.walk(dst_dir):
self.assertNotIn('broken', files)
self.assertIn('valid', files)
# a dangling symlink is copied if symlinks=True
dst_dir = os.path.join(self.mkdtemp(), 'destination3')

View File

@ -0,0 +1,2 @@
:func:`shutil.copytree` now applies the *ignore_dangling_symlinks* argument
recursively.