summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/library/shutil.rst3
-rw-r--r--Lib/shutil.py19
-rw-r--r--Lib/test/test_shutil.py10
-rw-r--r--Misc/NEWS.d/next/Library/2018-02-13-17-58-30.bpo-32689.a-3SnH.rst2
4 files changed, 32 insertions, 2 deletions
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index 174b7e875a..59390d0e90 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -355,6 +355,9 @@ Directory and files operations
copy the file more efficiently. See
:ref:`shutil-platform-dependent-efficient-copy-operations` section.
+ .. versionchanged:: 3.9
+ Accepts a :term:`path-like object` for both *src* and *dst*.
+
.. function:: disk_usage(path)
Return disk usage statistics about the given path as a :term:`named tuple`
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 5c1255a671..f0d0336636 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -730,8 +730,20 @@ def rmtree(path, ignore_errors=False, onerror=None):
rmtree.avoids_symlink_attacks = _use_fd_functions
def _basename(path):
- # A basename() variant which first strips the trailing slash, if present.
- # Thus we always get the last component of the path, even for directories.
+ """A basename() variant which first strips the trailing slash, if present.
+ Thus we always get the last component of the path, even for directories.
+
+ path: Union[PathLike, str]
+
+ e.g.
+ >>> os.path.basename('/bar/foo')
+ 'foo'
+ >>> os.path.basename('/bar/foo/')
+ ''
+ >>> _basename('/bar/foo/')
+ 'foo'
+ """
+ path = os.fspath(path)
sep = os.path.sep + (os.path.altsep or '')
return os.path.basename(path.rstrip(sep))
@@ -769,7 +781,10 @@ def move(src, dst, copy_function=copy2):
os.rename(src, dst)
return
+ # Using _basename instead of os.path.basename is important, as we must
+ # ignore any trailing slash to avoid the basename returning ''
real_dst = os.path.join(dst, _basename(src))
+
if os.path.exists(real_dst):
raise Error("Destination path '%s' already exists" % real_dst)
try:
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index ab0f96d251..428d4f3417 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -1835,6 +1835,16 @@ class TestMove(BaseTest, unittest.TestCase):
# Move a file inside an existing dir on the same filesystem.
self._check_move_file(self.src_file, self.dst_dir, self.dst_file)
+ def test_move_file_to_dir_pathlike_src(self):
+ # Move a pathlike file to another location on the same filesystem.
+ src = pathlib.Path(self.src_file)
+ self._check_move_file(src, self.dst_dir, self.dst_file)
+
+ def test_move_file_to_dir_pathlike_dst(self):
+ # Move a file to another pathlike location on the same filesystem.
+ dst = pathlib.Path(self.dst_dir)
+ self._check_move_file(self.src_file, dst, self.dst_file)
+
@mock_rename
def test_move_file_other_fs(self):
# Move a file to an existing dir on another filesystem.
diff --git a/Misc/NEWS.d/next/Library/2018-02-13-17-58-30.bpo-32689.a-3SnH.rst b/Misc/NEWS.d/next/Library/2018-02-13-17-58-30.bpo-32689.a-3SnH.rst
new file mode 100644
index 0000000000..d435351a3a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-02-13-17-58-30.bpo-32689.a-3SnH.rst
@@ -0,0 +1,2 @@
+Update :func:`shutil.move` function to allow for Path objects to be used as
+source argument. Patch by Emily Morehouse and Maxwell "5.13b" McKinnon.