Skip to content

Commit 8870433

Browse files
mbarkhaugiampaolo
authored andcommitted
bpo-39390 shutil: fix argument types for ignore callback (GH-18122)
1 parent 66b00a9 commit 8870433

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

Lib/shutil.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ def _ignore_patterns(path, names):
442442
def _copytree(entries, src, dst, symlinks, ignore, copy_function,
443443
ignore_dangling_symlinks, dirs_exist_ok=False):
444444
if ignore is not None:
445-
ignored_names = ignore(src, {x.name for x in entries})
445+
ignored_names = ignore(os.fspath(src), [x.name for x in entries])
446446
else:
447447
ignored_names = set()
448448

Lib/test/test_shutil.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,48 @@ def _filter(src, names):
579579
shutil.rmtree(src_dir)
580580
shutil.rmtree(os.path.dirname(dst_dir))
581581

582+
def test_copytree_arg_types_of_ignore(self):
583+
join = os.path.join
584+
exists = os.path.exists
585+
586+
tmp_dir = self.mkdtemp()
587+
src_dir = join(tmp_dir, "source")
588+
589+
os.mkdir(join(src_dir))
590+
os.mkdir(join(src_dir, 'test_dir'))
591+
os.mkdir(os.path.join(src_dir, 'test_dir', 'subdir'))
592+
write_file((src_dir, 'test_dir', 'subdir', 'test.txt'), '456')
593+
594+
invokations = []
595+
596+
def _ignore(src, names):
597+
invokations.append(src)
598+
self.assertIsInstance(src, str)
599+
self.assertIsInstance(names, list)
600+
self.assertEqual(len(names), len(set(names)))
601+
for name in names:
602+
self.assertIsInstance(name, str)
603+
return []
604+
605+
dst_dir = join(self.mkdtemp(), 'destination')
606+
shutil.copytree(src_dir, dst_dir, ignore=_ignore)
607+
self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir',
608+
'test.txt')))
609+
610+
dst_dir = join(self.mkdtemp(), 'destination')
611+
shutil.copytree(pathlib.Path(src_dir), dst_dir, ignore=_ignore)
612+
self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir',
613+
'test.txt')))
614+
615+
dst_dir = join(self.mkdtemp(), 'destination')
616+
src_dir_entry = list(os.scandir(tmp_dir))[0]
617+
self.assertIsInstance(src_dir_entry, os.DirEntry)
618+
shutil.copytree(src_dir_entry, dst_dir, ignore=_ignore)
619+
self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir',
620+
'test.txt')))
621+
622+
self.assertEqual(len(invokations), 9)
623+
582624
def test_copytree_retains_permissions(self):
583625
tmp_dir = self.mkdtemp()
584626
src_dir = os.path.join(tmp_dir, 'source')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a regression with the `ignore` callback of :func:`shutil.copytree`.
2+
The argument types are now str and List[str] again.

0 commit comments

Comments
 (0)