diff options
author | mbarkhau <mbarkhau@gmail.com> | 2020-01-24 14:51:16 (GMT) |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2020-01-24 14:51:16 (GMT) |
commit | 88704334e5262c6cd395a0809d4ef810f33f3ca5 (patch) | |
tree | 6ddbbf3be7e755ccaf6dab8d5dd14c533acda7a6 | |
parent | 66b00a9d3aacf6ed49412f48743e4913104a2bb3 (diff) | |
download | cpython-88704334e5262c6cd395a0809d4ef810f33f3ca5.zip cpython-88704334e5262c6cd395a0809d4ef810f33f3ca5.tar.gz cpython-88704334e5262c6cd395a0809d4ef810f33f3ca5.tar.bz2 |
bpo-39390 shutil: fix argument types for ignore callback (GH-18122)
-rw-r--r-- | Lib/shutil.py | 2 | ||||
-rw-r--r-- | Lib/test/test_shutil.py | 42 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2020-01-23-21-34-29.bpo-39390.D2tSXk.rst | 2 |
3 files changed, 45 insertions, 1 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py index 8f609b3..9a83a32 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -442,7 +442,7 @@ def ignore_patterns(*patterns): def _copytree(entries, src, dst, symlinks, ignore, copy_function, ignore_dangling_symlinks, dirs_exist_ok=False): if ignore is not None: - ignored_names = ignore(src, {x.name for x in entries}) + ignored_names = ignore(os.fspath(src), [x.name for x in entries]) else: ignored_names = set() diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 460b979..076c450 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -579,6 +579,48 @@ class TestCopyTree(BaseTest, unittest.TestCase): shutil.rmtree(src_dir) shutil.rmtree(os.path.dirname(dst_dir)) + def test_copytree_arg_types_of_ignore(self): + join = os.path.join + exists = os.path.exists + + tmp_dir = self.mkdtemp() + src_dir = join(tmp_dir, "source") + + os.mkdir(join(src_dir)) + os.mkdir(join(src_dir, 'test_dir')) + os.mkdir(os.path.join(src_dir, 'test_dir', 'subdir')) + write_file((src_dir, 'test_dir', 'subdir', 'test.txt'), '456') + + invokations = [] + + def _ignore(src, names): + invokations.append(src) + self.assertIsInstance(src, str) + self.assertIsInstance(names, list) + self.assertEqual(len(names), len(set(names))) + for name in names: + self.assertIsInstance(name, str) + return [] + + dst_dir = join(self.mkdtemp(), 'destination') + shutil.copytree(src_dir, dst_dir, ignore=_ignore) + self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir', + 'test.txt'))) + + dst_dir = join(self.mkdtemp(), 'destination') + shutil.copytree(pathlib.Path(src_dir), dst_dir, ignore=_ignore) + self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir', + 'test.txt'))) + + dst_dir = join(self.mkdtemp(), 'destination') + src_dir_entry = list(os.scandir(tmp_dir))[0] + self.assertIsInstance(src_dir_entry, os.DirEntry) + shutil.copytree(src_dir_entry, dst_dir, ignore=_ignore) + self.assertTrue(exists(join(dst_dir, 'test_dir', 'subdir', + 'test.txt'))) + + self.assertEqual(len(invokations), 9) + def test_copytree_retains_permissions(self): tmp_dir = self.mkdtemp() src_dir = os.path.join(tmp_dir, 'source') diff --git a/Misc/NEWS.d/next/Library/2020-01-23-21-34-29.bpo-39390.D2tSXk.rst b/Misc/NEWS.d/next/Library/2020-01-23-21-34-29.bpo-39390.D2tSXk.rst new file mode 100644 index 0000000..ffa961e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-01-23-21-34-29.bpo-39390.D2tSXk.rst @@ -0,0 +1,2 @@ +Fixed a regression with the `ignore` callback of :func:`shutil.copytree`. +The argument types are now str and List[str] again. |