bpo-32689: Updates shutil.move to allow for Path objects to be used a… · python/cpython@cf57cab

4 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -355,6 +355,9 @@ Directory and files operations

355355

copy the file more efficiently. See

356356

:ref:`shutil-platform-dependent-efficient-copy-operations` section.

357357
358+

.. versionchanged:: 3.9

359+

Accepts a :term:`path-like object` for both *src* and *dst*.

360+
358361

.. function:: disk_usage(path)

359362
360363

Return disk usage statistics about the given path as a :term:`named tuple`

Original file line numberDiff line numberDiff line change

@@ -730,8 +730,20 @@ def onerror(*args):

730730

rmtree.avoids_symlink_attacks = _use_fd_functions

731731
732732

def _basename(path):

733-

# A basename() variant which first strips the trailing slash, if present.

734-

# Thus we always get the last component of the path, even for directories.

733+

"""A basename() variant which first strips the trailing slash, if present.

734+

Thus we always get the last component of the path, even for directories.

735+
736+

path: Union[PathLike, str]

737+
738+

e.g.

739+

>>> os.path.basename('/bar/foo')

740+

'foo'

741+

>>> os.path.basename('/bar/foo/')

742+

''

743+

>>> _basename('/bar/foo/')

744+

'foo'

745+

"""

746+

path = os.fspath(path)

735747

sep = os.path.sep + (os.path.altsep or '')

736748

return os.path.basename(path.rstrip(sep))

737749

@@ -769,7 +781,10 @@ def move(src, dst, copy_function=copy2):

769781

os.rename(src, dst)

770782

return

771783
784+

# Using _basename instead of os.path.basename is important, as we must

785+

# ignore any trailing slash to avoid the basename returning ''

772786

real_dst = os.path.join(dst, _basename(src))

787+
773788

if os.path.exists(real_dst):

774789

raise Error("Destination path '%s' already exists" % real_dst)

775790

try:

Original file line numberDiff line numberDiff line change

@@ -1835,6 +1835,16 @@ def test_move_file_to_dir(self):

18351835

# Move a file inside an existing dir on the same filesystem.

18361836

self._check_move_file(self.src_file, self.dst_dir, self.dst_file)

18371837
1838+

def test_move_file_to_dir_pathlike_src(self):

1839+

# Move a pathlike file to another location on the same filesystem.

1840+

src = pathlib.Path(self.src_file)

1841+

self._check_move_file(src, self.dst_dir, self.dst_file)

1842+
1843+

def test_move_file_to_dir_pathlike_dst(self):

1844+

# Move a file to another pathlike location on the same filesystem.

1845+

dst = pathlib.Path(self.dst_dir)

1846+

self._check_move_file(self.src_file, dst, self.dst_file)

1847+
18381848

@mock_rename

18391849

def test_move_file_other_fs(self):

18401850

# Move a file to an existing dir on another filesystem.

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,2 @@

1+

Update :func:`shutil.move` function to allow for Path objects to be used as

2+

source argument. Patch by Emily Morehouse and Maxwell "5.13b" McKinnon.