From 27c2703f35a336dd4a2cee8bfd85980793ab6327 Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 19:57:59 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20ufunc=20annotations?= =?UTF-8?q?=20for=20logical-{not,and,or,xor}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/numpy-stubs/__init__.pyi | 8 ++++---- test/static/accept/ufuncs.pyi | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/numpy-stubs/__init__.pyi b/src/numpy-stubs/__init__.pyi index 9a335e14..5a4e8eb5 100644 --- a/src/numpy-stubs/__init__.pyi +++ b/src/numpy-stubs/__init__.pyi @@ -7102,7 +7102,7 @@ log: Final[_ufunc_1_1] = ... log2: Final[_ufunc_1_1] = ... log10: Final[_ufunc_1_1] = ... log1p: Final[_ufunc_1_1] = ... -logical_not: Final[_ufunc_1_1] = ... +logical_not: Final[_ufunc_1_1[_Call11Bool]] = ... negative: Final[_ufunc_1_1] = ... positive: Final[_ufunc_1_1] = ... rad2deg: Final[_ufunc_1_1] = ... @@ -7159,9 +7159,9 @@ ldexp: Final[_ufunc_2_1] = ... left_shift: Final[_ufunc_2_1] = ... logaddexp: Final[_ufunc_2_1] = ... logaddexp2: Final[_ufunc_2_1] = ... -logical_and: Final[_ufunc_2_1] = ... -logical_or: Final[_ufunc_2_1] = ... -logical_xor: Final[_ufunc_2_1] = ... +logical_and: Final[_ufunc_2_1[_Call21Bool]] = ... +logical_or: Final[_ufunc_2_1[_Call21Bool]] = ... +logical_xor: Final[_ufunc_2_1[_Call21Bool]] = ... maximum: Final[_ufunc_2_1] = ... minimum: Final[_ufunc_2_1] = ... mod: Final[_ufunc_2_1] = ... diff --git a/test/static/accept/ufuncs.pyi b/test/static/accept/ufuncs.pyi index 2f17a3f6..07f2290d 100644 --- a/test/static/accept/ufuncs.pyi +++ b/test/static/accept/ufuncs.pyi @@ -62,3 +62,25 @@ assert_type(np.isinf(AR_f8, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.isfinite(f8), np.bool_) assert_type(np.isfinite(AR_f8), npt.NDArray[np.bool_]) assert_type(np.isfinite(AR_f8, out=AR_bool), npt.NDArray[np.bool_]) + +assert_type(np.logical_not(True), np.bool_) +assert_type(np.logical_not(AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_not(AR_bool, out=AR_bool), npt.NDArray[np.bool_]) + +assert_type(np.logical_and(True, True), np.bool_) +assert_type(np.logical_and(AR_bool, AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_and(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_and(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_and(AR_bool, AR_i8), npt.NDArray[np.bool_]) + +assert_type(np.logical_or(True, True), np.bool_) +assert_type(np.logical_or(AR_bool, AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_or(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_or(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_or(AR_bool, AR_i8), npt.NDArray[np.bool_]) + +assert_type(np.logical_xor(True, True), np.bool_) +assert_type(np.logical_xor(AR_bool, AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_xor(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_xor(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_xor(AR_bool, AR_i8), npt.NDArray[np.bool_]) From dbe231652a8bd4484170baa929a41a0b8e8cfb0c Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 20:08:38 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20ufunc=20ann?= =?UTF-8?q?otations=20for=20logical=20operations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/numpy-stubs/__init__.pyi | 21 +++- src/numpy-stubs/_typing/_ufunc.pyi | 182 ++++++++++++++++++++++++++++- test/static/accept/ufuncs.pyi | 4 + test/static/reject/ufuncs.pyi | 6 + 4 files changed, 204 insertions(+), 9 deletions(-) diff --git a/src/numpy-stubs/__init__.pyi b/src/numpy-stubs/__init__.pyi index 5a4e8eb5..c86affdd 100644 --- a/src/numpy-stubs/__init__.pyi +++ b/src/numpy-stubs/__init__.pyi @@ -307,7 +307,18 @@ from ._typing._char_codes import ( _UnsignedIntegerCodes, _VoidCodes, ) -from ._typing._ufunc import _Call11Bool, _Call11Isnat, _Call21Bool, _gufunc_2_1, _ufunc_1_1, _ufunc_1_2, _ufunc_2_1, _ufunc_2_2 +from ._typing._ufunc import ( + _Call11Bool, + _Call11Isnat, + _Call11LogicalNot, + _Call21Bool, + _Call21Logical, + _gufunc_2_1, + _ufunc_1_1, + _ufunc_1_2, + _ufunc_2_1, + _ufunc_2_2, +) from .lib import scimath as emath from .lib._arraypad_impl import pad from .lib._arraysetops_impl import ( @@ -7102,7 +7113,7 @@ log: Final[_ufunc_1_1] = ... log2: Final[_ufunc_1_1] = ... log10: Final[_ufunc_1_1] = ... log1p: Final[_ufunc_1_1] = ... -logical_not: Final[_ufunc_1_1[_Call11Bool]] = ... +logical_not: Final[_ufunc_1_1[_Call11LogicalNot]] = ... negative: Final[_ufunc_1_1] = ... positive: Final[_ufunc_1_1] = ... rad2deg: Final[_ufunc_1_1] = ... @@ -7159,9 +7170,9 @@ ldexp: Final[_ufunc_2_1] = ... left_shift: Final[_ufunc_2_1] = ... logaddexp: Final[_ufunc_2_1] = ... logaddexp2: Final[_ufunc_2_1] = ... -logical_and: Final[_ufunc_2_1[_Call21Bool]] = ... -logical_or: Final[_ufunc_2_1[_Call21Bool]] = ... -logical_xor: Final[_ufunc_2_1[_Call21Bool]] = ... +logical_and: Final[_ufunc_2_1[_Call21Logical]] = ... +logical_or: Final[_ufunc_2_1[_Call21Logical]] = ... +logical_xor: Final[_ufunc_2_1[_Call21Logical]] = ... maximum: Final[_ufunc_2_1] = ... minimum: Final[_ufunc_2_1] = ... mod: Final[_ufunc_2_1] = ... diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index a876c744..08cf48b4 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -16,9 +16,9 @@ import numpy as np from numpy import _CastingKind, _OrderKACF # noqa: ICN003 from numpy._typing import _DTypeLikeBool, _NestedSequence -from ._array_like import ArrayLike, NDArray, _ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co -from ._dtype_like import DTypeLike, _DTypeLike -from ._scalars import _ScalarLike_co +from ._array_like import ArrayLike, NDArray, _ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co, _ArrayLikeNumber_co +from ._dtype_like import DTypeLike, _DTypeLike, _DTypeLikeObject +from ._scalars import _NumberLike_co, _ScalarLike_co from ._shape import _ShapeLike ### @@ -201,7 +201,7 @@ class _Call11Bool(Protocol): dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs2], ) -> _ArrayT: ... - @overload # (array) -> Array[bool] | bool + @overload # (array) -> Array[bool] def __call__( self, x: _AnyArray, @@ -255,6 +255,73 @@ class _Call11Isnat(Protocol): **kwds: Unpack[_Kwargs2], ) -> NDArray[np.bool]: ... +@type_check_only +class _Call11LogicalNot(Protocol): + @overload + def __call__( # (scalar, dtype: np.object_) -> np.object_ + self, + x: _NumberLike_co, + /, + dtype: _DTypeLikeObject, + out: None = None, + **kwargs: Unpack[_Kwargs2], + ) -> np.object_: ... + @overload + def __call__( # (scalar) -> bool + self, + x: _NumberLike_co, + /, + out: None = None, + dtype: DTypeLike | None = None, + **kwargs: Unpack[_Kwargs2], + ) -> np.bool: ... + @overload + def __call__( # (array-like, dtype: np.object_) -> np.object_ + self, + x: _ArrayLikeNumber_co, + /, + dtype: _DTypeLikeObject, + out: None = None, + **kwargs: Unpack[_Kwargs2], + ) -> np.object_: ... + @overload + def __call__( # (array-like, out: T) -> T + self, + x: _ArrayLikeNumber_co, + /, + out: _ArrayT | tuple[_ArrayT], + dtype: DTypeLike | None = None, + **kwargs: Unpack[_Kwargs2], + ) -> _ArrayT: ... + @overload # (array) -> Array[bool] + def __call__( + self, + x: _AnyArray, + /, + out: _Out1[_AnyArray] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs2], + ) -> NDArray[np.bool]: ... + @overload + def __call__( # (array-like) -> Array[bool] | bool + self, + x: _ArrayLikeNumber_co, + /, + out: None = None, + dtype: DTypeLike | None = None, + **kwargs: Unpack[_Kwargs2], + ) -> NDArray[np.bool] | np.bool: ... + @overload + def __call__( # (?) -> ? + self, + x: _CanArrayUFunc, + /, + out: _Out1[_AnyArray] | None = None, + dtype: DTypeLike | None = None, + **kwargs: Unpack[_Kwargs2], + ) -> NDArray[np.bool] | np.bool: ... + @type_check_only class _Call12(Protocol): @overload @@ -418,6 +485,113 @@ class _Call21Bool(Protocol): **kwds: Unpack[_Kwargs3], ) -> np.bool | NDArray[np.bool]: ... +@type_check_only +class _Call21Logical(Protocol): + @overload # (scalar, scalar, dtype: np.object_) -> np.object_ + def __call__( + self, + x1: _NumberLike_co, + x2: _NumberLike_co, + /, + dtype: _DTypeLikeObject, + out: None = None, + **kwds: Unpack[_Kwargs3], + ) -> np.object_: ... + @overload # (scalar, scalar) -> bool + def __call__( + self, + x1: _NumberLike_co, + x2: _NumberLike_co, + /, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> np.bool: ... + @overload # (array-like, array, dtype: np.object_) -> np.object_ + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: _AnyArray, + /, + dtype: _DTypeLikeObject, + out: None = None, + **kwds: Unpack[_Kwargs3], + ) -> np.object_: ... + @overload # (array-like, array, dtype: dtype[T]) -> Array[T] + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: _AnyArray, + /, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool]: ... + @overload # (array, array-like, dtype: np.object_) -> np.object_ + def __call__( + self, + x1: _AnyArray, + x2: _ArrayLikeNumber_co, + /, + dtype: _DTypeLikeObject, + out: None = None, + **kwds: Unpack[_Kwargs3], + ) -> np.object_: ... + @overload # (array, array-like, dtype: dtype[T]) -> Array[T] + def __call__( + self, + x1: _AnyArray, + x2: _ArrayLikeNumber_co, + /, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool]: ... + @overload # (array-like, array) -> Array[?] + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: _AnyArray, + /, + out: _Out1[_AnyArray] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool]: ... + @overload # (array, array-like) -> Array[?] + def __call__( + self, + x1: _AnyArray, + x2: _ArrayLikeNumber_co, + /, + out: _Out1[_AnyArray] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool]: ... + @overload # (array-like, array-like, out: T) -> T + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: ArrayLike, + /, + out: _ArrayT | tuple[_ArrayT], + *, + dtype: None = None, + **kwds: Unpack[_Kwargs3], + ) -> _ArrayT: ... + @overload # (array-like, array-like) -> Array[?] | ? + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: _ArrayLikeNumber_co, + /, + out: _Out1[_AnyArray] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool] | np.bool: ... + @type_check_only class _Call21(Protocol): @overload # (scalar, scalar, dtype: type[T]) -> T diff --git a/test/static/accept/ufuncs.pyi b/test/static/accept/ufuncs.pyi index 07f2290d..5e96ea3d 100644 --- a/test/static/accept/ufuncs.pyi +++ b/test/static/accept/ufuncs.pyi @@ -66,21 +66,25 @@ assert_type(np.isfinite(AR_f8, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_not(True), np.bool_) assert_type(np.logical_not(AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_not(AR_bool, out=AR_bool), npt.NDArray[np.bool_]) +assert_type(np.logical_not(AR_bool, dtype=np.object_), np.object_) assert_type(np.logical_and(True, True), np.bool_) assert_type(np.logical_and(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_bool, AR_i8), npt.NDArray[np.bool_]) +assert_type(np.logical_and(AR_bool, AR_bool, dtype=np.object_), np.object_) assert_type(np.logical_or(True, True), np.bool_) assert_type(np.logical_or(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_bool, AR_i8), npt.NDArray[np.bool_]) +assert_type(np.logical_or(AR_bool, AR_bool, dtype=np.object_), np.object_) assert_type(np.logical_xor(True, True), np.bool_) assert_type(np.logical_xor(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_bool, AR_i8), npt.NDArray[np.bool_]) +assert_type(np.logical_xor(AR_bool, AR_bool, dtype=np.object_), np.object_) diff --git a/test/static/reject/ufuncs.pyi b/test/static/reject/ufuncs.pyi index 67db31c2..15f18bb0 100644 --- a/test/static/reject/ufuncs.pyi +++ b/test/static/reject/ufuncs.pyi @@ -3,6 +3,7 @@ import numpy.typing as npt i8: np.int64 AR_f8: npt.NDArray[np.float64] +dt64: np.datetime64 np.sin.nin + "foo" # type: ignore[operator] # pyright: ignore[reportOperatorIssue] @@ -47,3 +48,8 @@ np.isnat(i8, dtype=np.int64) # type: ignore[call-overload] # pyright: ignore[r np.isnat(i8) # type: ignore[call-overload] # pyright: ignore[reportCallIssue,reportArgumentType] np.isinf(i8, dtype=np.int64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] np.isfinite(i8, dtype=np.int64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] + +np.logical_not(dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] +np.logical_and(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] +np.logical_or(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] +np.logical_xor(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] From 6b11b7a75032e88584b4050dd1a76ee7715b1d88 Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 20:19:01 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20annotation?= =?UTF-8?q?=20for=20`logical`=20related=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Joren Hammudoglu --- src/numpy-stubs/__init__.pyi | 4 +- src/numpy-stubs/_typing/_ufunc.pyi | 106 +++++++++++++++-------------- test/static/accept/ufuncs.pyi | 8 +-- 3 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/numpy-stubs/__init__.pyi b/src/numpy-stubs/__init__.pyi index c86affdd..055c6044 100644 --- a/src/numpy-stubs/__init__.pyi +++ b/src/numpy-stubs/__init__.pyi @@ -310,7 +310,7 @@ from ._typing._char_codes import ( from ._typing._ufunc import ( _Call11Bool, _Call11Isnat, - _Call11LogicalNot, + _Call11Logical, _Call21Bool, _Call21Logical, _gufunc_2_1, @@ -7113,7 +7113,7 @@ log: Final[_ufunc_1_1] = ... log2: Final[_ufunc_1_1] = ... log10: Final[_ufunc_1_1] = ... log1p: Final[_ufunc_1_1] = ... -logical_not: Final[_ufunc_1_1[_Call11LogicalNot]] = ... +logical_not: Final[_ufunc_1_1[_Call11Logical]] = ... negative: Final[_ufunc_1_1] = ... positive: Final[_ufunc_1_1] = ... rad2deg: Final[_ufunc_1_1] = ... diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index 08cf48b4..f3a29647 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -16,8 +16,16 @@ import numpy as np from numpy import _CastingKind, _OrderKACF # noqa: ICN003 from numpy._typing import _DTypeLikeBool, _NestedSequence -from ._array_like import ArrayLike, NDArray, _ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co, _ArrayLikeNumber_co -from ._dtype_like import DTypeLike, _DTypeLike, _DTypeLikeObject +from ._array_like import ( + ArrayLike, + NDArray, + _ArrayLike, + _ArrayLikeBool_co, + _ArrayLikeInt_co, + _ArrayLikeNumber_co, + _ArrayLikeObject_co, +) +from ._dtype_like import DTypeLike, _DTypeLike from ._scalars import _NumberLike_co, _ScalarLike_co from ._shape import _ShapeLike @@ -256,47 +264,47 @@ class _Call11Isnat(Protocol): ) -> NDArray[np.bool]: ... @type_check_only -class _Call11LogicalNot(Protocol): +class _Call11Logical(Protocol): @overload - def __call__( # (scalar, dtype: np.object_) -> np.object_ + def __call__( # (scalar, dtype: np.object_) -> bool self, - x: _NumberLike_co, + x: _ScalarLike_co, /, - dtype: _DTypeLikeObject, + dtype: _DTypeLike[np.object_], out: None = None, **kwargs: Unpack[_Kwargs2], - ) -> np.object_: ... + ) -> bool: ... @overload - def __call__( # (scalar) -> bool + def __call__( # (scalar) -> np.bool self, x: _NumberLike_co, /, out: None = None, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwargs: Unpack[_Kwargs2], ) -> np.bool: ... @overload def __call__( # (array-like, dtype: np.object_) -> np.object_ self, - x: _ArrayLikeNumber_co, + x: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, - dtype: _DTypeLikeObject, + dtype: _DTypeLike[np.object_], out: None = None, **kwargs: Unpack[_Kwargs2], - ) -> np.object_: ... + ) -> NDArray[np.object_] | bool: ... @overload def __call__( # (array-like, out: T) -> T self, x: _ArrayLikeNumber_co, /, - out: _ArrayT | tuple[_ArrayT], + out: _Out1[_ArrayT], dtype: DTypeLike | None = None, **kwargs: Unpack[_Kwargs2], ) -> _ArrayT: ... @overload # (array) -> Array[bool] def __call__( self, - x: _AnyArray, + x: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number], /, out: _Out1[_AnyArray] | None = None, *, @@ -309,7 +317,7 @@ class _Call11LogicalNot(Protocol): x: _ArrayLikeNumber_co, /, out: None = None, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwargs: Unpack[_Kwargs2], ) -> NDArray[np.bool] | np.bool: ... @overload @@ -320,8 +328,7 @@ class _Call11LogicalNot(Protocol): out: _Out1[_AnyArray] | None = None, dtype: DTypeLike | None = None, **kwargs: Unpack[_Kwargs2], - ) -> NDArray[np.bool] | np.bool: ... - + ) -> Any: ... @type_check_only class _Call12(Protocol): @overload @@ -490,13 +497,13 @@ class _Call21Logical(Protocol): @overload # (scalar, scalar, dtype: np.object_) -> np.object_ def __call__( self, - x1: _NumberLike_co, - x2: _NumberLike_co, + x1: _ScalarLike_co, + x2: _ScalarLike_co, /, - dtype: _DTypeLikeObject, + dtype: _DTypeLike[np.object_], out: None = None, **kwds: Unpack[_Kwargs3], - ) -> np.object_: ... + ) -> bool: ... @overload # (scalar, scalar) -> bool def __call__( self, @@ -504,56 +511,67 @@ class _Call21Logical(Protocol): x2: _NumberLike_co, /, out: None = None, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> np.bool: ... - @overload # (array-like, array, dtype: np.object_) -> np.object_ + @overload # (array-like, array, dtype: object_) -> Array[object_] def __call__( self, - x1: _ArrayLikeNumber_co, + x1: _ArrayLikeNumber_co | _ArrayLikeObject_co, x2: _AnyArray, /, - dtype: _DTypeLikeObject, + dtype: _DTypeLike[np.object_], out: None = None, **kwds: Unpack[_Kwargs3], - ) -> np.object_: ... + ) -> NDArray[np.object_]: ... @overload # (array-like, array, dtype: dtype[T]) -> Array[T] def __call__( self, x1: _ArrayLikeNumber_co, - x2: _AnyArray, + x2: NDArray[np.bool | np.number], /, out: None = None, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... - @overload # (array, array-like, dtype: np.object_) -> np.object_ + @overload # (array, array-like, dtype: object_) -> Array[object_] def __call__( self, x1: _AnyArray, - x2: _ArrayLikeNumber_co, + x2: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, - dtype: _DTypeLikeObject, + dtype: _DTypeLike[np.object_], out: None = None, **kwds: Unpack[_Kwargs3], - ) -> np.object_: ... + ) -> NDArray[np.object_]: ... @overload # (array, array-like, dtype: dtype[T]) -> Array[T] def __call__( self, - x1: _AnyArray, + x1: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number], x2: _ArrayLikeNumber_co, /, out: None = None, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... + @overload # (array-like, array-like, out: T) -> T + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: _ArrayLikeNumber_co, + /, + out: _Out1[_ArrayT], + *, + dtype: None = None, + **kwds: Unpack[_Kwargs3], + ) -> _ArrayT: ... @overload # (array-like, array) -> Array[?] def __call__( self, x1: _ArrayLikeNumber_co, x2: _AnyArray, /, - out: _Out1[_AnyArray] | None = None, + out: _Out1[NDArray[np.bool]] | None = None, *, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], @@ -564,34 +582,22 @@ class _Call21Logical(Protocol): x1: _AnyArray, x2: _ArrayLikeNumber_co, /, - out: _Out1[_AnyArray] | None = None, + out: _Out1[NDArray[np.bool]] | None = None, *, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... - @overload # (array-like, array-like, out: T) -> T - def __call__( - self, - x1: _ArrayLikeNumber_co, - x2: ArrayLike, - /, - out: _ArrayT | tuple[_ArrayT], - *, - dtype: None = None, - **kwds: Unpack[_Kwargs3], - ) -> _ArrayT: ... @overload # (array-like, array-like) -> Array[?] | ? def __call__( self, - x1: _ArrayLikeNumber_co, - x2: _ArrayLikeNumber_co, + x1: _ArrayLikeNumber_co | _ArrayLikeObject_co, + x2: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, out: _Out1[_AnyArray] | None = None, *, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], - ) -> NDArray[np.bool] | np.bool: ... - + ) -> Any: ... @type_check_only class _Call21(Protocol): @overload # (scalar, scalar, dtype: type[T]) -> T diff --git a/test/static/accept/ufuncs.pyi b/test/static/accept/ufuncs.pyi index 5e96ea3d..08bd3a3b 100644 --- a/test/static/accept/ufuncs.pyi +++ b/test/static/accept/ufuncs.pyi @@ -66,25 +66,25 @@ assert_type(np.isfinite(AR_f8, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_not(True), np.bool_) assert_type(np.logical_not(AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_not(AR_bool, out=AR_bool), npt.NDArray[np.bool_]) -assert_type(np.logical_not(AR_bool, dtype=np.object_), np.object_) +assert_type(np.logical_not(AR_bool, dtype=np.object_), npt.NDArray[np.object_] | bool) assert_type(np.logical_and(True, True), np.bool_) assert_type(np.logical_and(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_and(AR_bool, AR_i8), npt.NDArray[np.bool_]) -assert_type(np.logical_and(AR_bool, AR_bool, dtype=np.object_), np.object_) +assert_type(np.logical_and(AR_bool, AR_bool, dtype=np.object_), npt.NDArray[np.object_]) assert_type(np.logical_or(True, True), np.bool_) assert_type(np.logical_or(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_or(AR_bool, AR_i8), npt.NDArray[np.bool_]) -assert_type(np.logical_or(AR_bool, AR_bool, dtype=np.object_), np.object_) +assert_type(np.logical_or(AR_bool, AR_bool, dtype=np.object_), npt.NDArray[np.object_]) assert_type(np.logical_xor(True, True), np.bool_) assert_type(np.logical_xor(AR_bool, AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_bool, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_i8, AR_bool, out=AR_bool), npt.NDArray[np.bool_]) assert_type(np.logical_xor(AR_bool, AR_i8), npt.NDArray[np.bool_]) -assert_type(np.logical_xor(AR_bool, AR_bool, dtype=np.object_), np.object_) +assert_type(np.logical_xor(AR_bool, AR_bool, dtype=np.object_), npt.NDArray[np.object_]) From ecb6397949b3187de9daa3916dad51c81d809006 Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 20:21:29 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20ufunc=20ann?= =?UTF-8?q?otations=20for=20logical=20operations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/static/reject/ufuncs.pyi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/static/reject/ufuncs.pyi b/test/static/reject/ufuncs.pyi index 15f18bb0..c2d12a7a 100644 --- a/test/static/reject/ufuncs.pyi +++ b/test/static/reject/ufuncs.pyi @@ -49,7 +49,14 @@ np.isnat(i8) # type: ignore[call-overload] # pyright: ignore[reportCallIssue,r np.isinf(i8, dtype=np.int64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] np.isfinite(i8, dtype=np.int64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] -np.logical_not(dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] +np.logical_not(i8, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] +np.logical_not(dt64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] + +np.logical_and(dt64, dt64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] np.logical_and(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] + +np.logical_or(dt64, dt64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] np.logical_or(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] + +np.logical_xor(dt64, dt64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] np.logical_xor(dt64, dt64, dtype=np.datetime64) # type: ignore[arg-type] # pyright: ignore[reportArgumentType, reportCallIssue] From 60efc77369b952c2385d4ca4d589d0a52fa1ebb9 Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 20:43:55 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20fix=20keyword=20ann?= =?UTF-8?q?otation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Joren Hammudoglu --- src/numpy-stubs/_typing/_ufunc.pyi | 46 +++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index f3a29647..f1c23db8 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -271,6 +271,7 @@ class _Call11Logical(Protocol): x: _ScalarLike_co, /, dtype: _DTypeLike[np.object_], + *, out: None = None, **kwargs: Unpack[_Kwargs2], ) -> bool: ... @@ -280,6 +281,7 @@ class _Call11Logical(Protocol): x: _NumberLike_co, /, out: None = None, + *, dtype: _DTypeLikeBool | None = None, **kwargs: Unpack[_Kwargs2], ) -> np.bool: ... @@ -289,15 +291,17 @@ class _Call11Logical(Protocol): x: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, dtype: _DTypeLike[np.object_], + *, out: None = None, **kwargs: Unpack[_Kwargs2], ) -> NDArray[np.object_] | bool: ... @overload def __call__( # (array-like, out: T) -> T self, - x: _ArrayLikeNumber_co, + x: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, out: _Out1[_ArrayT], + *, dtype: DTypeLike | None = None, **kwargs: Unpack[_Kwargs2], ) -> _ArrayT: ... @@ -306,7 +310,7 @@ class _Call11Logical(Protocol): self, x: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number], /, - out: _Out1[_AnyArray] | None = None, + out: _Out1[NDArray[np.bool | np.number]] | None = None, *, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs2], @@ -317,6 +321,7 @@ class _Call11Logical(Protocol): x: _ArrayLikeNumber_co, /, out: None = None, + *, dtype: _DTypeLikeBool | None = None, **kwargs: Unpack[_Kwargs2], ) -> NDArray[np.bool] | np.bool: ... @@ -326,9 +331,11 @@ class _Call11Logical(Protocol): x: _CanArrayUFunc, /, out: _Out1[_AnyArray] | None = None, + *, dtype: DTypeLike | None = None, **kwargs: Unpack[_Kwargs2], ) -> Any: ... + @type_check_only class _Call12(Protocol): @overload @@ -501,6 +508,7 @@ class _Call21Logical(Protocol): x2: _ScalarLike_co, /, dtype: _DTypeLike[np.object_], + *, out: None = None, **kwds: Unpack[_Kwargs3], ) -> bool: ... @@ -511,6 +519,7 @@ class _Call21Logical(Protocol): x2: _NumberLike_co, /, out: None = None, + *, dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> np.bool: ... @@ -521,19 +530,10 @@ class _Call21Logical(Protocol): x2: _AnyArray, /, dtype: _DTypeLike[np.object_], + *, out: None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.object_]: ... - @overload # (array-like, array, dtype: dtype[T]) -> Array[T] - def __call__( - self, - x1: _ArrayLikeNumber_co, - x2: NDArray[np.bool | np.number], - /, - out: None = None, - dtype: _DTypeLikeBool | None = None, - **kwds: Unpack[_Kwargs3], - ) -> NDArray[np.bool]: ... @overload # (array, array-like, dtype: object_) -> Array[object_] def __call__( self, @@ -541,9 +541,21 @@ class _Call21Logical(Protocol): x2: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, dtype: _DTypeLike[np.object_], + *, out: None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.object_]: ... + @overload # (array-like, array, dtype: dtype[T]) -> Array[T] + def __call__( + self, + x1: _ArrayLikeNumber_co, + x2: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number], + /, + out: None = None, + *, + dtype: _DTypeLikeBool | None = None, + **kwds: Unpack[_Kwargs3], + ) -> NDArray[np.bool]: ... @overload # (array, array-like, dtype: dtype[T]) -> Array[T] def __call__( self, @@ -551,14 +563,15 @@ class _Call21Logical(Protocol): x2: _ArrayLikeNumber_co, /, out: None = None, + *, dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... @overload # (array-like, array-like, out: T) -> T def __call__( self, - x1: _ArrayLikeNumber_co, - x2: _ArrayLikeNumber_co, + x1: _ArrayLikeNumber_co | _ArrayLikeObject_co, + x2: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, out: _Out1[_ArrayT], *, @@ -569,7 +582,7 @@ class _Call21Logical(Protocol): def __call__( self, x1: _ArrayLikeNumber_co, - x2: _AnyArray, + x2: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number | complex], /, out: _Out1[NDArray[np.bool]] | None = None, *, @@ -579,7 +592,7 @@ class _Call21Logical(Protocol): @overload # (array, array-like) -> Array[?] def __call__( self, - x1: _AnyArray, + x1: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number | complex], x2: _ArrayLikeNumber_co, /, out: _Out1[NDArray[np.bool]] | None = None, @@ -598,6 +611,7 @@ class _Call21Logical(Protocol): dtype: DTypeLike | None = None, **kwds: Unpack[_Kwargs3], ) -> Any: ... + @type_check_only class _Call21(Protocol): @overload # (scalar, scalar, dtype: type[T]) -> T From 7c3f496814db7c4050b17ab1df0190c00819647e Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Tue, 18 Mar 2025 21:03:55 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=94=A5=20reorder=20keyword=20para?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/numpy-stubs/_typing/_ufunc.pyi | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index f1c23db8..dea0d67c 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -270,9 +270,9 @@ class _Call11Logical(Protocol): self, x: _ScalarLike_co, /, - dtype: _DTypeLike[np.object_], - *, out: None = None, + *, + dtype: _DTypeLike[np.object_], **kwargs: Unpack[_Kwargs2], ) -> bool: ... @overload @@ -280,9 +280,9 @@ class _Call11Logical(Protocol): self, x: _NumberLike_co, /, - out: None = None, - *, dtype: _DTypeLikeBool | None = None, + *, + out: None = None, **kwargs: Unpack[_Kwargs2], ) -> np.bool: ... @overload @@ -290,9 +290,9 @@ class _Call11Logical(Protocol): self, x: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, - dtype: _DTypeLike[np.object_], - *, out: None = None, + *, + dtype: _DTypeLike[np.object_], **kwargs: Unpack[_Kwargs2], ) -> NDArray[np.object_] | bool: ... @overload @@ -507,9 +507,9 @@ class _Call21Logical(Protocol): x1: _ScalarLike_co, x2: _ScalarLike_co, /, - dtype: _DTypeLike[np.object_], - *, out: None = None, + *, + dtype: _DTypeLike[np.object_], **kwds: Unpack[_Kwargs3], ) -> bool: ... @overload # (scalar, scalar) -> bool @@ -529,9 +529,9 @@ class _Call21Logical(Protocol): x1: _ArrayLikeNumber_co | _ArrayLikeObject_co, x2: _AnyArray, /, - dtype: _DTypeLike[np.object_], - *, out: None = None, + *, + dtype: _DTypeLike[np.object_], **kwds: Unpack[_Kwargs3], ) -> NDArray[np.object_]: ... @overload # (array, array-like, dtype: object_) -> Array[object_] @@ -540,9 +540,9 @@ class _Call21Logical(Protocol): x1: _AnyArray, x2: _ArrayLikeNumber_co | _ArrayLikeObject_co, /, - dtype: _DTypeLike[np.object_], - *, out: None = None, + *, + dtype: _DTypeLike[np.object_], **kwds: Unpack[_Kwargs3], ) -> NDArray[np.object_]: ... @overload # (array-like, array, dtype: dtype[T]) -> Array[T] From 72bdb73b9c3d3faad1d0710c62af5edc0f5ff91f Mon Sep 17 00:00:00 2001 From: GUAN MING Date: Wed, 19 Mar 2025 00:48:47 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=90=9B=20update=20logical=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Joren Hammudoglu --- src/numpy-stubs/_typing/_ufunc.pyi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index dea0d67c..7419a1ac 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -280,9 +280,9 @@ class _Call11Logical(Protocol): self, x: _NumberLike_co, /, - dtype: _DTypeLikeBool | None = None, - *, out: None = None, + *, + dtype: _DTypeLikeBool | None = None, **kwargs: Unpack[_Kwargs2], ) -> np.bool: ... @overload @@ -310,9 +310,9 @@ class _Call11Logical(Protocol): self, x: NDArray[np.bool | np.number] | _NestedSequence[np.bool | np.number], /, - out: _Out1[NDArray[np.bool | np.number]] | None = None, + out: _Out1[NDArray[np.bool]] | None = None, *, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs2], ) -> NDArray[np.bool]: ... @overload @@ -586,7 +586,7 @@ class _Call21Logical(Protocol): /, out: _Out1[NDArray[np.bool]] | None = None, *, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... @overload # (array, array-like) -> Array[?] @@ -597,7 +597,7 @@ class _Call21Logical(Protocol): /, out: _Out1[NDArray[np.bool]] | None = None, *, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... @overload # (array-like, array-like) -> Array[?] | ? From 23819618f62f75d170c6b28ad2d3032ea2e259c6 Mon Sep 17 00:00:00 2001 From: "Guan Ming(Wesley) Chiu" <105915352+guan404ming@users.noreply.github.com> Date: Wed, 19 Mar 2025 01:38:55 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=90=9B=20update=20src/numpy-stubs/=5F?= =?UTF-8?q?typing/=5Fufunc.pyi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joren Hammudoglu --- src/numpy-stubs/_typing/_ufunc.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numpy-stubs/_typing/_ufunc.pyi b/src/numpy-stubs/_typing/_ufunc.pyi index 7419a1ac..60a6d5c5 100644 --- a/src/numpy-stubs/_typing/_ufunc.pyi +++ b/src/numpy-stubs/_typing/_ufunc.pyi @@ -564,7 +564,7 @@ class _Call21Logical(Protocol): /, out: None = None, *, - dtype: DTypeLike | None = None, + dtype: _DTypeLikeBool | None = None, **kwds: Unpack[_Kwargs3], ) -> NDArray[np.bool]: ... @overload # (array-like, array-like, out: T) -> T