From 54fde0c2a104241077a61172c8de53d60519670a Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 1 Feb 2022 08:59:07 +0100 Subject: [PATCH] Improve protocol return types (#7093) * Dunder comparisons must return bool. * write() return type should be ignored. * Use custom comparison protocols in _operator.pyi --- stdlib/_operator.pyi | 27 ++++++++++++++++++++++----- stdlib/_typeshed/__init__.pyi | 10 +++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/stdlib/_operator.pyi b/stdlib/_operator.pyi index 77a88d4fa..375d8e4dd 100644 --- a/stdlib/_operator.pyi +++ b/stdlib/_operator.pyi @@ -1,5 +1,4 @@ import sys -from _typeshed import SupportsAnyComparison from typing import ( Any, AnyStr, @@ -25,6 +24,24 @@ _K = TypeVar("_K") _V = TypeVar("_V") _P = ParamSpec("_P") +# The following protocols return "Any" instead of bool, since the comparison +# operators can be overloaded to return an arbitrary object. For example, +# the numpy.array comparison dunders return another numpy.array. + +class _SupportsDunderLT(Protocol): + def __lt__(self, __other: Any) -> Any: ... + +class _SupportsDunderGT(Protocol): + def __gt__(self, __other: Any) -> Any: ... + +class _SupportsDunderLE(Protocol): + def __le__(self, __other: Any) -> Any: ... + +class _SupportsDunderGE(Protocol): + def __ge__(self, __other: Any) -> Any: ... + +_SupportsComparison = _SupportsDunderLE | _SupportsDunderGE | _SupportsDunderGT | _SupportsDunderLT + class _SupportsInversion(Protocol[_T_co]): def __invert__(self) -> _T_co: ... @@ -35,12 +52,12 @@ class _SupportsPos(Protocol[_T_co]): def __pos__(self) -> _T_co: ... # All four comparison functions must have the same signature, or we get false-positive errors -def lt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... -def le(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def lt(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... +def le(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... def eq(__a: object, __b: object) -> Any: ... def ne(__a: object, __b: object) -> Any: ... -def ge(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... -def gt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def ge(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... +def gt(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... def not_(__a: object) -> bool: ... def truth(__a: object) -> bool: ... def is_(__a: object, __b: object) -> bool: ... diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index b076c1f6c..d3878778b 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -38,16 +38,16 @@ class SupportsAnext(Protocol[_T_co]): # Comparison protocols class SupportsDunderLT(Protocol): - def __lt__(self, __other: Any) -> Any: ... + def __lt__(self, __other: Any) -> bool: ... class SupportsDunderGT(Protocol): - def __gt__(self, __other: Any) -> Any: ... + def __gt__(self, __other: Any) -> bool: ... class SupportsDunderLE(Protocol): - def __le__(self, __other: Any) -> Any: ... + def __le__(self, __other: Any) -> bool: ... class SupportsDunderGE(Protocol): - def __ge__(self, __other: Any) -> Any: ... + def __ge__(self, __other: Any) -> bool: ... class SupportsAllComparisons(SupportsDunderLT, SupportsDunderGT, SupportsDunderLE, SupportsDunderGE, Protocol): ... @@ -181,7 +181,7 @@ class SupportsNoArgReadline(Protocol[_T_co]): # stable class SupportsWrite(Protocol[_T_contra]): - def write(self, __s: _T_contra) -> Any: ... + def write(self, __s: _T_contra) -> object: ... ReadOnlyBuffer = bytes # stable # Anything that implements the read-write buffer interface.