From 32f5e3a3e7365c7196166529830ac732b16440e9 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Sat, 21 Dec 2024 16:09:51 -0700 Subject: [PATCH 01/21] MAINT: Prepare 2.2.x for further development --- doc/source/release.rst | 1 + doc/source/release/2.2.2-notes.rst | 19 +++++++++++++++++++ pavement.py | 2 +- pyproject.toml | 2 +- 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 doc/source/release/2.2.2-notes.rst diff --git a/doc/source/release.rst b/doc/source/release.rst index 6e9ab8a22cc0..4c83cd3d1ae4 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -5,6 +5,7 @@ Release notes .. toctree:: :maxdepth: 2 + 2.2.2 2.2.1 2.2.0 2.1.3 diff --git a/doc/source/release/2.2.2-notes.rst b/doc/source/release/2.2.2-notes.rst new file mode 100644 index 000000000000..271a16f4c32b --- /dev/null +++ b/doc/source/release/2.2.2-notes.rst @@ -0,0 +1,19 @@ +.. currentmodule:: numpy + +========================== +NumPy 2.2.2 Release Notes +========================== + + +Highlights +========== + +*We'll choose highlights for this release near the end of the release cycle.* + + +.. if release snippets have been incorporated already, uncomment the follow + line (leave the `.. include:: directive) + +.. **Content from release note snippets in doc/release/upcoming_changes:** + +.. include:: notes-towncrier.rst diff --git a/pavement.py b/pavement.py index 2d300fe35a5d..5b2e5578b08b 100644 --- a/pavement.py +++ b/pavement.py @@ -36,7 +36,7 @@ #----------------------------------- # Path to the release notes -RELEASE_NOTES = 'doc/source/release/2.2.1-notes.rst' +RELEASE_NOTES = 'doc/source/release/2.2.2-notes.rst' #------------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 85dd7c088c53..7c6b19d91fe5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ requires = [ [project] name = "numpy" -version = "2.2.1" +version = "2.2.2" # TODO: add `license-files` once PEP 639 is accepted (see meson-python#88) license = {file = "LICENSE.txt"} From 06cb2aa51aa6f38d413e9ff95d6d09b276ecd6d3 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sun, 22 Dec 2024 18:22:59 +0100 Subject: [PATCH 02/21] TYP: fix ``void`` arrays not accepting ``str`` keys in ``__setitem__`` --- numpy/__init__.pyi | 2 ++ numpy/typing/tests/data/pass/ndarray_misc.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 4972f3bf209c..a14234db2735 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -2133,6 +2133,8 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): value: _ConvertibleToDT64 | _NestedSequence[_ConvertibleToDT64], /, ) -> None: ... + @overload # void + def __setitem__(self: NDArray[void], key: str | list[str], value: object, /) -> None: ... @overload # catch-all def __setitem__(self, key: _ToIndices, value: ArrayLike, /) -> None: ... diff --git a/numpy/typing/tests/data/pass/ndarray_misc.py b/numpy/typing/tests/data/pass/ndarray_misc.py index 7b8ebea52a16..fef9d519b78b 100644 --- a/numpy/typing/tests/data/pass/ndarray_misc.py +++ b/numpy/typing/tests/data/pass/ndarray_misc.py @@ -174,3 +174,10 @@ class SubClass(npt.NDArray[np.float64]): ... complex(np.array(1.0, dtype=np.float64)) operator.index(np.array(1, dtype=np.int64)) + +# this fails on numpy 2.2.1 +# https://github.com/scipy/scipy/blob/a755ee77ec47a64849abe42c349936475a6c2f24/scipy/io/arff/tests/test_arffread.py#L41-L44 +A_float = np.array([[1, 5], [2, 4], [np.nan, np.nan]]) +A_void: npt.NDArray[np.void] = np.empty(3, [("yop", float), ("yap", float)]) +A_void["yop"] = A_float[:, 0] +A_void["yap"] = A_float[:, 1] From f367808ee3ba0b88678d69b6db3ff374ec74b6ed Mon Sep 17 00:00:00 2001 From: Joren Hammudoglu Date: Wed, 25 Dec 2024 18:03:59 +0100 Subject: [PATCH 03/21] TYP: fix unnecessarily broad `integer` binop return types (#28065) * TYP: fix unnecessarily broad `integer` binop return types * MAINT: Fix linter complaint. --------- Co-authored-by: Charles Harris --- numpy/_typing/_callable.pyi | 32 ++++++------------- numpy/typing/tests/data/reveal/arithmetic.pyi | 24 +++++++------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/numpy/_typing/_callable.pyi b/numpy/_typing/_callable.pyi index 56e24fb73911..75af1ae8efba 100644 --- a/numpy/_typing/_callable.pyi +++ b/numpy/_typing/_callable.pyi @@ -151,19 +151,15 @@ class _IntTrueDiv(Protocol[_NBit1]): class _UnsignedIntOp(Protocol[_NBit1]): # NOTE: `uint64 + signedinteger -> float64` @overload - def __call__(self, other: bool, /) -> unsignedinteger[_NBit1]: ... + def __call__(self, other: int, /) -> unsignedinteger[_NBit1]: ... @overload - def __call__(self, other: int | signedinteger[Any], /) -> Any: ... + def __call__(self, other: float, /) -> float64: ... @overload - def __call__(self, other: float, /) -> floating[_NBit1] | float64: ... + def __call__(self, other: complex, /) -> complex128: ... @overload - def __call__( - self, other: complex, / - ) -> complexfloating[_NBit1, _NBit1] | complex128: ... + def __call__(self, other: unsignedinteger[_NBit2], /) -> unsignedinteger[_NBit1] | unsignedinteger[_NBit2]: ... @overload - def __call__( - self, other: unsignedinteger[_NBit2], / - ) -> unsignedinteger[_NBit1] | unsignedinteger[_NBit2]: ... + def __call__(self, other: signedinteger, /) -> Any: ... @type_check_only class _UnsignedIntBitOp(Protocol[_NBit1]): @@ -207,19 +203,13 @@ class _UnsignedIntDivMod(Protocol[_NBit1]): @type_check_only class _SignedIntOp(Protocol[_NBit1]): @overload - def __call__(self, other: bool, /) -> signedinteger[_NBit1]: ... - @overload - def __call__(self, other: int, /) -> signedinteger[_NBit1] | int_: ... + def __call__(self, other: int, /) -> signedinteger[_NBit1]: ... @overload - def __call__(self, other: float, /) -> floating[_NBit1] | float64: ... + def __call__(self, other: float, /) -> float64: ... @overload - def __call__( - self, other: complex, / - ) -> complexfloating[_NBit1, _NBit1] | complex128: ... + def __call__(self, other: complex, /) -> complex128: ... @overload - def __call__( - self, other: signedinteger[_NBit2], / - ) -> signedinteger[_NBit1] | signedinteger[_NBit2]: ... + def __call__(self, other: signedinteger[_NBit2], /) -> signedinteger[_NBit1] | signedinteger[_NBit2]: ... @type_check_only class _SignedIntBitOp(Protocol[_NBit1]): @@ -261,9 +251,7 @@ class _SignedIntDivMod(Protocol[_NBit1]): @type_check_only class _FloatOp(Protocol[_NBit1]): @overload - def __call__(self, other: bool, /) -> floating[_NBit1]: ... - @overload - def __call__(self, other: int, /) -> floating[_NBit1] | floating[_NBitInt]: ... + def __call__(self, other: int, /) -> floating[_NBit1]: ... @overload def __call__(self, other: float, /) -> floating[_NBit1] | float64: ... @overload diff --git a/numpy/typing/tests/data/reveal/arithmetic.pyi b/numpy/typing/tests/data/reveal/arithmetic.pyi index c1eee5d3fc29..d89dd529ebe4 100644 --- a/numpy/typing/tests/data/reveal/arithmetic.pyi +++ b/numpy/typing/tests/data/reveal/arithmetic.pyi @@ -412,10 +412,10 @@ assert_type(c16 + AR_f, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(f16 + c16, np.complex128 | np.complexfloating[_128Bit, _128Bit]) assert_type(c16 + c16, np.complex128) assert_type(f8 + c16, np.complex128) -assert_type(i8 + c16, np.complexfloating[_64Bit, _64Bit]) +assert_type(i8 + c16, np.complex128) assert_type(c8 + c16, np.complex128 | np.complex64) assert_type(f4 + c16, np.complex128 | np.complex64) -assert_type(i4 + c16, np.complex128 | np.complex64) +assert_type(i4 + c16, np.complex128) assert_type(b_ + c16, np.complex128) assert_type(b + c16, np.complex128) assert_type(c + c16, np.complex128) @@ -463,9 +463,9 @@ assert_type(f8 + AR_f, npt.NDArray[np.floating[Any]]) assert_type(f16 + f8, np.floating[_128Bit] | np.float64) assert_type(f8 + f8, np.float64) -assert_type(i8 + f8, np.floating[_64Bit]) +assert_type(i8 + f8, np.float64) assert_type(f4 + f8, np.floating[_32Bit] | np.float64) -assert_type(i4 + f8, np.floating[_32Bit] | np.float64) +assert_type(i4 + f8,np.float64) assert_type(b_ + f8, np.float64) assert_type(b + f8, np.float64) assert_type(c + f8, np.complex128 | np.float64) @@ -502,8 +502,8 @@ assert_type(i8 + i4, np.signedinteger[_32Bit] | np.signedinteger[_64Bit]) assert_type(i8 + u4, Any) assert_type(i8 + b_, np.int64) assert_type(i8 + b, np.int64) -assert_type(i8 + c, np.complexfloating[_64Bit, _64Bit]) -assert_type(i8 + f, np.floating[_64Bit]) +assert_type(i8 + c, np.complex128) +assert_type(i8 + f, np.float64) assert_type(i8 + AR_f, npt.NDArray[np.floating[Any]]) assert_type(u8 + u8, np.uint64) @@ -511,8 +511,8 @@ assert_type(u8 + i4, Any) assert_type(u8 + u4, np.unsignedinteger[_32Bit] | np.unsignedinteger[_64Bit]) assert_type(u8 + b_, np.uint64) assert_type(u8 + b, np.uint64) -assert_type(u8 + c, np.complexfloating[_64Bit, _64Bit]) -assert_type(u8 + f, np.floating[_64Bit]) +assert_type(u8 + c, np.complex128) +assert_type(u8 + f, np.float64) assert_type(u8 + AR_f, npt.NDArray[np.floating[Any]]) assert_type(i8 + i8, np.int64) @@ -521,8 +521,8 @@ assert_type(i4 + i8, np.signedinteger[_32Bit] | np.signedinteger[_64Bit]) assert_type(u4 + i8, Any) assert_type(b_ + i8, np.int64) assert_type(b + i8, np.int64) -assert_type(c + i8, np.complexfloating[_64Bit, _64Bit]) -assert_type(f + i8, np.floating[_64Bit]) +assert_type(c + i8, np.complex128) +assert_type(f + i8, np.float64) assert_type(AR_f + i8, npt.NDArray[np.floating[Any]]) assert_type(u8 + u8, np.uint64) @@ -530,8 +530,8 @@ assert_type(i4 + u8, Any) assert_type(u4 + u8, np.unsignedinteger[_32Bit] | np.unsignedinteger[_64Bit]) assert_type(b_ + u8, np.uint64) assert_type(b + u8, np.uint64) -assert_type(c + u8, np.complexfloating[_64Bit, _64Bit]) -assert_type(f + u8, np.floating[_64Bit]) +assert_type(c + u8, np.complex128) +assert_type(f + u8, np.float64) assert_type(AR_f + u8, npt.NDArray[np.floating[Any]]) assert_type(i4 + i8, np.signedinteger[_32Bit] | np.signedinteger[_64Bit]) From dfe61e9fa5207623d2203af682c719e83c3eb2a2 Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 6 Jan 2025 18:04:12 +0100 Subject: [PATCH 04/21] TYP: Better ``ndarray`` binop return types for ``float64`` & ``complex128`` --- numpy/__init__.pyi | 491 +++++++++++++----- numpy/_typing/__init__.py | 8 +- numpy/_typing/_array_like.py | 6 + numpy/typing/tests/data/reveal/arithmetic.pyi | 116 +++-- .../tests/data/reveal/false_positives.pyi | 14 - numpy/typing/tests/data/reveal/mod.pyi | 16 +- 6 files changed, 438 insertions(+), 213 deletions(-) delete mode 100644 numpy/typing/tests/data/reveal/false_positives.pyi diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index a14234db2735..395f13565208 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -23,11 +23,14 @@ from numpy._typing import ( _SupportsArray, _NestedSequence, _FiniteNestedSequence, + _ArrayLike, _ArrayLikeBool_co, _ArrayLikeUInt_co, _ArrayLikeInt, _ArrayLikeInt_co, + _ArrayLikeFloat64_co, _ArrayLikeFloat_co, + _ArrayLikeComplex128_co, _ArrayLikeComplex_co, _ArrayLikeNumber_co, _ArrayLikeTD64_co, @@ -800,6 +803,7 @@ _1NShapeT = TypeVar("_1NShapeT", bound=tuple[L[1], Unpack[tuple[L[1], ...]]]) # _SCT = TypeVar("_SCT", bound=generic) _SCT_co = TypeVar("_SCT_co", bound=generic, covariant=True) _NumberT = TypeVar("_NumberT", bound=number[Any]) +_RealNumberT = TypeVar("_RealNumberT", bound=floating | integer) _FloatingT_co = TypeVar("_FloatingT_co", bound=floating[Any], default=floating[Any], covariant=True) _IntegerT = TypeVar("_IntegerT", bound=integer) _IntegerT_co = TypeVar("_IntegerT_co", bound=integer[Any], default=integer[Any], covariant=True) @@ -833,14 +837,16 @@ _1D: TypeAlias = tuple[int] _2D: TypeAlias = tuple[int, int] _2Tuple: TypeAlias = tuple[_T, _T] -_ArrayUInt_co: TypeAlias = NDArray[np.bool | unsignedinteger[Any]] -_ArrayInt_co: TypeAlias = NDArray[np.bool | integer[Any]] -_ArrayFloat_co: TypeAlias = NDArray[np.bool | integer[Any] | floating[Any]] -_ArrayComplex_co: TypeAlias = NDArray[np.bool | integer[Any] | floating[Any] | complexfloating[Any, Any]] -_ArrayNumber_co: TypeAlias = NDArray[np.bool | number[Any]] -_ArrayTD64_co: TypeAlias = NDArray[np.bool | integer[Any] | timedelta64] +_ArrayUInt_co: TypeAlias = NDArray[unsignedinteger | np.bool] +_ArrayInt_co: TypeAlias = NDArray[integer | np.bool] +_ArrayFloat64_co: TypeAlias = NDArray[floating[_64Bit] | float32 | float16 | integer | np.bool] +_ArrayFloat_co: TypeAlias = NDArray[floating | integer | np.bool] +_ArrayComplex128_co: TypeAlias = NDArray[number[_64Bit] | number[_32Bit] | float16 | integer | np.bool] +_ArrayComplex_co: TypeAlias = NDArray[inexact | integer | np.bool] +_ArrayNumber_co: TypeAlias = NDArray[number | np.bool] +_ArrayTD64_co: TypeAlias = NDArray[timedelta64 | integer | np.bool] -_Float64_co: TypeAlias = float | floating[_64Bit] | float32 | float16 | integer[Any] | np.bool +_Float64_co: TypeAlias = float | floating[_64Bit] | float32 | float16 | integer | np.bool _Complex64_co: TypeAlias = number[_32Bit] | number[_16Bit] | number[_8Bit] | builtins.bool | np.bool _Complex128_co: TypeAlias = complex | number[_64Bit] | _Complex64_co @@ -2617,111 +2623,192 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): ) -> ndarray[_ShapeT, dtype[floating[_AnyNBitInexact]]]: ... @overload def __abs__(self: _RealArrayT, /) -> _RealArrayT: ... + def __invert__(self: _IntegralArrayT, /) -> _IntegralArrayT: ... # noqa: PYI019 def __neg__(self: _NumericArrayT, /) -> _NumericArrayT: ... # noqa: PYI019 def __pos__(self: _NumericArrayT, /) -> _NumericArrayT: ... # noqa: PYI019 # Binary ops + + # TODO: Support the "1d @ 1d -> scalar" case + @overload + def __matmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... + @overload + def __matmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __matmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __matmul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __matmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __matmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __matmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __matmul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __matmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __matmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __matmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... + def __matmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __matmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __matmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __matmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... @overload def __matmul__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __matmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload # signature equivalent to __matmul__ + def __rmatmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... + @overload + def __rmatmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] @overload - def __rmatmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __rmatmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __rmatmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rmatmul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rmatmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rmatmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __rmatmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rmatmul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rmatmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __rmatmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[overload-overlap] @overload def __rmatmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... @overload - def __rmatmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __rmatmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... @overload def __rmatmul__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __rmatmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __mod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __mod__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... + @overload + def __mod__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __mod__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __mod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __mod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __mod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __mod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... @overload - def __mod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[timedelta64]: ... + def __mod__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... @overload def __mod__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __mod__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload # signature equivalent to __mod__ + def __rmod__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... @overload - def __rmod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __rmod__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __rmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rmod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] @overload - def __rmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rmod__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rmod__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[timedelta64]: ... + def __rmod__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __rmod__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... @overload def __rmod__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __rmod__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __divmod__(self: NDArray[np.bool], other: _ArrayLikeBool_co) -> _2Tuple[NDArray[int8]]: ... # type: ignore[misc] + def __divmod__(self: NDArray[_RealNumberT], rhs: int | np.bool, /) -> _2Tuple[ndarray[_ShapeT_co, dtype[_RealNumberT]]]: ... + @overload + def __divmod__(self: NDArray[_RealNumberT], rhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[np.bool], rhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[int8]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[np.bool], rhs: _ArrayLike[_RealNumberT], /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[floating[_64Bit]], rhs: _ArrayLikeFloat64_co, /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __divmod__(self: _ArrayFloat64_co, rhs: _ArrayLike[floating[_64Bit]], /) -> _2Tuple[NDArray[float64]]: ... @overload - def __divmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger[Any]]]: ... # type: ignore[misc] + def __divmod__(self: _ArrayUInt_co, rhs: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger]]: ... # type: ignore[overload-overlap] @overload - def __divmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger[Any]]]: ... # type: ignore[misc] + def __divmod__(self: _ArrayInt_co, rhs: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger]]: ... # type: ignore[overload-overlap] @overload - def __divmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating[Any]]]: ... # type: ignore[misc] + def __divmod__(self: _ArrayFloat_co, rhs: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating]]: ... @overload - def __divmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... + def __divmod__(self: NDArray[timedelta64], rhs: _ArrayLike[timedelta64], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... + @overload # signature equivalent to __divmod__ + def __rdivmod__(self: NDArray[_RealNumberT], lhs: int | np.bool, /) -> _2Tuple[ndarray[_ShapeT_co, dtype[_RealNumberT]]]: ... @overload - def __rdivmod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[int8]]: ... # type: ignore[misc] + def __rdivmod__(self: NDArray[_RealNumberT], lhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] @overload - def __rdivmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger[Any]]]: ... # type: ignore[misc] + def __rdivmod__(self: NDArray[np.bool], lhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[int8]]: ... # type: ignore[overload-overlap] @overload - def __rdivmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger[Any]]]: ... # type: ignore[misc] + def __rdivmod__(self: NDArray[np.bool], lhs: _ArrayLike[_RealNumberT], /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] @overload - def __rdivmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating[Any]]]: ... # type: ignore[misc] + def __rdivmod__(self: NDArray[floating[_64Bit]], lhs: _ArrayLikeFloat64_co, /) -> _2Tuple[NDArray[float64]]: ... @overload - def __rdivmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... + def __rdivmod__(self: _ArrayFloat64_co, lhs: _ArrayLike[floating[_64Bit]], /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __rdivmod__(self: _ArrayUInt_co, lhs: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: _ArrayInt_co, lhs: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: _ArrayFloat_co, lhs: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating]]: ... + @overload + def __rdivmod__(self: NDArray[timedelta64], lhs: _ArrayLike[timedelta64], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... @overload - def __add__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __add__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __add__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __add__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __add__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __add__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __add__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __add__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __add__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __add__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __add__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __add__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __add__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __add__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... # type: ignore[misc] + def __add__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... @overload def __add__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... @overload @@ -2731,20 +2818,34 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): @overload def __add__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload # signature equivalent to __add__ + def __radd__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __radd__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __radd__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __radd__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __radd__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __radd__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __radd__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __radd__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __radd__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __radd__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __radd__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __radd__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] @overload - def __radd__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __radd__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] @overload - def __radd__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __radd__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] @overload - def __radd__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... # type: ignore[misc] + def __radd__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... @overload def __radd__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... @overload @@ -2754,20 +2855,34 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): @overload def __radd__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload + def __sub__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __sub__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload def __sub__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NoReturn: ... @overload - def __sub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __sub__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __sub__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __sub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __sub__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __sub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __sub__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __sub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __sub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __sub__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __sub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __sub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... # type: ignore[misc] + def __sub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... @overload def __sub__(self: NDArray[datetime64], other: _ArrayLikeTD64_co, /) -> NDArray[datetime64]: ... @overload @@ -2777,22 +2892,36 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): @overload def __sub__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload + def __rsub__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __rsub__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload def __rsub__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NoReturn: ... @overload - def __rsub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rsub__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rsub__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rsub__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rsub__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __rsub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rsub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __rsub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rsub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __rsub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __rsub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] @overload - def __rsub__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __rsub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] @overload - def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... # type: ignore[misc] + def __rsub__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] @overload - def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... # type: ignore[misc] + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + @overload + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... @overload def __rsub__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[timedelta64]: ... @overload @@ -2801,156 +2930,252 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): def __rsub__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __mul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __mul__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __mul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __mul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __mul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __mul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __mul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __mul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __mul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __mul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __mul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __mul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __mul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __mul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + def __mul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __mul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + def __mul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __mul__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __mul__(self: _ArrayFloat_co, other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... @overload def __mul__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __mul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + @overload # signature equivalent to __mul__ + def __rmul__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __rmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[misc] + def __rmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __rmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rmul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __rmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __rmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __rmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] @overload - def __rmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] @overload - def __rmul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + def __rmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] @overload - def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + def __rmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rmul__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __rmul__(self: _ArrayFloat_co, other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... @overload def __rmul__(self: NDArray[object_], other: Any, /) -> Any: ... @overload def __rmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __floordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __truediv__(self: _ArrayInt_co, other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __floordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __truediv__(self: _ArrayFloat64_co, other: _ArrayLikeInt_co | _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __floordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __truediv__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __floordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __truediv__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __floordiv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[int64]: ... + def __truediv__(self: NDArray[floating], other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... @overload - def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + def __truediv__(self: _ArrayFloat_co, other: _ArrayLike[floating], /) -> NDArray[floating]: ... @overload - def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + def __truediv__(self: NDArray[complexfloating], other: _ArrayLikeNumber_co, /) -> NDArray[complexfloating]: ... @overload - def __floordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + def __truediv__(self: _ArrayNumber_co, other: _ArrayLike[complexfloating], /) -> NDArray[complexfloating]: ... @overload - def __floordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __truediv__(self: NDArray[inexact], other: _ArrayLikeNumber_co, /) -> NDArray[inexact]: ... + @overload + def __truediv__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[float64]: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __truediv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __truediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __rtruediv__(self: _ArrayInt_co, other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rfloordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rtruediv__(self: _ArrayFloat64_co, other: _ArrayLikeInt_co | _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __rfloordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rtruediv__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rtruediv__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __rfloordiv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[int64]: ... + def __rtruediv__(self: NDArray[floating], other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... @overload - def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLikeTD64_co, /) -> NoReturn: ... + def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLike[floating], /) -> NDArray[floating]: ... @overload - def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + def __rtruediv__(self: NDArray[complexfloating], other: _ArrayLikeNumber_co, /) -> NDArray[complexfloating]: ... @overload - def __rfloordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + def __rtruediv__(self: _ArrayNumber_co, other: _ArrayLike[complexfloating], /) -> NDArray[complexfloating]: ... @overload - def __rfloordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __rtruediv__(self: NDArray[inexact], other: _ArrayLikeNumber_co, /) -> NDArray[inexact]: ... + @overload + def __rtruediv__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rtruediv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[float64]: ... + @overload + def __rtruediv__(self: NDArray[integer | floating], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rtruediv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rtruediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __pow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __floordiv__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... @overload - def __pow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __floordiv__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __pow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __floordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] @overload - def __pow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __floordiv__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __pow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... + def __floordiv__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __pow__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __floordiv__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __pow__(self: NDArray[object_], other: Any, /) -> Any: ... + def __floordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __pow__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __floordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[int64]: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __floordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __floordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __rpow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] + def __rfloordiv__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... @overload - def __rpow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc] + def __rfloordiv__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __rpow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc] + def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] @overload - def __rpow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] @overload - def __rpow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... + def __rfloordiv__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rpow__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __rfloordiv__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __rpow__(self: NDArray[object_], other: Any, /) -> Any: ... + def __rfloordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] @overload - def __rpow__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __rfloordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[int64]: ... + @overload + def __rfloordiv__(self: NDArray[floating | integer], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rfloordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rfloordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __truediv__(self: _ArrayInt_co, other: _ArrayInt_co, /) -> NDArray[float64]: ... # type: ignore[misc] + def __pow__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... @overload - def __truediv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __pow__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __truediv__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __pow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] @overload - def __truediv__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __pow__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __truediv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[float64]: ... + def __pow__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + def __pow__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + def __pow__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __truediv__(self: NDArray[object_], other: Any, /) -> Any: ... + def __pow__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __truediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __pow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __pow__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __pow__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __pow__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload - def __rtruediv__(self: _ArrayInt_co, other: _ArrayInt_co, /) -> NDArray[float64]: ... # type: ignore[misc] + def __rpow__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... @overload - def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating[Any]]: ... # type: ignore[misc] + def __rpow__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __rtruediv__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc] + def __rpow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] @overload - def __rtruediv__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co, /) -> NDArray[number[Any]]: ... + def __rpow__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] @overload - def __rtruediv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]], /) -> NDArray[float64]: ... + def __rpow__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... @overload - def __rtruediv__(self: NDArray[np.bool], other: _ArrayLikeTD64_co, /) -> NoReturn: ... + def __rpow__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... @overload - def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + def __rpow__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... @overload - def __rtruediv__(self: NDArray[object_], other: Any, /) -> Any: ... + def __rpow__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... @overload - def __rtruediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + def __rpow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __rpow__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rpow__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rpow__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... @overload def __lshift__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[misc] diff --git a/numpy/_typing/__init__.py b/numpy/_typing/__init__.py index 687e124ec2bb..dd9b133ddf88 100644 --- a/numpy/_typing/__init__.py +++ b/numpy/_typing/__init__.py @@ -121,15 +121,14 @@ NDArray as NDArray, ArrayLike as ArrayLike, _ArrayLike as _ArrayLike, - _FiniteNestedSequence as _FiniteNestedSequence, - _SupportsArray as _SupportsArray, - _SupportsArrayFunc as _SupportsArrayFunc, _ArrayLikeInt as _ArrayLikeInt, _ArrayLikeBool_co as _ArrayLikeBool_co, _ArrayLikeUInt_co as _ArrayLikeUInt_co, _ArrayLikeInt_co as _ArrayLikeInt_co, _ArrayLikeFloat_co as _ArrayLikeFloat_co, + _ArrayLikeFloat64_co as _ArrayLikeFloat64_co, _ArrayLikeComplex_co as _ArrayLikeComplex_co, + _ArrayLikeComplex128_co as _ArrayLikeComplex128_co, _ArrayLikeNumber_co as _ArrayLikeNumber_co, _ArrayLikeTD64_co as _ArrayLikeTD64_co, _ArrayLikeDT64_co as _ArrayLikeDT64_co, @@ -140,6 +139,9 @@ _ArrayLikeString_co as _ArrayLikeString_co, _ArrayLikeAnyString_co as _ArrayLikeAnyString_co, _ArrayLikeUnknown as _ArrayLikeUnknown, + _FiniteNestedSequence as _FiniteNestedSequence, + _SupportsArray as _SupportsArray, + _SupportsArrayFunc as _SupportsArrayFunc, _UnknownType as _UnknownType, ) diff --git a/numpy/_typing/_array_like.py b/numpy/_typing/_array_like.py index 27b59b75373a..292b99d918e2 100644 --- a/numpy/_typing/_array_like.py +++ b/numpy/_typing/_array_like.py @@ -21,6 +21,7 @@ str_, bytes_, ) +from ._nbit_base import _32Bit, _64Bit from ._nested_sequence import _NestedSequence from ._shape import _Shape @@ -165,6 +166,11 @@ def __array_function__( _ArrayLikeString_co ) +__Float64_co: TypeAlias = np.floating[_64Bit] | np.float32 | np.float16 | np.integer | np.bool +__Complex128_co: TypeAlias = np.number[_64Bit] | np.number[_32Bit] | np.float16 | np.integer | np.bool +_ArrayLikeFloat64_co: TypeAlias = _DualArrayLike[dtype[__Float64_co], float | int] +_ArrayLikeComplex128_co: TypeAlias = _DualArrayLike[dtype[__Complex128_co], complex | float | int] + # NOTE: This includes `builtins.bool`, but not `numpy.bool`. _ArrayLikeInt: TypeAlias = _DualArrayLike[ dtype[integer[Any]], diff --git a/numpy/typing/tests/data/reveal/arithmetic.pyi b/numpy/typing/tests/data/reveal/arithmetic.pyi index d89dd529ebe4..46ac003508c4 100644 --- a/numpy/typing/tests/data/reveal/arithmetic.pyi +++ b/numpy/typing/tests/data/reveal/arithmetic.pyi @@ -51,6 +51,7 @@ AR_m: npt.NDArray[np.timedelta64] AR_M: npt.NDArray[np.datetime64] AR_O: npt.NDArray[np.object_] AR_number: npt.NDArray[np.number[Any]] +AR_Any: npt.NDArray[Any] AR_LIKE_b: list[bool] AR_LIKE_u: list[np.uint32] @@ -61,18 +62,19 @@ AR_LIKE_m: list[np.timedelta64] AR_LIKE_M: list[np.datetime64] AR_LIKE_O: list[np.object_] + # Array subtraction assert_type(AR_number - AR_number, npt.NDArray[np.number[Any]]) -assert_type(AR_b - AR_LIKE_u, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_b - AR_LIKE_u, npt.NDArray[np.uint32]) assert_type(AR_b - AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_b - AR_LIKE_f, npt.NDArray[np.floating[Any]]) assert_type(AR_b - AR_LIKE_c, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(AR_b - AR_LIKE_m, npt.NDArray[np.timedelta64]) assert_type(AR_b - AR_LIKE_O, Any) -assert_type(AR_LIKE_u - AR_b, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_LIKE_u - AR_b, npt.NDArray[np.uint32]) assert_type(AR_LIKE_i - AR_b, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f - AR_b, npt.NDArray[np.floating[Any]]) assert_type(AR_LIKE_c - AR_b, npt.NDArray[np.complexfloating[Any, Any]]) @@ -80,7 +82,7 @@ assert_type(AR_LIKE_m - AR_b, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_M - AR_b, npt.NDArray[np.datetime64]) assert_type(AR_LIKE_O - AR_b, Any) -assert_type(AR_u - AR_LIKE_b, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_u - AR_LIKE_b, npt.NDArray[np.uint32]) assert_type(AR_u - AR_LIKE_u, npt.NDArray[np.unsignedinteger[Any]]) assert_type(AR_u - AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_u - AR_LIKE_f, npt.NDArray[np.floating[Any]]) @@ -88,7 +90,7 @@ assert_type(AR_u - AR_LIKE_c, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(AR_u - AR_LIKE_m, npt.NDArray[np.timedelta64]) assert_type(AR_u - AR_LIKE_O, Any) -assert_type(AR_LIKE_b - AR_u, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_LIKE_b - AR_u, npt.NDArray[np.uint32]) assert_type(AR_LIKE_u - AR_u, npt.NDArray[np.unsignedinteger[Any]]) assert_type(AR_LIKE_i - AR_u, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f - AR_u, npt.NDArray[np.floating[Any]]) @@ -97,7 +99,7 @@ assert_type(AR_LIKE_m - AR_u, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_M - AR_u, npt.NDArray[np.datetime64]) assert_type(AR_LIKE_O - AR_u, Any) -assert_type(AR_i - AR_LIKE_b, npt.NDArray[np.signedinteger[Any]]) +assert_type(AR_i - AR_LIKE_b, npt.NDArray[np.int64]) assert_type(AR_i - AR_LIKE_u, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_i - AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_i - AR_LIKE_f, npt.NDArray[np.floating[Any]]) @@ -105,7 +107,7 @@ assert_type(AR_i - AR_LIKE_c, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(AR_i - AR_LIKE_m, npt.NDArray[np.timedelta64]) assert_type(AR_i - AR_LIKE_O, Any) -assert_type(AR_LIKE_b - AR_i, npt.NDArray[np.signedinteger[Any]]) +assert_type(AR_LIKE_b - AR_i, npt.NDArray[np.int64]) assert_type(AR_LIKE_u - AR_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_i - AR_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f - AR_i, npt.NDArray[np.floating[Any]]) @@ -114,32 +116,32 @@ assert_type(AR_LIKE_m - AR_i, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_M - AR_i, npt.NDArray[np.datetime64]) assert_type(AR_LIKE_O - AR_i, Any) -assert_type(AR_f - AR_LIKE_b, npt.NDArray[np.floating[Any]]) -assert_type(AR_f - AR_LIKE_u, npt.NDArray[np.floating[Any]]) -assert_type(AR_f - AR_LIKE_i, npt.NDArray[np.floating[Any]]) -assert_type(AR_f - AR_LIKE_f, npt.NDArray[np.floating[Any]]) +assert_type(AR_f - AR_LIKE_b, npt.NDArray[np.float64]) +assert_type(AR_f - AR_LIKE_u, npt.NDArray[np.float64]) +assert_type(AR_f - AR_LIKE_i, npt.NDArray[np.float64]) +assert_type(AR_f - AR_LIKE_f, npt.NDArray[np.float64]) assert_type(AR_f - AR_LIKE_c, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(AR_f - AR_LIKE_O, Any) -assert_type(AR_LIKE_b - AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_u - AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_i - AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_f - AR_f, npt.NDArray[np.floating[Any]]) +assert_type(AR_LIKE_b - AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_u - AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_i - AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_f - AR_f, npt.NDArray[np.float64]) assert_type(AR_LIKE_c - AR_f, npt.NDArray[np.complexfloating[Any, Any]]) assert_type(AR_LIKE_O - AR_f, Any) -assert_type(AR_c - AR_LIKE_b, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_c - AR_LIKE_u, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_c - AR_LIKE_i, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_c - AR_LIKE_f, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_c - AR_LIKE_c, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(AR_c - AR_LIKE_b, npt.NDArray[np.complex128]) +assert_type(AR_c - AR_LIKE_u, npt.NDArray[np.complex128]) +assert_type(AR_c - AR_LIKE_i, npt.NDArray[np.complex128]) +assert_type(AR_c - AR_LIKE_f, npt.NDArray[np.complex128]) +assert_type(AR_c - AR_LIKE_c, npt.NDArray[np.complex128]) assert_type(AR_c - AR_LIKE_O, Any) -assert_type(AR_LIKE_b - AR_c, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_LIKE_u - AR_c, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_LIKE_i - AR_c, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_LIKE_f - AR_c, npt.NDArray[np.complexfloating[Any, Any]]) -assert_type(AR_LIKE_c - AR_c, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(AR_LIKE_b - AR_c, npt.NDArray[np.complex128]) +assert_type(AR_LIKE_u - AR_c, npt.NDArray[np.complex128]) +assert_type(AR_LIKE_i - AR_c, npt.NDArray[np.complex128]) +assert_type(AR_LIKE_f - AR_c, npt.NDArray[np.complex128]) +assert_type(AR_LIKE_c - AR_c, npt.NDArray[np.complex128]) assert_type(AR_LIKE_O - AR_c, Any) assert_type(AR_m - AR_LIKE_b, npt.NDArray[np.timedelta64]) @@ -186,53 +188,53 @@ assert_type(AR_LIKE_O - AR_O, Any) # Array floor division assert_type(AR_b // AR_LIKE_b, npt.NDArray[np.int8]) -assert_type(AR_b // AR_LIKE_u, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_b // AR_LIKE_u, npt.NDArray[np.uint32]) assert_type(AR_b // AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_b // AR_LIKE_f, npt.NDArray[np.floating[Any]]) assert_type(AR_b // AR_LIKE_O, Any) assert_type(AR_LIKE_b // AR_b, npt.NDArray[np.int8]) -assert_type(AR_LIKE_u // AR_b, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_LIKE_u // AR_b, npt.NDArray[np.uint32]) assert_type(AR_LIKE_i // AR_b, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f // AR_b, npt.NDArray[np.floating[Any]]) assert_type(AR_LIKE_O // AR_b, Any) -assert_type(AR_u // AR_LIKE_b, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_u // AR_LIKE_b, npt.NDArray[np.uint32]) assert_type(AR_u // AR_LIKE_u, npt.NDArray[np.unsignedinteger[Any]]) assert_type(AR_u // AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_u // AR_LIKE_f, npt.NDArray[np.floating[Any]]) assert_type(AR_u // AR_LIKE_O, Any) -assert_type(AR_LIKE_b // AR_u, npt.NDArray[np.unsignedinteger[Any]]) +assert_type(AR_LIKE_b // AR_u, npt.NDArray[np.uint32]) assert_type(AR_LIKE_u // AR_u, npt.NDArray[np.unsignedinteger[Any]]) assert_type(AR_LIKE_i // AR_u, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f // AR_u, npt.NDArray[np.floating[Any]]) assert_type(AR_LIKE_m // AR_u, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_O // AR_u, Any) -assert_type(AR_i // AR_LIKE_b, npt.NDArray[np.signedinteger[Any]]) +assert_type(AR_i // AR_LIKE_b, npt.NDArray[np.int64]) assert_type(AR_i // AR_LIKE_u, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_i // AR_LIKE_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_i // AR_LIKE_f, npt.NDArray[np.floating[Any]]) assert_type(AR_i // AR_LIKE_O, Any) -assert_type(AR_LIKE_b // AR_i, npt.NDArray[np.signedinteger[Any]]) +assert_type(AR_LIKE_b // AR_i, npt.NDArray[np.int64]) assert_type(AR_LIKE_u // AR_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_i // AR_i, npt.NDArray[np.signedinteger[Any]]) assert_type(AR_LIKE_f // AR_i, npt.NDArray[np.floating[Any]]) assert_type(AR_LIKE_m // AR_i, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_O // AR_i, Any) -assert_type(AR_f // AR_LIKE_b, npt.NDArray[np.floating[Any]]) -assert_type(AR_f // AR_LIKE_u, npt.NDArray[np.floating[Any]]) -assert_type(AR_f // AR_LIKE_i, npt.NDArray[np.floating[Any]]) -assert_type(AR_f // AR_LIKE_f, npt.NDArray[np.floating[Any]]) +assert_type(AR_f // AR_LIKE_b, npt.NDArray[np.float64]) +assert_type(AR_f // AR_LIKE_u, npt.NDArray[np.float64]) +assert_type(AR_f // AR_LIKE_i, npt.NDArray[np.float64]) +assert_type(AR_f // AR_LIKE_f, npt.NDArray[np.float64]) assert_type(AR_f // AR_LIKE_O, Any) -assert_type(AR_LIKE_b // AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_u // AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_i // AR_f, npt.NDArray[np.floating[Any]]) -assert_type(AR_LIKE_f // AR_f, npt.NDArray[np.floating[Any]]) +assert_type(AR_LIKE_b // AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_u // AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_i // AR_f, npt.NDArray[np.float64]) +assert_type(AR_LIKE_f // AR_f, npt.NDArray[np.float64]) assert_type(AR_LIKE_m // AR_f, npt.NDArray[np.timedelta64]) assert_type(AR_LIKE_O // AR_f, Any) @@ -407,7 +409,7 @@ assert_type(c16 + b_, np.complex128) assert_type(c16 + b, np.complex128) assert_type(c16 + c, np.complex128) assert_type(c16 + f, np.complex128) -assert_type(c16 + AR_f, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(c16 + AR_f, npt.NDArray[np.complex128]) assert_type(f16 + c16, np.complex128 | np.complexfloating[_128Bit, _128Bit]) assert_type(c16 + c16, np.complex128) @@ -420,7 +422,7 @@ assert_type(b_ + c16, np.complex128) assert_type(b + c16, np.complex128) assert_type(c + c16, np.complex128) assert_type(f + c16, np.complex128) -assert_type(AR_f + c16, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(AR_f + c16, npt.NDArray[np.complex128]) assert_type(c8 + f16, np.complexfloating[_32Bit, _32Bit] | np.complexfloating[_128Bit, _128Bit]) assert_type(c8 + c16, np.complex64 | np.complex128) @@ -433,7 +435,7 @@ assert_type(c8 + b_, np.complex64) assert_type(c8 + b, np.complex64) assert_type(c8 + c, np.complex64 | np.complex128) assert_type(c8 + f, np.complex64 | np.complex128) -assert_type(c8 + AR_f, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(c8 + AR_f, npt.NDArray[np.complexfloating]) assert_type(f16 + c8, np.complexfloating[_128Bit, _128Bit] | np.complex64) assert_type(c16 + c8, np.complex128) @@ -446,7 +448,7 @@ assert_type(b_ + c8, np.complex64) assert_type(b + c8, np.complex64) assert_type(c + c8, np.complex64 | np.complex128) assert_type(f + c8, np.complex64 | np.complex128) -assert_type(AR_f + c8, npt.NDArray[np.complexfloating[Any, Any]]) +assert_type(AR_f + c8, npt.NDArray[np.complexfloating]) # Float @@ -459,18 +461,18 @@ assert_type(f8 + b_, np.float64) assert_type(f8 + b, np.float64) assert_type(f8 + c, np.float64 | np.complex128) assert_type(f8 + f, np.float64) -assert_type(f8 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(f8 + AR_f, npt.NDArray[np.float64]) assert_type(f16 + f8, np.floating[_128Bit] | np.float64) assert_type(f8 + f8, np.float64) assert_type(i8 + f8, np.float64) -assert_type(f4 + f8, np.floating[_32Bit] | np.float64) +assert_type(f4 + f8, np.float32 | np.float64) assert_type(i4 + f8,np.float64) assert_type(b_ + f8, np.float64) assert_type(b + f8, np.float64) assert_type(c + f8, np.complex128 | np.float64) assert_type(f + f8, np.float64) -assert_type(AR_f + f8, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + f8, npt.NDArray[np.float64]) assert_type(f4 + f16, np.float32 | np.floating[_128Bit]) assert_type(f4 + f8, np.float32 | np.float64) @@ -481,7 +483,7 @@ assert_type(f4 + b_, np.float32) assert_type(f4 + b, np.float32) assert_type(f4 + c, np.complex64 | np.complex128) assert_type(f4 + f, np.float32 | np.float64) -assert_type(f4 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(f4 + AR_f, npt.NDArray[np.float64]) assert_type(f16 + f4, np.floating[_128Bit] | np.float32) assert_type(f8 + f4, np.float64) @@ -492,7 +494,7 @@ assert_type(b_ + f4, np.float32) assert_type(b + f4, np.float32) assert_type(c + f4, np.complex64 | np.complex128) assert_type(f + f4, np.float64 | np.float32) -assert_type(AR_f + f4, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + f4, npt.NDArray[np.float64]) # Int @@ -504,7 +506,7 @@ assert_type(i8 + b_, np.int64) assert_type(i8 + b, np.int64) assert_type(i8 + c, np.complex128) assert_type(i8 + f, np.float64) -assert_type(i8 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(i8 + AR_f, npt.NDArray[np.float64]) assert_type(u8 + u8, np.uint64) assert_type(u8 + i4, Any) @@ -513,7 +515,7 @@ assert_type(u8 + b_, np.uint64) assert_type(u8 + b, np.uint64) assert_type(u8 + c, np.complex128) assert_type(u8 + f, np.float64) -assert_type(u8 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(u8 + AR_f, npt.NDArray[np.float64]) assert_type(i8 + i8, np.int64) assert_type(u8 + i8, Any) @@ -523,7 +525,7 @@ assert_type(b_ + i8, np.int64) assert_type(b + i8, np.int64) assert_type(c + i8, np.complex128) assert_type(f + i8, np.float64) -assert_type(AR_f + i8, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + i8, npt.NDArray[np.float64]) assert_type(u8 + u8, np.uint64) assert_type(i4 + u8, Any) @@ -532,13 +534,13 @@ assert_type(b_ + u8, np.uint64) assert_type(b + u8, np.uint64) assert_type(c + u8, np.complex128) assert_type(f + u8, np.float64) -assert_type(AR_f + u8, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + u8, npt.NDArray[np.float64]) assert_type(i4 + i8, np.signedinteger[_32Bit] | np.signedinteger[_64Bit]) assert_type(i4 + i4, np.int32) assert_type(i4 + b_, np.int32) assert_type(i4 + b, np.int32) -assert_type(i4 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(i4 + AR_f, npt.NDArray[np.float64]) assert_type(u4 + i8, Any) assert_type(u4 + i4, Any) @@ -546,13 +548,13 @@ assert_type(u4 + u8, np.unsignedinteger[_32Bit] | np.unsignedinteger[_64Bit]) assert_type(u4 + u4, np.uint32) assert_type(u4 + b_, np.uint32) assert_type(u4 + b, np.uint32) -assert_type(u4 + AR_f, npt.NDArray[np.floating[Any]]) +assert_type(u4 + AR_f, npt.NDArray[np.float64]) assert_type(i8 + i4, np.signedinteger[_32Bit] | np.signedinteger[_64Bit]) assert_type(i4 + i4, np.int32) assert_type(b_ + i4, np.int32) assert_type(b + i4, np.int32) -assert_type(AR_f + i4, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + i4, npt.NDArray[np.float64]) assert_type(i8 + u4, Any) assert_type(i4 + u4, Any) @@ -560,4 +562,8 @@ assert_type(u8 + u4, np.unsignedinteger[_32Bit] | np.unsignedinteger[_64Bit]) assert_type(u4 + u4, np.uint32) assert_type(b_ + u4, np.uint32) assert_type(b + u4, np.uint32) -assert_type(AR_f + u4, npt.NDArray[np.floating[Any]]) +assert_type(AR_f + u4, npt.NDArray[np.float64]) + +# Any + +assert_type(AR_Any + 2, npt.NDArray[Any]) diff --git a/numpy/typing/tests/data/reveal/false_positives.pyi b/numpy/typing/tests/data/reveal/false_positives.pyi deleted file mode 100644 index 7ae95e16a720..000000000000 --- a/numpy/typing/tests/data/reveal/false_positives.pyi +++ /dev/null @@ -1,14 +0,0 @@ -from typing import Any - -import numpy as np -import numpy.typing as npt - -from typing_extensions import assert_type - -AR_Any: npt.NDArray[Any] - -# Mypy bug where overload ambiguity is ignored for `Any`-parametrized types; -# xref numpy/numpy#20099 and python/mypy#11347 -# -# The expected output would be something akin to `npt.NDArray[Any]` -assert_type(AR_Any + 2, npt.NDArray[np.signedinteger[Any]]) diff --git a/numpy/typing/tests/data/reveal/mod.pyi b/numpy/typing/tests/data/reveal/mod.pyi index e7e6082753be..bd7a632b0a24 100644 --- a/numpy/typing/tests/data/reveal/mod.pyi +++ b/numpy/typing/tests/data/reveal/mod.pyi @@ -83,7 +83,7 @@ assert_type(i4 % i8, np.int64 | np.int32) assert_type(i4 % f8, np.float64 | np.float32) assert_type(i4 % i4, np.int32) assert_type(i4 % f4, np.float32) -assert_type(i8 % AR_b, npt.NDArray[np.signedinteger[Any]]) +assert_type(i8 % AR_b, npt.NDArray[np.int64]) assert_type(divmod(i8, b), tuple[np.signedinteger[_64Bit], np.signedinteger[_64Bit]]) assert_type(divmod(i8, f), tuple[np.floating[_64Bit], np.floating[_64Bit]]) @@ -93,7 +93,7 @@ assert_type(divmod(i8, i4), tuple[np.signedinteger[_64Bit], np.signedinteger[_64 assert_type(divmod(i8, f4), tuple[np.floating[_64Bit], np.floating[_64Bit]] | tuple[np.floating[_32Bit], np.floating[_32Bit]]) assert_type(divmod(i4, i4), tuple[np.signedinteger[_32Bit], np.signedinteger[_32Bit]]) assert_type(divmod(i4, f4), tuple[np.floating[_32Bit], np.floating[_32Bit]]) -assert_type(divmod(i8, AR_b), tuple[npt.NDArray[np.signedinteger[Any]], npt.NDArray[np.signedinteger[Any]]]) +assert_type(divmod(i8, AR_b), tuple[npt.NDArray[np.int64], npt.NDArray[np.int64]]) assert_type(b % i8, np.signedinteger[_64Bit]) assert_type(f % i8, np.floating[_64Bit]) @@ -103,7 +103,7 @@ assert_type(i8 % i4, np.int64 | np.int32) assert_type(f8 % i4, np.float64) assert_type(i4 % i4, np.int32) assert_type(f4 % i4, np.float32) -assert_type(AR_b % i8, npt.NDArray[np.signedinteger[Any]]) +assert_type(AR_b % i8, npt.NDArray[np.int64]) assert_type(divmod(b, i8), tuple[np.signedinteger[_64Bit], np.signedinteger[_64Bit]]) assert_type(divmod(f, i8), tuple[np.floating[_64Bit], np.floating[_64Bit]]) @@ -113,7 +113,7 @@ assert_type(divmod(i4, i8), tuple[np.signedinteger[_64Bit], np.signedinteger[_64 assert_type(divmod(f4, i8), tuple[np.floating[_64Bit], np.floating[_64Bit]] | tuple[np.floating[_32Bit], np.floating[_32Bit]]) assert_type(divmod(i4, i4), tuple[np.signedinteger[_32Bit], np.signedinteger[_32Bit]]) assert_type(divmod(f4, i4), tuple[np.floating[_32Bit], np.floating[_32Bit]]) -assert_type(divmod(AR_b, i8), tuple[npt.NDArray[np.signedinteger[Any]], npt.NDArray[np.signedinteger[Any]]]) +assert_type(divmod(AR_b, i8), tuple[npt.NDArray[np.int64], npt.NDArray[np.int64]]) # float @@ -121,25 +121,25 @@ assert_type(f8 % b, np.float64) assert_type(f8 % f, np.float64) assert_type(i8 % f4, np.floating[_64Bit] | np.floating[_32Bit]) assert_type(f4 % f4, np.float32) -assert_type(f8 % AR_b, npt.NDArray[np.floating[Any]]) +assert_type(f8 % AR_b, npt.NDArray[np.float64]) assert_type(divmod(f8, b), tuple[np.float64, np.float64]) assert_type(divmod(f8, f), tuple[np.float64, np.float64]) assert_type(divmod(f8, f8), tuple[np.float64, np.float64]) assert_type(divmod(f8, f4), tuple[np.float64, np.float64]) assert_type(divmod(f4, f4), tuple[np.float32, np.float32]) -assert_type(divmod(f8, AR_b), tuple[npt.NDArray[np.floating[Any]], npt.NDArray[np.floating[Any]]]) +assert_type(divmod(f8, AR_b), tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]) assert_type(b % f8, np.float64) assert_type(f % f8, np.float64) assert_type(f8 % f8, np.float64) assert_type(f8 % f8, np.float64) assert_type(f4 % f4, np.float32) -assert_type(AR_b % f8, npt.NDArray[np.floating[Any]]) +assert_type(AR_b % f8, npt.NDArray[np.float64]) assert_type(divmod(b, f8), tuple[np.float64, np.float64]) assert_type(divmod(f, f8), tuple[np.float64, np.float64]) assert_type(divmod(f8, f8), tuple[np.float64, np.float64]) assert_type(divmod(f4, f8), tuple[np.float64, np.float64] | tuple[np.float32, np.float32]) assert_type(divmod(f4, f4), tuple[np.float32, np.float32]) -assert_type(divmod(AR_b, f8), tuple[npt.NDArray[np.floating[Any]], npt.NDArray[np.floating[Any]]]) +assert_type(divmod(AR_b, f8), tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]) From 1fc37e65bd0b3d035ef30aed37a4f5a6d6244214 Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 6 Jan 2025 19:41:24 +0100 Subject: [PATCH 05/21] TYP: Return the correct ``bool`` from ``issubdtype`` --- numpy/_core/numerictypes.pyi | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/numpy/_core/numerictypes.pyi b/numpy/_core/numerictypes.pyi index c2a7cb6261d4..ace5913f0f84 100644 --- a/numpy/_core/numerictypes.pyi +++ b/numpy/_core/numerictypes.pyi @@ -177,12 +177,9 @@ class _TypeCodes(TypedDict): Datetime: L['Mm'] All: L['?bhilqnpBHILQNPefdgFDGSUVOMm'] -def isdtype( - dtype: dtype[Any] | type[Any], - kind: DTypeLike | tuple[DTypeLike, ...], -) -> builtins.bool: ... +def isdtype(dtype: dtype[Any] | type[Any], kind: DTypeLike | tuple[DTypeLike, ...]) -> builtins.bool: ... -def issubdtype(arg1: DTypeLike, arg2: DTypeLike) -> bool: ... +def issubdtype(arg1: DTypeLike, arg2: DTypeLike) -> builtins.bool: ... typecodes: _TypeCodes ScalarType: tuple[ From 69c30fbd4082c4141cbdfdc9622ed83b40dc0014 Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 6 Jan 2025 20:19:51 +0100 Subject: [PATCH 06/21] TYP: Always accept ``date[time]`` in the ``datetime64`` constructor --- numpy/__init__.pyi | 8 +++++--- numpy/typing/tests/data/pass/scalars.py | 9 +++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index a14234db2735..63c38b744acb 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -4311,11 +4311,13 @@ class datetime64(_RealMixin, generic[_DT64ItemT_co], Generic[_DT64ItemT_co]): @overload def __init__(self: datetime64[int], value: int | bytes | str | dt.date, format: _TimeUnitSpec[_IntTimeUnit], /) -> None: ... @overload - def __init__(self: datetime64[dt.datetime], value: int | bytes | str, format: _TimeUnitSpec[_NativeTimeUnit], /) -> None: ... + def __init__( + self: datetime64[dt.datetime], value: int | bytes | str | dt.date, format: _TimeUnitSpec[_NativeTimeUnit], / + ) -> None: ... @overload - def __init__(self: datetime64[dt.date], value: int | bytes | str, format: _TimeUnitSpec[_DateUnit], /) -> None: ... + def __init__(self: datetime64[dt.date], value: int | bytes | str | dt.date, format: _TimeUnitSpec[_DateUnit], /) -> None: ... @overload - def __init__(self, value: bytes | str | None, format: _TimeUnitSpec = ..., /) -> None: ... + def __init__(self, value: bytes | str | dt.date | None, format: _TimeUnitSpec = ..., /) -> None: ... @overload def __add__(self: datetime64[_AnyDT64Item], x: int | integer[Any] | np.bool, /) -> datetime64[_AnyDT64Item]: ... diff --git a/numpy/typing/tests/data/pass/scalars.py b/numpy/typing/tests/data/pass/scalars.py index 01beb0b29f52..89f24cb92991 100644 --- a/numpy/typing/tests/data/pass/scalars.py +++ b/numpy/typing/tests/data/pass/scalars.py @@ -89,9 +89,18 @@ def __float__(self) -> float: np.datetime64("2019") np.datetime64(b"2019") np.datetime64("2019", "D") +np.datetime64("2019", "us") +np.datetime64("2019", "as") +np.datetime64(np.datetime64()) np.datetime64(np.datetime64()) np.datetime64(dt.datetime(2000, 5, 3)) +np.datetime64(dt.datetime(2000, 5, 3), "D") +np.datetime64(dt.datetime(2000, 5, 3), "us") +np.datetime64(dt.datetime(2000, 5, 3), "as") np.datetime64(dt.date(2000, 5, 3)) +np.datetime64(dt.date(2000, 5, 3), "D") +np.datetime64(dt.date(2000, 5, 3), "us") +np.datetime64(dt.date(2000, 5, 3), "as") np.datetime64(None) np.datetime64(None, "D") From 0a62d0f649d6733c0fbad0acdda5d245639bb0b5 Mon Sep 17 00:00:00 2001 From: Joren Hammudoglu Date: Thu, 2 Jan 2025 23:42:38 +0100 Subject: [PATCH 07/21] MAINT: bump ``mypy`` to ``1.14.1`` (#28089) * MAINT: bump `mypy` to `1.14.1` * TYP: fix new `mypy==1.14.1` type-test errors * TYP: backport `collections.abc.Buffer` for `npt.ArrayLike` on `python<3.11` --- environment.yml | 2 +- numpy/_typing/_array_like.py | 19 +++++++++---------- .../typing/tests/data/reveal/index_tricks.pyi | 12 ++++++------ requirements/test_requirements.txt | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/environment.yml b/environment.yml index ff9fd9e84c20..46655d750d0d 100644 --- a/environment.yml +++ b/environment.yml @@ -25,7 +25,7 @@ dependencies: - hypothesis # For type annotations - typing_extensions>=4.2.0 # needed for python < 3.10 - - mypy=1.13.0 + - mypy=1.14.1 - orjson # makes mypy faster # For building docs - sphinx>=4.5.0 diff --git a/numpy/_typing/_array_like.py b/numpy/_typing/_array_like.py index 292b99d918e2..7798e5d5d751 100644 --- a/numpy/_typing/_array_like.py +++ b/numpy/_typing/_array_like.py @@ -88,17 +88,16 @@ def __array_function__( ) if sys.version_info >= (3, 12): - from collections.abc import Buffer - - ArrayLike: TypeAlias = Buffer | _DualArrayLike[ - dtype[Any], - bool | int | float | complex | str | bytes, - ] + from collections.abc import Buffer as _Buffer else: - ArrayLike: TypeAlias = _DualArrayLike[ - dtype[Any], - bool | int | float | complex | str | bytes, - ] + @runtime_checkable + class _Buffer(Protocol): + def __buffer__(self, flags: int, /) -> memoryview: ... + +ArrayLike: TypeAlias = _Buffer | _DualArrayLike[ + dtype[Any], + bool | int | float | complex | str | bytes, +] # `ArrayLike_co`: array-like objects that can be coerced into `X` # given the casting rules `same_kind` diff --git a/numpy/typing/tests/data/reveal/index_tricks.pyi b/numpy/typing/tests/data/reveal/index_tricks.pyi index 7f5dcf8ccc3e..1db10928d2f5 100644 --- a/numpy/typing/tests/data/reveal/index_tricks.pyi +++ b/numpy/typing/tests/data/reveal/index_tricks.pyi @@ -58,13 +58,13 @@ assert_type(np.mgrid[1:1:2, None:10], npt.NDArray[Any]) assert_type(np.ogrid[1:1:2], tuple[npt.NDArray[Any], ...]) assert_type(np.ogrid[1:1:2, None:10], tuple[npt.NDArray[Any], ...]) -assert_type(np.index_exp[0:1], tuple[slice]) -assert_type(np.index_exp[0:1, None:3], tuple[slice, slice]) -assert_type(np.index_exp[0, 0:1, ..., [0, 1, 3]], tuple[Literal[0], slice, EllipsisType, list[int]]) +assert_type(np.index_exp[0:1], tuple[slice[int, int, None]]) +assert_type(np.index_exp[0:1, None:3], tuple[slice[int, int, None], slice[None, int, None]]) +assert_type(np.index_exp[0, 0:1, ..., [0, 1, 3]], tuple[Literal[0], slice[int, int, None], EllipsisType, list[int]]) -assert_type(np.s_[0:1], slice) -assert_type(np.s_[0:1, None:3], tuple[slice, slice]) -assert_type(np.s_[0, 0:1, ..., [0, 1, 3]], tuple[Literal[0], slice, EllipsisType, list[int]]) +assert_type(np.s_[0:1], slice[int, int, None]) +assert_type(np.s_[0:1, None:3], tuple[slice[int, int, None], slice[None, int, None]]) +assert_type(np.s_[0, 0:1, ..., [0, 1, 3]], tuple[Literal[0], slice[int, int, None], EllipsisType, list[int]]) assert_type(np.ix_(AR_LIKE_b), tuple[npt.NDArray[np.bool], ...]) assert_type(np.ix_(AR_LIKE_i, AR_LIKE_f), tuple[npt.NDArray[np.float64], ...]) diff --git a/requirements/test_requirements.txt b/requirements/test_requirements.txt index dc28402d2cb5..7ea464dadc40 100644 --- a/requirements/test_requirements.txt +++ b/requirements/test_requirements.txt @@ -14,7 +14,7 @@ cffi; python_version < '3.10' # For testing types. Notes on the restrictions: # - Mypy relies on C API features not present in PyPy # NOTE: Keep mypy in sync with environment.yml -mypy==1.13.0; platform_python_implementation != "PyPy" +mypy==1.14.1; platform_python_implementation != "PyPy" typing_extensions>=4.2.0 # for optional f2py encoding detection charset-normalizer From 57afaf591f9cc631b5c2f073236cdc9e868d66b4 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Tue, 7 Jan 2025 11:52:51 +0100 Subject: [PATCH 08/21] BUG: Fix auxdata initialization in ufunc slow path The reason this was not found earlier is that auxdata is currently set by most function and the fast path seems to be taken a shocking amount of times. There are no further similar missing inits. Closes gh-28117 --- numpy/_core/src/umath/ufunc_object.c | 2 +- numpy/_core/tests/test_nep50_promotions.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/numpy/_core/src/umath/ufunc_object.c b/numpy/_core/src/umath/ufunc_object.c index 8748ad5e4974..657330b6f4be 100644 --- a/numpy/_core/src/umath/ufunc_object.c +++ b/numpy/_core/src/umath/ufunc_object.c @@ -1108,7 +1108,7 @@ execute_ufunc_loop(PyArrayMethod_Context *context, int masked, * based on the fixed strides. */ PyArrayMethod_StridedLoop *strided_loop; - NpyAuxData *auxdata; + NpyAuxData *auxdata = NULL; npy_intp fixed_strides[NPY_MAXARGS]; NpyIter_GetInnerFixedStrideArray(iter, fixed_strides); diff --git a/numpy/_core/tests/test_nep50_promotions.py b/numpy/_core/tests/test_nep50_promotions.py index 688be5338437..9eec02239e34 100644 --- a/numpy/_core/tests/test_nep50_promotions.py +++ b/numpy/_core/tests/test_nep50_promotions.py @@ -237,6 +237,20 @@ def test_integer_comparison(sctype, other_val, comp): assert_array_equal(comp(other_val, val_obj), comp(other_val, val)) +@pytest.mark.parametrize("arr", [ + np.ones((100, 100), dtype=np.uint8)[::2], # not trivially iterable + np.ones(20000, dtype=">u4"), # cast and >buffersize + np.ones(100, dtype=">u4"), # fast path compatible with cast +]) +def test_integer_comparison_with_cast(arr): + # Similar to above, but mainly test a few cases that cover the slow path + # the test is limited to unsigned ints and -1 for simplicity. + res = arr >= -1 + assert_array_equal(res, np.ones_like(arr, dtype=bool)) + res = arr < -1 + assert_array_equal(res, np.zeros_like(arr, dtype=bool)) + + @pytest.mark.parametrize("comp", [np.equal, np.not_equal, np.less_equal, np.less, np.greater_equal, np.greater]) From 383d1e1c59401558ac1deadc77ff76cffa77ac54 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 9 Jan 2025 10:34:48 -0700 Subject: [PATCH 09/21] BUG: move reduction initialization to ufunc initialization (#28123) * BUG: move reduction initialization to ufunc initialization * MAINT: refactor to call get_initial_from_ufunc during init * TST: add test for multithreaded reductions * MAINT: fix linter * Apply suggestions from code review Co-authored-by: Sebastian Berg * MAINT: simplify further --------- Co-authored-by: Sebastian Berg --- numpy/_core/src/multiarray/multiarraymodule.c | 37 +++++++-------- numpy/_core/src/umath/legacy_array_method.c | 45 +++++++++++++++---- numpy/_core/tests/test_multithreading.py | 14 ++++++ numpy/testing/_private/utils.py | 4 +- 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/numpy/_core/src/multiarray/multiarraymodule.c b/numpy/_core/src/multiarray/multiarraymodule.c index c9d46d859f60..d337a84e9baf 100644 --- a/numpy/_core/src/multiarray/multiarraymodule.c +++ b/numpy/_core/src/multiarray/multiarraymodule.c @@ -5033,6 +5033,24 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) { goto err; } + /* + * Initialize the default PyDataMem_Handler capsule singleton. + */ + PyDataMem_DefaultHandler = PyCapsule_New( + &default_handler, MEM_HANDLER_CAPSULE_NAME, NULL); + if (PyDataMem_DefaultHandler == NULL) { + goto err; + } + + /* + * Initialize the context-local current handler + * with the default PyDataMem_Handler capsule. + */ + current_handler = PyContextVar_New("current_allocator", PyDataMem_DefaultHandler); + if (current_handler == NULL) { + goto err; + } + if (initumath(m) != 0) { goto err; } @@ -5067,7 +5085,7 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) { * init_string_dtype() but that needs to happen after * the legacy dtypemeta classes are available. */ - + if (npy_cache_import_runtime( "numpy.dtypes", "_add_dtype_helper", &npy_runtime_imports._add_dtype_helper) == -1) { @@ -5081,23 +5099,6 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) { } PyDict_SetItemString(d, "StringDType", (PyObject *)&PyArray_StringDType); - /* - * Initialize the default PyDataMem_Handler capsule singleton. - */ - PyDataMem_DefaultHandler = PyCapsule_New( - &default_handler, MEM_HANDLER_CAPSULE_NAME, NULL); - if (PyDataMem_DefaultHandler == NULL) { - goto err; - } - /* - * Initialize the context-local current handler - * with the default PyDataMem_Handler capsule. - */ - current_handler = PyContextVar_New("current_allocator", PyDataMem_DefaultHandler); - if (current_handler == NULL) { - goto err; - } - // initialize static reference to a zero-like array npy_static_pydata.zero_pyint_like_arr = PyArray_ZEROS( 0, NULL, NPY_DEFAULT_INT, NPY_FALSE); diff --git a/numpy/_core/src/umath/legacy_array_method.c b/numpy/_core/src/umath/legacy_array_method.c index 9592df0e1366..705262fedd38 100644 --- a/numpy/_core/src/umath/legacy_array_method.c +++ b/numpy/_core/src/umath/legacy_array_method.c @@ -311,7 +311,7 @@ get_initial_from_ufunc( } } else if (context->descriptors[0]->type_num == NPY_OBJECT - && !reduction_is_empty) { + && !reduction_is_empty) { /* Allows `sum([object()])` to work, but use 0 when empty. */ Py_DECREF(identity_obj); return 0; @@ -323,13 +323,6 @@ get_initial_from_ufunc( return -1; } - if (PyTypeNum_ISNUMBER(context->descriptors[0]->type_num)) { - /* For numbers we can cache to avoid going via Python ints */ - memcpy(context->method->legacy_initial, initial, - context->descriptors[0]->elsize); - context->method->get_reduction_initial = ©_cached_initial; - } - /* Reduction can use the initial value */ return 1; } @@ -427,11 +420,47 @@ PyArray_NewLegacyWrappingArrayMethod(PyUFuncObject *ufunc, }; PyBoundArrayMethodObject *bound_res = PyArrayMethod_FromSpec_int(&spec, 1); + if (bound_res == NULL) { return NULL; } PyArrayMethodObject *res = bound_res->method; + + // set cached initial value for numeric reductions to avoid creating + // a python int in every reduction + if (PyTypeNum_ISNUMBER(bound_res->dtypes[0]->type_num) && + ufunc->nin == 2 && ufunc->nout == 1) { + + PyArray_Descr *descrs[3]; + + for (int i = 0; i < 3; i++) { + // only dealing with numeric legacy dtypes so this should always be + // valid + descrs[i] = bound_res->dtypes[i]->singleton; + } + + PyArrayMethod_Context context = { + (PyObject *)ufunc, + bound_res->method, + descrs, + }; + + int ret = get_initial_from_ufunc(&context, 0, context.method->legacy_initial); + + if (ret < 0) { + Py_DECREF(bound_res); + return NULL; + } + + // only use the cached initial value if it's valid + if (ret > 0) { + context.method->get_reduction_initial = ©_cached_initial; + } + } + + Py_INCREF(res); Py_DECREF(bound_res); + return res; } diff --git a/numpy/_core/tests/test_multithreading.py b/numpy/_core/tests/test_multithreading.py index 754688501c2d..2512b7c199dc 100644 --- a/numpy/_core/tests/test_multithreading.py +++ b/numpy/_core/tests/test_multithreading.py @@ -120,3 +120,17 @@ def legacy_125(): task1.start() task2.start() + +def test_parallel_reduction(): + # gh-28041 + NUM_THREADS = 50 + + b = threading.Barrier(NUM_THREADS) + + x = np.arange(1000) + + def closure(): + b.wait() + np.sum(x) + + run_threaded(closure, NUM_THREADS, max_workers=NUM_THREADS) diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py index 4ebfb54bd563..fafc4cd34a23 100644 --- a/numpy/testing/_private/utils.py +++ b/numpy/testing/_private/utils.py @@ -2684,9 +2684,9 @@ def _get_glibc_version(): _glibc_older_than = lambda x: (_glibcver != '0.0' and _glibcver < x) -def run_threaded(func, iters, pass_count=False): +def run_threaded(func, iters, pass_count=False, max_workers=8): """Runs a function many times in parallel""" - with concurrent.futures.ThreadPoolExecutor(max_workers=8) as tpe: + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as tpe: if pass_count: futures = [tpe.submit(func, i) for i in range(iters)] else: From 4606ced811f685a4bb79320e8fc5f8ceda347b48 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 9 Jan 2025 01:09:05 +0100 Subject: [PATCH 10/21] TYP: Fix ``interp`` to accept and return scalars Co-authored-by: PTUsumit <2301109104@ptuniv.edu.in> --- numpy/lib/_function_base_impl.pyi | 97 ++++++++++++++++--- .../tests/data/reveal/lib_function_base.pyi | 9 ++ 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/numpy/lib/_function_base_impl.pyi b/numpy/lib/_function_base_impl.pyi index a55a4c3f6b81..214ad1f04f4b 100644 --- a/numpy/lib/_function_base_impl.pyi +++ b/numpy/lib/_function_base_impl.pyi @@ -1,4 +1,4 @@ -from collections.abc import Sequence, Iterator, Callable, Iterable +from collections.abc import Sequence, Callable, Iterable from typing import ( Concatenate, Literal as L, @@ -15,8 +15,9 @@ from typing import ( ) from typing_extensions import deprecated +import numpy as np from numpy import ( - vectorize as vectorize, + vectorize, generic, integer, floating, @@ -35,19 +36,22 @@ from numpy._typing import ( NDArray, ArrayLike, DTypeLike, - _ShapeLike, - _ScalarLike_co, - _DTypeLike, _ArrayLike, + _DTypeLike, + _ShapeLike, _ArrayLikeBool_co, _ArrayLikeInt_co, _ArrayLikeFloat_co, _ArrayLikeComplex_co, + _ArrayLikeNumber_co, _ArrayLikeTD64_co, _ArrayLikeDT64_co, _ArrayLikeObject_co, _FloatLike_co, _ComplexLike_co, + _NumberLike_co, + _ScalarLike_co, + _NestedSequence ) __all__ = [ @@ -303,24 +307,87 @@ def diff( append: ArrayLike = ..., ) -> NDArray[Any]: ... -@overload +@overload # float scalar def interp( - x: _ArrayLikeFloat_co, + x: _FloatLike_co, + xp: _ArrayLikeFloat_co, + fp: _ArrayLikeFloat_co, + left: _FloatLike_co | None = None, + right: _FloatLike_co | None = None, + period: _FloatLike_co | None = None, +) -> float64: ... +@overload # float array +def interp( + x: NDArray[floating | integer | np.bool] | _NestedSequence[_FloatLike_co], xp: _ArrayLikeFloat_co, fp: _ArrayLikeFloat_co, - left: None | _FloatLike_co = ..., - right: None | _FloatLike_co = ..., - period: None | _FloatLike_co = ..., + left: _FloatLike_co | None = None, + right: _FloatLike_co | None = None, + period: _FloatLike_co | None = None, ) -> NDArray[float64]: ... -@overload +@overload # float scalar or array def interp( x: _ArrayLikeFloat_co, xp: _ArrayLikeFloat_co, - fp: _ArrayLikeComplex_co, - left: None | _ComplexLike_co = ..., - right: None | _ComplexLike_co = ..., - period: None | _FloatLike_co = ..., + fp: _ArrayLikeFloat_co, + left: _FloatLike_co | None = None, + right: _FloatLike_co | None = None, + period: _FloatLike_co | None = None, +) -> NDArray[float64] | float64: ... +@overload # complex scalar +def interp( + x: _FloatLike_co, + xp: _ArrayLikeFloat_co, + fp: _ArrayLike[complexfloating], + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, +) -> complex128: ... +@overload # complex or float scalar +def interp( + x: _FloatLike_co, + xp: _ArrayLikeFloat_co, + fp: Sequence[complex | complexfloating], + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, +) -> complex128 | float64: ... +@overload # complex array +def interp( + x: NDArray[floating | integer | np.bool] | _NestedSequence[_FloatLike_co], + xp: _ArrayLikeFloat_co, + fp: _ArrayLike[complexfloating], + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, ) -> NDArray[complex128]: ... +@overload # complex or float array +def interp( + x: NDArray[floating | integer | np.bool] | _NestedSequence[_FloatLike_co], + xp: _ArrayLikeFloat_co, + fp: Sequence[complex | complexfloating], + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, +) -> NDArray[complex128 | float64]: ... +@overload # complex scalar or array +def interp( + x: _ArrayLikeFloat_co, + xp: _ArrayLikeFloat_co, + fp: _ArrayLike[complexfloating], + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, +) -> NDArray[complex128] | complex128: ... +@overload # complex or float scalar or array +def interp( + x: _ArrayLikeFloat_co, + xp: _ArrayLikeFloat_co, + fp: _ArrayLikeNumber_co, + left: _NumberLike_co | None = None, + right: _NumberLike_co | None = None, + period: _FloatLike_co | None = None, +) -> NDArray[complex128 | float64] | complex128 | float64: ... @overload def angle(z: _ComplexLike_co, deg: bool = ...) -> floating[Any]: ... diff --git a/numpy/typing/tests/data/reveal/lib_function_base.pyi b/numpy/typing/tests/data/reveal/lib_function_base.pyi index 6267163e4280..9cd06a36f3e0 100644 --- a/numpy/typing/tests/data/reveal/lib_function_base.pyi +++ b/numpy/typing/tests/data/reveal/lib_function_base.pyi @@ -94,6 +94,15 @@ assert_type(np.diff("bob", n=0), str) assert_type(np.diff(AR_f8, axis=0), npt.NDArray[Any]) assert_type(np.diff(AR_LIKE_f8, prepend=1.5), npt.NDArray[Any]) +assert_type(np.interp(1, [1], AR_f8), np.float64) +assert_type(np.interp(1, [1], [1]), np.float64) +assert_type(np.interp(1, [1], AR_c16), np.complex128) +assert_type(np.interp(1, [1], [1j]), np.complex128) # pyright correctly infers `complex128 | float64` +assert_type(np.interp([1], [1], AR_f8), npt.NDArray[np.float64]) +assert_type(np.interp([1], [1], [1]), npt.NDArray[np.float64]) +assert_type(np.interp([1], [1], AR_c16), npt.NDArray[np.complex128]) +assert_type(np.interp([1], [1], [1j]), npt.NDArray[np.complex128]) # pyright correctly infers `NDArray[complex128 | float64]` + assert_type(np.angle(f8), np.floating[Any]) assert_type(np.angle(AR_f8), npt.NDArray[np.floating[Any]]) assert_type(np.angle(AR_c16, deg=True), npt.NDArray[np.floating[Any]]) From c8e22169af53fd5e8ec28a1531f670585b1569b9 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 9 Jan 2025 14:12:30 -0700 Subject: [PATCH 11/21] BUG: call PyType_Ready in f2py to avoid data races --- numpy/f2py/rules.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py index bf7b46c89f08..84137811a446 100644 --- a/numpy/f2py/rules.py +++ b/numpy/f2py/rules.py @@ -245,6 +245,11 @@ if (! PyErr_Occurred()) on_exit(f2py_report_on_exit,(void*)\"#modulename#\"); #endif + + if (PyType_Ready(&PyFortran_Type) < 0) { + return NULL; + } + return m; } #ifdef __cplusplus From 8dc4ff81a641c234bedd360a497fd99aec6ab18f Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 10 Jan 2025 13:12:28 -0700 Subject: [PATCH 12/21] BUG: remove unnecessary call to PyArray_UpdateFlags --- numpy/_core/src/multiarray/iterators.c | 1 - 1 file changed, 1 deletion(-) diff --git a/numpy/_core/src/multiarray/iterators.c b/numpy/_core/src/multiarray/iterators.c index 2806670d3e07..c3b6500f69d0 100644 --- a/numpy/_core/src/multiarray/iterators.c +++ b/numpy/_core/src/multiarray/iterators.c @@ -136,7 +136,6 @@ PyArray_RawIterBaseInit(PyArrayIterObject *it, PyArrayObject *ao) nd = PyArray_NDIM(ao); /* The legacy iterator only supports 32 dimensions */ assert(nd <= NPY_MAXDIMS_LEGACY_ITERS); - PyArray_UpdateFlags(ao, NPY_ARRAY_C_CONTIGUOUS); if (PyArray_ISCONTIGUOUS(ao)) { it->contiguous = 1; } From ef83ffadf14b0e326c125e14bbab832d328c4521 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 10 Jan 2025 13:47:31 -0700 Subject: [PATCH 13/21] TST: add some features to the run_threaded helper --- numpy/_core/tests/test_multithreading.py | 17 ++++++-------- numpy/testing/_private/utils.py | 28 +++++++++++++++++------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/numpy/_core/tests/test_multithreading.py b/numpy/_core/tests/test_multithreading.py index 2512b7c199dc..f4fe387a44e5 100644 --- a/numpy/_core/tests/test_multithreading.py +++ b/numpy/_core/tests/test_multithreading.py @@ -18,6 +18,7 @@ def func(seed): run_threaded(func, 500, pass_count=True) + def test_parallel_ufunc_execution(): # if the loop data cache or dispatch cache are not thread-safe # computing ufuncs simultaneously in multiple threads leads @@ -31,18 +32,14 @@ def func(): # see gh-26690 NUM_THREADS = 50 - b = threading.Barrier(NUM_THREADS) - a = np.ones(1000) - def f(): + def f(b): b.wait() return a.sum() - threads = [threading.Thread(target=f) for _ in range(NUM_THREADS)] + run_threaded(f, NUM_THREADS, max_workers=NUM_THREADS, pass_barrier=True) - [t.start() for t in threads] - [t.join() for t in threads] def test_temp_elision_thread_safety(): amid = np.ones(50000) @@ -121,16 +118,16 @@ def legacy_125(): task1.start() task2.start() + def test_parallel_reduction(): # gh-28041 NUM_THREADS = 50 - b = threading.Barrier(NUM_THREADS) - x = np.arange(1000) - def closure(): + def closure(b): b.wait() np.sum(x) - run_threaded(closure, NUM_THREADS, max_workers=NUM_THREADS) + run_threaded(closure, NUM_THREADS, max_workers=NUM_THREADS, + pass_barrier=True) diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py index fafc4cd34a23..1e84101d2e49 100644 --- a/numpy/testing/_private/utils.py +++ b/numpy/testing/_private/utils.py @@ -18,6 +18,7 @@ import pprint import sysconfig import concurrent.futures +import threading import numpy as np from numpy._core import ( @@ -2684,12 +2685,23 @@ def _get_glibc_version(): _glibc_older_than = lambda x: (_glibcver != '0.0' and _glibcver < x) -def run_threaded(func, iters, pass_count=False, max_workers=8): +def run_threaded(func, iters=8, pass_count=False, max_workers=8, + pass_barrier=False, outer_iterations=1): """Runs a function many times in parallel""" - with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as tpe: - if pass_count: - futures = [tpe.submit(func, i) for i in range(iters)] - else: - futures = [tpe.submit(func) for _ in range(iters)] - for f in futures: - f.result() + for _ in range(outer_iterations): + with (concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) + as tpe): + args = [] + if pass_barrier: + if max_workers != iters: + raise RuntimeError( + "Must set max_workers equal to the number of " + "iterations to avoid deadlocks.") + barrier = threading.Barrier(max_workers) + args.append(barrier) + if pass_count: + futures = [tpe.submit(func, i, *args) for i in range(iters)] + else: + futures = [tpe.submit(func, *args) for _ in range(iters)] + for f in futures: + f.result() From 422214363991fdea8c9553539244e3d082021b99 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 10 Jan 2025 13:47:55 -0700 Subject: [PATCH 14/21] TST: add test from gh-28042 --- numpy/_core/tests/test_multithreading.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/numpy/_core/tests/test_multithreading.py b/numpy/_core/tests/test_multithreading.py index f4fe387a44e5..a7f3c8269a5b 100644 --- a/numpy/_core/tests/test_multithreading.py +++ b/numpy/_core/tests/test_multithreading.py @@ -131,3 +131,14 @@ def closure(b): run_threaded(closure, NUM_THREADS, max_workers=NUM_THREADS, pass_barrier=True) + + +def test_parallel_flat_iterator(): + x = np.arange(20).reshape(5, 4).T + + def closure(b): + b.wait() + for _ in range(100): + list(x.flat) + + run_threaded(closure, outer_iterations=100, pass_barrier=True) From 94ac8eecd6e4f8524bd85746e9739d424254a637 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Wed, 15 Jan 2025 16:53:55 -0700 Subject: [PATCH 15/21] BUG: Avoid data race in PyArray_CheckFromAny_int (#28154) * BUG: Avoid data race in PyArray_CheckFromAny_int * TST: add test * MAINT: simplify byteswapping code in PyArray_CheckFromAny_int * MAINT: drop ISBYTESWAPPED check --- numpy/_core/src/multiarray/ctors.c | 16 +++++----------- numpy/_core/src/multiarray/dtypemeta.h | 5 +++++ numpy/_core/tests/test_multithreading.py | 13 +++++++++++++ numpy/testing/_private/utils.py | 8 ++++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/numpy/_core/src/multiarray/ctors.c b/numpy/_core/src/multiarray/ctors.c index c9f9ac3941a9..cfa8b9231818 100644 --- a/numpy/_core/src/multiarray/ctors.c +++ b/numpy/_core/src/multiarray/ctors.c @@ -1829,18 +1829,12 @@ PyArray_CheckFromAny_int(PyObject *op, PyArray_Descr *in_descr, { PyObject *obj; if (requires & NPY_ARRAY_NOTSWAPPED) { - if (!in_descr && PyArray_Check(op) && - PyArray_ISBYTESWAPPED((PyArrayObject* )op)) { - in_descr = PyArray_DescrNew(PyArray_DESCR((PyArrayObject *)op)); - if (in_descr == NULL) { - return NULL; - } - } - else if (in_descr && !PyArray_ISNBO(in_descr->byteorder)) { - PyArray_DESCR_REPLACE(in_descr); + if (!in_descr && PyArray_Check(op)) { + in_descr = PyArray_DESCR((PyArrayObject *)op); + Py_INCREF(in_descr); } - if (in_descr && in_descr->byteorder != NPY_IGNORE) { - in_descr->byteorder = NPY_NATIVE; + if (in_descr) { + PyArray_DESCR_REPLACE_CANONICAL(in_descr); } } diff --git a/numpy/_core/src/multiarray/dtypemeta.h b/numpy/_core/src/multiarray/dtypemeta.h index d1b0b13b4bca..8b3abbeb1883 100644 --- a/numpy/_core/src/multiarray/dtypemeta.h +++ b/numpy/_core/src/multiarray/dtypemeta.h @@ -285,6 +285,11 @@ PyArray_SETITEM(PyArrayObject *arr, char *itemptr, PyObject *v) v, itemptr, arr); } +// Like PyArray_DESCR_REPLACE, but calls ensure_canonical instead of DescrNew +#define PyArray_DESCR_REPLACE_CANONICAL(descr) do { \ + PyArray_Descr *_new_ = NPY_DT_CALL_ensure_canonical(descr); \ + Py_XSETREF(descr, _new_); \ + } while(0) #endif /* NUMPY_CORE_SRC_MULTIARRAY_DTYPEMETA_H_ */ diff --git a/numpy/_core/tests/test_multithreading.py b/numpy/_core/tests/test_multithreading.py index a7f3c8269a5b..b614f2c76385 100644 --- a/numpy/_core/tests/test_multithreading.py +++ b/numpy/_core/tests/test_multithreading.py @@ -134,6 +134,7 @@ def closure(b): def test_parallel_flat_iterator(): + # gh-28042 x = np.arange(20).reshape(5, 4).T def closure(b): @@ -142,3 +143,15 @@ def closure(b): list(x.flat) run_threaded(closure, outer_iterations=100, pass_barrier=True) + + # gh-28143 + def prepare_args(): + return [np.arange(10)] + + def closure(x, b): + b.wait() + for _ in range(100): + y = np.arange(10) + y.flat[x] = x + + run_threaded(closure, pass_barrier=True, prepare_args=prepare_args) diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py index 1e84101d2e49..3c2d398e8a29 100644 --- a/numpy/testing/_private/utils.py +++ b/numpy/testing/_private/utils.py @@ -2686,12 +2686,16 @@ def _get_glibc_version(): def run_threaded(func, iters=8, pass_count=False, max_workers=8, - pass_barrier=False, outer_iterations=1): + pass_barrier=False, outer_iterations=1, + prepare_args=None): """Runs a function many times in parallel""" for _ in range(outer_iterations): with (concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as tpe): - args = [] + if prepare_args is None: + args = [] + else: + args = prepare_args() if pass_barrier: if max_workers != iters: raise RuntimeError( From feae11d3964d37bebc58c0239c50efcc8a4b6f89 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 22 Dec 2024 21:57:43 +0000 Subject: [PATCH 16/21] TST: Add f2py case regression Co-authored-by: germasch --- numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 | 5 +++++ numpy/f2py/tests/test_regression.py | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 diff --git a/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 b/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 new file mode 100644 index 000000000000..1c4b8c192b1b --- /dev/null +++ b/numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 @@ -0,0 +1,5 @@ +subroutine inquire_next(IU) + IMPLICIT NONE + integer :: IU + !f2py intent(in) IU +end subroutine diff --git a/numpy/f2py/tests/test_regression.py b/numpy/f2py/tests/test_regression.py index 335c8470d2af..c62f82ac3fc0 100644 --- a/numpy/f2py/tests/test_regression.py +++ b/numpy/f2py/tests/test_regression.py @@ -122,6 +122,15 @@ def test_gh26148b(self): assert(res[0] == 8) assert(res[1] == 15) +class TestLowerF2PYDirectives(util.F2PyTest): + # Check variables are cased correctly + sources = [util.getpath("tests", "src", "regression", "lower_f2py_fortran.f90")] + + @pytest.mark.slow + def test_gh28014(self): + self.module.inquire_next(3) + assert True + @pytest.mark.slow def test_gh26623(): # Including libraries with . should not generate an incorrect meson.build From a19acf1f66e6c8a57ecd37710b444e5bf8d10b89 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 22 Dec 2024 21:58:36 +0000 Subject: [PATCH 17/21] BUG: Fix casing for f2py directives --- numpy/f2py/auxfuncs.py | 7 ++++++- numpy/f2py/crackfortran.py | 8 +++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/numpy/f2py/auxfuncs.py b/numpy/f2py/auxfuncs.py index 095e2600f317..e926a52d1b51 100644 --- a/numpy/f2py/auxfuncs.py +++ b/numpy/f2py/auxfuncs.py @@ -26,7 +26,7 @@ 'hasexternals', 'hasinitvalue', 'hasnote', 'hasresultnote', 'isallocatable', 'isarray', 'isarrayofstrings', 'ischaracter', 'ischaracterarray', 'ischaracter_or_characterarray', - 'iscomplex', + 'iscomplex', 'iscstyledirective', 'iscomplexarray', 'iscomplexfunction', 'iscomplexfunction_warn', 'isdouble', 'isdummyroutine', 'isexternal', 'isfunction', 'isfunction_wrap', 'isint1', 'isint1array', 'isinteger', 'isintent_aux', @@ -423,6 +423,11 @@ def isrequired(var): return not isoptional(var) and isintent_nothide(var) +def iscstyledirective(f2py_line): + directives = {"callstatement", "callprotoargument", "pymethoddef"} + return any(directive in f2py_line.lower() for directive in directives) + + def isintent_in(var): if 'intent' not in var: return 1 diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 6eea03477808..94cb64abe035 100644 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -510,11 +510,9 @@ def readfortrancode(ffile, dowithline=show, istop=1): origfinalline = '' else: if localdolowercase: - # lines with intent() should be lowered otherwise - # TestString::test_char fails due to mixed case - # f2py directives without intent() should be left untouched - # gh-2547, gh-27697, gh-26681 - finalline = ll.lower() if "intent" in ll.lower() or not is_f2py_directive else ll + # only skip lowering for C style constructs + # gh-2547, gh-27697, gh-26681, gh-28014 + finalline = ll.lower() if not (is_f2py_directive and iscstyledirective(ll)) else ll else: finalline = ll origfinalline = ll From f782790c08c50120b68641b3557ab96f5c1964c7 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 16 Jan 2025 20:55:08 +0100 Subject: [PATCH 18/21] TYP: Fix overlapping overloads issue in 2->1 ufuncs --- numpy/_typing/_ufunc.pyi | 160 +++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 49 deletions(-) diff --git a/numpy/_typing/_ufunc.pyi b/numpy/_typing/_ufunc.pyi index 997d297f65d9..b5ac0ff635dd 100644 --- a/numpy/_typing/_ufunc.pyi +++ b/numpy/_typing/_ufunc.pyi @@ -4,32 +4,32 @@ The signatures of the ufuncs are too varied to reasonably type with a single class. So instead, `ufunc` has been expanded into four private subclasses, one for each combination of `~ufunc.nin` and `~ufunc.nout`. - """ from typing import ( Any, Generic, + Literal, NoReturn, - TypedDict, - overload, + Protocol, + SupportsIndex, TypeAlias, + TypedDict, TypeVar, - Literal, - SupportsIndex, - Protocol, + overload, type_check_only, ) + from typing_extensions import LiteralString, Unpack import numpy as np -from numpy import ufunc, _CastingKind, _OrderKACF +from numpy import _CastingKind, _OrderKACF, ufunc from numpy.typing import NDArray -from ._shape import _ShapeLike -from ._scalars import _ScalarLike_co from ._array_like import ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co from ._dtype_like import DTypeLike +from ._scalars import _ScalarLike_co +from ._shape import _ShapeLike _T = TypeVar("_T") _2Tuple: TypeAlias = tuple[_T, _T] @@ -61,6 +61,13 @@ class _SupportsArrayUFunc(Protocol): **kwargs: Any, ) -> Any: ... +@type_check_only +class _UFunc3Kwargs(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + subok: bool + signature: _3Tuple[str | None] | str | None # NOTE: `reduce`, `accumulate`, `reduceat` and `outer` raise a ValueError for # ufuncs that don't accept two input arguments and return one output argument. @@ -72,6 +79,8 @@ class _SupportsArrayUFunc(Protocol): # NOTE: If 2 output types are returned then `out` must be a # 2-tuple of arrays. Otherwise `None` or a plain array are also acceptable +# pyright: reportIncompatibleMethodOverride=false + @type_check_only class _UFunc_Nin1_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] @property @@ -162,34 +171,61 @@ class _UFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: i @property def signature(self) -> None: ... - @overload + @overload # (scalar, scalar) -> scalar def __call__( self, - __x1: _ScalarLike_co, - __x2: _ScalarLike_co, - out: None = ..., + x1: _ScalarLike_co, + x2: _ScalarLike_co, + /, + out: None = None, *, - where: None | _ArrayLikeBool_co = ..., - casting: _CastingKind = ..., - order: _OrderKACF = ..., - dtype: DTypeLike = ..., - subok: bool = ..., - signature: str | _3Tuple[None | str] = ..., + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], ) -> Any: ... - @overload + @overload # (array-like, array) -> array def __call__( self, - __x1: ArrayLike, - __x2: ArrayLike, - out: None | NDArray[Any] | tuple[NDArray[Any]] = ..., + x1: ArrayLike, + x2: NDArray[np.generic], + /, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, *, - where: None | _ArrayLikeBool_co = ..., - casting: _CastingKind = ..., - order: _OrderKACF = ..., - dtype: DTypeLike = ..., - subok: bool = ..., - signature: str | _3Tuple[None | str] = ..., + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any]: ... + @overload # (array, array-like) -> array + def __call__( + self, + x1: NDArray[np.generic], + x2: ArrayLike, + /, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any]: ... + @overload # (array-like, array-like, out=array) -> array + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: NDArray[np.generic] | tuple[NDArray[np.generic]], + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], ) -> NDArray[Any]: ... + @overload # (array-like, array-like) -> array | scalar + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any] | Any: ... def at( self, @@ -227,35 +263,61 @@ class _UFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: i out: None | NDArray[Any] = ..., ) -> NDArray[Any]: ... - # Expand `**kwargs` into explicit keyword-only arguments - @overload + @overload # (scalar, scalar) -> scalar def outer( self, A: _ScalarLike_co, B: _ScalarLike_co, - /, *, - out: None = ..., - where: None | _ArrayLikeBool_co = ..., - casting: _CastingKind = ..., - order: _OrderKACF = ..., - dtype: DTypeLike = ..., - subok: bool = ..., - signature: str | _3Tuple[None | str] = ..., + /, + *, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], ) -> Any: ... - @overload - def outer( # type: ignore[misc] + @overload # (array-like, array) -> array + def outer( self, A: ArrayLike, + B: NDArray[np.generic], + /, + *, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any]: ... + @overload # (array, array-like) -> array + def outer( + self, + A: NDArray[np.generic], B: ArrayLike, - /, *, - out: None | NDArray[Any] | tuple[NDArray[Any]] = ..., - where: None | _ArrayLikeBool_co = ..., - casting: _CastingKind = ..., - order: _OrderKACF = ..., - dtype: DTypeLike = ..., - subok: bool = ..., - signature: str | _3Tuple[None | str] = ..., + /, + *, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], ) -> NDArray[Any]: ... + @overload # (array-like, array-like, out=array) -> array + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: NDArray[np.generic] | tuple[NDArray[np.generic]], + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any]: ... + @overload # (array-like, array-like) -> array | scalar + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: NDArray[np.generic] | tuple[NDArray[np.generic]] | None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Any] | Any: ... @type_check_only class _UFunc_Nin1_Nout2(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] From 6a5f537ca978ed9d5204aa9d24845abf330b765f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20Boya=20Garc=C3=ADa?= Date: Thu, 16 Jan 2025 22:20:02 +0100 Subject: [PATCH 19/21] TYP: preserve shape-type in ndarray.astype() This patch changes the return type in astype() from NDArray to ndarray so that shape information is preserved and adds tests for it. Similar changes are added to np.astype() for consistency. --- numpy/__init__.pyi | 4 ++-- numpy/_core/numeric.pyi | 8 ++++---- numpy/typing/tests/data/reveal/ndarray_conversion.pyi | 8 ++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 742bc7442082..4ab62ecc8f34 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -2500,7 +2500,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): casting: _CastingKind = ..., subok: builtins.bool = ..., copy: builtins.bool | _CopyMode = ..., - ) -> NDArray[_SCT]: ... + ) -> ndarray[_ShapeT_co, dtype[_SCT]]: ... @overload def astype( self, @@ -2509,7 +2509,7 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DType_co]): casting: _CastingKind = ..., subok: builtins.bool = ..., copy: builtins.bool | _CopyMode = ..., - ) -> NDArray[Any]: ... + ) -> ndarray[_ShapeT_co, dtype[Any]]: ... @overload def view(self) -> Self: ... diff --git a/numpy/_core/numeric.pyi b/numpy/_core/numeric.pyi index 41c9873877e0..d23300752cd7 100644 --- a/numpy/_core/numeric.pyi +++ b/numpy/_core/numeric.pyi @@ -872,15 +872,15 @@ def array_equiv(a1: ArrayLike, a2: ArrayLike) -> bool: ... @overload def astype( - x: NDArray[Any], + x: ndarray[_ShapeType, dtype[Any]], dtype: _DTypeLike[_SCT], copy: bool = ..., device: None | L["cpu"] = ..., -) -> NDArray[_SCT]: ... +) -> ndarray[_ShapeType, dtype[_SCT]]: ... @overload def astype( - x: NDArray[Any], + x: ndarray[_ShapeType, dtype[Any]], dtype: DTypeLike, copy: bool = ..., device: None | L["cpu"] = ..., -) -> NDArray[Any]: ... +) -> ndarray[_ShapeType, dtype[Any]]: ... diff --git a/numpy/typing/tests/data/reveal/ndarray_conversion.pyi b/numpy/typing/tests/data/reveal/ndarray_conversion.pyi index 789585ec963b..b6909e64f780 100644 --- a/numpy/typing/tests/data/reveal/ndarray_conversion.pyi +++ b/numpy/typing/tests/data/reveal/ndarray_conversion.pyi @@ -11,6 +11,7 @@ i4_2d: np.ndarray[tuple[int, int], np.dtype[np.int32]] f8_3d: np.ndarray[tuple[int, int, int], np.dtype[np.float64]] cG_4d: np.ndarray[tuple[int, int, int, int], np.dtype[np.clongdouble]] i0_nd: npt.NDArray[np.int_] +uncertain_dtype: np.int32 | np.float64 | np.str_ # item assert_type(i0_nd.item(), int) @@ -50,6 +51,13 @@ assert_type(i0_nd.astype(np.float64, "K", "unsafe", True, True), npt.NDArray[np. assert_type(np.astype(i0_nd, np.float64), npt.NDArray[np.float64]) +assert_type(i4_2d.astype(np.uint16), np.ndarray[tuple[int, int], np.dtype[np.uint16]]) +assert_type(np.astype(i4_2d, np.uint16), np.ndarray[tuple[int, int], np.dtype[np.uint16]]) +assert_type(f8_3d.astype(np.int16), np.ndarray[tuple[int, int, int], np.dtype[np.int16]]) +assert_type(np.astype(f8_3d, np.int16), np.ndarray[tuple[int, int, int], np.dtype[np.int16]]) +assert_type(i4_2d.astype(uncertain_dtype), np.ndarray[tuple[int, int], np.dtype[np.generic[Any]]]) +assert_type(np.astype(i4_2d, uncertain_dtype), np.ndarray[tuple[int, int], np.dtype[Any]]) + # byteswap assert_type(i0_nd.byteswap(), npt.NDArray[np.int_]) assert_type(i0_nd.byteswap(True), npt.NDArray[np.int_]) From b04e32c15e6b3ad268fe5b314209915e7779764e Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 16 Jan 2025 16:32:52 +0100 Subject: [PATCH 20/21] TYP: Fix missing and spurious top-level exports --- numpy/__init__.pyi | 98 +++++++++++++++--------- numpy/typing/tests/data/fail/modules.pyi | 1 - 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 742bc7442082..ce021af22b68 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -1,3 +1,4 @@ +# ruff: noqa: I001 import builtins import sys import mmap @@ -206,17 +207,19 @@ else: ) from typing import ( - Literal as L, Any, + ClassVar, + Final, + Generic, + Literal as L, NoReturn, SupportsComplex, SupportsFloat, SupportsInt, SupportsIndex, - Final, - final, - ClassVar, TypeAlias, + TypedDict, + final, type_check_only, ) @@ -225,11 +228,13 @@ from typing import ( # library include `typing_extensions` stubs: # https://github.com/python/typeshed/blob/main/stdlib/typing_extensions.pyi from _typeshed import StrOrBytesPath, SupportsFlush, SupportsLenAndGetItem, SupportsWrite -from typing_extensions import CapsuleType, Generic, LiteralString, Never, Protocol, Self, TypeVar, Unpack, deprecated, overload +from typing_extensions import CapsuleType, LiteralString, Never, Protocol, Self, TypeVar, Unpack, deprecated, overload from numpy import ( + char, core, ctypeslib, + dtypes, exceptions, f2py, fft, @@ -238,15 +243,22 @@ from numpy import ( ma, polynomial, random, - testing, - typing, - version, - dtypes, rec, - char, strings, + testing, + typing, ) +# available through `__getattr__`, but not in `__all__` or `__dir__` +from numpy import ( + __config__ as __config__, + matlib as matlib, + matrixlib as matrixlib, + version as version, +) +if sys.version_info < (3, 12): + from numpy import distutils as distutils + from numpy._core.records import ( record, recarray, @@ -440,6 +452,7 @@ from numpy.lib._arraypad_impl import ( from numpy.lib._arraysetops_impl import ( ediff1d, + in1d, intersect1d, isin, setdiff1d, @@ -481,6 +494,8 @@ from numpy.lib._function_base_impl import ( bartlett, blackman, kaiser, + trapezoid, + trapz, i0, meshgrid, delete, @@ -488,7 +503,6 @@ from numpy.lib._function_base_impl import ( append, interp, quantile, - trapezoid, ) from numpy.lib._histograms_impl import ( @@ -627,13 +641,10 @@ from numpy.matrixlib import ( bmat, ) -__all__ = [ - "emath", "show_config", "version", "__version__", "__array_namespace_info__", - +__all__ = [ # noqa: RUF022 # __numpy_submodules__ - "linalg", "fft", "dtypes", "random", "polynomial", "ma", "exceptions", "lib", - "ctypeslib", "testing", "test", "rec", "char", "strings", - "core", "typing", "f2py", + "char", "core", "ctypeslib", "dtypes", "exceptions", "f2py", "fft", "lib", "linalg", + "ma", "polynomial", "random", "rec", "strings", "test", "testing", "typing", # _core.__all__ "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "atan2", "bitwise_invert", @@ -651,8 +662,8 @@ __all__ = [ "tensordot", "little_endian", "fromiter", "array_equal", "array_equiv", "indices", "fromfunction", "isclose", "isscalar", "binary_repr", "base_repr", "ones", "identity", "allclose", "putmask", "flatnonzero", "inf", "nan", "False_", "True_", - "bitwise_not", "full", "full_like", "matmul", "vecdot", "shares_memory", - "may_share_memory", "_get_promotion_state", "_set_promotion_state", + "bitwise_not", "full", "full_like", "matmul", "vecdot", "vecmat", + "shares_memory", "may_share_memory", "all", "amax", "amin", "any", "argmax", "argmin", "argpartition", "argsort", "around", "choose", "clip", "compress", "cumprod", "cumsum", "cumulative_prod", "cumulative_sum", "diagonal", "mean", "max", "min", "matrix_transpose", "ndim", @@ -667,7 +678,7 @@ __all__ = [ "frompyfunc", "gcd", "greater", "greater_equal", "heaviside", "hypot", "invert", "isfinite", "isinf", "isnan", "isnat", "lcm", "ldexp", "left_shift", "less", "less_equal", "log", "log10", "log1p", "log2", "logaddexp", "logaddexp2", - "logical_and", "logical_not", "logical_or", "logical_xor", "maximum", "minimum", + "logical_and", "logical_not", "logical_or", "logical_xor", "matvec", "maximum", "minimum", "mod", "modf", "multiply", "negative", "nextafter", "not_equal", "pi", "positive", "power", "rad2deg", "radians", "reciprocal", "remainder", "right_shift", "rint", "sign", "signbit", "sin", "sinh", "spacing", "sqrt", "square", "subtract", "tan", @@ -686,7 +697,7 @@ __all__ = [ "array2string", "array_str", "array_repr", "set_printoptions", "get_printoptions", "printoptions", "format_float_positional", "format_float_scientific", "require", "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall", - "errstate", "_no_nep50_warning", + "errstate", # _core.function_base.__all__ "logspace", "linspace", "geomspace", # _core.getlimits.__all__ @@ -696,7 +707,8 @@ __all__ = [ "vstack", # _core.einsumfunc.__all__ "einsum", "einsum_path", - + # matrixlib.__all__ + "matrix", "bmat", "asmatrix", # lib._histograms_impl.__all__ "histogram", "histogramdd", "histogram_bin_edges", # lib._nanfunctions_impl.__all__ @@ -704,13 +716,12 @@ __all__ = [ "nanpercentile", "nanvar", "nanstd", "nanprod", "nancumsum", "nancumprod", "nanquantile", # lib._function_base_impl.__all__ - # NOTE: `trapz` is omitted because it is deprecated "select", "piecewise", "trim_zeros", "copy", "iterable", "percentile", "diff", "gradient", "angle", "unwrap", "sort_complex", "flip", "rot90", "extract", "place", "vectorize", "asarray_chkfinite", "average", "bincount", "digitize", "cov", "corrcoef", "median", "sinc", "hamming", "hanning", "bartlett", "blackman", - "kaiser", "i0", "meshgrid", "delete", "insert", "append", "interp", "quantile", - "trapezoid", + "kaiser", "trapezoid", "trapz", "i0", "meshgrid", "delete", "insert", "append", + "interp", "quantile", # lib._twodim_base_impl.__all__ "diag", "diagflat", "eye", "fliplr", "flipud", "tri", "triu", "tril", "vander", "histogram2d", "mask_indices", "tril_indices", "tril_indices_from", "triu_indices", @@ -724,9 +735,8 @@ __all__ = [ "iscomplexobj", "isrealobj", "imag", "iscomplex", "isreal", "nan_to_num", "real", "real_if_close", "typename", "mintypecode", "common_type", # lib._arraysetops_impl.__all__ - # NOTE: `in1d` is omitted because it is deprecated - "ediff1d", "intersect1d", "isin", "setdiff1d", "setxor1d", "union1d", "unique", - "unique_all", "unique_counts", "unique_inverse", "unique_values", + "ediff1d", "in1d", "intersect1d", "isin", "setdiff1d", "setxor1d", "union1d", + "unique", "unique_all", "unique_counts", "unique_inverse", "unique_values", # lib._ufunclike_impl.__all__ "fix", "isneginf", "isposinf", # lib._arraypad_impl.__all__ @@ -746,9 +756,9 @@ __all__ = [ "index_exp", "ix_", "ndenumerate", "ndindex", "fill_diagonal", "diag_indices", "diag_indices_from", - # matrixlib.__all__ - "matrix", "bmat", "asmatrix", -] + # __init__.__all__ + "emath", "show_config", "__version__", "__array_namespace_info__", +] # fmt: skip ### Constrained types (for internal use only) # Only use these for functions; never as generic type parameter. @@ -1047,6 +1057,16 @@ _IntTD64Unit: TypeAlias = L[_MonthUnit, _IntTimeUnit] _TD64Unit: TypeAlias = L[_DateUnit, _TimeUnit] _TimeUnitSpec: TypeAlias = _TD64UnitT | tuple[_TD64UnitT, SupportsIndex] +### TypedDict's (for internal use only) + +@type_check_only +class _FormerAttrsDict(TypedDict): + object: LiteralString + float: LiteralString + complex: LiteralString + str: LiteralString + int: LiteralString + ### Protocols (for internal use only) @type_check_only @@ -1150,22 +1170,26 @@ class _IntegralMixin(_RealMixin): ### Public API __version__: Final[LiteralString] = ... -__array_api_version__: Final = "2023.12" -test: Final[PytestTester] = ... e: Final[float] = ... euler_gamma: Final[float] = ... +pi: Final[float] = ... inf: Final[float] = ... nan: Final[float] = ... -pi: Final[float] = ... - little_endian: Final[builtins.bool] = ... - False_: Final[np.bool[L[False]]] = ... True_: Final[np.bool[L[True]]] = ... - newaxis: Final[None] = None +# not in __all__ +__NUMPY_SETUP__: Final[L[False]] = False +__numpy_submodules__: Final[set[LiteralString]] = ... +__expired_attributes__: Final[dict[LiteralString, LiteralString]] +__former_attrs__: Final[_FormerAttrsDict] = ... +__future_scalars__: Final[set[L["bytes", "str", "object"]]] = ... +__array_api_version__: Final[L["2023.12"]] = "2023.12" +test: Final[PytestTester] = ... + @final class dtype(Generic[_SCT_co]): names: None | tuple[builtins.str, ...] diff --git a/numpy/typing/tests/data/fail/modules.pyi b/numpy/typing/tests/data/fail/modules.pyi index c86627e0c8ea..541be15b24ae 100644 --- a/numpy/typing/tests/data/fail/modules.pyi +++ b/numpy/typing/tests/data/fail/modules.pyi @@ -13,6 +13,5 @@ np.math # E: Module has no attribute # e.g. one must first execute `import numpy.lib.recfunctions` np.lib.recfunctions # E: Module has no attribute -np.__NUMPY_SETUP__ # E: Module has no attribute np.__deprecated_attrs__ # E: Module has no attribute np.__expired_functions__ # E: Module has no attribute From 0d106a5162608e04f30688ed9226efdba765b405 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Sat, 18 Jan 2025 12:22:51 -0700 Subject: [PATCH 21/21] REL: Prepare for the NumPy 2.2.2 release [wheel build] - Create 2.2.2-changelog.rst. - Update 2.2.2-notes.rst. - Update .mailmap. --- .mailmap | 1 + doc/changelog/2.2.2-changelog.rst | 37 ++++++++++++++++++++ doc/source/release/2.2.2-notes.rst | 54 +++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 doc/changelog/2.2.2-changelog.rst diff --git a/.mailmap b/.mailmap index 4853320b7835..1ae0bce7f11a 100644 --- a/.mailmap +++ b/.mailmap @@ -398,6 +398,7 @@ Julien Schueller Junyan Ou Justus Magin Justus Magin +Kai Germaschewski Kai Striega Kai Striega Kasia Leszek diff --git a/doc/changelog/2.2.2-changelog.rst b/doc/changelog/2.2.2-changelog.rst new file mode 100644 index 000000000000..ac856c97174c --- /dev/null +++ b/doc/changelog/2.2.2-changelog.rst @@ -0,0 +1,37 @@ + +Contributors +============ + +A total of 8 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* Alicia Boya García + +* Charles Harris +* Joren Hammudoglu +* Kai Germaschewski + +* Nathan Goldbaum +* PTUsumit + +* Rohit Goswami +* Sebastian Berg + +Pull requests merged +==================== + +A total of 16 pull requests were merged for this release. + +* `#28050 `__: MAINT: Prepare 2.2.x for further development +* `#28055 `__: TYP: fix ``void`` arrays not accepting ``str`` keys in ``__setitem__`` +* `#28066 `__: TYP: fix unnecessarily broad ``integer`` binop return types (#28065) +* `#28112 `__: TYP: Better ``ndarray`` binop return types for ``float64`` &... +* `#28113 `__: TYP: Return the correct ``bool`` from ``issubdtype`` +* `#28114 `__: TYP: Always accept ``date[time]`` in the ``datetime64`` constructor +* `#28120 `__: BUG: Fix auxdata initialization in ufunc slow path +* `#28131 `__: BUG: move reduction initialization to ufunc initialization +* `#28132 `__: TYP: Fix ``interp`` to accept and return scalars +* `#28137 `__: BUG: call PyType_Ready in f2py to avoid data races +* `#28145 `__: BUG: remove unnecessary call to PyArray_UpdateFlags +* `#28160 `__: BUG: Avoid data race in PyArray_CheckFromAny_int +* `#28175 `__: BUG: Fix f2py directives and --lower casing +* `#28176 `__: TYP: Fix overlapping overloads issue in 2->1 ufuncs +* `#28177 `__: TYP: preserve shape-type in ndarray.astype() +* `#28178 `__: TYP: Fix missing and spurious top-level exports diff --git a/doc/source/release/2.2.2-notes.rst b/doc/source/release/2.2.2-notes.rst index 271a16f4c32b..8a3de547ec81 100644 --- a/doc/source/release/2.2.2-notes.rst +++ b/doc/source/release/2.2.2-notes.rst @@ -4,16 +4,46 @@ NumPy 2.2.2 Release Notes ========================== +NumPy 2.2.2 is a patch release that fixes bugs found after the 2.2.1 release. +The number of typing fixes/updates is notable. This release supports Python +versions 3.10-3.13. + + +Contributors +============ + +A total of 8 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* Alicia Boya García + +* Charles Harris +* Joren Hammudoglu +* Kai Germaschewski + +* Nathan Goldbaum +* PTUsumit + +* Rohit Goswami +* Sebastian Berg + + +Pull requests merged +==================== + +A total of 16 pull requests were merged for this release. + +* `#28050 `__: MAINT: Prepare 2.2.x for further development +* `#28055 `__: TYP: fix ``void`` arrays not accepting ``str`` keys in ``__setitem__`` +* `#28066 `__: TYP: fix unnecessarily broad ``integer`` binop return types (#28065) +* `#28112 `__: TYP: Better ``ndarray`` binop return types for ``float64`` &... +* `#28113 `__: TYP: Return the correct ``bool`` from ``issubdtype`` +* `#28114 `__: TYP: Always accept ``date[time]`` in the ``datetime64`` constructor +* `#28120 `__: BUG: Fix auxdata initialization in ufunc slow path +* `#28131 `__: BUG: move reduction initialization to ufunc initialization +* `#28132 `__: TYP: Fix ``interp`` to accept and return scalars +* `#28137 `__: BUG: call PyType_Ready in f2py to avoid data races +* `#28145 `__: BUG: remove unnecessary call to PyArray_UpdateFlags +* `#28160 `__: BUG: Avoid data race in PyArray_CheckFromAny_int +* `#28175 `__: BUG: Fix f2py directives and --lower casing +* `#28176 `__: TYP: Fix overlapping overloads issue in 2->1 ufuncs +* `#28177 `__: TYP: preserve shape-type in ndarray.astype() +* `#28178 `__: TYP: Fix missing and spurious top-level exports -Highlights -========== - -*We'll choose highlights for this release near the end of the release cycle.* - - -.. if release snippets have been incorporated already, uncomment the follow - line (leave the `.. include:: directive) - -.. **Content from release note snippets in doc/release/upcoming_changes:** - -.. include:: notes-towncrier.rst