Skip to content

Commit 3de355d

Browse files
committed
Add an extra test for circular and multiple ultimately dangling links
1 parent c0686d6 commit 3de355d

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

Lib/test/test_shutil.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,57 @@ def test_copytree_dangling_symlinks(self):
10581058
shutil.copytree(src_dir, dst_dir, symlinks=True)
10591059
self.assertIn('test.txt', os.listdir(dst_dir))
10601060

1061+
@os_helper.skip_unless_symlink
1062+
def test_copytree_dangling_links_to_links(self):
1063+
src_dir = self.mkdtemp()
1064+
create_file(os.path.join(src_dir, 'c'), 'abc')
1065+
os.symlink('IDONTEXIST', os.path.join(src_dir, 'foo'))
1066+
os.symlink(os.path.join(src_dir, 'foo'), os.path.join(src_dir, 'broken'))
1067+
1068+
# A dangling symlink should raise an error.
1069+
dst_dir = os.path.join(self.mkdtemp(), 'destination')
1070+
self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
1071+
self.assertEqual(['c'], os.listdir(dst_dir))
1072+
1073+
# Dangling symlinks should be ignored with the proper flag.
1074+
dst_dir = os.path.join(self.mkdtemp(), 'destination2')
1075+
shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
1076+
self.assertEqual(['c'], os.listdir(dst_dir))
1077+
1078+
# a dangling symlink is copied if symlinks=True
1079+
dst_dir = os.path.join(self.mkdtemp(), 'destination3')
1080+
shutil.copytree(src_dir, dst_dir, symlinks=True)
1081+
self.assertEqual({'broken', 'c', 'foo'}, set(os.listdir(dst_dir)))
1082+
1083+
@os_helper.skip_unless_symlink
1084+
def test_copytree_circular_symlinks(self):
1085+
src_dir = self.mkdtemp()
1086+
os.symlink('a', os.path.join(src_dir, 'b'))
1087+
os.symlink('b', os.path.join(src_dir, 'a'))
1088+
create_file(os.path.join(src_dir, 'c'), 'abc')
1089+
1090+
# A circular symlink should raise an error if symlinks=False and
1091+
# ignore_dangling_symlinks=False
1092+
dst_dir = os.path.join(self.mkdtemp(), 'destination')
1093+
with self.assertRaises(Error):
1094+
shutil.copytree(src_dir, dst_dir, symlinks=False,
1095+
ignore_dangling_symlinks=False)
1096+
self.assertEqual(['c'], os.listdir(dst_dir))
1097+
1098+
# ...however it should work if ignore_dangling_symlinks=True...
1099+
dst_dir = os.path.join(self.mkdtemp(), 'destination')
1100+
shutil.copytree(src_dir, dst_dir, symlinks=False,
1101+
ignore_dangling_symlinks=True)
1102+
self.assertEqual(['c'], os.listdir(dst_dir))
1103+
1104+
# ...and of course if symlinks=True
1105+
for ignore in (True, False):
1106+
dst_dir = os.path.join(self.mkdtemp(), 'destination')
1107+
with self.subTest(ignore_dangling_symlinks=ignore):
1108+
shutil.copytree(src_dir, dst_dir, symlinks=True,
1109+
ignore_dangling_symlinks=ignore)
1110+
self.assertEqual({'a', 'b', 'c'}, set(os.listdir(dst_dir)))
1111+
10611112
@os_helper.skip_unless_symlink
10621113
def test_copytree_symlink_dir(self):
10631114
src_dir = self.mkdtemp()

0 commit comments

Comments
 (0)