summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBas van Beek <43369155+BvB93@users.noreply.github.com>2021-01-22 00:44:58 +0100
committerGitHub <noreply@github.com>2021-01-21 16:44:58 -0700
commit33273e4ae770cac1ee0cb304ad5a0056bb59ad56 (patch)
tree546680d3c4778ad3bceed02e3fab73277ca46fe3
parentb91f3c00ee113596acd3e508a593187258291f61 (diff)
downloadnumpy-33273e4ae770cac1ee0cb304ad5a0056bb59ad56.tar.gz
ENH: Add dtype support to the array comparison ops (#18128)
* ENH: Added `_ArrayLikeNumber` * ENH: Added dtype support to the array comparison ops * MAINT: Made `dtype` and `ndarray` covariant The dtypes scalar-type and ndarrays' dtype are now covariant instead of invariant. This change is necasary in order to ensure that all generic subclasses can be used as underlying scalar type. * TST: Updated the comparison typing tests * MAINT: Fixed an issue where certain `array > arraylike` operations where neglected More specifically operations between array-likes of `timedelta64` and `ndarray`s that can be cast into `timedelta64`. For example: ar_i = np.array([1]) seq_m = [np.timedelta64()] ar_i > seq_m
-rw-r--r--numpy/__init__.pyi137
-rw-r--r--numpy/typing/__init__.py5
-rw-r--r--numpy/typing/_array_like.py18
-rw-r--r--numpy/typing/_callable.py16
-rw-r--r--numpy/typing/tests/data/fail/comparisons.py28
-rw-r--r--numpy/typing/tests/data/pass/comparisons.py96
-rw-r--r--numpy/typing/tests/data/reveal/comparisons.py77
7 files changed, 282 insertions, 95 deletions
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
index dbf807783..3d92a543b 100644
--- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -9,8 +9,16 @@ from numpy.core._internal import _ctypes
from numpy.typing import (
# Arrays
ArrayLike,
+ _ArrayND,
+ _ArrayOrScalar,
+ _NestedSequence,
+ _RecursiveSequence,
+ _ArrayLikeNumber_co,
+ _ArrayLikeTD64_co,
+ _ArrayLikeDT64_co,
# DTypes
+
DTypeLike,
_SupportsDType,
_VoidDTypeLike,
@@ -127,6 +135,7 @@ from typing import (
Iterable,
List,
Mapping,
+ NoReturn,
Optional,
overload,
Sequence,
@@ -584,19 +593,19 @@ where: Any
who: Any
_NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray)
-_DTypeScalar = TypeVar("_DTypeScalar", bound=generic)
+_DTypeScalar_co = TypeVar("_DTypeScalar_co", covariant=True, bound=generic)
_ByteOrder = Literal["S", "<", ">", "=", "|", "L", "B", "N", "I"]
-class dtype(Generic[_DTypeScalar]):
+class dtype(Generic[_DTypeScalar_co]):
names: Optional[Tuple[str, ...]]
# Overload for subclass of generic
@overload
def __new__(
cls,
- dtype: Type[_DTypeScalar],
+ dtype: Type[_DTypeScalar_co],
align: bool = ...,
copy: bool = ...,
- ) -> dtype[_DTypeScalar]: ...
+ ) -> dtype[_DTypeScalar_co]: ...
# Overloads for string aliases, Python types, and some assorted
# other special cases. Order is sometimes important because of the
# subtype relationships
@@ -711,10 +720,10 @@ class dtype(Generic[_DTypeScalar]):
@overload
def __new__(
cls,
- dtype: dtype[_DTypeScalar],
+ dtype: dtype[_DTypeScalar_co],
align: bool = ...,
copy: bool = ...,
- ) -> dtype[_DTypeScalar]: ...
+ ) -> dtype[_DTypeScalar_co]: ...
# TODO: handle _SupportsDType better
@overload
def __new__(
@@ -791,7 +800,7 @@ class dtype(Generic[_DTypeScalar]):
@property
def str(self) -> builtins.str: ...
@property
- def type(self) -> Type[_DTypeScalar]: ...
+ def type(self) -> Type[_DTypeScalar_co]: ...
class _flagsobj:
aligned: bool
@@ -1319,6 +1328,7 @@ class _ArrayOrScalarCommon:
) -> _NdArraySubClass: ...
_DType = TypeVar("_DType", bound=dtype[Any])
+_DType_co = TypeVar("_DType_co", covariant=True, bound=dtype[Any])
# TODO: Set the `bound` to something more suitable once we
# have proper shape support
@@ -1327,7 +1337,7 @@ _ShapeType = TypeVar("_ShapeType", bound=Any)
_BufferType = Union[ndarray, bytes, bytearray, memoryview]
_Casting = Literal["no", "equiv", "safe", "same_kind", "unsafe"]
-class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]):
+class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]):
@property
def base(self) -> Optional[ndarray]: ...
@property
@@ -1352,7 +1362,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]):
order: _OrderKACF = ...,
) -> _ArraySelf: ...
@overload
- def __array__(self, __dtype: None = ...) -> ndarray[Any, _DType]: ...
+ def __array__(self, __dtype: None = ...) -> ndarray[Any, _DType_co]: ...
@overload
def __array__(self, __dtype: DTypeLike) -> ndarray[Any, dtype[Any]]: ...
@property
@@ -1464,10 +1474,77 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]):
def __iter__(self) -> Any: ...
def __contains__(self, key) -> bool: ...
def __index__(self) -> int: ...
- def __lt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
- def __le__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
- def __gt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
- def __ge__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
+
+ # The last overload is for catching recursive objects whose
+ # nesting is too deep.
+ # The first overload is for catching `bytes` (as they are a subtype of
+ # `Sequence[int]`) and `str`. As `str` is a recusive sequence of
+ # strings, it will pass through the final overload otherwise
+
+ @overload
+ def __lt__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ...
+ @overload
+ def __lt__(self: _ArrayND[Union[number[Any], bool_]], other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __lt__(self: _ArrayND[Union[bool_, integer[Any], timedelta64]], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __lt__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __lt__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __lt__(
+ self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]],
+ other: _RecursiveSequence,
+ ) -> _ArrayOrScalar[bool_]: ...
+
+ @overload
+ def __le__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ...
+ @overload
+ def __le__(self: _ArrayND[Union[number[Any], bool_]], other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __le__(self: _ArrayND[Union[bool_, integer[Any], timedelta64]], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __le__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __le__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __le__(
+ self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]],
+ other: _RecursiveSequence,
+ ) -> _ArrayOrScalar[bool_]: ...
+
+ @overload
+ def __gt__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ...
+ @overload
+ def __gt__(self: _ArrayND[Union[number[Any], bool_]], other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __gt__(self: _ArrayND[Union[bool_, integer[Any], timedelta64]], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __gt__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __gt__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __gt__(
+ self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]],
+ other: _RecursiveSequence,
+ ) -> _ArrayOrScalar[bool_]: ...
+
+ @overload
+ def __ge__(self: _ArrayND[Any], other: _NestedSequence[Union[str, bytes]]) -> NoReturn: ...
+ @overload
+ def __ge__(self: _ArrayND[Union[number[Any], bool_]], other: _ArrayLikeNumber_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __ge__(self: _ArrayND[Union[bool_, integer[Any], timedelta64]], other: _ArrayLikeTD64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __ge__(self: _ArrayND[datetime64], other: _ArrayLikeDT64_co) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __ge__(self: _ArrayND[object_], other: Any) -> _ArrayOrScalar[bool_]: ...
+ @overload
+ def __ge__(
+ self: _ArrayND[Union[number[Any], datetime64, timedelta64, bool_]],
+ other: _RecursiveSequence,
+ ) -> _ArrayOrScalar[bool_]: ...
+
def __matmul__(self, other: ArrayLike) -> Any: ...
# NOTE: `ndarray` does not implement `__imatmul__`
def __rmatmul__(self, other: ArrayLike) -> Any: ...
@@ -1516,7 +1593,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]):
def __ior__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
# Keep `dtype` at the bottom to avoid name conflicts with `np.dtype`
@property
- def dtype(self) -> _DType: ...
+ def dtype(self) -> _DType_co: ...
# NOTE: while `np.generic` is not technically an instance of `ABCMeta`,
# the `@abstractmethod` decorator is herein used to (forcefully) deny
@@ -1586,10 +1663,10 @@ class number(generic, Generic[_NBit1]): # type: ignore
__rpow__: _NumberOp
__truediv__: _NumberOp
__rtruediv__: _NumberOp
- __lt__: _ComparisonOp[_NumberLike_co]
- __le__: _ComparisonOp[_NumberLike_co]
- __gt__: _ComparisonOp[_NumberLike_co]
- __ge__: _ComparisonOp[_NumberLike_co]
+ __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
class bool_(generic):
def __init__(self, __value: object = ...) -> None: ...
@@ -1628,10 +1705,10 @@ class bool_(generic):
__rmod__: _BoolMod
__divmod__: _BoolDivMod
__rdivmod__: _BoolDivMod
- __lt__: _ComparisonOp[_NumberLike_co]
- __le__: _ComparisonOp[_NumberLike_co]
- __gt__: _ComparisonOp[_NumberLike_co]
- __ge__: _ComparisonOp[_NumberLike_co]
+ __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
class object_(generic):
def __init__(self, __value: object = ...) -> None: ...
@@ -1660,10 +1737,10 @@ class datetime64(generic):
@overload
def __sub__(self, other: _TD64Like_co) -> datetime64: ...
def __rsub__(self, other: datetime64) -> timedelta64: ...
- __lt__: _ComparisonOp[datetime64]
- __le__: _ComparisonOp[datetime64]
- __gt__: _ComparisonOp[datetime64]
- __ge__: _ComparisonOp[datetime64]
+ __lt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __le__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __gt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __ge__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
# Support for `__index__` was added in python 3.8 (bpo-20092)
if sys.version_info >= (3, 8):
@@ -1762,10 +1839,10 @@ class timedelta64(generic):
def __rmod__(self, other: timedelta64) -> timedelta64: ...
def __divmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
def __rdivmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
- __lt__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]]
- __le__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]]
- __gt__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]]
- __ge__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]]
+ __lt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __le__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __gt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __ge__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
class unsignedinteger(integer[_NBit1]):
# NOTE: `uint64 + signedinteger -> float64`
diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py
index a1d943235..4ec1f4b2f 100644
--- a/numpy/typing/__init__.py
+++ b/numpy/typing/__init__.py
@@ -302,18 +302,23 @@ from ._array_like import (
ArrayLike as ArrayLike,
_ArrayLike,
_NestedSequence,
+ _RecursiveSequence,
_SupportsArray,
+ _ArrayND,
+ _ArrayOrScalar,
_ArrayLikeBool_co,
_ArrayLikeUInt_co,
_ArrayLikeInt_co,
_ArrayLikeFloat_co,
_ArrayLikeComplex_co,
+ _ArrayLikeNumber_co,
_ArrayLikeTD64_co,
_ArrayLikeDT64_co,
_ArrayLikeObject_co,
_ArrayLikeVoid_co,
_ArrayLikeStr_co,
_ArrayLikeBytes_co,
+
)
if __doc__ is not None:
diff --git a/numpy/typing/_array_like.py b/numpy/typing/_array_like.py
index 35413393c..133f38800 100644
--- a/numpy/typing/_array_like.py
+++ b/numpy/typing/_array_like.py
@@ -12,6 +12,7 @@ from numpy import (
integer,
floating,
complexfloating,
+ number,
timedelta64,
datetime64,
object_,
@@ -33,15 +34,17 @@ else:
HAVE_PROTOCOL = True
_T = TypeVar("_T")
+_ScalarType = TypeVar("_ScalarType", bound=generic)
_DType = TypeVar("_DType", bound="dtype[Any]")
+_DType_co = TypeVar("_DType_co", covariant=True, bound="dtype[Any]")
if TYPE_CHECKING or HAVE_PROTOCOL:
# The `_SupportsArray` protocol only cares about the default dtype
# (i.e. `dtype=None`) of the to-be returned array.
# Concrete implementations of the protocol are responsible for adding
# any and all remaining overloads
- class _SupportsArray(Protocol[_DType]):
- def __array__(self, dtype: None = ...) -> ndarray[Any, _DType]: ...
+ class _SupportsArray(Protocol[_DType_co]):
+ def __array__(self, dtype: None = ...) -> ndarray[Any, _DType_co]: ...
else:
_SupportsArray = Any
@@ -100,6 +103,10 @@ _ArrayLikeComplex_co = _ArrayLike[
"dtype[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]]",
Union[bool, int, float, complex],
]
+_ArrayLikeNumber_co = _ArrayLike[
+ "dtype[Union[bool_, number[Any]]]",
+ Union[bool, int, float, complex],
+]
_ArrayLikeTD64_co = _ArrayLike[
"dtype[Union[bool_, integer[Any], timedelta64]]",
Union[bool, int],
@@ -116,3 +123,10 @@ _ArrayLikeBytes_co = _ArrayLike[
"dtype[bytes_]",
bytes,
]
+
+if TYPE_CHECKING:
+ _ArrayND = ndarray[Any, dtype[_ScalarType]]
+ _ArrayOrScalar = Union[_ScalarType, _ArrayND[_ScalarType]]
+else:
+ _ArrayND = Any
+ _ArrayOrScalar = Any
diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py
index e1fdee3ba..1591ca144 100644
--- a/numpy/typing/_callable.py
+++ b/numpy/typing/_callable.py
@@ -8,6 +8,8 @@ See the `Mypy documentation`_ on protocols for more details.
"""
+from __future__ import annotations
+
import sys
from typing import (
Union,
@@ -21,6 +23,7 @@ from typing import (
from numpy import (
ndarray,
+ dtype,
generic,
bool_,
timedelta64,
@@ -44,7 +47,7 @@ from ._scalars import (
_NumberLike_co,
)
from . import NBitBase
-from ._array_like import ArrayLike
+from ._array_like import ArrayLike, _ArrayOrScalar
if sys.version_info >= (3, 8):
from typing import Protocol
@@ -58,8 +61,9 @@ else:
HAVE_PROTOCOL = True
if TYPE_CHECKING or HAVE_PROTOCOL:
- _T = TypeVar("_T")
- _2Tuple = Tuple[_T, _T]
+ _T1 = TypeVar("_T1")
+ _T2 = TypeVar("_T2")
+ _2Tuple = Tuple[_T1, _T1]
_NBit1 = TypeVar("_NBit1", bound=NBitBase)
_NBit2 = TypeVar("_NBit2", bound=NBitBase)
@@ -316,11 +320,11 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
class _NumberOp(Protocol):
def __call__(self, __other: _NumberLike_co) -> Any: ...
- class _ComparisonOp(Protocol[_T]):
+ class _ComparisonOp(Protocol[_T1, _T2]):
@overload
- def __call__(self, __other: _T) -> bool_: ...
+ def __call__(self, __other: _T1) -> bool_: ...
@overload
- def __call__(self, __other: ArrayLike) -> Union[ndarray, bool_]: ...
+ def __call__(self, __other: _T2) -> _ArrayOrScalar[bool_]: ...
else:
_BoolOp = Any
diff --git a/numpy/typing/tests/data/fail/comparisons.py b/numpy/typing/tests/data/fail/comparisons.py
new file mode 100644
index 000000000..cad1c6555
--- /dev/null
+++ b/numpy/typing/tests/data/fail/comparisons.py
@@ -0,0 +1,28 @@
+from typing import Any
+import numpy as np
+
+AR_i: np.ndarray[Any, np.dtype[np.int64]]
+AR_f: np.ndarray[Any, np.dtype[np.float64]]
+AR_c: np.ndarray[Any, np.dtype[np.complex128]]
+AR_m: np.ndarray[Any, np.dtype[np.timedelta64]]
+AR_M: np.ndarray[Any, np.dtype[np.datetime64]]
+
+AR_f > AR_m # E: Unsupported operand types
+AR_c > AR_m # E: Unsupported operand types
+
+AR_m > AR_f # E: Unsupported operand types
+AR_m > AR_c # E: Unsupported operand types
+
+AR_i > AR_M # E: Unsupported operand types
+AR_f > AR_M # E: Unsupported operand types
+AR_m > AR_M # E: Unsupported operand types
+
+AR_M > AR_i # E: Unsupported operand types
+AR_M > AR_f # E: Unsupported operand types
+AR_M > AR_m # E: Unsupported operand types
+
+# Unfortunately `NoReturn` errors are not the most descriptive
+_1 = AR_i > str() # E: Need type annotation
+_2 = AR_i > bytes() # E: Need type annotation
+_3 = str() > AR_M # E: Need type annotation
+_4 = bytes() > AR_M # E: Need type annotation
diff --git a/numpy/typing/tests/data/pass/comparisons.py b/numpy/typing/tests/data/pass/comparisons.py
index b298117a6..ce41de435 100644
--- a/numpy/typing/tests/data/pass/comparisons.py
+++ b/numpy/typing/tests/data/pass/comparisons.py
@@ -1,3 +1,6 @@
+from __future__ import annotations
+
+from typing import Any
import numpy as np
c16 = np.complex128()
@@ -20,11 +23,62 @@ c = complex()
f = float()
i = int()
-AR = np.array([0], dtype=np.int64)
-AR.setflags(write=False)
-
SEQ = (0, 1, 2, 3, 4)
+AR_b: np.ndarray[Any, np.dtype[np.bool_]] = np.array([True])
+AR_u: np.ndarray[Any, np.dtype[np.uint32]] = np.array([1], dtype=np.uint32)
+AR_i: np.ndarray[Any, np.dtype[np.int_]] = np.array([1])
+AR_f: np.ndarray[Any, np.dtype[np.float_]] = np.array([1.0])
+AR_c: np.ndarray[Any, np.dtype[np.complex_]] = np.array([1.0j])
+AR_m: np.ndarray[Any, np.dtype[np.timedelta64]] = np.array([np.timedelta64("1")])
+AR_M: np.ndarray[Any, np.dtype[np.datetime64]] = np.array([np.datetime64("1")])
+AR_O: np.ndarray[Any, np.dtype[np.object_]] = np.array([1], dtype=object)
+
+# Arrays
+
+AR_b > AR_b
+AR_b > AR_u
+AR_b > AR_i
+AR_b > AR_f
+AR_b > AR_c
+
+AR_u > AR_b
+AR_u > AR_u
+AR_u > AR_i
+AR_u > AR_f
+AR_u > AR_c
+
+AR_i > AR_b
+AR_i > AR_u
+AR_i > AR_i
+AR_i > AR_f
+AR_i > AR_c
+
+AR_f > AR_b
+AR_f > AR_u
+AR_f > AR_i
+AR_f > AR_f
+AR_f > AR_c
+
+AR_c > AR_b
+AR_c > AR_u
+AR_c > AR_i
+AR_c > AR_f
+AR_c > AR_c
+
+AR_m > AR_b
+AR_m > AR_u
+AR_m > AR_i
+AR_b > AR_m
+AR_u > AR_m
+AR_i > AR_m
+
+AR_M > AR_M
+
+AR_O > AR_O
+1 > AR_O
+AR_O > 1
+
# Time structures
dt > dt
@@ -33,7 +87,7 @@ td > td
td > i
td > i4
td > i8
-td > AR
+td > AR_i
td > SEQ
# boolean
@@ -51,7 +105,7 @@ b_ > f4
b_ > c
b_ > c16
b_ > c8
-b_ > AR
+b_ > AR_i
b_ > SEQ
# Complex
@@ -67,7 +121,7 @@ c16 > b
c16 > c
c16 > f
c16 > i
-c16 > AR
+c16 > AR_i
c16 > SEQ
c16 > c16
@@ -81,7 +135,7 @@ b > c16
c > c16
f > c16
i > c16
-AR > c16
+AR_i > c16
SEQ > c16
c8 > c16
@@ -95,7 +149,7 @@ c8 > b
c8 > c
c8 > f
c8 > i
-c8 > AR
+c8 > AR_i
c8 > SEQ
c16 > c8
@@ -109,7 +163,7 @@ b > c8
c > c8
f > c8
i > c8
-AR > c8
+AR_i > c8
SEQ > c8
# Float
@@ -123,7 +177,7 @@ f8 > b
f8 > c
f8 > f
f8 > i
-f8 > AR
+f8 > AR_i
f8 > SEQ
f8 > f8
@@ -135,7 +189,7 @@ b > f8
c > f8
f > f8
i > f8
-AR > f8
+AR_i > f8
SEQ > f8
f4 > f8
@@ -147,7 +201,7 @@ f4 > b
f4 > c
f4 > f
f4 > i
-f4 > AR
+f4 > AR_i
f4 > SEQ
f8 > f4
@@ -159,7 +213,7 @@ b > f4
c > f4
f > f4
i > f4
-AR > f4
+AR_i > f4
SEQ > f4
# Int
@@ -173,7 +227,7 @@ i8 > b
i8 > c
i8 > f
i8 > i
-i8 > AR
+i8 > AR_i
i8 > SEQ
u8 > u8
@@ -184,7 +238,7 @@ u8 > b
u8 > c
u8 > f
u8 > i
-u8 > AR
+u8 > AR_i
u8 > SEQ
i8 > i8
@@ -196,7 +250,7 @@ b > i8
c > i8
f > i8
i > i8
-AR > i8
+AR_i > i8
SEQ > i8
u8 > u8
@@ -207,7 +261,7 @@ b > u8
c > u8
f > u8
i > u8
-AR > u8
+AR_i > u8
SEQ > u8
i4 > i8
@@ -215,7 +269,7 @@ i4 > i4
i4 > i
i4 > b_
i4 > b
-i4 > AR
+i4 > AR_i
i4 > SEQ
u4 > i8
@@ -225,7 +279,7 @@ u4 > u4
u4 > i
u4 > b_
u4 > b
-u4 > AR
+u4 > AR_i
u4 > SEQ
i8 > i4
@@ -233,7 +287,7 @@ i4 > i4
i > i4
b_ > i4
b > i4
-AR > i4
+AR_i > i4
SEQ > i4
i8 > u4
@@ -243,5 +297,5 @@ u4 > u4
b_ > u4
b > u4
i > u4
-AR > u4
+AR_i > u4
SEQ > u4
diff --git a/numpy/typing/tests/data/reveal/comparisons.py b/numpy/typing/tests/data/reveal/comparisons.py
index 507f713c7..5053a9e82 100644
--- a/numpy/typing/tests/data/reveal/comparisons.py
+++ b/numpy/typing/tests/data/reveal/comparisons.py
@@ -33,8 +33,13 @@ reveal_type(td > td) # E: numpy.bool_
reveal_type(td > i) # E: numpy.bool_
reveal_type(td > i4) # E: numpy.bool_
reveal_type(td > i8) # E: numpy.bool_
-reveal_type(td > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(td > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+
+reveal_type(td > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(td > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(AR > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(AR > td) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > td) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
# boolean
@@ -51,8 +56,8 @@ reveal_type(b_ > f4) # E: numpy.bool_
reveal_type(b_ > c) # E: numpy.bool_
reveal_type(b_ > c16) # E: numpy.bool_
reveal_type(b_ > c8) # E: numpy.bool_
-reveal_type(b_ > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(b_ > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(b_ > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(b_ > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
# Complex
@@ -67,8 +72,8 @@ reveal_type(c16 > b) # E: numpy.bool_
reveal_type(c16 > c) # E: numpy.bool_
reveal_type(c16 > f) # E: numpy.bool_
reveal_type(c16 > i) # E: numpy.bool_
-reveal_type(c16 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(c16 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(c16 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(c16 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(c16 > c16) # E: numpy.bool_
reveal_type(f8 > c16) # E: numpy.bool_
@@ -81,8 +86,8 @@ reveal_type(b > c16) # E: numpy.bool_
reveal_type(c > c16) # E: numpy.bool_
reveal_type(f > c16) # E: numpy.bool_
reveal_type(i > c16) # E: numpy.bool_
-reveal_type(AR > c16) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > c16) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > c16) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > c16) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(c8 > c16) # E: numpy.bool_
reveal_type(c8 > f8) # E: numpy.bool_
@@ -95,8 +100,8 @@ reveal_type(c8 > b) # E: numpy.bool_
reveal_type(c8 > c) # E: numpy.bool_
reveal_type(c8 > f) # E: numpy.bool_
reveal_type(c8 > i) # E: numpy.bool_
-reveal_type(c8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(c8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(c8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(c8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(c16 > c8) # E: numpy.bool_
reveal_type(f8 > c8) # E: numpy.bool_
@@ -109,8 +114,8 @@ reveal_type(b > c8) # E: numpy.bool_
reveal_type(c > c8) # E: numpy.bool_
reveal_type(f > c8) # E: numpy.bool_
reveal_type(i > c8) # E: numpy.bool_
-reveal_type(AR > c8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > c8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > c8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > c8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
# Float
@@ -123,8 +128,8 @@ reveal_type(f8 > b) # E: numpy.bool_
reveal_type(f8 > c) # E: numpy.bool_
reveal_type(f8 > f) # E: numpy.bool_
reveal_type(f8 > i) # E: numpy.bool_
-reveal_type(f8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(f8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(f8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(f8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(f8 > f8) # E: numpy.bool_
reveal_type(i8 > f8) # E: numpy.bool_
@@ -135,8 +140,8 @@ reveal_type(b > f8) # E: numpy.bool_
reveal_type(c > f8) # E: numpy.bool_
reveal_type(f > f8) # E: numpy.bool_
reveal_type(i > f8) # E: numpy.bool_
-reveal_type(AR > f8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > f8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > f8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > f8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(f4 > f8) # E: numpy.bool_
reveal_type(f4 > i8) # E: numpy.bool_
@@ -147,8 +152,8 @@ reveal_type(f4 > b) # E: numpy.bool_
reveal_type(f4 > c) # E: numpy.bool_
reveal_type(f4 > f) # E: numpy.bool_
reveal_type(f4 > i) # E: numpy.bool_
-reveal_type(f4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(f4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(f4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(f4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(f8 > f4) # E: numpy.bool_
reveal_type(i8 > f4) # E: numpy.bool_
@@ -159,8 +164,8 @@ reveal_type(b > f4) # E: numpy.bool_
reveal_type(c > f4) # E: numpy.bool_
reveal_type(f > f4) # E: numpy.bool_
reveal_type(i > f4) # E: numpy.bool_
-reveal_type(AR > f4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > f4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > f4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > f4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
# Int
@@ -173,8 +178,8 @@ reveal_type(i8 > b) # E: numpy.bool_
reveal_type(i8 > c) # E: numpy.bool_
reveal_type(i8 > f) # E: numpy.bool_
reveal_type(i8 > i) # E: numpy.bool_
-reveal_type(i8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(i8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(i8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(i8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(u8 > u8) # E: numpy.bool_
reveal_type(u8 > i4) # E: numpy.bool_
@@ -184,8 +189,8 @@ reveal_type(u8 > b) # E: numpy.bool_
reveal_type(u8 > c) # E: numpy.bool_
reveal_type(u8 > f) # E: numpy.bool_
reveal_type(u8 > i) # E: numpy.bool_
-reveal_type(u8 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(u8 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(u8 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(u8 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(i8 > i8) # E: numpy.bool_
reveal_type(u8 > i8) # E: numpy.bool_
@@ -196,8 +201,8 @@ reveal_type(b > i8) # E: numpy.bool_
reveal_type(c > i8) # E: numpy.bool_
reveal_type(f > i8) # E: numpy.bool_
reveal_type(i > i8) # E: numpy.bool_
-reveal_type(AR > i8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > i8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > i8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > i8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(u8 > u8) # E: numpy.bool_
reveal_type(i4 > u8) # E: numpy.bool_
@@ -207,16 +212,16 @@ reveal_type(b > u8) # E: numpy.bool_
reveal_type(c > u8) # E: numpy.bool_
reveal_type(f > u8) # E: numpy.bool_
reveal_type(i > u8) # E: numpy.bool_
-reveal_type(AR > u8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > u8) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > u8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > u8) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(i4 > i8) # E: numpy.bool_
reveal_type(i4 > i4) # E: numpy.bool_
reveal_type(i4 > i) # E: numpy.bool_
reveal_type(i4 > b_) # E: numpy.bool_
reveal_type(i4 > b) # E: numpy.bool_
-reveal_type(i4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(i4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(i4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(i4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(u4 > i8) # E: numpy.bool_
reveal_type(u4 > i4) # E: numpy.bool_
@@ -225,16 +230,16 @@ reveal_type(u4 > u4) # E: numpy.bool_
reveal_type(u4 > i) # E: numpy.bool_
reveal_type(u4 > b_) # E: numpy.bool_
reveal_type(u4 > b) # E: numpy.bool_
-reveal_type(u4 > AR) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(u4 > SEQ) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(u4 > AR) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(u4 > SEQ) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(i8 > i4) # E: numpy.bool_
reveal_type(i4 > i4) # E: numpy.bool_
reveal_type(i > i4) # E: numpy.bool_
reveal_type(b_ > i4) # E: numpy.bool_
reveal_type(b > i4) # E: numpy.bool_
-reveal_type(AR > i4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > i4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > i4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > i4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
reveal_type(i8 > u4) # E: numpy.bool_
reveal_type(i4 > u4) # E: numpy.bool_
@@ -243,5 +248,5 @@ reveal_type(u4 > u4) # E: numpy.bool_
reveal_type(b_ > u4) # E: numpy.bool_
reveal_type(b > u4) # E: numpy.bool_
reveal_type(i > u4) # E: numpy.bool_
-reveal_type(AR > u4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
-reveal_type(SEQ > u4) # E: Union[numpy.ndarray[Any, Any], numpy.bool_]
+reveal_type(AR > u4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]
+reveal_type(SEQ > u4) # E: Union[numpy.bool_, numpy.ndarray[Any, numpy.dtype[numpy.bool_]]]