summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2020-10-29 11:36:46 +0200
committerGitHub <noreply@github.com>2020-10-29 11:36:46 +0200
commitb10ee24730097204b72c12bcbb74555083e9b54b (patch)
tree96a0fe89cf323861f05e6fee3e20b5f592aaf46f
parentc5b2676a5cc32b316a76d4ad636b6b3109f09c2e (diff)
parent939985d0859bbce349c8cccf866679eb113aeab3 (diff)
downloadnumpy-b10ee24730097204b72c12bcbb74555083e9b54b.tar.gz
Merge pull request #17613 from BvB93/cleanup
ENH: Add annotations for 9 `ndarray`/`generic` magic methods
-rw-r--r--numpy/__init__.pyi87
-rw-r--r--numpy/typing/_callable.py128
-rw-r--r--numpy/typing/tests/data/fail/arithmetic.py9
-rw-r--r--numpy/typing/tests/data/fail/scalars.py2
-rw-r--r--numpy/typing/tests/data/pass/arithmetic.py36
-rw-r--r--numpy/typing/tests/data/pass/mod.py149
-rw-r--r--numpy/typing/tests/data/pass/scalars.py53
-rw-r--r--numpy/typing/tests/data/reveal/arithmetic.py37
-rw-r--r--numpy/typing/tests/data/reveal/mod.py149
-rw-r--r--numpy/typing/tests/test_typing.py2
10 files changed, 609 insertions, 43 deletions
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
index ce4aa1ae6..c8ef60c2d 100644
--- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -28,13 +28,21 @@ from numpy.typing._callable import (
_BoolBitOp,
_BoolSub,
_BoolTrueDiv,
+ _BoolMod,
+ _BoolDivMod,
_TD64Div,
_IntTrueDiv,
_UnsignedIntOp,
_UnsignedIntBitOp,
+ _UnsignedIntMod,
+ _UnsignedIntDivMod,
_SignedIntOp,
_SignedIntBitOp,
+ _SignedIntMod,
+ _SignedIntDivMod,
_FloatOp,
+ _FloatMod,
+ _FloatDivMod,
_ComplexOp,
_NumberOp,
)
@@ -55,8 +63,6 @@ from typing import (
overload,
Sequence,
Sized,
- SupportsAbs,
- SupportsBytes,
SupportsComplex,
SupportsFloat,
SupportsInt,
@@ -978,9 +984,7 @@ _ArrayLikeIntOrBool = Union[
_ArraySelf = TypeVar("_ArraySelf", bound=_ArrayOrScalarCommon)
-class _ArrayOrScalarCommon(
- SupportsInt, SupportsFloat, SupportsComplex, SupportsBytes, SupportsAbs[Any]
-):
+class _ArrayOrScalarCommon:
@property
def T(self: _ArraySelf) -> _ArraySelf: ...
@property
@@ -1004,9 +1008,6 @@ class _ArrayOrScalarCommon(
@property
def strides(self) -> _Shape: ...
def __array__(self, __dtype: DtypeLike = ...) -> ndarray: ...
- def __int__(self) -> int: ...
- def __float__(self) -> float: ...
- def __complex__(self) -> complex: ...
def __bool__(self) -> bool: ...
def __bytes__(self) -> bytes: ...
def __str__(self) -> str: ...
@@ -1019,13 +1020,6 @@ class _ArrayOrScalarCommon(
def __ne__(self, other): ...
def __gt__(self, other): ...
def __ge__(self, other): ...
- def __mod__(self, other): ...
- def __rmod__(self, other): ...
- def __divmod__(self, other): ...
- def __rdivmod__(self, other): ...
- def __neg__(self: _ArraySelf) -> _ArraySelf: ...
- def __pos__(self: _ArraySelf) -> _ArraySelf: ...
- def __abs__(self: _ArraySelf) -> _ArraySelf: ...
def astype(
self: _ArraySelf,
dtype: DtypeLike,
@@ -1572,14 +1566,28 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container):
# Many of these special methods are irrelevant currently, since protocols
# aren't supported yet. That said, I'm adding them for completeness.
# https://docs.python.org/3/reference/datamodel.html
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
def __len__(self) -> int: ...
def __setitem__(self, key, value): ...
def __iter__(self) -> Any: ...
def __contains__(self, key) -> bool: ...
def __index__(self) -> int: ...
- def __matmul__(self, other): ...
- def __imatmul__(self, other): ...
- def __rmatmul__(self, other): ...
+ def __matmul__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
+ # NOTE: `ndarray` does not implement `__imatmul__`
+ def __rmatmul__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
+ def __neg__(self: _ArraySelf) -> Union[_ArraySelf, generic]: ...
+ def __pos__(self: _ArraySelf) -> Union[_ArraySelf, generic]: ...
+ def __abs__(self: _ArraySelf) -> Union[_ArraySelf, generic]: ...
+ def __mod__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
+ def __rmod__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
+ def __divmod__(
+ self, other: ArrayLike
+ ) -> Union[Tuple[ndarray, ndarray], Tuple[generic, generic]]: ...
+ def __rdivmod__(
+ self, other: ArrayLike
+ ) -> Union[Tuple[ndarray, ndarray], Tuple[generic, generic]]: ...
def __add__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
def __radd__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
def __sub__(self, other: ArrayLike) -> Union[ndarray, generic]: ...
@@ -1610,7 +1618,7 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container):
def __itruediv__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
def __ifloordiv__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
def __ipow__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
- def __imod__(self, other): ...
+ def __imod__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
def __ilshift__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
def __irshift__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
def __iand__(self: _ArraySelf, other: ArrayLike) -> _ArraySelf: ...
@@ -1639,6 +1647,12 @@ class number(generic, Generic[_NBit_co]): # type: ignore
def real(self: _ArraySelf) -> _ArraySelf: ...
@property
def imag(self: _ArraySelf) -> _ArraySelf: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __neg__(self: _ArraySelf) -> _ArraySelf: ...
+ def __pos__(self: _ArraySelf) -> _ArraySelf: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
# Ensure that objects annotated as `number` support arithmetic operations
__add__: _NumberOp
__radd__: _NumberOp
@@ -1659,6 +1673,10 @@ class bool_(generic):
def real(self: _ArraySelf) -> _ArraySelf: ...
@property
def imag(self: _ArraySelf) -> _ArraySelf: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
__add__: _BoolOp[bool_]
__radd__: _BoolOp[bool_]
__sub__: _BoolSub
@@ -1682,6 +1700,10 @@ class bool_(generic):
__rxor__: _BoolBitOp[bool_]
__or__: _BoolBitOp[bool_]
__ror__: _BoolBitOp[bool_]
+ __mod__: _BoolMod
+ __rmod__: _BoolMod
+ __divmod__: _BoolDivMod
+ __rdivmod__: _BoolDivMod
class object_(generic):
def __init__(self, __value: object = ...) -> None: ...
@@ -1727,6 +1749,8 @@ class integer(number[_NBit_co]): # type: ignore
def __index__(self) -> int: ...
__truediv__: _IntTrueDiv[_NBit_co]
__rtruediv__: _IntTrueDiv[_NBit_co]
+ def __mod__(self, value: Union[_IntLike, integer]) -> integer: ...
+ def __rmod__(self, value: Union[_IntLike, integer]) -> integer: ...
def __invert__(self: _IntType) -> _IntType: ...
# Ensure that objects annotated as `integer` support bit-wise operations
def __lshift__(self, other: Union[_IntLike, _BoolLike]) -> integer: ...
@@ -1762,6 +1786,10 @@ class signedinteger(integer[_NBit_co]):
__rxor__: _SignedIntBitOp[_NBit_co]
__or__: _SignedIntBitOp[_NBit_co]
__ror__: _SignedIntBitOp[_NBit_co]
+ __mod__: _SignedIntMod[_NBit_co]
+ __rmod__: _SignedIntMod[_NBit_co]
+ __divmod__: _SignedIntDivMod[_NBit_co]
+ __rdivmod__: _SignedIntDivMod[_NBit_co]
int8 = signedinteger[_8Bit]
int16 = signedinteger[_16Bit]
@@ -1774,6 +1802,12 @@ class timedelta64(generic):
__value: Union[None, int, _CharLike, dt.timedelta, timedelta64] = ...,
__format: Union[_CharLike, Tuple[_CharLike, _IntLike]] = ...,
) -> None: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __neg__(self: _ArraySelf) -> _ArraySelf: ...
+ def __pos__(self: _ArraySelf) -> _ArraySelf: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
def __add__(self, other: Union[timedelta64, _IntLike, _BoolLike]) -> timedelta64: ...
def __radd__(self, other: Union[timedelta64, _IntLike, _BoolLike]) -> timedelta64: ...
def __sub__(self, other: Union[timedelta64, _IntLike, _BoolLike]) -> timedelta64: ...
@@ -1785,6 +1819,9 @@ class timedelta64(generic):
def __rtruediv__(self, other: timedelta64) -> float64: ...
def __rfloordiv__(self, other: timedelta64) -> int64: ...
def __mod__(self, other: timedelta64) -> timedelta64: ...
+ def __rmod__(self, other: timedelta64) -> timedelta64: ...
+ def __divmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
+ def __rdivmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
class unsignedinteger(integer[_NBit_co]):
# NOTE: `uint64 + signedinteger -> float64`
@@ -1809,6 +1846,10 @@ class unsignedinteger(integer[_NBit_co]):
__rxor__: _UnsignedIntBitOp[_NBit_co]
__or__: _UnsignedIntBitOp[_NBit_co]
__ror__: _UnsignedIntBitOp[_NBit_co]
+ __mod__: _UnsignedIntMod[_NBit_co]
+ __rmod__: _UnsignedIntMod[_NBit_co]
+ __divmod__: _UnsignedIntDivMod[_NBit_co]
+ __rdivmod__: _UnsignedIntDivMod[_NBit_co]
uint8 = unsignedinteger[_8Bit]
uint16 = unsignedinteger[_16Bit]
@@ -1834,6 +1875,10 @@ class floating(inexact[_NBit_co]):
__rfloordiv__: _FloatOp[_NBit_co]
__pow__: _FloatOp[_NBit_co]
__rpow__: _FloatOp[_NBit_co]
+ __mod__: _FloatMod[_NBit_co]
+ __rmod__: _FloatMod[_NBit_co]
+ __divmod__: _FloatDivMod[_NBit_co]
+ __rdivmod__: _FloatDivMod[_NBit_co]
float16 = floating[_16Bit]
float32 = floating[_32Bit]
@@ -1878,7 +1923,9 @@ class void(flexible):
self, val: ArrayLike, dtype: DtypeLike, offset: int = ...
) -> None: ...
-class character(flexible): ... # type: ignore
+class character(flexible): # type: ignore
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
# NOTE: Most `np.bytes_` / `np.str_` methods return their
# builtin `bytes` / `str` counterpart
diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py
index b16891b0e..91b7a4ec2 100644
--- a/numpy/typing/_callable.py
+++ b/numpy/typing/_callable.py
@@ -9,7 +9,15 @@ See the `Mypy documentation`_ on protocols for more details.
"""
import sys
-from typing import Union, TypeVar, overload, Any, TYPE_CHECKING, NoReturn
+from typing import (
+ Union,
+ TypeVar,
+ overload,
+ Any,
+ Tuple,
+ NoReturn,
+ TYPE_CHECKING,
+)
from numpy import (
generic,
@@ -19,13 +27,10 @@ from numpy import (
integer,
unsignedinteger,
signedinteger,
- int32,
- int64,
+ int8,
floating,
- float32,
float64,
complexfloating,
- complex64,
complex128,
)
from ._scalars import (
@@ -49,9 +54,14 @@ else:
HAVE_PROTOCOL = True
if TYPE_CHECKING or HAVE_PROTOCOL:
+ _T = TypeVar("_T")
+ _2Tuple = Tuple[_T, _T]
+
_NBit_co = TypeVar("_NBit_co", covariant=True, bound=NBitBase)
_NBit = TypeVar("_NBit", bound=NBitBase)
+
_IntType = TypeVar("_IntType", bound=integer)
+ _FloatType = TypeVar("_FloatType", bound=floating)
_NumberType = TypeVar("_NumberType", bound=number)
_NumberType_co = TypeVar("_NumberType_co", covariant=True, bound=number)
_GenericType_co = TypeVar("_GenericType_co", covariant=True, bound=generic)
@@ -97,6 +107,30 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
@overload
def __call__(self, __other: _NumberType) -> _NumberType: ...
+ class _BoolMod(Protocol):
+ @overload
+ def __call__(self, __other: _BoolLike) -> int8: ...
+ @overload # platform dependent
+ def __call__(self, __other: int) -> signedinteger[Any]: ...
+ @overload
+ def __call__(self, __other: float) -> float64: ...
+ @overload
+ def __call__(self, __other: _IntType) -> _IntType: ...
+ @overload
+ def __call__(self, __other: _FloatType) -> _FloatType: ...
+
+ class _BoolDivMod(Protocol):
+ @overload
+ def __call__(self, __other: _BoolLike) -> _2Tuple[int8]: ...
+ @overload # platform dependent
+ def __call__(self, __other: int) -> _2Tuple[signedinteger[Any]]: ...
+ @overload
+ def __call__(self, __other: float) -> _2Tuple[float64]: ...
+ @overload
+ def __call__(self, __other: _IntType) -> _2Tuple[_IntType]: ...
+ @overload
+ def __call__(self, __other: _FloatType) -> _2Tuple[_FloatType]: ...
+
class _TD64Div(Protocol[_NumberType_co]):
@overload
def __call__(self, __other: timedelta64) -> _NumberType_co: ...
@@ -144,6 +178,34 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
self, __other: unsignedinteger[_NBit]
) -> unsignedinteger[Union[_NBit_co, _NBit]]: ...
+ class _UnsignedIntMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ...
+ @overload
+ def __call__(
+ self, __other: Union[int, signedinteger[Any]]
+ ) -> Union[signedinteger[Any], float64]: ...
+ @overload
+ def __call__(self, __other: float) -> float64: ...
+ @overload
+ def __call__(
+ self, __other: unsignedinteger[_NBit]
+ ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ...
+
+ class _UnsignedIntDivMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ...
+ @overload
+ def __call__(
+ self, __other: Union[int, signedinteger[Any]]
+ ) -> Union[_2Tuple[signedinteger[Any]], _2Tuple[float64]]: ...
+ @overload
+ def __call__(self, __other: float) -> _2Tuple[float64]: ...
+ @overload
+ def __call__(
+ self, __other: unsignedinteger[_NBit]
+ ) -> _2Tuple[unsignedinteger[Union[_NBit_co, _NBit]]]: ...
+
class _SignedIntOp(Protocol[_NBit_co]):
@overload
def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ...
@@ -168,6 +230,30 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
self, __other: signedinteger[_NBit]
) -> signedinteger[Union[_NBit_co, _NBit]]: ...
+ class _SignedIntMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ...
+ @overload
+ def __call__(self, __other: int) -> signedinteger[Any]: ...
+ @overload
+ def __call__(self, __other: float) -> float64: ...
+ @overload
+ def __call__(
+ self, __other: signedinteger[_NBit]
+ ) -> signedinteger[Union[_NBit_co, _NBit]]: ...
+
+ class _SignedIntDivMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ...
+ @overload
+ def __call__(self, __other: int) -> _2Tuple[signedinteger[Any]]: ...
+ @overload
+ def __call__(self, __other: float) -> _2Tuple[float64]: ...
+ @overload
+ def __call__(
+ self, __other: signedinteger[_NBit]
+ ) -> _2Tuple[signedinteger[Union[_NBit_co, _NBit]]]: ...
+
class _FloatOp(Protocol[_NBit_co]):
@overload
def __call__(self, __other: bool) -> floating[_NBit_co]: ...
@@ -182,6 +268,30 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
self, __other: Union[integer[_NBit], floating[_NBit]]
) -> floating[Union[_NBit_co, _NBit]]: ...
+ class _FloatMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> floating[_NBit_co]: ...
+ @overload
+ def __call__(self, __other: int) -> floating[Any]: ...
+ @overload
+ def __call__(self, __other: float) -> float64: ...
+ @overload
+ def __call__(
+ self, __other: Union[integer[_NBit], floating[_NBit]]
+ ) -> floating[Union[_NBit_co, _NBit]]: ...
+
+ class _FloatDivMod(Protocol[_NBit_co]):
+ @overload
+ def __call__(self, __other: bool) -> _2Tuple[floating[_NBit_co]]: ...
+ @overload
+ def __call__(self, __other: int) -> _2Tuple[floating[Any]]: ...
+ @overload
+ def __call__(self, __other: float) -> _2Tuple[float64]: ...
+ @overload
+ def __call__(
+ self, __other: Union[integer[_NBit], floating[_NBit]]
+ ) -> _2Tuple[floating[Union[_NBit_co, _NBit]]]: ...
+
class _ComplexOp(Protocol[_NBit_co]):
@overload
def __call__(self, __other: bool) -> complexfloating[_NBit_co, _NBit_co]: ...
@@ -207,12 +317,20 @@ else:
_BoolBitOp = Any
_BoolSub = Any
_BoolTrueDiv = Any
+ _BoolMod = Any
+ _BoolDivMod = Any
_TD64Div = Any
_IntTrueDiv = Any
_UnsignedIntOp = Any
_UnsignedIntBitOp = Any
+ _UnsignedIntMod = Any
+ _UnsignedIntDivMod = Any
_SignedIntOp = Any
_SignedIntBitOp = Any
+ _SignedIntMod = Any
+ _SignedIntDivMod = Any
_FloatOp = Any
+ _FloatMod = Any
+ _FloatDivMod = Any
_ComplexOp = Any
_NumberOp = Any
diff --git a/numpy/typing/tests/data/fail/arithmetic.py b/numpy/typing/tests/data/fail/arithmetic.py
index 169e104f9..f32eddc4b 100644
--- a/numpy/typing/tests/data/fail/arithmetic.py
+++ b/numpy/typing/tests/data/fail/arithmetic.py
@@ -10,10 +10,7 @@ dt + dt # E: Unsupported operand types
td - dt # E: Unsupported operand types
td % 1 # E: Unsupported operand types
td / dt # E: No overload
+td % dt # E: Unsupported operand types
-# NOTE: The 1 tests below currently don't work due to the broad
-# (i.e. untyped) signature of `.__mod__()`.
-# TODO: Revisit this once annotations are added to the
-# `_ArrayOrScalarCommon` magic methods.
-
-# td % dt # E: Unsupported operand types
+-b_ # E: Unsupported operand type
++b_ # E: Unsupported operand type
diff --git a/numpy/typing/tests/data/fail/scalars.py b/numpy/typing/tests/data/fail/scalars.py
index e7c4c7485..5fffa89b1 100644
--- a/numpy/typing/tests/data/fail/scalars.py
+++ b/numpy/typing/tests/data/fail/scalars.py
@@ -64,3 +64,5 @@ np.timedelta64(value=0) # E: Unexpected keyword argument
np.bytes_(b"hello", encoding='utf-8') # E: No overload variant
np.str_("hello", encoding='utf-8') # E: No overload variant
+
+complex(np.bytes_("1")) # E: No overload variant
diff --git a/numpy/typing/tests/data/pass/arithmetic.py b/numpy/typing/tests/data/pass/arithmetic.py
index f26eab879..ffbaf2975 100644
--- a/numpy/typing/tests/data/pass/arithmetic.py
+++ b/numpy/typing/tests/data/pass/arithmetic.py
@@ -23,6 +23,42 @@ i = int(1)
AR = np.ones(1, dtype=np.float64)
AR.setflags(write=False)
+# unary ops
+
+-c16
+-c8
+-f8
+-f4
+-i8
+-i4
+-u8
+-u4
+-td
+-AR
+
++c16
++c8
++f8
++f4
++i8
++i4
++u8
++u4
++td
++AR
+
+abs(c16)
+abs(c8)
+abs(f8)
+abs(f4)
+abs(i8)
+abs(i4)
+abs(u8)
+abs(u4)
+abs(td)
+abs(b_)
+abs(AR)
+
# Time structures
dt + td
diff --git a/numpy/typing/tests/data/pass/mod.py b/numpy/typing/tests/data/pass/mod.py
new file mode 100644
index 000000000..b5b9afb2a
--- /dev/null
+++ b/numpy/typing/tests/data/pass/mod.py
@@ -0,0 +1,149 @@
+import numpy as np
+
+f8 = np.float64(1)
+i8 = np.int64(1)
+u8 = np.uint64(1)
+
+f4 = np.float32(1)
+i4 = np.int32(1)
+u4 = np.uint32(1)
+
+td = np.timedelta64(1, "D")
+b_ = np.bool_(1)
+
+b = bool(1)
+f = float(1)
+i = int(1)
+
+AR = np.array([1], dtype=np.bool_)
+AR.setflags(write=False)
+
+AR2 = np.array([1], dtype=np.timedelta64)
+AR2.setflags(write=False)
+
+# Time structures
+
+td % td
+td % AR2
+AR2 % td
+
+divmod(td, td)
+divmod(td, AR2)
+divmod(AR2, td)
+
+# Bool
+
+b_ % b
+b_ % i
+b_ % f
+b_ % b_
+b_ % i8
+b_ % u8
+b_ % f8
+b_ % AR
+
+divmod(b_, b)
+divmod(b_, i)
+divmod(b_, f)
+divmod(b_, b_)
+divmod(b_, i8)
+divmod(b_, u8)
+divmod(b_, f8)
+divmod(b_, AR)
+
+b % b_
+i % b_
+f % b_
+b_ % b_
+i8 % b_
+u8 % b_
+f8 % b_
+AR % b_
+
+divmod(b, b_)
+divmod(i, b_)
+divmod(f, b_)
+divmod(b_, b_)
+divmod(i8, b_)
+divmod(u8, b_)
+divmod(f8, b_)
+divmod(AR, b_)
+
+# int
+
+i8 % b
+i8 % i
+i8 % f
+i8 % i8
+i8 % f8
+i4 % i8
+i4 % f8
+i4 % i4
+i4 % f4
+i8 % AR
+
+divmod(i8, b)
+divmod(i8, i)
+divmod(i8, f)
+divmod(i8, i8)
+divmod(i8, f8)
+divmod(i8, i4)
+divmod(i8, f4)
+divmod(i4, i4)
+divmod(i4, f4)
+divmod(i8, AR)
+
+b % i8
+i % i8
+f % i8
+i8 % i8
+f8 % i8
+i8 % i4
+f8 % i4
+i4 % i4
+f4 % i4
+AR % i8
+
+divmod(b, i8)
+divmod(i, i8)
+divmod(f, i8)
+divmod(i8, i8)
+divmod(f8, i8)
+divmod(i4, i8)
+divmod(f4, i8)
+divmod(i4, i4)
+divmod(f4, i4)
+divmod(AR, i8)
+
+# float
+
+f8 % b
+f8 % i
+f8 % f
+i8 % f4
+f4 % f4
+f8 % AR
+
+divmod(f8, b)
+divmod(f8, i)
+divmod(f8, f)
+divmod(f8, f8)
+divmod(f8, f4)
+divmod(f4, f4)
+divmod(f8, AR)
+
+b % f8
+i % f8
+f % f8
+f8 % f8
+f8 % f8
+f4 % f4
+AR % f8
+
+divmod(b, f8)
+divmod(i, f8)
+divmod(f, f8)
+divmod(f8, f8)
+divmod(f4, f8)
+divmod(f4, f4)
+divmod(AR, f8)
diff --git a/numpy/typing/tests/data/pass/scalars.py b/numpy/typing/tests/data/pass/scalars.py
index 49ddb8ed9..04e974983 100644
--- a/numpy/typing/tests/data/pass/scalars.py
+++ b/numpy/typing/tests/data/pass/scalars.py
@@ -1,6 +1,7 @@
import sys
import datetime as dt
+import pytest
import numpy as np
@@ -62,16 +63,6 @@ np.str_("hello")
np.str_(b"hello", 'utf-8')
np.str_(b"hello", encoding='utf-8')
-# Protocols
-float(np.int8(4))
-int(np.int16(5))
-np.int8(np.float32(6))
-
-# TODO(alan): test after https://github.com/python/typeshed/pull/2004
-# complex(np.int32(8))
-
-abs(np.int8(4))
-
# Array-ish semantics
np.int8().real
np.int16().imag
@@ -114,3 +105,45 @@ np.void(True)
np.void(np.bool_(True))
np.void(b"test")
np.void(np.bytes_("test"))
+
+# Protocols
+i8 = np.int64()
+u8 = np.uint64()
+f8 = np.float64()
+c16 = np.complex128()
+b_ = np.bool_()
+td = np.timedelta64()
+U = np.str_("1")
+S = np.bytes_("1")
+AR = np.array(1, dtype=np.float64)
+
+int(i8)
+int(u8)
+int(f8)
+int(b_)
+int(td)
+int(U)
+int(S)
+int(AR)
+with pytest.warns(np.ComplexWarning):
+ int(c16)
+
+float(i8)
+float(u8)
+float(f8)
+float(b_)
+float(td)
+float(U)
+float(S)
+float(AR)
+with pytest.warns(np.ComplexWarning):
+ float(c16)
+
+complex(i8)
+complex(u8)
+complex(f8)
+complex(c16)
+complex(b_)
+complex(td)
+complex(U)
+complex(AR)
diff --git a/numpy/typing/tests/data/reveal/arithmetic.py b/numpy/typing/tests/data/reveal/arithmetic.py
index a1290304a..8a133c136 100644
--- a/numpy/typing/tests/data/reveal/arithmetic.py
+++ b/numpy/typing/tests/data/reveal/arithmetic.py
@@ -23,6 +23,42 @@ i = int()
AR = np.array([0], dtype=np.float64)
AR.setflags(write=False)
+# unary ops
+
+reveal_type(-c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit]
+reveal_type(-c8) # E: numpy.complexfloating[numpy.typing._32Bit, numpy.typing._32Bit]
+reveal_type(-f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(-f4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(-i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(-i4) # E: numpy.signedinteger[numpy.typing._32Bit]
+reveal_type(-u8) # E: numpy.unsignedinteger[numpy.typing._64Bit]
+reveal_type(-u4) # E: numpy.unsignedinteger[numpy.typing._32Bit]
+reveal_type(-td) # E: numpy.timedelta64
+reveal_type(-AR) # E: Union[numpy.ndarray*, numpy.generic]
+
+reveal_type(+c16) # E: numpy.complexfloating[numpy.typing._64Bit, numpy.typing._64Bit]
+reveal_type(+c8) # E: numpy.complexfloating[numpy.typing._32Bit, numpy.typing._32Bit]
+reveal_type(+f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(+f4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(+i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(+i4) # E: numpy.signedinteger[numpy.typing._32Bit]
+reveal_type(+u8) # E: numpy.unsignedinteger[numpy.typing._64Bit]
+reveal_type(+u4) # E: numpy.unsignedinteger[numpy.typing._32Bit]
+reveal_type(+td) # E: numpy.timedelta64
+reveal_type(+AR) # E: Union[numpy.ndarray*, numpy.generic]
+
+reveal_type(abs(c16)) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(abs(c8)) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(abs(f8)) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(abs(f4)) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(abs(i8)) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(abs(i4)) # E: numpy.signedinteger[numpy.typing._32Bit]
+reveal_type(abs(u8)) # E: numpy.unsignedinteger[numpy.typing._64Bit]
+reveal_type(abs(u4)) # E: numpy.unsignedinteger[numpy.typing._32Bit]
+reveal_type(abs(td)) # E: numpy.timedelta64
+reveal_type(abs(b_)) # E: numpy.bool_
+reveal_type(abs(AR)) # E: Union[numpy.ndarray*, numpy.generic]
+
# Time structures
reveal_type(dt + td) # E: numpy.datetime64
@@ -47,7 +83,6 @@ reveal_type(td / f4) # E: numpy.timedelta64
reveal_type(td / f8) # E: numpy.timedelta64
reveal_type(td / td) # E: numpy.floating[numpy.typing._64Bit]
reveal_type(td // td) # E: numpy.signedinteger[numpy.typing._64Bit]
-reveal_type(td % td) # E: numpy.timedelta64
# boolean
diff --git a/numpy/typing/tests/data/reveal/mod.py b/numpy/typing/tests/data/reveal/mod.py
new file mode 100644
index 000000000..9cd2c2fcf
--- /dev/null
+++ b/numpy/typing/tests/data/reveal/mod.py
@@ -0,0 +1,149 @@
+import numpy as np
+
+f8 = np.float64()
+i8 = np.int64()
+u8 = np.uint64()
+
+f4 = np.float32()
+i4 = np.int32()
+u4 = np.uint32()
+
+td = np.timedelta64(0, "D")
+b_ = np.bool_()
+
+b = bool()
+f = float()
+i = int()
+
+AR = np.array([1], dtype=np.bool_)
+AR.setflags(write=False)
+
+AR2 = np.array([1], dtype=np.timedelta64)
+AR2.setflags(write=False)
+
+# Time structures
+
+reveal_type(td % td) # E: numpy.timedelta64
+reveal_type(AR2 % td) # E: Union[numpy.ndarray, numpy.generic]
+reveal_type(td % AR2) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(td, td)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.timedelta64]
+reveal_type(divmod(AR2, td)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+reveal_type(divmod(td, AR2)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+# Bool
+
+reveal_type(b_ % b) # E: numpy.signedinteger[numpy.typing._8Bit]
+reveal_type(b_ % i) # E: numpy.signedinteger[Any]
+reveal_type(b_ % f) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(b_ % b_) # E: numpy.signedinteger[numpy.typing._8Bit]
+reveal_type(b_ % i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(b_ % u8) # E: numpy.unsignedinteger[numpy.typing._64Bit]
+reveal_type(b_ % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(b_ % AR) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(b_, b)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]]
+reveal_type(divmod(b_, i)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]]
+reveal_type(divmod(b_, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(b_, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]]
+reveal_type(divmod(b_, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(b_, u8)) # E: Tuple[numpy.unsignedinteger[numpy.typing._64Bit], numpy.unsignedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(b_, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(b_, AR)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+reveal_type(b % b_) # E: numpy.signedinteger[numpy.typing._8Bit]
+reveal_type(i % b_) # E: numpy.signedinteger[Any]
+reveal_type(f % b_) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(b_ % b_) # E: numpy.signedinteger[numpy.typing._8Bit]
+reveal_type(i8 % b_) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(u8 % b_) # E: numpy.unsignedinteger[numpy.typing._64Bit]
+reveal_type(f8 % b_) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(AR % b_) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(b, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]]
+reveal_type(divmod(i, b_)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]]
+reveal_type(divmod(f, b_)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(b_, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._8Bit], numpy.signedinteger[numpy.typing._8Bit]]
+reveal_type(divmod(i8, b_)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(u8, b_)) # E: Tuple[numpy.unsignedinteger[numpy.typing._64Bit], numpy.unsignedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(f8, b_)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(AR, b_)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+# int
+
+reveal_type(i8 % b) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(i8 % i) # E: numpy.signedinteger[Any]
+reveal_type(i8 % f) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i8 % i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(i8 % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i4 % i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(i4 % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i4 % i4) # E: numpy.signedinteger[numpy.typing._32Bit]
+reveal_type(i4 % f4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(i8 % AR) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(i8, b)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(i8, i)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]]
+reveal_type(divmod(i8, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i8, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(i8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i8, i4)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(i8, f4)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i4, i4)) # E: Tuple[numpy.signedinteger[numpy.typing._32Bit], numpy.signedinteger[numpy.typing._32Bit]]
+reveal_type(divmod(i4, f4)) # E: Tuple[numpy.floating[numpy.typing._32Bit], numpy.floating[numpy.typing._32Bit]]
+reveal_type(divmod(i8, AR)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+reveal_type(b % i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(i % i8) # E: numpy.signedinteger[Any]
+reveal_type(f % i8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i8 % i8) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(f8 % i8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i8 % i4) # E: numpy.signedinteger[numpy.typing._64Bit]
+reveal_type(f8 % i4) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i4 % i4) # E: numpy.signedinteger[numpy.typing._32Bit]
+reveal_type(f4 % i4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(AR % i8) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(b, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(i, i8)) # E: Tuple[numpy.signedinteger[Any], numpy.signedinteger[Any]]
+reveal_type(divmod(f, i8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i8, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(f8, i8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i4, i8)) # E: Tuple[numpy.signedinteger[numpy.typing._64Bit], numpy.signedinteger[numpy.typing._64Bit]]
+reveal_type(divmod(f4, i8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i4, i4)) # E: Tuple[numpy.signedinteger[numpy.typing._32Bit], numpy.signedinteger[numpy.typing._32Bit]]
+reveal_type(divmod(f4, i4)) # E: Tuple[numpy.floating[numpy.typing._32Bit], numpy.floating[numpy.typing._32Bit]]
+reveal_type(divmod(AR, i8)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+# float
+
+reveal_type(f8 % b) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(f8 % i) # E: numpy.floating[Any]
+reveal_type(f8 % f) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i8 % f4) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(f4 % f4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(f8 % AR) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(f8, b)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f8, i)) # E: Tuple[numpy.floating[Any], numpy.floating[Any]]
+reveal_type(divmod(f8, f)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f8, f4)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f4, f4)) # E: Tuple[numpy.floating[numpy.typing._32Bit], numpy.floating[numpy.typing._32Bit]]
+reveal_type(divmod(f8, AR)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
+
+reveal_type(b % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(i % f8) # E: numpy.floating[Any]
+reveal_type(f % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(f8 % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(f8 % f8) # E: numpy.floating[numpy.typing._64Bit]
+reveal_type(f4 % f4) # E: numpy.floating[numpy.typing._32Bit]
+reveal_type(AR % f8) # E: Union[numpy.ndarray, numpy.generic]
+
+reveal_type(divmod(b, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(i, f8)) # E: Tuple[numpy.floating[Any], numpy.floating[Any]]
+reveal_type(divmod(f, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f8, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f4, f8)) # E: Tuple[numpy.floating[numpy.typing._64Bit], numpy.floating[numpy.typing._64Bit]]
+reveal_type(divmod(f4, f4)) # E: Tuple[numpy.floating[numpy.typing._32Bit], numpy.floating[numpy.typing._32Bit]]
+reveal_type(divmod(AR, f8)) # E: Union[Tuple[numpy.ndarray, numpy.ndarray], Tuple[numpy.generic, numpy.generic]]
diff --git a/numpy/typing/tests/test_typing.py b/numpy/typing/tests/test_typing.py
index 84b0ab3cc..90de4fd6d 100644
--- a/numpy/typing/tests/test_typing.py
+++ b/numpy/typing/tests/test_typing.py
@@ -156,7 +156,7 @@ def test_reveal(path):
assert "Revealed type is" in error_line
marker = lines[lineno].split("# E:")[-1].strip()
- _test_reveal(path, marker, error_line, lineno)
+ _test_reveal(path, marker, error_line, 1 + lineno)
_REVEAL_MSG = """Reveal mismatch at line {}