diff -r e063f1b724d7 Doc/library/shutil.rst --- a/Doc/library/shutil.rst Tue Mar 13 00:16:17 2012 -0700 +++ b/Doc/library/shutil.rst Tue Mar 13 04:32:55 2012 -0400 @@ -118,7 +118,7 @@ match one of the glob-style *patterns* provided. See the example below. -.. function:: copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False) +.. function:: copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, makedirs_function=os.makedirs) Recursively copy an entire directory tree rooted at *src*. The destination directory, named by *dst*, must not already exist; it will be created as @@ -155,6 +155,10 @@ as arguments. By default, :func:`shutil.copy2` is used, but any function that supports the same signature (like :func:`shutil.copy`) can be used. + The *makedirs_function* argument, if given, should be a callable that can + be used to create the destination directory. By default, we simply use the + :func:`os.makedirs` function. + .. versionchanged:: 3.2 Added the *copy_function* argument to be able to provide a custom copy function. diff -r e063f1b724d7 Lib/shutil.py --- a/Lib/shutil.py Tue Mar 13 00:16:17 2012 -0700 +++ b/Lib/shutil.py Tue Mar 13 04:32:55 2012 -0400 @@ -205,7 +205,7 @@ return _ignore_patterns def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False): + ignore_dangling_symlinks=False, makedirs_function=os.makedirs): """Recursively copy a directory tree. The destination directory must not already exist. @@ -239,6 +239,9 @@ destination path as arguments. By default, copy2() is used, but any function that supports the same signature (like copy()) can be used. + The optional makedirs_function argument is a callable that is used to + create the directory structure. We default to os.makedirs here. + """ names = os.listdir(src) if ignore is not None: @@ -246,7 +249,7 @@ else: ignored_names = set() - os.makedirs(dst) + makedirs_function(dst) errors = [] for name in names: if name in ignored_names: diff -r e063f1b724d7 Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py Tue Mar 13 00:16:17 2012 -0700 +++ b/Lib/test/test_shutil.py Tue Mar 13 04:32:55 2012 -0400 @@ -577,10 +577,26 @@ shutil.copytree(src_dir, dst_dir, copy_function=_copy) self.assertEqual(len(copied), 2) + + def test_copytree_makedirs_func(self): + + src_dir = self.mkdtemp() + dst_dir = os.path.join(self.mkdtemp(), 'destination') + write_file((src_dir, 'test.txt'), '123') + + created = [] + def _makedirs(dir_name): + created.append(dir_name) + os.makedirs(dir_name) + + shutil.copytree(src_dir, dst_dir, makedirs_function=_makedirs) + self.assertEqual(len(created), 1) + self.assertEqual(created[0], dst_dir) + @support.skip_unless_symlink def test_copytree_dangling_symlinks(self): - # a dangling symlink raises an error at the end + # a dangling symlink raises an error at the end src_dir = self.mkdtemp() dst_dir = os.path.join(self.mkdtemp(), 'destination') os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))