Skip to content

Commit 1dd1b70

Browse files
authored
_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 <>
1 parent 8d4a4f9 commit 1dd1b70

File tree

8 files changed

+37
-51
lines changed

8 files changed

+37
-51
lines changed

stdlib/2/__builtin__.pyi

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ class _SupportsIndex(Protocol):
6565
class _SupportsTrunc(Protocol):
6666
def __trunc__(self) -> int: ...
6767

68-
class _SupportsLessThan(Protocol):
69-
def __lt__(self, __other: Any) -> bool: ...
70-
7168
_T = TypeVar("_T")
7269
_T_co = TypeVar("_T_co", covariant=True)
7370
_KT = TypeVar("_KT")
@@ -79,7 +76,6 @@ _T3 = TypeVar("_T3")
7976
_T4 = TypeVar("_T4")
8077
_T5 = TypeVar("_T5")
8178
_TT = TypeVar("_TT", bound="type")
82-
_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan)
8379
_TBE = TypeVar("_TBE", bound="BaseException")
8480

8581
class object:

stdlib/2/builtins.pyi

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ class _SupportsIndex(Protocol):
6565
class _SupportsTrunc(Protocol):
6666
def __trunc__(self) -> int: ...
6767

68-
class _SupportsLessThan(Protocol):
69-
def __lt__(self, __other: Any) -> bool: ...
70-
7168
_T = TypeVar("_T")
7269
_T_co = TypeVar("_T_co", covariant=True)
7370
_KT = TypeVar("_KT")
@@ -79,7 +76,6 @@ _T3 = TypeVar("_T3")
7976
_T4 = TypeVar("_T4")
8077
_T5 = TypeVar("_T5")
8178
_TT = TypeVar("_TT", bound="type")
82-
_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan)
8379
_TBE = TypeVar("_TBE", bound="BaseException")
8480

8581
class object:

stdlib/2/heapq.pyi

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1+
from _typeshed import SupportsLessThan
12
from typing import Any, Callable, Iterable, List, Optional, Protocol, TypeVar
23

34
_T = TypeVar("_T")
45

5-
class _Sortable(Protocol):
6-
def __lt__(self: _T, other: _T) -> bool: ...
7-
86
def cmp_lt(x, y) -> bool: ...
97
def heappush(heap: List[_T], item: _T) -> None: ...
108
def heappop(heap: List[_T]) -> _T: ...
119
def heappushpop(heap: List[_T], item: _T) -> _T: ...
1210
def heapify(x: List[_T]) -> None: ...
1311
def heapreplace(heap: List[_T], item: _T) -> _T: ...
1412
def merge(*iterables: Iterable[_T]) -> Iterable[_T]: ...
15-
def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], _Sortable]] = ...) -> List[_T]: ...
16-
def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], _Sortable]] = ...) -> List[_T]: ...
13+
def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ...
14+
def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ...
1715
def _heapify_max(__x: List[_T]) -> None: ... # undocumented

stdlib/2and3/_typeshed/__init__.pyi

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import array
1616
import mmap
1717
import sys
18-
from typing import AbstractSet, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union
18+
from typing import AbstractSet, Any, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union
1919
from typing_extensions import Literal, final
2020

2121
_KT = TypeVar("_KT")
@@ -26,6 +26,11 @@ _VT_co = TypeVar("_VT_co", covariant=True)
2626
_T_co = TypeVar("_T_co", covariant=True)
2727
_T_contra = TypeVar("_T_contra", contravariant=True)
2828

29+
class SupportsLessThan(Protocol):
30+
def __lt__(self, __other: Any) -> bool: ...
31+
32+
SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001
33+
2934
# Mapping-like protocols
3035

3136
class SupportsItems(Protocol[_KT_co, _VT_co]):

stdlib/3/builtins.pyi

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ from _typeshed import (
88
OpenTextMode,
99
ReadableBuffer,
1010
SupportsKeysAndGetItem,
11+
SupportsLessThan,
12+
SupportsLessThanT,
1113
SupportsWrite,
1214
)
1315
from abc import ABCMeta
@@ -67,9 +69,6 @@ class _SupportsIndex(Protocol):
6769
class _SupportsTrunc(Protocol):
6870
def __trunc__(self) -> int: ...
6971

70-
class _SupportsLessThan(Protocol):
71-
def __lt__(self, __other: Any) -> bool: ...
72-
7372
_T = TypeVar("_T")
7473
_T_co = TypeVar("_T_co", covariant=True)
7574
_KT = TypeVar("_KT")
@@ -81,7 +80,6 @@ _T3 = TypeVar("_T3")
8180
_T4 = TypeVar("_T4")
8281
_T5 = TypeVar("_T5")
8382
_TT = TypeVar("_TT", bound="type")
84-
_SupportsLessThanT = TypeVar("_SupportsLessThanT", bound=_SupportsLessThan)
8583
_TBE = TypeVar("_TBE", bound="BaseException")
8684

