diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 427a120159633d..e91c35a856bc71 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -210,7 +210,7 @@ Directory and files operations .. function:: copytree(src, dst, symlinks=False, ignore=None, \ copy_function=copy2, ignore_dangling_symlinks=False, \ - dirs_exist_ok=False) + dirs_exist_ok=False, use_srcentry=True) Recursively copy an entire directory tree rooted at *src* to a directory named *dst* and return the destination directory. *dirs_exist_ok* dictates @@ -248,6 +248,9 @@ Directory and files operations each file. It will be called with the source path and the destination path as arguments. By default, :func:`shutil.copy2` is used, but any function that supports the same signature (like :func:`shutil.copy`) can be used. + If *use_srcentry* is true, the *copy_function* gets the srcentry, otherwise + it gets the srcname. The functions copy() and copy2() can handle the + srcentry. .. versionchanged:: 3.3 Copy metadata when *symlinks* is false. @@ -263,6 +266,8 @@ Directory and files operations Platform-specific fast-copy syscalls may be used internally in order to copy the file more efficiently. See :ref:`shutil-platform-dependent-efficient-copy-operations` section. + Added *use_srcentry* parameter to control if the srcentry or the srcname + is passed to the *copy_function*. .. versionadded:: 3.8 The *dirs_exist_ok* parameter. diff --git a/Lib/shutil.py b/Lib/shutil.py index 8d0de72b44a3a4..f1de1535654dc6 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -432,7 +432,7 @@ def _ignore_patterns(path, names): return _ignore_patterns def _copytree(entries, src, dst, symlinks, ignore, copy_function, - ignore_dangling_symlinks, dirs_exist_ok=False): + ignore_dangling_symlinks, dirs_exist_ok, use_srcentry): if ignore is not None: ignored_names = ignore(src, set(os.listdir(src))) else: @@ -440,7 +440,6 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function, os.makedirs(dst, exist_ok=dirs_exist_ok) errors = [] - use_srcentry = copy_function is copy2 or copy_function is copy for srcentry in entries: if srcentry.name in ignored_names: @@ -490,7 +489,8 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function, return dst def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False, dirs_exist_ok=False): + ignore_dangling_symlinks=False, dirs_exist_ok=False, + use_srcentry=True): """Recursively copy a directory tree and return the destination directory. dirs_exist_ok dictates whether to raise an exception in case dst or any @@ -526,12 +526,17 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, destination path as arguments. By default, copy2() is used, but any function that supports the same signature (like copy()) can be used. + When the copy_function should recieve a srcentry (like copy2() and + copy()), set use_srcentry to true, otherwise the function will pass + only the srcname to the copy_function. + """ with os.scandir(src) as entries: return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks, ignore=ignore, copy_function=copy_function, ignore_dangling_symlinks=ignore_dangling_symlinks, - dirs_exist_ok=dirs_exist_ok) + dirs_exist_ok=dirs_exist_ok, + use_srcentry=use_srcentry) # version vulnerable to race conditions def _rmtree_unsafe(path, onerror): diff --git a/Misc/NEWS.d/next/Library/2019-01-03-19-08-44.bpo-35652.6c7eB5.rst b/Misc/NEWS.d/next/Library/2019-01-03-19-08-44.bpo-35652.6c7eB5.rst new file mode 100644 index 00000000000000..5ceb9f0663c561 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-01-03-19-08-44.bpo-35652.6c7eB5.rst @@ -0,0 +1 @@ +shutil.copytree has now the `use_srcentry` argument. With this it's possible to control if the *copy_function* will get a srcentry or srcname. \ No newline at end of file