Skip to content

Introduce _typeshed.GenericPath and _typeshed.AnyStr_co #7970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions stdlib/_typeshed/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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,
Expand Down Expand Up @@ -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]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good name!

StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] # stable

OpenTextModeUpdating: TypeAlias = Literal[
Expand Down
7 changes: 3 additions & 4 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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: ...
Expand Down
12 changes: 4 additions & 8 deletions stdlib/filecmp.pyi
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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: ...
Expand Down
10 changes: 4 additions & 6 deletions stdlib/fileinput.pyi
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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):
Expand Down
13 changes: 7 additions & 6 deletions stdlib/os/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import sys
from _typeshed import (
AnyStr_co,
BytesPath,
FileDescriptorLike,
GenericPath,
OpenBinaryMode,
OpenBinaryModeReading,
OpenBinaryModeUpdating,
Expand Down Expand Up @@ -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 -----

Expand Down Expand Up @@ -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]: ...
Expand Down Expand Up @@ -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: ...
Expand All @@ -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):
Expand Down Expand Up @@ -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":
Expand Down
42 changes: 21 additions & 21 deletions stdlib/tempfile.pyi
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"]

Expand All @@ -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 = ...,
Expand All @@ -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 = ...,
Expand All @@ -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 = ...,
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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]: ...

Expand All @@ -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]: ...
Expand All @@ -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]: ...
Expand All @@ -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]: ...
Expand All @@ -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(
Expand All @@ -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(
Expand All @@ -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]):
Expand Down Expand Up @@ -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: ...
Expand All @@ -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: ...
Expand Down