8785
class object:
@@ -714,9 +712,9 @@ class list(MutableSequence[_T], Generic[_T]):
714712
def remove(self, __value: _T) -> None: ...
715713
def reverse(self) -> None: ...
716714
@overload
717-
def sort(self: List[_SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ...
715+
def sort(self: List[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ...
718716
@overload
719-
def sort(self, *, key: Callable[[_T], _SupportsLessThan], reverse: bool = ...) -> None: ...
717+
def sort(self, *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> None: ...
720718
def __len__(self) -> int: ...
721719
def __iter__(self) -> Iterator[_T]: ...
722720
def __str__(self) -> str: ...
@@ -1024,32 +1022,32 @@ def map(
10241022
) -> Iterator[_S]: ...
10251023
@overload
10261024
def max(
1027-
__arg1: _SupportsLessThanT, __arg2: _SupportsLessThanT, *_args: _SupportsLessThanT, key: None = ...
1028-
) -> _SupportsLessThanT: ...
1025+
__arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ...
1026+
) -> SupportsLessThanT: ...
10291027
@overload
1030-
def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], _SupportsLessThanT]) -> _T: ...
1028+
def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThanT]) -> _T: ...
10311029
@overload
1032-
def max(__iterable: Iterable[_SupportsLessThanT], *, key: None = ...) -> _SupportsLessThanT: ...
1030+
def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ...
10331031
@overload
1034-
def max(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThanT]) -> _T: ...
1032+
def max(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThanT]) -> _T: ...
10351033
@overload
1036-
def max(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., default: _T) -> Union[_SupportsLessThanT, _T]: ...
1034+
def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ...
10371035
@overload
1038-
def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], _SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ...
1036+
def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ...
10391037
@overload
10401038
def min(
1041-
__arg1: _SupportsLessThanT, __arg2: _SupportsLessThanT, *_args: _SupportsLessThanT, key: None = ...
1042-
) -> _SupportsLessThanT: ...
1039+
__arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ...
1040+
) -> SupportsLessThanT: ...
10431041
@overload
1044-
def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], _SupportsLessThanT]) -> _T: ...
1042+
def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThanT]) -> _T: ...
10451043
@overload
1046-
def min(__iterable: Iterable[_SupportsLessThanT], *, key: None = ...) -> _SupportsLessThanT: ...
1044+
def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ...
10471045
@overload
1048-
def min(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThanT]) -> _T: ...
1046+
def min(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThanT]) -> _T: ...
10491047
@overload
1050-
def min(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., default: _T) -> Union[_SupportsLessThanT, _T]: ...
1048+
def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ...
10511049
@overload
1052-
def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], _SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ...
1050+
def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThanT], default: _T2) -> Union[_T1, _T2]: ...
10531051
@overload
10541052
def next(__i: Iterator[_T]) -> _T: ...
10551053
@overload
@@ -1209,9 +1207,9 @@ def round(number: SupportsRound[_T], ndigits: None) -> int: ...
12091207
def round(number: SupportsRound[_T], ndigits: int) -> _T: ...
12101208
def setattr(__obj: Any, __name: str, __value: Any) -> None: ...
12111209
@overload
1212-
def sorted(__iterable: Iterable[_SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> List[_SupportsLessThanT]: ...
1210+
def sorted(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> List[SupportsLessThanT]: ...
12131211
@overload
1214-
def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], _SupportsLessThan], reverse: bool = ...) -> List[_T]: ...
1212+
def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> List[_T]: ...
12151213

12161214
if sys.version_info >= (3, 8):
12171215
@overload

stdlib/3/functools.pyi

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
from _typeshed import SupportsLessThan
23
from typing import (
34
Any,
45
Callable,
@@ -59,11 +60,7 @@ def wraps(
5960
wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...
6061
) -> Callable[[_AnyCallable], _AnyCallable]: ...
6162
def total_ordering(cls: Type[_T]) -> Type[_T]: ...
62-
63-
class _SupportsLessThan(Protocol):
64-
def __lt__(self, __other: Any) -> bool: ...
65-
66-
def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], _SupportsLessThan]: ...
63+
def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsLessThan]: ...
6764

6865
class partial(Generic[_T]):
6966
func: Callable[..., _T]

stdlib/3/heapq.pyi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from _typeshed import SupportsLessThan
12
from typing import Any, Callable, Iterable, List, Optional, TypeVar
23

34
_T = TypeVar("_T")
@@ -8,6 +9,6 @@ def heappushpop(__heap: List[_T], __item: _T) -> _T: ...
89
def heapify(__heap: List[_T]) -> None: ...
910
def heapreplace(__heap: List[_T], __item: _T) -> _T: ...
1011
def merge(*iterables: Iterable[_T], key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ...) -> Iterable[_T]: ...
11-
def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ...
12-
def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ...
12+
def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ...
13+
def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ...
1314
def _heapify_max(__x: List[_T]) -> None: ... # undocumented

stdlib/3/statistics.pyi

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
from _typeshed import SupportsLessThanT
23
from decimal import Decimal
34
from fractions import Fraction
45
from typing import Any, Hashable, Iterable, List, Optional, Protocol, SupportsFloat, Type, TypeVar, Union
@@ -7,12 +8,6 @@ _T = TypeVar("_T")
78
# Most functions in this module accept homogeneous collections of one of these types
89
_Number = TypeVar("_Number", float, Decimal, Fraction)
910

10-
# Used in median_high, median_low
11-
class _Sortable(Protocol):
12-
def __lt__(self, other: Any) -> bool: ...
13-
14-
_SortableT = TypeVar("_SortableT", bound=_Sortable)
15-
1611
# Used in mode, multimode
1712
_HashableT = TypeVar("_HashableT", bound=Hashable)
1813

@@ -28,8 +23,8 @@ if sys.version_info >= (3, 6):
2823
def harmonic_mean(data: Iterable[_Number]) -> _Number: ...
2924

3025
def median(data: Iterable[_Number]) -> _Number: ...
31-
def median_low(data: Iterable[_SortableT]) -> _SortableT: ...
32-
def median_high(data: Iterable[_SortableT]) -> _SortableT: ...
26+
def median_low(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ...
27+
def median_high(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ...
3328
def median_grouped(data: Iterable[_Number], interval: _Number = ...) -> _Number: ...
3429
def mode(data: Iterable[_HashableT]) -> _HashableT: ...
3530

0 commit comments

Comments
 (0)