Skip to content

Commit 7401d28

Browse files
committed
Catch SameFileError explicitly in _copytree
If not, it is caught as a shutil.Error for which it is assumed to be a recursive error, resulting in splitting of the error string as ``` shutil.Error: ['<', 'D', 'i', 'r', 'E', 'n', 't', 'r', 'y', ' ', ..., 's', 'a', 'm', 'e', ' ', 'f', 'i', 'l', 'e'] ```
1 parent aeb9b65 commit 7401d28

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

Lib/shutil.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,11 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
529529
else:
530530
# Will raise a SpecialFileError for unsupported file types
531531
copy_function(srcobj, dstname)
532-
# catch the Error from the recursive copytree so that we can
533-
# continue with other files
532+
except SameFileError as err:
533+
errors.append((srcname, dstname, str(err)))
534534
except Error as err:
535+
# catch the Error from the recursive copytree so that we can
536+
# continue with other files
535537
errors.extend(err.args[0])
536538
except OSError as why:
537539
errors.append((srcname, dstname, str(why)))

Lib/test/test_shutil.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,32 @@ def test_copytree_subdirectory(self):
11011101
rv = shutil.copytree(src_dir, dst_dir)
11021102
self.assertEqual(['pol'], os.listdir(rv))
11031103

1104+
def test_copytree_to_itself_gives_sensible_error_message(self):
1105+
base_dir = self.mkdtemp()
1106+
src_dir = os.path.join(base_dir, "src")
1107+
os.makedirs(src_dir)
1108+
create_file((src_dir, "somefilename"), "somecontent")
1109+
_assert_are_the_same_file_is_raised(src_dir, src_dir)
1110+
1111+
def test_copytree_to_backpointing_symlink_gives_sensible_error_message(self):
1112+
base_dir = self.mkdtemp()
1113+
src_dir = os.path.join(base_dir, "src")
1114+
target_dir = os.path.join(base_dir, "target")
1115+
os.makedirs(src_dir)
1116+
os.makedirs(target_dir)
1117+
some_file = os.path.join(src_dir, "somefilename")
1118+
create_file(some_file, "somecontent")
1119+
os.symlink(some_file, os.path.join(target_dir, "somefilename"))
1120+
_assert_are_the_same_file_is_raised(src_dir, target_dir)
1121+
1122+
def _assert_are_the_same_file_is_raised(src_dir, target_dir):
1123+
try:
1124+
shutil.copytree(src_dir, target_dir, dirs_exist_ok=True)
1125+
raise Exception("copytree did not raise")
1126+
except Error as error:
1127+
assert len(error.args[0]) == 1
1128+
assert "are the same file" in error.args[0][0][2]
1129+
11041130
class TestCopy(BaseTest, unittest.TestCase):
11051131

11061132
### shutil.copymode

0 commit comments

Comments
 (0)