From 1dd1b701c97e4bff9b8e05fb58ce8d3dd27aa213 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 25 Oct 2020 15:04:43 -0700 Subject: [PATCH] _typeshed: add SupportsLessThan, SupportsLessThanT (#4711) And use it everywhere. Note there seemed to be a discrepancy between heapq in Python 2 and 3, so I changed that. It should probably be more widely used within heapq, but leaving that out of scope for this PR. Co-authored-by: hauntsaninja <> --- stdlib/2/__builtin__.pyi | 4 --- stdlib/2/builtins.pyi | 4 --- stdlib/2/heapq.pyi | 8 +++--- stdlib/2and3/_typeshed/__init__.pyi | 7 ++++- stdlib/3/builtins.pyi | 42 ++++++++++++++--------------- stdlib/3/functools.pyi | 7 ++--- stdlib/3/heapq.pyi | 5 ++-- stdlib/3/statistics.pyi | 11 +++----- 8 files changed, 37 insertions(+), 51 deletions(-) diff --git a/stdlib/2/__builtin__.pyi b/stdlib/2/__builtin__.pyi index 86dbfe460..691122bba 100644 --- a/stdlib/2/__builtin__.pyi +++ b/stdlib/2/__builtin__.pyi @@ -65,9 +65,6 @@ class _SupportsIndex(Protocol): class _SupportsTrunc(Protocol): def __trunc__(self) -> int: ... -class _SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _KT = TypeVar("_KT") @@ -79,7 +76,6 @@ _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _TT = TypeVar("_TT", bound="type") -_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan) _TBE = TypeVar("_TBE", bound="BaseException") class object: diff --git a/stdlib/2/builtins.pyi b/stdlib/2/builtins.pyi index 86dbfe460..691122bba 100644 --- a/stdlib/2/builtins.pyi +++ b/stdlib/2/builtins.pyi @@ -65,9 +65,6 @@ class _SupportsIndex(Protocol): class _SupportsTrunc(Protocol): def __trunc__(self) -> int: ... -class _SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _KT = TypeVar("_KT") @@ -79,7 +76,6 @@ _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _TT = TypeVar("_TT", bound="type") -_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan) _TBE = TypeVar("_TBE", bound="BaseException") class object: diff --git a/stdlib/2/heapq.pyi b/stdlib/2/heapq.pyi index 5c56a0710..d6da32d76 100644 --- a/stdlib/2/heapq.pyi +++ b/stdlib/2/heapq.pyi @@ -1,10 +1,8 @@ +from _typeshed import SupportsLessThan from typing import Any, Callable, Iterable, List, Optional, Protocol, TypeVar _T = TypeVar("_T") -class _Sortable(Protocol): - def __lt__(self: _T, other: _T) -> bool: ... - def cmp_lt(x, y) -> bool: ... def heappush(heap: List[_T], item: _T) -> None: ... def heappop(heap: List[_T]) -> _T: ... @@ -12,6 +10,6 @@ def heappushpop(heap: List[_T], item: _T) -> _T: ... def heapify(x: List[_T]) -> None: ... def heapreplace(heap: List[_T], item: _T) -> _T: ... def merge(*iterables: Iterable[_T]) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], _Sortable]] = ...) -> List[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], _Sortable]] = ...) -> List[_T]: ... +def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... def _heapify_max(__x: List[_T]) -> None: ... # undocumented diff --git a/stdlib/2and3/_typeshed/__init__.pyi b/stdlib/2and3/_typeshed/__init__.pyi index 5efbc2517..5e2d72ca8 100644 --- a/stdlib/2and3/_typeshed/__init__.pyi +++ b/stdlib/2and3/_typeshed/__init__.pyi @@ -15,7 +15,7 @@ import array import mmap import sys -from typing import AbstractSet, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union +from typing import AbstractSet, Any, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union from typing_extensions import Literal, final _KT = TypeVar("_KT") @@ -26,6 +26,11 @@ _VT_co = TypeVar("_VT_co", covariant=True) _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) +class SupportsLessThan(Protocol): + def __lt__(self, __other: Any) -> bool: ... + +SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001 + # Mapping-like protocols class SupportsItems(Protocol[_KT_co, _VT_co]): diff --git a/stdlib/3/builtins.pyi b/stdlib/3/builtins.pyi index 0ec3d675e..4f336abea 100644 --- a/stdlib/3/builtins.pyi +++ b/stdlib/3/builtins.pyi @@ -8,6 +8,8 @@ from _typeshed import ( OpenTextMode, ReadableBuffer, SupportsKeysAndGetItem, + SupportsLessThan, + SupportsLessThanT, SupportsWrite, ) from abc import ABCMeta @@ -67,9 +69,6 @@ class _SupportsIndex(Protocol): class _SupportsTrunc(Protocol): def __trunc__(self) -> int: ... -class _SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _KT = TypeVar("_KT") @@ -81,7 +80,6 @@ _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _TT = TypeVar("_TT", bound="type") -_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan) _TBE = TypeVar("_TBE", bound="BaseException") class object: @@ -714,9 +712,9 @@ class list(MutableSequence[_T], Generic[_T]): def remove(self, __value: _T) -> None: ... def reverse(self) -> None: ... @overload - def sort(self: List[_SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ... + def sort(self: List[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ... @overload - def sort(self, *, key: Callable[[_T], _SupportsLessThan], reverse: bool = ...) -> None: ... + def sort(self, *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... def __str__(self) -> str: ... @@ -1024,32 +1022,32 @@ def map( ) -> Iterator[_S]: ... @overload def max( - __arg1: _SupportsLessThanT, __arg2: _SupportsLessThanT, *_args: _SupportsLessThanT, key: None = ... -) -> _SupportsLessThanT: ... + __arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ... +) -> SupportsLessThanT: ... @overload -def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], _SupportsLessThanT]) -> _T: ... +def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThanT]) -> _T: ... @overload -def max(__iterable: Iterable[_SupportsLessThanT], *, key: None = ...) -> _SupportsLessThanT: ... +def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ... @overload -def max(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThanT]) -> _T: ... +def max(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThanT]) -> _T: ... @overload -def max(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., default: _T) -> Union[_SupportsLessThanT, _T]: ... +def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ... @overload -def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], _SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ... +def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ... @overload def min( - __arg1: _SupportsLessThanT, __arg2: _SupportsLessThanT, *_args: _SupportsLessThanT, key: None = ... -) -> _SupportsLessThanT: ... + __arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ... +) -> SupportsLessThanT: ... @overload -def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], _SupportsLessThanT]) -> _T: ... +def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThanT]) -> _T: ... @overload -def min(__iterable: Iterable[_SupportsLessThanT], *, key: None = ...) -> _SupportsLessThanT: ... +def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ... @overload -def min(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThanT]) -> _T: ... +def min(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThanT]) -> _T: ... @overload -def min(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., default: _T) -> Union[_SupportsLessThanT, _T]: ... +def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ... @overload -def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], _SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ... +def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ... @overload def next(__i: Iterator[_T]) -> _T: ... @overload @@ -1209,9 +1207,9 @@ def round(number: SupportsRound[_T], ndigits: None) -> int: ... def round(number: SupportsRound[_T], ndigits: int) -> _T: ... def setattr(__obj: Any, __name: str, __value: Any) -> None: ... @overload -def sorted(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> List[_SupportsLessThanT]: ... +def sorted(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> List[SupportsLessThanT]: ... @overload -def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThan], reverse: bool = ...) -> List[_T]: ... +def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> List[_T]: ... if sys.version_info >= (3, 8): @overload diff --git a/stdlib/3/functools.pyi b/stdlib/3/functools.pyi index 2a411b5e6..dd41a9e32 100644 --- a/stdlib/3/functools.pyi +++ b/stdlib/3/functools.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import SupportsLessThan from typing import ( Any, Callable, @@ -59,11 +60,7 @@ def wraps( wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ... ) -> Callable[[_AnyCallable], _AnyCallable]: ... def total_ordering(cls: Type[_T]) -> Type[_T]: ... - -class _SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - -def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], _SupportsLessThan]: ... +def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsLessThan]: ... class partial(Generic[_T]): func: Callable[..., _T] diff --git a/stdlib/3/heapq.pyi b/stdlib/3/heapq.pyi index 42cbb1fd3..5592e615f 100644 --- a/stdlib/3/heapq.pyi +++ b/stdlib/3/heapq.pyi @@ -1,3 +1,4 @@ +from _typeshed import SupportsLessThan from typing import Any, Callable, Iterable, List, Optional, TypeVar _T = TypeVar("_T") @@ -8,6 +9,6 @@ def heappushpop(__heap: List[_T], __item: _T) -> _T: ... def heapify(__heap: List[_T]) -> None: ... def heapreplace(__heap: List[_T], __item: _T) -> _T: ... def merge(*iterables: Iterable[_T], key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ...) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ... +def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... def _heapify_max(__x: List[_T]) -> None: ... # undocumented diff --git a/stdlib/3/statistics.pyi b/stdlib/3/statistics.pyi index cdda11c78..f963802eb 100644 --- a/stdlib/3/statistics.pyi +++ b/stdlib/3/statistics.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import SupportsLessThanT from decimal import Decimal from fractions import Fraction from typing import Any, Hashable, Iterable, List, Optional, Protocol, SupportsFloat, Type, TypeVar, Union @@ -7,12 +8,6 @@ _T = TypeVar("_T") # Most functions in this module accept homogeneous collections of one of these types _Number = TypeVar("_Number", float, Decimal, Fraction) -# Used in median_high, median_low -class _Sortable(Protocol): - def __lt__(self, other: Any) -> bool: ... - -_SortableT = TypeVar("_SortableT", bound=_Sortable) - # Used in mode, multimode _HashableT = TypeVar("_HashableT", bound=Hashable) @@ -28,8 +23,8 @@ if sys.version_info >= (3, 6): def harmonic_mean(data: Iterable[_Number]) -> _Number: ... def median(data: Iterable[_Number]) -> _Number: ... -def median_low(data: Iterable[_SortableT]) -> _SortableT: ... -def median_high(data: Iterable[_SortableT]) -> _SortableT: ... +def median_low(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ... +def median_high(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ... def median_grouped(data: Iterable[_Number], interval: _Number = ...) -> _Number: ... def mode(data: Iterable[_HashableT]) -> _HashableT: ...