From c2aba0b0b980191efad7ebefc4d73ee98cec31e8 Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 1 Apr 2025 22:46:04 -0400 Subject: [PATCH 1/3] Exact return types instead of shutil._PathReturn --- stdlib/shutil.pyi | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/stdlib/shutil.pyi b/stdlib/shutil.pyi index 0fe560fd9b6a..c42bc0c7fcef 100644 --- a/stdlib/shutil.pyi +++ b/stdlib/shutil.pyi @@ -36,9 +36,8 @@ __all__ = [ ] _StrOrBytesPathT = TypeVar("_StrOrBytesPathT", bound=StrOrBytesPath) -# Return value of some functions that may either return a path-like object that was passed in or -# a string -_PathReturn: TypeAlias = Any +_StrPathT = TypeVar("_StrPathT", bound=StrPath) +_BytesPathT = TypeVar("_BytesPathT", bound=BytesPath) class Error(OSError): ... class SameFileError(Error): ... @@ -52,23 +51,23 @@ def copyfile(src: StrOrBytesPath, dst: _StrOrBytesPathT, *, follow_symlinks: boo def copymode(src: StrOrBytesPath, dst: StrOrBytesPath, *, follow_symlinks: bool = True) -> None: ... def copystat(src: StrOrBytesPath, dst: StrOrBytesPath, *, follow_symlinks: bool = True) -> None: ... @overload -def copy(src: StrPath, dst: StrPath, *, follow_symlinks: bool = True) -> _PathReturn: ... +def copy(src: StrPath, dst: _StrPathT, *, follow_symlinks: bool = True) -> _StrPathT | str: ... @overload -def copy(src: BytesPath, dst: BytesPath, *, follow_symlinks: bool = True) -> _PathReturn: ... +def copy(src: BytesPath, dst: _BytesPathT, *, follow_symlinks: bool = True) -> _BytesPathT | bytes: ... @overload -def copy2(src: StrPath, dst: StrPath, *, follow_symlinks: bool = True) -> _PathReturn: ... +def copy2(src: StrPath, dst: _StrPathT, *, follow_symlinks: bool = True) -> _StrPathT | str: ... @overload -def copy2(src: BytesPath, dst: BytesPath, *, follow_symlinks: bool = True) -> _PathReturn: ... +def copy2(src: BytesPath, dst: _BytesPathT, *, follow_symlinks: bool = True) -> _BytesPathT | bytes: ... def ignore_patterns(*patterns: StrPath) -> Callable[[Any, list[str]], set[str]]: ... def copytree( src: StrPath, - dst: StrPath, + dst: _StrPathT, symlinks: bool = False, ignore: None | Callable[[str, list[str]], Iterable[str]] | Callable[[StrPath, list[str]], Iterable[str]] = None, copy_function: Callable[[str, str], object] = ..., ignore_dangling_symlinks: bool = False, dirs_exist_ok: bool = False, -) -> _PathReturn: ... +) -> _StrPathT: ... _OnErrorCallback: TypeAlias = Callable[[Callable[..., Any], str, ExcInfo], object] _OnExcCallback: TypeAlias = Callable[[Callable[..., Any], str, BaseException], object] @@ -129,12 +128,7 @@ _CopyFn: TypeAlias = Callable[[str, str], object] | Callable[[StrPath, StrPath], # N.B. shutil.move appears to take bytes arguments, however, # this does not work when dst is (or is within) an existing directory. # (#6832) -if sys.version_info >= (3, 9): - def move(src: StrPath, dst: StrPath, copy_function: _CopyFn = ...) -> _PathReturn: ... - -else: - # See https://bugs.python.org/issue32689 - def move(src: str, dst: StrPath, copy_function: _CopyFn = ...) -> _PathReturn: ... +def move(src: StrPath, dst: _StrPathT, copy_function: _CopyFn = ...) -> _StrPathT | str: ... class _ntuple_diskusage(NamedTuple): total: int From 1268b6968a4e710c663b4d0b2a5e5b13e71ae4f0 Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 1 Apr 2025 22:57:12 -0400 Subject: [PATCH 2/3] Move can return None --- stdlib/shutil.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/shutil.pyi b/stdlib/shutil.pyi index c42bc0c7fcef..3e8b691d09d5 100644 --- a/stdlib/shutil.pyi +++ b/stdlib/shutil.pyi @@ -128,7 +128,7 @@ _CopyFn: TypeAlias = Callable[[str, str], object] | Callable[[StrPath, StrPath], # N.B. shutil.move appears to take bytes arguments, however, # this does not work when dst is (or is within) an existing directory. # (#6832) -def move(src: StrPath, dst: _StrPathT, copy_function: _CopyFn = ...) -> _StrPathT | str: ... +def move(src: StrPath, dst: _StrPathT, copy_function: _CopyFn = ...) -> _StrPathT | str | None: ... class _ntuple_diskusage(NamedTuple): total: int From 48bc12d1a84b04e1db548720e46a5ef614c33be4 Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 1 Apr 2025 23:00:24 -0400 Subject: [PATCH 3/3] Use MaybeNone for move --- stdlib/shutil.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/shutil.pyi b/stdlib/shutil.pyi index 3e8b691d09d5..ea2c29d4625f 100644 --- a/stdlib/shutil.pyi +++ b/stdlib/shutil.pyi @@ -1,6 +1,6 @@ import os import sys -from _typeshed import BytesPath, ExcInfo, FileDescriptorOrPath, StrOrBytesPath, StrPath, SupportsRead, SupportsWrite +from _typeshed import BytesPath, ExcInfo, FileDescriptorOrPath, MaybeNone, StrOrBytesPath, StrPath, SupportsRead, SupportsWrite from collections.abc import Callable, Iterable, Sequence from tarfile import _TarfileFilter from typing import Any, AnyStr, NamedTuple, NoReturn, Protocol, TypeVar, overload @@ -128,7 +128,7 @@ _CopyFn: TypeAlias = Callable[[str, str], object] | Callable[[StrPath, StrPath], # N.B. shutil.move appears to take bytes arguments, however, # this does not work when dst is (or is within) an existing directory. # (#6832) -def move(src: StrPath, dst: _StrPathT, copy_function: _CopyFn = ...) -> _StrPathT | str | None: ... +def move(src: StrPath, dst: _StrPathT, copy_function: _CopyFn = ...) -> _StrPathT | str | MaybeNone: ... class _ntuple_diskusage(NamedTuple): total: int