diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index 2bf963d3ffa8..3e5601e9b8bd 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -10,7 +10,7 @@ import sys from collections.abc import Awaitable, Container, Iterable, Set as AbstractSet from os import PathLike from types import TracebackType -from typing import Any, Generic, Protocol, TypeVar, Union +from typing import Any, AnyStr, Generic, Protocol, TypeVar, Union from typing_extensions import Final, Literal, LiteralString, TypeAlias, final _KT = TypeVar("_KT") @@ -26,6 +26,9 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # def __enter__(self: Self) -> Self: ... Self = TypeVar("Self") # noqa: Y001 +# covariant version of typing.AnyStr, useful for protocols +AnyStr_co = TypeVar("AnyStr_co", str, bytes, covariant=True) # noqa: Y001 + # For partially known annotations. Usually, fields where type annotations # haven't been added are left unannotated, but in some situations this # isn't possible or a type is already partially known. In cases like these, @@ -112,9 +115,9 @@ class SupportsItemAccess(SupportsGetItem[_KT_contra, _VT], Protocol[_KT_contra, def __setitem__(self, __k: _KT_contra, __v: _VT) -> None: ... def __delitem__(self, __v: _KT_contra) -> None: ... -# These aliases are simple strings in Python 2. StrPath: TypeAlias = str | PathLike[str] # stable BytesPath: TypeAlias = bytes | PathLike[bytes] # stable +GenericPath: TypeAlias = AnyStr | PathLike[AnyStr] StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] # stable OpenTextModeUpdating: TypeAlias = Literal[ diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 4a0c85b0dbef..1f49f1317769 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -3,6 +3,7 @@ import types from _ast import AST from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import ( + AnyStr_co, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, @@ -1104,10 +1105,8 @@ def chr(__i: int) -> str: ... # We define this here instead of using os.PathLike to avoid import cycle issues. # See https://github.com/python/typeshed/pull/991#issuecomment-288160993 -_AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) - -class _PathLike(Protocol[_AnyStr_co]): - def __fspath__(self) -> _AnyStr_co: ... +class _PathLike(Protocol[AnyStr_co]): + def __fspath__(self) -> AnyStr_co: ... if sys.version_info >= (3, 10): def aiter(__async_iterable: SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... diff --git a/stdlib/filecmp.pyi b/stdlib/filecmp.pyi index 4c81692750e6..dd4a0628b026 100644 --- a/stdlib/filecmp.pyi +++ b/stdlib/filecmp.pyi @@ -1,7 +1,6 @@ import sys -from _typeshed import StrOrBytesPath +from _typeshed import GenericPath, StrOrBytesPath from collections.abc import Callable, Iterable, Sequence -from os import PathLike from typing import Any, AnyStr, Generic from typing_extensions import Literal @@ -15,17 +14,14 @@ BUFSIZE: Literal[8192] def cmp(f1: StrOrBytesPath, f2: StrOrBytesPath, shallow: bool | Literal[0, 1] = ...) -> bool: ... def cmpfiles( - a: AnyStr | PathLike[AnyStr], - b: AnyStr | PathLike[AnyStr], - common: Iterable[AnyStr | PathLike[AnyStr]], - shallow: bool | Literal[0, 1] = ..., + a: GenericPath[AnyStr], b: GenericPath[AnyStr], common: Iterable[GenericPath[AnyStr]], shallow: bool | Literal[0, 1] = ... ) -> tuple[list[AnyStr], list[AnyStr], list[AnyStr]]: ... class dircmp(Generic[AnyStr]): def __init__( self, - a: AnyStr | PathLike[AnyStr], - b: AnyStr | PathLike[AnyStr], + a: GenericPath[AnyStr], + b: GenericPath[AnyStr], ignore: Sequence[AnyStr] | None = ..., hide: Sequence[AnyStr] | None = ..., ) -> None: ... diff --git a/stdlib/fileinput.pyi b/stdlib/fileinput.pyi index 0df88e553f49..e0babbcd40cc 100644 --- a/stdlib/fileinput.pyi +++ b/stdlib/fileinput.pyi @@ -1,8 +1,8 @@ import sys -from _typeshed import Self, StrOrBytesPath +from _typeshed import AnyStr_co, Self, StrOrBytesPath from collections.abc import Callable, Iterable, Iterator from types import TracebackType -from typing import IO, Any, AnyStr, Generic, Protocol, TypeVar, overload +from typing import IO, Any, AnyStr, Generic, Protocol, overload from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): @@ -28,10 +28,8 @@ if sys.version_info >= (3, 11): else: _TextMode: TypeAlias = Literal["r", "rU", "U"] -_AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) - -class _HasReadlineAndFileno(Protocol[_AnyStr_co]): - def readline(self) -> _AnyStr_co: ... +class _HasReadlineAndFileno(Protocol[AnyStr_co]): + def readline(self) -> AnyStr_co: ... def fileno(self) -> int: ... if sys.version_info >= (3, 10): diff --git a/stdlib/os/__init__.pyi b/stdlib/os/__init__.pyi index 2310de701d54..68ea2948f17e 100644 --- a/stdlib/os/__init__.pyi +++ b/stdlib/os/__init__.pyi @@ -1,7 +1,9 @@ import sys from _typeshed import ( + AnyStr_co, BytesPath, FileDescriptorLike, + GenericPath, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, @@ -32,7 +34,6 @@ path = _path _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") -_AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) # ----- os variables ----- @@ -356,9 +357,9 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo # See https://github.com/python/typeshed/pull/6560#issuecomment-991253327 @runtime_checkable -class PathLike(Protocol[_AnyStr_co]): +class PathLike(Protocol[AnyStr_co]): @abstractmethod - def __fspath__(self) -> _AnyStr_co: ... + def __fspath__(self) -> AnyStr_co: ... @overload def listdir(path: StrPath | None = ...) -> list[str]: ... @@ -726,7 +727,7 @@ if sys.platform != "win32": def makedev(__major: int, __minor: int) -> int: ... def pathconf(path: _FdOrAnyPath, name: str | int) -> int: ... # Unix only -def readlink(path: AnyStr | PathLike[AnyStr], *, dir_fd: int | None = ...) -> AnyStr: ... +def readlink(path: GenericPath[AnyStr], *, dir_fd: int | None = ...) -> AnyStr: ... def remove(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... def removedirs(name: StrOrBytesPath) -> None: ... def rename(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = ..., dst_dir_fd: int | None = ...) -> None: ... @@ -747,7 +748,7 @@ if sys.version_info >= (3, 7): def scandir(path: int) -> _ScandirIterator[str]: ... @overload -def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... +def scandir(path: GenericPath[AnyStr]) -> _ScandirIterator[AnyStr]: ... def stat(path: _FdOrAnyPath, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> stat_result: ... if sys.version_info < (3, 7): @@ -778,7 +779,7 @@ def utime( _OnError: TypeAlias = Callable[[OSError], Any] def walk( - top: AnyStr | PathLike[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... + top: GenericPath[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... ) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]: ... if sys.platform != "win32": diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 0ffe1c0e2ef2..b27b881d5b5b 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -1,7 +1,6 @@ import io -import os import sys -from _typeshed import Self, StrPath, WriteableBuffer +from _typeshed import BytesPath, GenericPath, Self, StrPath, WriteableBuffer from collections.abc import Iterable, Iterator from types import TracebackType from typing import IO, Any, AnyStr, Generic, overload @@ -31,7 +30,6 @@ TMP_MAX: int tempdir: str | None template: str -_Dir: TypeAlias = AnyStr | os.PathLike[AnyStr] _StrMode: TypeAlias = Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] _BytesMode: TypeAlias = Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] @@ -44,7 +42,7 @@ if sys.version_info >= (3, 8): newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., @@ -57,7 +55,7 @@ if sys.version_info >= (3, 8): newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., @@ -70,7 +68,7 @@ if sys.version_info >= (3, 8): newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., @@ -85,7 +83,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[str]: ... @overload @@ -96,7 +94,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[bytes]: ... @overload @@ -107,7 +105,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[Any]: ... @@ -123,7 +121,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[str]: ... @@ -135,7 +133,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[bytes]: ... @@ -147,7 +145,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[Any]: ... @@ -160,7 +158,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[str]: ... @overload def TemporaryFile( @@ -170,7 +168,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[bytes]: ... @overload def TemporaryFile( @@ -180,7 +178,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[Any]: ... class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): @@ -367,14 +365,16 @@ class TemporaryDirectory(Generic[AnyStr]): self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _Dir[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ignore_cleanup_errors: bool = ..., ) -> None: ... else: @overload def __init__(self: TemporaryDirectory[str], suffix: None = ..., prefix: None = ..., dir: None = ...) -> None: ... @overload - def __init__(self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _Dir[AnyStr] | None = ...) -> None: ... + def __init__( + self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: GenericPath[AnyStr] | None = ... + ) -> None: ... def cleanup(self) -> None: ... def __enter__(self) -> AnyStr: ... @@ -385,18 +385,18 @@ class TemporaryDirectory(Generic[AnyStr]): # The overloads overlap, but they should still work fine. @overload def mkstemp( # type: ignore[misc] - suffix: str | None = ..., prefix: str | None = ..., dir: _Dir[str] | None = ..., text: bool = ... + suffix: str | None = ..., prefix: str | None = ..., dir: StrPath | None = ..., text: bool = ... ) -> tuple[int, str]: ... @overload def mkstemp( - suffix: bytes | None = ..., prefix: bytes | None = ..., dir: _Dir[bytes] | None = ..., text: bool = ... + suffix: bytes | None = ..., prefix: bytes | None = ..., dir: BytesPath | None = ..., text: bool = ... ) -> tuple[int, bytes]: ... # The overloads overlap, but they should still work fine. @overload -def mkdtemp(suffix: str | None = ..., prefix: str | None = ..., dir: _Dir[str] | None = ...) -> str: ... # type: ignore[misc] +def mkdtemp(suffix: str | None = ..., prefix: str | None = ..., dir: StrPath | None = ...) -> str: ... # type: ignore[misc] @overload -def mkdtemp(suffix: bytes | None = ..., prefix: bytes | None = ..., dir: _Dir[bytes] | None = ...) -> bytes: ... +def mkdtemp(suffix: bytes | None = ..., prefix: bytes | None = ..., dir: BytesPath | None = ...) -> bytes: ... def mktemp(suffix: str = ..., prefix: str = ..., dir: StrPath | None = ...) -> str: ... def gettempdirb() -> bytes: ... def gettempprefixb() -> bytes: ...