Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
6ffface4
Commit
6ffface4
authored
Jun 11, 2014
by
R David Murray
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#19840: Add copy_function to shutil.move.
Patch by Claudiu Popa.
parent
6fe56a32
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
54 additions
and
9 deletions
+54
-9
Doc/library/shutil.rst
Doc/library/shutil.rst
+17
-5
Doc/whatsnew/3.5.rst
Doc/whatsnew/3.5.rst
+8
-0
Lib/shutil.py
Lib/shutil.py
+11
-4
Lib/test/test_shutil.py
Lib/test/test_shutil.py
+18
-0
No files found.
Doc/library/shutil.rst
View file @
6ffface4
...
@@ -191,7 +191,8 @@ Directory and files operations
...
@@ -191,7 +191,8 @@ Directory and files operations
match one of the glob-style *patterns* provided. See the example below.
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)
Recursively copy an entire directory tree rooted at *src*, returning the
Recursively copy an entire directory tree rooted at *src*, returning the
destination directory. The destination
destination directory. The destination
...
@@ -282,7 +283,7 @@ Directory and files operations
...
@@ -282,7 +283,7 @@ Directory and files operations
.. versionadded:: 3.3
.. versionadded:: 3.3
.. function:: move(src, dst)
.. function:: move(src, dst
, copy_function=copy2
)
Recursively move a file or directory (*src*) to another location (*dst*)
Recursively move a file or directory (*src*) to another location (*dst*)
and return the destination.
and return the destination.
...
@@ -295,15 +296,26 @@ Directory and files operations
...
@@ -295,15 +296,26 @@ Directory and files operations
:func:`os.rename` semantics.
:func:`os.rename` semantics.
If the destination is on the current filesystem, then :func:`os.rename` is
If the destination is on the current filesystem, then :func:`os.rename` is
used. Otherwise, *src* is copied (using :func:`shutil.copy2`) to *dst* and
used. Otherwise, *src* is copied to *dst* using *copy_function* and then
then removed. In case of symlinks, a new symlink pointing to the target of
removed. In case of symlinks, a new symlink pointing to the target of *src*
*src* will be created in or as *dst* and *src* will be removed.
will be created in or as *dst* and *src* will be removed.
If *copy_function* is given, it must be a callable that takes two arguments
*src* and *dst*, and will be used to copy *src* to *dest* if
:func:`os.rename` cannot be used. If the source is a directory,
:func:`copytree` is called, passing it the :func:`copy_function`. The
default *copy_function* is :func:`copy2`. Using :func:`copy` as the
*copy_function* allows the move to succeed when it is not possible to also
copy the metadata, at the expense of not copying any of the metadata.
.. versionchanged:: 3.3
.. versionchanged:: 3.3
Added explicit symlink handling for foreign filesystems, thus adapting
Added explicit symlink handling for foreign filesystems, thus adapting
it to the behavior of GNU's :program:`mv`.
it to the behavior of GNU's :program:`mv`.
Now returns *dst*.
Now returns *dst*.
.. versionchanged:: 3.5
Added the *copy_function* keyword argument.
.. function:: disk_usage(path)
.. function:: disk_usage(path)
Return disk usage statistics about the given path as a :term:`named tuple`
Return disk usage statistics about the given path as a :term:`named tuple`
...
...
Doc/whatsnew/3.5.rst
View file @
6ffface4
...
@@ -176,6 +176,14 @@ ipaddress
...
@@ -176,6 +176,14 @@ ipaddress
network objects from existing addresses (contributed by Peter Moody
network objects from existing addresses (contributed by Peter Moody
and Antoine Pitrou in :issue:`16531`).
and Antoine Pitrou in :issue:`16531`).
shutil
------
* :func:`~shutil.move` now accepts a *copy_function* argument, allowing,
for example, :func:`~shutil.copy` to be used instead of the default
:func:`~shutil.copy2` if there is a need to ignore metadata. (Contributed by
Claudiu Popa in :issue:`19840`.)
signal
signal
------
------
...
...
Lib/shutil.py
View file @
6ffface4
...
@@ -486,7 +486,7 @@ def _basename(path):
...
@@ -486,7 +486,7 @@ def _basename(path):
sep
=
os
.
path
.
sep
+
(
os
.
path
.
altsep
or
''
)
sep
=
os
.
path
.
sep
+
(
os
.
path
.
altsep
or
''
)
return
os
.
path
.
basename
(
path
.
rstrip
(
sep
))
return
os
.
path
.
basename
(
path
.
rstrip
(
sep
))
def
move
(
src
,
dst
):
def
move
(
src
,
dst
,
copy_function
=
copy2
):
"""Recursively move a file or directory to another location. This is
"""Recursively move a file or directory to another location. This is
similar to the Unix "mv" command. Return the file or directory's
similar to the Unix "mv" command. Return the file or directory's
destination.
destination.
...
@@ -503,6 +503,11 @@ def move(src, dst):
...
@@ -503,6 +503,11 @@ def move(src, dst):
recreated under the new name if os.rename() fails because of cross
recreated under the new name if os.rename() fails because of cross
filesystem renames.
filesystem renames.
The optional `copy_function` argument is a callable that will be used
to copy the source or it will be delegated to `copytree`.
By default, copy2() is used, but any function that supports the same
signature (like copy()) can be used.
A lot more could be done here... A look at a mv.c shows a lot of
A lot more could be done here... A look at a mv.c shows a lot of
the issues this implementation glosses over.
the issues this implementation glosses over.
...
@@ -527,11 +532,13 @@ def move(src, dst):
...
@@ -527,11 +532,13 @@ def move(src, dst):
os
.
unlink
(
src
)
os
.
unlink
(
src
)
elif
os
.
path
.
isdir
(
src
):
elif
os
.
path
.
isdir
(
src
):
if
_destinsrc
(
src
,
dst
):
if
_destinsrc
(
src
,
dst
):
raise
Error
(
"Cannot move a directory '%s' into itself '%s'."
%
(
src
,
dst
))
raise
Error
(
"Cannot move a directory '%s' into itself"
copytree
(
src
,
real_dst
,
symlinks
=
True
)
" '%s'."
%
(
src
,
dst
))
copytree
(
src
,
real_dst
,
copy_function
=
copy_function
,
symlinks
=
True
)
rmtree
(
src
)
rmtree
(
src
)
else
:
else
:
copy
2
(
src
,
real_dst
)
copy
_function
(
src
,
real_dst
)
os
.
unlink
(
src
)
os
.
unlink
(
src
)
return
real_dst
return
real_dst
...
...
Lib/test/test_shutil.py
View file @
6ffface4
...
@@ -1592,6 +1592,24 @@ class TestMove(unittest.TestCase):
...
@@ -1592,6 +1592,24 @@ class TestMove(unittest.TestCase):
rv
=
shutil
.
move
(
self
.
src_file
,
os
.
path
.
join
(
self
.
dst_dir
,
'bar'
))
rv
=
shutil
.
move
(
self
.
src_file
,
os
.
path
.
join
(
self
.
dst_dir
,
'bar'
))
self
.
assertEqual
(
rv
,
os
.
path
.
join
(
self
.
dst_dir
,
'bar'
))
self
.
assertEqual
(
rv
,
os
.
path
.
join
(
self
.
dst_dir
,
'bar'
))
@
mock_rename
def
test_move_file_special_function
(
self
):
moved
=
[]
def
_copy
(
src
,
dst
):
moved
.
append
((
src
,
dst
))
shutil
.
move
(
self
.
src_file
,
self
.
dst_dir
,
copy_function
=
_copy
)
self
.
assertEqual
(
len
(
moved
),
1
)
@
mock_rename
def
test_move_dir_special_function
(
self
):
moved
=
[]
def
_copy
(
src
,
dst
):
moved
.
append
((
src
,
dst
))
support
.
create_empty_file
(
os
.
path
.
join
(
self
.
src_dir
,
'child'
))
support
.
create_empty_file
(
os
.
path
.
join
(
self
.
src_dir
,
'child1'
))
shutil
.
move
(
self
.
src_dir
,
self
.
dst_dir
,
copy_function
=
_copy
)
self
.
assertEqual
(
len
(
moved
),
3
)
class
TestCopyFile
(
unittest
.
TestCase
):
class
TestCopyFile
(
unittest
.
TestCase
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment