Skip to content

Commit a759059

Browse files
authored
gh-132322: Ensure shutil functions return str when using pathlib
Fixes issue #132322 by normalizing return types in shutil.copy, copy2, copyfile, copytree, and move using os.fspath(), so that they consistently return str even when pathlib.Path is passed. All relevant tests pass locally
1 parent a4ea80d commit a759059

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

Lib/shutil.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def copyfile(src, dst, *, follow_symlinks=True):
310310
if _HAS_FCOPYFILE:
311311
try:
312312
_fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
313-
return dst
313+
return os.fspath(dst)
314314
except _GiveupOnFastCopy:
315315
pass
316316
# Linux / Android / Solaris
@@ -319,20 +319,20 @@ def copyfile(src, dst, *, follow_symlinks=True):
319319
if _USE_CP_COPY_FILE_RANGE:
320320
try:
321321
_fastcopy_copy_file_range(fsrc, fdst)
322-
return dst
322+
return os.fspath(dst)
323323
except _GiveupOnFastCopy:
324324
pass
325325
if _USE_CP_SENDFILE:
326326
try:
327327
_fastcopy_sendfile(fsrc, fdst)
328-
return dst
328+
return os.fspath(dst)
329329
except _GiveupOnFastCopy:
330330
pass
331331
# Windows, see:
332332
# https://github.com/python/cpython/pull/7160#discussion_r195405230
333333
elif _WINDOWS and file_size > 0:
334334
_copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
335-
return dst
335+
return os.fspath(dst)
336336

337337
copyfileobj(fsrc, fdst)
338338

@@ -343,7 +343,7 @@ def copyfile(src, dst, *, follow_symlinks=True):
343343
else:
344344
raise
345345

346-
return dst
346+
return os.fspath(dst)
347347

348348
def copymode(src, dst, *, follow_symlinks=True):
349349
"""Copy mode bits from src to dst.
@@ -481,7 +481,7 @@ def copy(src, dst, *, follow_symlinks=True):
481481
dst = os.path.join(dst, os.path.basename(src))
482482
copyfile(src, dst, follow_symlinks=follow_symlinks)
483483
copymode(src, dst, follow_symlinks=follow_symlinks)
484-
return dst
484+
return os.fspath(dst)
485485

486486
def copy2(src, dst, *, follow_symlinks=True):
487487
"""Copy data and metadata. Return the file's destination.
@@ -505,7 +505,7 @@ def copy2(src, dst, *, follow_symlinks=True):
505505
flags |= _winapi.COPY_FILE_COPY_SYMLINK
506506
try:
507507
_winapi.CopyFile2(src_, dst_, flags)
508-
return dst
508+
return os.fspath(dst)
509509
except OSError as exc:
510510
if (exc.winerror == _winapi.ERROR_PRIVILEGE_NOT_HELD
511511
and not follow_symlinks):
@@ -521,7 +521,7 @@ def copy2(src, dst, *, follow_symlinks=True):
521521

522522
copyfile(src, dst, follow_symlinks=follow_symlinks)
523523
copystat(src, dst, follow_symlinks=follow_symlinks)
524-
return dst
524+
return os.fspath(dst)
525525

526526
def ignore_patterns(*patterns):
527527
"""Function that can be used as copytree() ignore parameter.
@@ -599,7 +599,7 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
599599
errors.append((src, dst, str(why)))
600600
if errors:
601601
raise Error(errors)
602-
return dst
602+
return os.fspath(dst)
603603

604604
def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
605605
ignore_dangling_symlinks=False, dirs_exist_ok=False):
@@ -930,7 +930,7 @@ def move(src, dst, copy_function=copy2):
930930
else:
931931
copy_function(src, real_dst)
932932
os.unlink(src)
933-
return real_dst
933+
return os.fspath(real_dst)
934934

935935
def _destinsrc(src, dst):
936936
src = os.path.abspath(src)

0 commit comments

Comments
 (0)