diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index d5e0c691e..2bf963d3f 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -11,7 +11,7 @@ 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_extensions import Final, Literal, TypeAlias, final +from typing_extensions import Final, Literal, LiteralString, TypeAlias, final _KT = TypeVar("_KT") _KT_co = TypeVar("_KT_co", covariant=True) @@ -248,3 +248,6 @@ class structseq(Generic[_T_co]): # but only has any meaning if you supply it a dict where the keys are strings. # https://github.com/python/typeshed/pull/6560#discussion_r767149830 def __new__(cls: type[Self], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> Self: ... + +# Superset of typing.AnyStr that also inclues LiteralString +AnyOrLiteralStr = TypeVar("AnyOrLiteralStr", str, bytes, LiteralString) # noqa: Y001 diff --git a/stdlib/genericpath.pyi b/stdlib/genericpath.pyi index 984d0c3cf..911d582fd 100644 --- a/stdlib/genericpath.pyi +++ b/stdlib/genericpath.pyi @@ -2,7 +2,7 @@ import os from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRichComparisonT from collections.abc import Sequence from typing import overload -from typing_extensions import Literal +from typing_extensions import Literal, LiteralString __all__ = [ "commonprefix", @@ -22,6 +22,8 @@ __all__ = [ # Iterable[T], so that list[T] | Literal[""] could be used as a return # type. But because this only works when T is str, we need Sequence[T] instead. @overload +def commonprefix(m: Sequence[LiteralString]) -> LiteralString: ... +@overload def commonprefix(m: Sequence[StrPath]) -> str: ... @overload def commonprefix(m: Sequence[BytesPath]) -> bytes | Literal[""]: ... diff --git a/stdlib/ntpath.pyi b/stdlib/ntpath.pyi index ffe5cc1e5..d6c04af8e 100644 --- a/stdlib/ntpath.pyi +++ b/stdlib/ntpath.pyi @@ -43,6 +43,7 @@ from posixpath import ( supports_unicode_filenames as supports_unicode_filenames, ) from typing import AnyStr, overload +from typing_extensions import LiteralString if sys.version_info >= (3, 7) or sys.platform != "win32": __all__ = [ @@ -130,12 +131,14 @@ else: def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -altsep: str +altsep: LiteralString # First parameter is not actually pos-only, # but must be defined as pos-only in the stub or cross-platform code doesn't type-check, # as the parameter name is different in posixpath.join() @overload +def join(__path: LiteralString, *paths: LiteralString) -> LiteralString: ... +@overload def join(__path: StrPath, *paths: StrPath) -> str: ... @overload def join(__path: BytesPath, *paths: BytesPath) -> bytes: ... diff --git a/stdlib/posixpath.pyi b/stdlib/posixpath.pyi index 4cec7c770..8d880a072 100644 --- a/stdlib/posixpath.pyi +++ b/stdlib/posixpath.pyi @@ -1,5 +1,5 @@ import sys -from _typeshed import BytesPath, StrOrBytesPath, StrPath +from _typeshed import AnyOrLiteralStr, BytesPath, StrOrBytesPath, StrPath from collections.abc import Sequence from genericpath import ( commonprefix as commonprefix, @@ -16,6 +16,7 @@ from genericpath import ( ) from os import PathLike from typing import AnyStr, overload +from typing_extensions import LiteralString __all__ = [ "normcase", @@ -60,14 +61,14 @@ __all__ = [ supports_unicode_filenames: bool # aliases (also in os) -curdir: str -pardir: str -sep: str -altsep: str | None -extsep: str -pathsep: str -defpath: str -devnull: str +curdir: LiteralString +pardir: LiteralString +sep: LiteralString +altsep: LiteralString | None +extsep: LiteralString +pathsep: LiteralString +defpath: LiteralString +devnull: LiteralString # Overloads are necessary to work around python/mypy#3644. @overload @@ -77,11 +78,11 @@ def abspath(path: AnyStr) -> AnyStr: ... @overload def basename(p: PathLike[AnyStr]) -> AnyStr: ... @overload -def basename(p: AnyStr) -> AnyStr: ... +def basename(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def dirname(p: PathLike[AnyStr]) -> AnyStr: ... @overload -def dirname(p: AnyStr) -> AnyStr: ... +def dirname(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def expanduser(path: PathLike[AnyStr]) -> AnyStr: ... @overload @@ -93,11 +94,13 @@ def expandvars(path: AnyStr) -> AnyStr: ... @overload def normcase(s: PathLike[AnyStr]) -> AnyStr: ... @overload -def normcase(s: AnyStr) -> AnyStr: ... +def normcase(s: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def normpath(path: PathLike[AnyStr]) -> AnyStr: ... @overload -def normpath(path: AnyStr) -> AnyStr: ... +def normpath(path: AnyOrLiteralStr) -> AnyOrLiteralStr: ... +@overload +def commonpath(paths: Sequence[LiteralString]) -> LiteralString: ... @overload def commonpath(paths: Sequence[StrPath]) -> str: ... @overload @@ -107,6 +110,8 @@ def commonpath(paths: Sequence[BytesPath]) -> bytes: ... # but must be defined as pos-only in the stub or cross-platform code doesn't type-check, # as the parameter name is different in ntpath.join() @overload +def join(__a: LiteralString, *paths: LiteralString) -> LiteralString: ... +@overload def join(__a: StrPath, *paths: StrPath) -> str: ... @overload def join(__a: BytesPath, *paths: BytesPath) -> bytes: ... @@ -123,6 +128,8 @@ else: @overload def realpath(filename: AnyStr) -> AnyStr: ... +@overload +def relpath(path: LiteralString, start: LiteralString | None = ...) -> LiteralString: ... @overload def relpath(path: BytesPath, start: BytesPath | None = ...) -> bytes: ... @overload @@ -130,15 +137,15 @@ def relpath(path: StrPath, start: StrPath | None = ...) -> str: ... @overload def split(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def split(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... @overload def splitdrive(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... @overload def splitext(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... def isabs(s: StrOrBytesPath) -> bool: ... def islink(path: StrOrBytesPath | int) -> bool: ... def ismount(path: StrOrBytesPath | int) -> bool: ...