mirror of
https://github.com/davidhalter/typeshed.git
synced 2026-05-07 05:54:02 +08:00
Drop Python 3.8 support in builtins (#13762)
* remove py38 branches in `builtins` * combined `builtins.dict` tests with those exclusive to `>=3.9`
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
"""
|
||||
Tests for `dict.__(r)or__`.
|
||||
|
||||
`dict.__or__` and `dict.__ror__` were only added in py39,
|
||||
hence why these are in a separate file to the other test cases for `dict`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Mapping, TypeVar, Union
|
||||
from typing_extensions import Self, assert_type
|
||||
|
||||
_KT = TypeVar("_KT")
|
||||
_VT = TypeVar("_VT")
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
|
||||
class CustomDictSubclass(dict[_KT, _VT]):
|
||||
pass
|
||||
|
||||
class CustomMappingWithDunderOr(Mapping[_KT, _VT]):
|
||||
def __or__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
|
||||
return {}
|
||||
|
||||
def __ror__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
|
||||
return {}
|
||||
|
||||
def __ior__(self, other: Mapping[_KT, _VT]) -> Self:
|
||||
return self
|
||||
|
||||
def test_dict_dot_or(
|
||||
a: dict[int, int],
|
||||
b: CustomDictSubclass[int, int],
|
||||
c: dict[str, str],
|
||||
d: Mapping[int, int],
|
||||
e: CustomMappingWithDunderOr[str, str],
|
||||
) -> None:
|
||||
# dict.__(r)or__ always returns a dict, even if called on a subclass of dict:
|
||||
assert_type(a | b, dict[int, int])
|
||||
assert_type(b | a, dict[int, int])
|
||||
|
||||
assert_type(a | c, dict[Union[int, str], Union[int, str]])
|
||||
|
||||
# arbitrary mappings are not accepted by `dict.__or__`;
|
||||
# it has to be a subclass of `dict`
|
||||
a | d # type: ignore
|
||||
|
||||
# but Mappings such as `os._Environ` or `CustomMappingWithDunderOr`,
|
||||
# which define `__ror__` methods that accept `dict`, are fine:
|
||||
assert_type(a | os.environ, dict[Union[str, int], Union[str, int]])
|
||||
assert_type(os.environ | a, dict[Union[str, int], Union[str, int]])
|
||||
|
||||
assert_type(c | os.environ, dict[str, str])
|
||||
assert_type(c | e, dict[str, str])
|
||||
|
||||
assert_type(os.environ | c, dict[str, str])
|
||||
assert_type(e | c, dict[str, str])
|
||||
|
||||
# store "untainted" `CustomMappingWithDunderOr[str, str]` to test `__ior__` against ` dict[str, str]` later
|
||||
# Invalid `e |= a` causes pyright to join `Unknown` to `e`'s type
|
||||
f = e
|
||||
|
||||
e |= c
|
||||
e |= a # type: ignore
|
||||
|
||||
c |= f
|
||||
|
||||
c |= a # type: ignore
|
||||
@@ -1,7 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Generic, Iterable, TypeVar, Union
|
||||
from typing_extensions import assert_type
|
||||
import os
|
||||
from typing import Any, Dict, Generic, Iterable, Mapping, TypeVar, Union
|
||||
from typing_extensions import Self, assert_type
|
||||
|
||||
# These do follow `__init__` overloads order:
|
||||
# mypy and pyright have different opinions about this one:
|
||||
@@ -148,3 +149,61 @@ def test11() -> str:
|
||||
|
||||
def test12() -> str:
|
||||
return d_str.get("key", int_value) # type: ignore[arg-type]
|
||||
|
||||
|
||||
# Tests for `dict.__(r)or__`.
|
||||
|
||||
|
||||
class CustomDictSubclass(dict[_KT, _VT]):
|
||||
pass
|
||||
|
||||
|
||||
class CustomMappingWithDunderOr(Mapping[_KT, _VT]):
|
||||
def __or__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
|
||||
return {}
|
||||
|
||||
def __ror__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
|
||||
return {}
|
||||
|
||||
def __ior__(self, other: Mapping[_KT, _VT]) -> Self:
|
||||
return self
|
||||
|
||||
|
||||
def test_dict_dot_or(
|
||||
a: dict[int, int],
|
||||
b: CustomDictSubclass[int, int],
|
||||
c: dict[str, str],
|
||||
d: Mapping[int, int],
|
||||
e: CustomMappingWithDunderOr[str, str],
|
||||
) -> None:
|
||||
# dict.__(r)or__ always returns a dict, even if called on a subclass of dict:
|
||||
assert_type(a | b, dict[int, int])
|
||||
assert_type(b | a, dict[int, int])
|
||||
|
||||
assert_type(a | c, dict[Union[int, str], Union[int, str]])
|
||||
|
||||
# arbitrary mappings are not accepted by `dict.__or__`;
|
||||
# it has to be a subclass of `dict`
|
||||
a | d # type: ignore
|
||||
|
||||
# but Mappings such as `os._Environ` or `CustomMappingWithDunderOr`,
|
||||
# which define `__ror__` methods that accept `dict`, are fine:
|
||||
assert_type(a | os.environ, dict[Union[str, int], Union[str, int]])
|
||||
assert_type(os.environ | a, dict[Union[str, int], Union[str, int]])
|
||||
|
||||
assert_type(c | os.environ, dict[str, str])
|
||||
assert_type(c | e, dict[str, str])
|
||||
|
||||
assert_type(os.environ | c, dict[str, str])
|
||||
assert_type(e | c, dict[str, str])
|
||||
|
||||
# store "untainted" `CustomMappingWithDunderOr[str, str]` to test `__ior__` against ` dict[str, str]` later
|
||||
# Invalid `e |= a` causes pyright to join `Unknown` to `e`'s type
|
||||
f = e
|
||||
|
||||
e |= c
|
||||
e |= a # type: ignore
|
||||
|
||||
c |= f
|
||||
|
||||
c |= a # type: ignore
|
||||
|
||||
+34
-50
@@ -32,7 +32,7 @@ from _typeshed import (
|
||||
)
|
||||
from collections.abc import Awaitable, Callable, Iterable, Iterator, MutableSet, Reversible, Set as AbstractSet, Sized
|
||||
from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper
|
||||
from types import CellType, CodeType, TracebackType
|
||||
from types import CellType, CodeType, GenericAlias, TracebackType
|
||||
|
||||
# mypy crashes if any of {ByteString, Sequence, MutableSequence, Mapping, MutableMapping}
|
||||
# are imported from collections.abc in builtins.pyi
|
||||
@@ -72,9 +72,6 @@ from typing_extensions import ( # noqa: Y023
|
||||
deprecated,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
from types import GenericAlias
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_I = TypeVar("_I", default=int)
|
||||
_T_co = TypeVar("_T_co", covariant=True)
|
||||
@@ -377,10 +374,8 @@ class float:
|
||||
def __rpow__(self, value: float, mod: None = None, /) -> Any: ...
|
||||
def __getnewargs__(self) -> tuple[float]: ...
|
||||
def __trunc__(self) -> int: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __ceil__(self) -> int: ...
|
||||
def __floor__(self) -> int: ...
|
||||
|
||||
def __ceil__(self) -> int: ...
|
||||
def __floor__(self) -> int: ...
|
||||
@overload
|
||||
def __round__(self, ndigits: None = None, /) -> int: ...
|
||||
@overload
|
||||
@@ -519,16 +514,15 @@ class str(Sequence[str]):
|
||||
) -> LiteralString: ...
|
||||
@overload
|
||||
def replace(self, old: str, new: str, count: SupportsIndex = -1, /) -> str: ... # type: ignore[misc]
|
||||
if sys.version_info >= (3, 9):
|
||||
@overload
|
||||
def removeprefix(self: LiteralString, prefix: LiteralString, /) -> LiteralString: ...
|
||||
@overload
|
||||
def removeprefix(self, prefix: str, /) -> str: ... # type: ignore[misc]
|
||||
@overload
|
||||
def removesuffix(self: LiteralString, suffix: LiteralString, /) -> LiteralString: ...
|
||||
@overload
|
||||
def removesuffix(self, suffix: str, /) -> str: ... # type: ignore[misc]
|
||||
|
||||
@overload
|
||||
def removeprefix(self: LiteralString, prefix: LiteralString, /) -> LiteralString: ...
|
||||
@overload
|
||||
def removeprefix(self, prefix: str, /) -> str: ... # type: ignore[misc]
|
||||
@overload
|
||||
def removesuffix(self: LiteralString, suffix: LiteralString, /) -> LiteralString: ...
|
||||
@overload
|
||||
def removesuffix(self, suffix: str, /) -> str: ... # type: ignore[misc]
|
||||
def rfind(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
|
||||
def rindex(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
|
||||
@overload
|
||||
@@ -666,10 +660,8 @@ class bytes(Sequence[int]):
|
||||
def lstrip(self, bytes: ReadableBuffer | None = None, /) -> bytes: ...
|
||||
def partition(self, sep: ReadableBuffer, /) -> tuple[bytes, bytes, bytes]: ...
|
||||
def replace(self, old: ReadableBuffer, new: ReadableBuffer, count: SupportsIndex = -1, /) -> bytes: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def removeprefix(self, prefix: ReadableBuffer, /) -> bytes: ...
|
||||
def removesuffix(self, suffix: ReadableBuffer, /) -> bytes: ...
|
||||
|
||||
def removeprefix(self, prefix: ReadableBuffer, /) -> bytes: ...
|
||||
def removesuffix(self, suffix: ReadableBuffer, /) -> bytes: ...
|
||||
def rfind(
|
||||
self, sub: ReadableBuffer | SupportsIndex, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
|
||||
) -> int: ...
|
||||
@@ -771,10 +763,8 @@ class bytearray(MutableSequence[int]):
|
||||
def partition(self, sep: ReadableBuffer, /) -> tuple[bytearray, bytearray, bytearray]: ...
|
||||
def pop(self, index: int = -1, /) -> int: ...
|
||||
def remove(self, value: int, /) -> None: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def removeprefix(self, prefix: ReadableBuffer, /) -> bytearray: ...
|
||||
def removesuffix(self, suffix: ReadableBuffer, /) -> bytearray: ...
|
||||
|
||||
def removeprefix(self, prefix: ReadableBuffer, /) -> bytearray: ...
|
||||
def removesuffix(self, suffix: ReadableBuffer, /) -> bytearray: ...
|
||||
def replace(self, old: ReadableBuffer, new: ReadableBuffer, count: SupportsIndex = -1, /) -> bytearray: ...
|
||||
def rfind(
|
||||
self, sub: ReadableBuffer | SupportsIndex, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
|
||||
@@ -1009,8 +999,7 @@ class tuple(Sequence[_T_co]):
|
||||
def __rmul__(self, value: SupportsIndex, /) -> tuple[_T_co, ...]: ...
|
||||
def count(self, value: Any, /) -> int: ...
|
||||
def index(self, value: Any, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
|
||||
# Doesn't exist at runtime, but deleting this breaks mypy and pyright. See:
|
||||
# https://github.com/python/typeshed/issues/7580
|
||||
@@ -1092,8 +1081,7 @@ class list(MutableSequence[_T]):
|
||||
def __lt__(self, value: list[_T], /) -> bool: ...
|
||||
def __le__(self, value: list[_T], /) -> bool: ...
|
||||
def __eq__(self, value: object, /) -> bool: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
|
||||
class dict(MutableMapping[_KT, _VT]):
|
||||
# __init__ should be kept roughly in line with `collections.UserDict.__init__`, which has similar semantics
|
||||
@@ -1162,21 +1150,20 @@ class dict(MutableMapping[_KT, _VT]):
|
||||
def __eq__(self, value: object, /) -> bool: ...
|
||||
def __reversed__(self) -> Iterator[_KT]: ...
|
||||
__hash__: ClassVar[None] # type: ignore[assignment]
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
@overload
|
||||
def __or__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
|
||||
@overload
|
||||
def __or__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
|
||||
@overload
|
||||
def __ror__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
|
||||
@overload
|
||||
def __ror__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
|
||||
# dict.__ior__ should be kept roughly in line with MutableMapping.update()
|
||||
@overload # type: ignore[misc]
|
||||
def __ior__(self, value: SupportsKeysAndGetItem[_KT, _VT], /) -> Self: ...
|
||||
@overload
|
||||
def __ior__(self, value: Iterable[tuple[_KT, _VT]], /) -> Self: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
@overload
|
||||
def __or__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
|
||||
@overload
|
||||
def __or__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
|
||||
@overload
|
||||
def __ror__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
|
||||
@overload
|
||||
def __ror__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
|
||||
# dict.__ior__ should be kept roughly in line with MutableMapping.update()
|
||||
@overload # type: ignore[misc]
|
||||
def __ior__(self, value: SupportsKeysAndGetItem[_KT, _VT], /) -> Self: ...
|
||||
@overload
|
||||
def __ior__(self, value: Iterable[tuple[_KT, _VT]], /) -> Self: ...
|
||||
|
||||
class set(MutableSet[_T]):
|
||||
@overload
|
||||
@@ -1215,8 +1202,7 @@ class set(MutableSet[_T]):
|
||||
def __gt__(self, value: AbstractSet[object], /) -> bool: ...
|
||||
def __eq__(self, value: object, /) -> bool: ...
|
||||
__hash__: ClassVar[None] # type: ignore[assignment]
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
|
||||
class frozenset(AbstractSet[_T_co]):
|
||||
@overload
|
||||
@@ -1244,15 +1230,13 @@ class frozenset(AbstractSet[_T_co]):
|
||||
def __gt__(self, value: AbstractSet[object], /) -> bool: ...
|
||||
def __eq__(self, value: object, /) -> bool: ...
|
||||
def __hash__(self) -> int: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
|
||||
class enumerate(Generic[_T]):
|
||||
def __new__(cls, iterable: Iterable[_T], start: int = 0) -> Self: ...
|
||||
def __iter__(self) -> Self: ...
|
||||
def __next__(self) -> tuple[int, _T]: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
|
||||
|
||||
@final
|
||||
class range(Sequence[int]):
|
||||
|
||||
Reference in New Issue
Block a user