From f379ba97896b365c5b1689ec309e9b61d0ce8641 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Thu, 11 Jan 2024 15:19:10 +0100 Subject: [PATCH 1/5] WIP: MAINT: change list-of-array to tuple-of-array returns (Numba compat) Functions in NumPy that return lists of arrays are problematic for Numba. See https://github.com/numba/numba/issues/8008 for a detailed discussion on that. This changes the return types to tuples, which are easier to support for Numba, because tuples are immutable. This change is not backwards-compatible. Estimated impact: - idiomatic end user code should continue to work unchanged, - code that attempts to append or otherwise mutate the list will start raising an exception, which should be easy to fix, - user code that does `if isinstance(..., list):` on the return value of a function like `atleast1d` will break. This should be rare, but since it may not result in a clean error it is probably the place with the highest impact. - user code with explicit `list[NDArray]` type annotations will need to be updated. [skip cirrus] [skip circle] --- numpy/_core/shape_base.py | 20 +++++++-------- numpy/lib/_shape_base_impl.py | 44 ++++++++++++++++---------------- numpy/lib/_shape_base_impl.pyi | 20 +++++++-------- numpy/lib/_stride_tricks_impl.py | 18 +++++++------ 4 files changed, 52 insertions(+), 50 deletions(-) diff --git a/numpy/_core/shape_base.py b/numpy/_core/shape_base.py index 72fe9e9a11c5..cd13b3d0b839 100644 --- a/numpy/_core/shape_base.py +++ b/numpy/_core/shape_base.py @@ -36,7 +36,7 @@ def atleast_1d(*arys): Returns ------- ret : ndarray - An array, or list of arrays, each with ``a.ndim >= 1``. + An array, or tuple of arrays, each with ``a.ndim >= 1``. Copies are made only if necessary. See Also @@ -57,7 +57,7 @@ def atleast_1d(*arys): True >>> np.atleast_1d(1, [3, 4]) - [array([1]), array([3, 4])] + (array([1]), array([3, 4])) """ res = [] @@ -71,7 +71,7 @@ def atleast_1d(*arys): if len(res) == 1: return res[0] else: - return res + return tuple(res) def _atleast_2d_dispatcher(*arys): @@ -93,7 +93,7 @@ def atleast_2d(*arys): Returns ------- res, res2, ... : ndarray - An array, or list of arrays, each with ``a.ndim >= 2``. + An array, or tuple of arrays, each with ``a.ndim >= 2``. Copies are avoided where possible, and views with two or more dimensions are returned. @@ -113,7 +113,7 @@ def atleast_2d(*arys): True >>> np.atleast_2d(1, [1, 2], [[1, 2]]) - [array([[1]]), array([[1, 2]]), array([[1, 2]])] + (array([[1]]), array([[1, 2]]), array([[1, 2]])) """ res = [] @@ -129,7 +129,7 @@ def atleast_2d(*arys): if len(res) == 1: return res[0] else: - return res + return tuple(res) def _atleast_3d_dispatcher(*arys): @@ -151,7 +151,7 @@ def atleast_3d(*arys): Returns ------- res1, res2, ... : ndarray - An array, or list of arrays, each with ``a.ndim >= 3``. Copies are + An array, or tuple of arrays, each with ``a.ndim >= 3``. Copies are avoided where possible, and views with three or more dimensions are returned. For example, a 1-D array of shape ``(N,)`` becomes a view of shape ``(1, N, 1)``, and a 2-D array of shape ``(M, N)`` becomes a @@ -201,7 +201,7 @@ def atleast_3d(*arys): if len(res) == 1: return res[0] else: - return res + return tuple(res) def _arrays_for_stack_dispatcher(arrays): @@ -282,7 +282,7 @@ def vstack(tup, *, dtype=None, casting="same_kind"): """ arrs = atleast_2d(*tup) - if not isinstance(arrs, list): + if not isinstance(arrs, tuple): arrs = [arrs] return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting) @@ -349,7 +349,7 @@ def hstack(tup, *, dtype=None, casting="same_kind"): """ arrs = atleast_1d(*tup) - if not isinstance(arrs, list): + if not isinstance(arrs, tuple): arrs = [arrs] # As a special case, dimension 0 of 1-dimensional arrays is "horizontal" if arrs and arrs[0].ndim == 1: diff --git a/numpy/lib/_shape_base_impl.py b/numpy/lib/_shape_base_impl.py index 6a84e9f82cf2..2d931a10f16e 100644 --- a/numpy/lib/_shape_base_impl.py +++ b/numpy/lib/_shape_base_impl.py @@ -726,7 +726,7 @@ def dstack(tup): """ arrs = atleast_3d(*tup) - if not isinstance(arrs, list): + if not isinstance(arrs, tuple): arrs = [arrs] return _nx.concatenate(arrs, 2) @@ -764,11 +764,11 @@ def array_split(ary, indices_or_sections, axis=0): -------- >>> x = np.arange(8.0) >>> np.array_split(x, 3) - [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])] + (array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])) >>> x = np.arange(9) >>> np.array_split(x, 4) - [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])] + (array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])) """ try: @@ -797,7 +797,7 @@ def array_split(ary, indices_or_sections, axis=0): end = div_points[i + 1] sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0)) - return sub_arys + return tuple(sub_arys) def _split_dispatcher(ary, indices_or_sections, axis=None): @@ -833,8 +833,8 @@ def split(ary, indices_or_sections, axis=0): Returns ------- - sub-arrays : list of ndarrays - A list of sub-arrays as views into `ary`. + sub-arrays : tuple of ndarrays + A tuple of sub-arrays as views into `ary`. Raises ------ @@ -860,15 +860,15 @@ def split(ary, indices_or_sections, axis=0): -------- >>> x = np.arange(9.0) >>> np.split(x, 3) - [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])] + (array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])) >>> x = np.arange(8.0) >>> np.split(x, [3, 5, 6, 10]) - [array([0., 1., 2.]), + (array([0., 1., 2.]), array([3., 4.]), array([5.]), array([6., 7.]), - array([], dtype=float64)] + array([], dtype=float64)) """ try: @@ -936,16 +936,16 @@ def hsplit(ary, indices_or_sections): [[4., 5.], [6., 7.]]]) >>> np.hsplit(x, 2) - [array([[[0., 1.]], + (array([[[0., 1.]], [[4., 5.]]]), array([[[2., 3.]], - [[6., 7.]]])] + [[6., 7.]]])) With a 1-D array, the split is along axis 0. >>> x = np.array([0, 1, 2, 3, 4, 5]) >>> np.hsplit(x, 2) - [array([0, 1, 2]), array([3, 4, 5])] + (array([0, 1, 2]), array([3, 4, 5])) """ if _nx.ndim(ary) == 0: @@ -978,13 +978,13 @@ def vsplit(ary, indices_or_sections): [ 8., 9., 10., 11.], [12., 13., 14., 15.]]) >>> np.vsplit(x, 2) - [array([[0., 1., 2., 3.], + (array([[0., 1., 2., 3.], [4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.], - [12., 13., 14., 15.]])] + [12., 13., 14., 15.]])) >>> np.vsplit(x, np.array([3, 6])) - [array([[ 0., 1., 2., 3.], + (array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], - [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)] + [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)) With a higher dimensional array the split is still along the first axis. @@ -995,9 +995,9 @@ def vsplit(ary, indices_or_sections): [[4., 5.], [6., 7.]]]) >>> np.vsplit(x, 2) - [array([[[0., 1.], + (array([[[0., 1.], [2., 3.]]]), array([[[4., 5.], - [6., 7.]]])] + [6., 7.]]])) """ if _nx.ndim(ary) < 2: @@ -1027,15 +1027,15 @@ def dsplit(ary, indices_or_sections): [[ 8., 9., 10., 11.], [12., 13., 14., 15.]]]) >>> np.dsplit(x, 2) - [array([[[ 0., 1.], + (array([[[ 0., 1.], [ 4., 5.]], [[ 8., 9.], [12., 13.]]]), array([[[ 2., 3.], [ 6., 7.]], [[10., 11.], - [14., 15.]]])] + [14., 15.]]])) >>> np.dsplit(x, np.array([3, 6])) - [array([[[ 0., 1., 2.], + (array([[[ 0., 1., 2.], [ 4., 5., 6.]], [[ 8., 9., 10.], [12., 13., 14.]]]), @@ -1043,7 +1043,7 @@ def dsplit(ary, indices_or_sections): [ 7.]], [[11.], [15.]]]), - array([], shape=(2, 2, 0), dtype=float64)] + array([], shape=(2, 2, 0), dtype=float64)) """ if _nx.ndim(ary) < 3: raise ValueError('dsplit only works on arrays of 3 or more dimensions') diff --git a/numpy/lib/_shape_base_impl.pyi b/numpy/lib/_shape_base_impl.pyi index 07adb3c12858..4a5736ff1005 100644 --- a/numpy/lib/_shape_base_impl.pyi +++ b/numpy/lib/_shape_base_impl.pyi @@ -115,59 +115,59 @@ def array_split( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> list[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT]]: ... @overload def array_split( ary: ArrayLike, indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def split( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> list[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT]]: ... @overload def split( ary: ArrayLike, indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def hsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> list[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT]]: ... @overload def hsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def vsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> list[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT]]: ... @overload def vsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def dsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> list[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT]]: ... @overload def dsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def get_array_wrap(*args: _SupportsArrayWrap) -> _ArrayWrap: ... diff --git a/numpy/lib/_stride_tricks_impl.py b/numpy/lib/_stride_tricks_impl.py index d8c5dcdfba2d..9fc095e9a502 100644 --- a/numpy/lib/_stride_tricks_impl.py +++ b/numpy/lib/_stride_tricks_impl.py @@ -502,7 +502,7 @@ def broadcast_arrays(*args, subok=False): Returns ------- - broadcasted : list of arrays + broadcasted : tuple of arrays These arrays are views on the original arrays. They are typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location. If you need @@ -526,17 +526,19 @@ def broadcast_arrays(*args, subok=False): >>> x = np.array([[1,2,3]]) >>> y = np.array([[4],[5]]) >>> np.broadcast_arrays(x, y) - [array([[1, 2, 3], - [1, 2, 3]]), array([[4, 4, 4], - [5, 5, 5]])] + (array([[1, 2, 3], + [1, 2, 3]]), + array([[4, 4, 4], + [5, 5, 5]])) Here is a useful idiom for getting contiguous copies instead of non-contiguous views. >>> [np.array(a) for a in np.broadcast_arrays(x, y)] [array([[1, 2, 3], - [1, 2, 3]]), array([[4, 4, 4], - [5, 5, 5]])] + [1, 2, 3]]), + array([[4, 4, 4], + [5, 5, 5]])] """ # nditer is not used here to avoid the limit of 32 arrays. @@ -552,5 +554,5 @@ def broadcast_arrays(*args, subok=False): # Common case where nothing needs to be broadcasted. return args - return [_broadcast_to(array, shape, subok=subok, readonly=False) - for array in args] + return tuple([_broadcast_to(array, shape, subok=subok, readonly=False) + for array in args]) From ac375303aecc96576de46e13790ade30a84bd946 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 19 Jan 2024 18:10:08 +0100 Subject: [PATCH 2/5] ENH: finish list[ndarray] -> tuple[ndarray] changes --- numpy/_core/shape_base.py | 4 ++-- numpy/_core/shape_base.pyi | 6 +++--- numpy/lib/_shape_base_impl.py | 8 +++++--- numpy/lib/_stride_tricks_impl.py | 6 +++--- numpy/lib/_stride_tricks_impl.pyi | 2 +- .../tests/data/reveal/array_constructors.pyi | 8 +++++--- numpy/typing/tests/data/reveal/shape_base.pyi | 20 +++++++++---------- .../tests/data/reveal/stride_tricks.pyi | 4 ++-- 8 files changed, 31 insertions(+), 27 deletions(-) diff --git a/numpy/_core/shape_base.py b/numpy/_core/shape_base.py index cd13b3d0b839..1efdcbc091b0 100644 --- a/numpy/_core/shape_base.py +++ b/numpy/_core/shape_base.py @@ -283,7 +283,7 @@ def vstack(tup, *, dtype=None, casting="same_kind"): """ arrs = atleast_2d(*tup) if not isinstance(arrs, tuple): - arrs = [arrs] + arrs = (arrs,) return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting) @@ -350,7 +350,7 @@ def hstack(tup, *, dtype=None, casting="same_kind"): """ arrs = atleast_1d(*tup) if not isinstance(arrs, tuple): - arrs = [arrs] + arrs = (arrs,) # As a special case, dimension 0 of 1-dimensional arrays is "horizontal" if arrs and arrs[0].ndim == 1: return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting) diff --git a/numpy/_core/shape_base.pyi b/numpy/_core/shape_base.pyi index 10116f1ee9e7..b9220ff84157 100644 --- a/numpy/_core/shape_base.pyi +++ b/numpy/_core/shape_base.pyi @@ -20,21 +20,21 @@ def atleast_1d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_1d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_1d(*arys: ArrayLike) -> list[NDArray[Any]]: ... +def atleast_1d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... @overload def atleast_2d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_2d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_2d(*arys: ArrayLike) -> list[NDArray[Any]]: ... +def atleast_2d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... @overload def atleast_3d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_3d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_3d(*arys: ArrayLike) -> list[NDArray[Any]]: ... +def atleast_3d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... @overload def vstack( diff --git a/numpy/lib/_shape_base_impl.py b/numpy/lib/_shape_base_impl.py index 2d931a10f16e..ed61e5f57bf9 100644 --- a/numpy/lib/_shape_base_impl.py +++ b/numpy/lib/_shape_base_impl.py @@ -727,7 +727,7 @@ def dstack(tup): """ arrs = atleast_3d(*tup) if not isinstance(arrs, tuple): - arrs = [arrs] + arrs = (arrs,) return _nx.concatenate(arrs, 2) @@ -983,8 +983,10 @@ def vsplit(ary, indices_or_sections): [12., 13., 14., 15.]])) >>> np.vsplit(x, np.array([3, 6])) (array([[ 0., 1., 2., 3.], - [ 4., 5., 6., 7.], - [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)) + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]]), + array([[12., 13., 14., 15.]]), + array([], shape=(0, 4), dtype=float64)) With a higher dimensional array the split is still along the first axis. diff --git a/numpy/lib/_stride_tricks_impl.py b/numpy/lib/_stride_tricks_impl.py index 9fc095e9a502..53bb5ea51fb5 100644 --- a/numpy/lib/_stride_tricks_impl.py +++ b/numpy/lib/_stride_tricks_impl.py @@ -546,7 +546,7 @@ def broadcast_arrays(*args, subok=False): # return np.nditer(args, flags=['multi_index', 'zerosize_ok'], # order='C').itviews - args = [np.array(_m, copy=False, subok=subok) for _m in args] + args = tuple(np.array(_m, copy=False, subok=subok) for _m in args) shape = _broadcast_shape(*args) @@ -554,5 +554,5 @@ def broadcast_arrays(*args, subok=False): # Common case where nothing needs to be broadcasted. return args - return tuple([_broadcast_to(array, shape, subok=subok, readonly=False) - for array in args]) + return tuple(_broadcast_to(array, shape, subok=subok, readonly=False) + for array in args) diff --git a/numpy/lib/_stride_tricks_impl.pyi b/numpy/lib/_stride_tricks_impl.pyi index 4c9a98e85f78..b15d2548ba37 100644 --- a/numpy/lib/_stride_tricks_impl.pyi +++ b/numpy/lib/_stride_tricks_impl.pyi @@ -77,4 +77,4 @@ def broadcast_shapes(*args: _ShapeLike) -> _Shape: ... def broadcast_arrays( *args: ArrayLike, subok: bool = ..., -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... diff --git a/numpy/typing/tests/data/reveal/array_constructors.pyi b/numpy/typing/tests/data/reveal/array_constructors.pyi index 697d38c26216..ba1ba823150c 100644 --- a/numpy/typing/tests/data/reveal/array_constructors.pyi +++ b/numpy/typing/tests/data/reveal/array_constructors.pyi @@ -186,13 +186,15 @@ assert_type(np.identity(10, dtype=int), npt.NDArray[Any]) assert_type(np.atleast_1d(A), npt.NDArray[np.float64]) assert_type(np.atleast_1d(C), npt.NDArray[Any]) -assert_type(np.atleast_1d(A, A), list[npt.NDArray[Any]]) -assert_type(np.atleast_1d(A, C), list[npt.NDArray[Any]]) -assert_type(np.atleast_1d(C, C), list[npt.NDArray[Any]]) +assert_type(np.atleast_1d(A, A), tuple[npt.NDArray[Any]]) +assert_type(np.atleast_1d(A, C), tuple[npt.NDArray[Any]]) +assert_type(np.atleast_1d(C, C), tuple[npt.NDArray[Any]]) assert_type(np.atleast_2d(A), npt.NDArray[np.float64]) +assert_type(np.atleast_2d(A, A), tuple[npt.NDArray[Any]]) assert_type(np.atleast_3d(A), npt.NDArray[np.float64]) +assert_type(np.atleast_3d(A, A), tuple[npt.NDArray[Any]]) assert_type(np.vstack([A, A]), np.ndarray[Any, Any]) assert_type(np.vstack([A, A], dtype=np.float64), npt.NDArray[np.float64]) diff --git a/numpy/typing/tests/data/reveal/shape_base.pyi b/numpy/typing/tests/data/reveal/shape_base.pyi index 69940cc1ac2c..86f0ef2442c1 100644 --- a/numpy/typing/tests/data/reveal/shape_base.pyi +++ b/numpy/typing/tests/data/reveal/shape_base.pyi @@ -32,20 +32,20 @@ assert_type(np.column_stack([AR_LIKE_f8]), npt.NDArray[Any]) assert_type(np.dstack([AR_i8]), npt.NDArray[np.int64]) assert_type(np.dstack([AR_LIKE_f8]), npt.NDArray[Any]) -assert_type(np.array_split(AR_i8, [3, 5, 6, 10]), list[npt.NDArray[np.int64]]) -assert_type(np.array_split(AR_LIKE_f8, [3, 5, 6, 10]), list[npt.NDArray[Any]]) +assert_type(np.array_split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) +assert_type(np.array_split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) -assert_type(np.split(AR_i8, [3, 5, 6, 10]), list[npt.NDArray[np.int64]]) -assert_type(np.split(AR_LIKE_f8, [3, 5, 6, 10]), list[npt.NDArray[Any]]) +assert_type(np.split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) +assert_type(np.split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) -assert_type(np.hsplit(AR_i8, [3, 5, 6, 10]), list[npt.NDArray[np.int64]]) -assert_type(np.hsplit(AR_LIKE_f8, [3, 5, 6, 10]), list[npt.NDArray[Any]]) +assert_type(np.hsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) +assert_type(np.hsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) -assert_type(np.vsplit(AR_i8, [3, 5, 6, 10]), list[npt.NDArray[np.int64]]) -assert_type(np.vsplit(AR_LIKE_f8, [3, 5, 6, 10]), list[npt.NDArray[Any]]) +assert_type(np.vsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) +assert_type(np.vsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) -assert_type(np.dsplit(AR_i8, [3, 5, 6, 10]), list[npt.NDArray[np.int64]]) -assert_type(np.dsplit(AR_LIKE_f8, [3, 5, 6, 10]), list[npt.NDArray[Any]]) +assert_type(np.dsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) +assert_type(np.dsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) assert_type(np.kron(AR_b, AR_b), npt.NDArray[np.bool]) assert_type(np.kron(AR_b, AR_i8), npt.NDArray[np.signedinteger[Any]]) diff --git a/numpy/typing/tests/data/reveal/stride_tricks.pyi b/numpy/typing/tests/data/reveal/stride_tricks.pyi index 25719d11cef1..d62e16c12737 100644 --- a/numpy/typing/tests/data/reveal/stride_tricks.pyi +++ b/numpy/typing/tests/data/reveal/stride_tricks.pyi @@ -29,5 +29,5 @@ assert_type(np.broadcast_to(AR_f8, [4, 6], subok=True), npt.NDArray[np.float64]) assert_type(np.broadcast_shapes((1, 2), [3, 1], (3, 2)), tuple[int, ...]) assert_type(np.broadcast_shapes((6, 7), (5, 6, 1), 7, (5, 1, 7)), tuple[int, ...]) -assert_type(np.broadcast_arrays(AR_f8, AR_f8), list[npt.NDArray[Any]]) -assert_type(np.broadcast_arrays(AR_f8, AR_LIKE_f), list[npt.NDArray[Any]]) +assert_type(np.broadcast_arrays(AR_f8, AR_f8), tuple[npt.NDArray[Any]]) +assert_type(np.broadcast_arrays(AR_f8, AR_LIKE_f), tuple[npt.NDArray[Any]]) From 779d74d6847724aa0e71d69bc03b63ffea501083 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 19 Jan 2024 18:45:31 +0100 Subject: [PATCH 3/5] ENH: tuple returns for ogrid/meshgrid/histogramdd Also some small docstring improvements to make clearer what is returned. --- numpy/lib/_function_base_impl.py | 6 ++--- numpy/lib/_function_base_impl.pyi | 2 +- numpy/lib/_histograms_impl.py | 4 ++-- numpy/lib/_histograms_impl.pyi | 2 +- numpy/lib/_index_tricks_impl.py | 23 ++++++++++++++----- numpy/lib/_index_tricks_impl.pyi | 2 +- numpy/typing/tests/data/reveal/histograms.pyi | 8 +++---- .../typing/tests/data/reveal/index_tricks.pyi | 4 ++-- .../tests/data/reveal/lib_function_base.pyi | 4 ++-- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/numpy/lib/_function_base_impl.py b/numpy/lib/_function_base_impl.py index 171506096a9a..8db6eaba6f0f 100644 --- a/numpy/lib/_function_base_impl.py +++ b/numpy/lib/_function_base_impl.py @@ -4986,7 +4986,7 @@ def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None): @array_function_dispatch(_meshgrid_dispatcher) def meshgrid(*xi, copy=True, sparse=False, indexing='xy'): """ - Return a list of coordinate matrices from coordinate vectors. + Return a tuple of coordinate matrices from coordinate vectors. Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given @@ -5027,7 +5027,7 @@ def meshgrid(*xi, copy=True, sparse=False, indexing='xy'): Returns ------- - X1, X2,..., XN : list of ndarrays + X1, X2,..., XN : tuple of ndarrays For vectors `x1`, `x2`,..., `xn` with lengths ``Ni=len(xi)``, returns ``(N1, N2, N3,..., Nn)`` shaped arrays if indexing='ij' or ``(N2, N1, N3,..., Nn)`` shaped arrays if indexing='xy' @@ -5136,7 +5136,7 @@ def meshgrid(*xi, copy=True, sparse=False, indexing='xy'): output = np.broadcast_arrays(*output, subok=True) if copy: - output = [x.copy() for x in output] + output = tuple(x.copy() for x in output) return output diff --git a/numpy/lib/_function_base_impl.pyi b/numpy/lib/_function_base_impl.pyi index 3ddbe710bbbd..97a35e1d1ca0 100644 --- a/numpy/lib/_function_base_impl.pyi +++ b/numpy/lib/_function_base_impl.pyi @@ -626,7 +626,7 @@ def meshgrid( copy: bool = ..., sparse: bool = ..., indexing: L["xy", "ij"] = ..., -) -> list[NDArray[Any]]: ... +) -> tuple[NDArray[Any]]: ... @overload def delete( diff --git a/numpy/lib/_histograms_impl.py b/numpy/lib/_histograms_impl.py index 3ab13558bac5..06b3a70128ce 100644 --- a/numpy/lib/_histograms_impl.py +++ b/numpy/lib/_histograms_impl.py @@ -957,8 +957,8 @@ def histogramdd(sample, bins=10, range=None, density=None, weights=None): H : ndarray The multidimensional histogram of sample x. See density and weights for the different possible semantics. - edges : list - A list of D arrays describing the bin edges for each dimension. + edges : tuple of ndarrays + A tuple of D arrays describing the bin edges for each dimension. See Also -------- diff --git a/numpy/lib/_histograms_impl.pyi b/numpy/lib/_histograms_impl.pyi index ce02718adcd5..60ca2172b121 100644 --- a/numpy/lib/_histograms_impl.pyi +++ b/numpy/lib/_histograms_impl.pyi @@ -44,4 +44,4 @@ def histogramdd( range: Sequence[tuple[float, float]] = ..., density: None | bool = ..., weights: None | ArrayLike = ..., -) -> tuple[NDArray[Any], list[NDArray[Any]]]: ... +) -> tuple[NDArray[Any], tuple[NDArray[Any]]]: ... diff --git a/numpy/lib/_index_tricks_impl.py b/numpy/lib/_index_tricks_impl.py index f559b68ca758..8d2e11278c46 100644 --- a/numpy/lib/_index_tricks_impl.py +++ b/numpy/lib/_index_tricks_impl.py @@ -189,7 +189,8 @@ def __getitem__(self, key): slobj[k] = slice(None, None) nn[k] = nn[k][tuple(slobj)] slobj[k] = _nx.newaxis - return nn + return tuple(nn) # ogrid -> tuple of arrays + return nn # mgrid -> ndarray except (IndexError, TypeError): step = key.step stop = key.stop @@ -225,8 +226,9 @@ class MGridClass(nd_grid): Returns ------- - mesh-grid - `ndarray`\\ s all of the same dimensions + mesh-grid : ndarray + A single array, containing a set of `ndarray`\\ s all of the same + dimensions. stacked along the first axis. See Also -------- @@ -251,6 +253,13 @@ class MGridClass(nd_grid): >>> np.mgrid[-1:1:5j] array([-1. , -0.5, 0. , 0.5, 1. ]) + >>> np.mgrid[0:4].shape + (4,) + >>> np.mgrid[0:4, 0:5].shape + (2, 4, 5) + >>> np.mgrid[0:4, 0:5, 0:6].shape + (3, 4, 5, 6) + """ def __init__(self): @@ -277,8 +286,10 @@ class OGridClass(nd_grid): Returns ------- - mesh-grid - `ndarray`\\ s with only one dimension not equal to 1 + mesh-grid : ndarray or tuple of ndarrays + If the input is a single slice, returns an array. + If the input is multiple slices, returns a tuple of arrays, with + only one dimension not equal to 1. See Also -------- @@ -292,7 +303,7 @@ class OGridClass(nd_grid): >>> from numpy import ogrid >>> ogrid[-1:1:5j] array([-1. , -0.5, 0. , 0.5, 1. ]) - >>> ogrid[0:5,0:5] + >>> ogrid[0:5, 0:5] [array([[0], [1], [2], diff --git a/numpy/lib/_index_tricks_impl.pyi b/numpy/lib/_index_tricks_impl.pyi index e67ff1e2b82d..82485c00d0c0 100644 --- a/numpy/lib/_index_tricks_impl.pyi +++ b/numpy/lib/_index_tricks_impl.pyi @@ -74,7 +74,7 @@ class nd_grid(Generic[_BoolType]): def __getitem__( self: nd_grid[Literal[True]], key: slice | Sequence[slice], - ) -> list[NDArray[Any]]: ... + ) -> tuple[NDArray[Any]]: ... class MGridClass(nd_grid[Literal[False]]): def __init__(self) -> None: ... diff --git a/numpy/typing/tests/data/reveal/histograms.pyi b/numpy/typing/tests/data/reveal/histograms.pyi index 68df0b96f48d..b968771518ea 100644 --- a/numpy/typing/tests/data/reveal/histograms.pyi +++ b/numpy/typing/tests/data/reveal/histograms.pyi @@ -21,7 +21,7 @@ assert_type(np.histogram(AR_i8, bins="rice", range=(0, 3)), tuple[npt.NDArray[An assert_type(np.histogram(AR_i8, bins="scott", weights=AR_f8), tuple[npt.NDArray[Any], npt.NDArray[Any]]) assert_type(np.histogram(AR_f8, bins=1, density=True), tuple[npt.NDArray[Any], npt.NDArray[Any]]) -assert_type(np.histogramdd(AR_i8, bins=[1]), tuple[npt.NDArray[Any], list[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_i8, range=[(0, 3)]), tuple[npt.NDArray[Any], list[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_i8, weights=AR_f8), tuple[npt.NDArray[Any], list[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_f8, density=True), tuple[npt.NDArray[Any], list[npt.NDArray[Any]]]) +assert_type(np.histogramdd(AR_i8, bins=[1]), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) +assert_type(np.histogramdd(AR_i8, range=[(0, 3)]), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) +assert_type(np.histogramdd(AR_i8, weights=AR_f8), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) +assert_type(np.histogramdd(AR_f8, density=True), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) diff --git a/numpy/typing/tests/data/reveal/index_tricks.pyi b/numpy/typing/tests/data/reveal/index_tricks.pyi index f9fb34b5fcd1..d98f9b1e1a8f 100644 --- a/numpy/typing/tests/data/reveal/index_tricks.pyi +++ b/numpy/typing/tests/data/reveal/index_tricks.pyi @@ -51,8 +51,8 @@ assert_type(np.ravel_multi_index((3, 1, 4, 1), (6, 7, 8, 9)), np.intp) assert_type(np.mgrid[1:1:2], npt.NDArray[Any]) assert_type(np.mgrid[1:1:2, None:10], npt.NDArray[Any]) -assert_type(np.ogrid[1:1:2], list[npt.NDArray[Any]]) -assert_type(np.ogrid[1:1:2, None:10], list[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]) diff --git a/numpy/typing/tests/data/reveal/lib_function_base.pyi b/numpy/typing/tests/data/reveal/lib_function_base.pyi index affedf1743d5..675b02c7e484 100644 --- a/numpy/typing/tests/data/reveal/lib_function_base.pyi +++ b/numpy/typing/tests/data/reveal/lib_function_base.pyi @@ -159,8 +159,8 @@ assert_type(np.quantile(AR_f8, [0.5], keepdims=True), Any) assert_type(np.quantile(AR_f8, [0.5], axis=[1]), Any) assert_type(np.quantile(AR_f8, [0.5], out=AR_c16), npt.NDArray[np.complex128]) -assert_type(np.meshgrid(AR_f8, AR_i8, copy=False), list[npt.NDArray[Any]]) -assert_type(np.meshgrid(AR_f8, AR_i8, AR_c16, indexing="ij"), list[npt.NDArray[Any]]) +assert_type(np.meshgrid(AR_f8, AR_i8, copy=False), tuple[npt.NDArray[Any]]) +assert_type(np.meshgrid(AR_f8, AR_i8, AR_c16, indexing="ij"), tuple[npt.NDArray[Any]]) assert_type(np.delete(AR_f8, np.s_[:5]), npt.NDArray[np.float64]) assert_type(np.delete(AR_LIKE_f8, [0, 4, 9], axis=0), npt.NDArray[Any]) From 02f6b7f54e6593f71341772424370edd2d279e95 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 19 Jan 2024 18:52:34 +0100 Subject: [PATCH 4/5] DOC: add release note for the `list[ndarray]` -> `tuple[ndarray]` change --- doc/release/upcoming_changes/25570.change | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 doc/release/upcoming_changes/25570.change diff --git a/doc/release/upcoming_changes/25570.change b/doc/release/upcoming_changes/25570.change new file mode 100644 index 000000000000..d2bd97eab67f --- /dev/null +++ b/doc/release/upcoming_changes/25570.change @@ -0,0 +1,7 @@ +Functions that returned a list of ndarrays have been changed to return a tuple +of ndarrays instead. Returning tuples consistently whenever a sequence of +arrays is returned makes it easier for JIT compilers like Numba, as well as for +static type checkers in some cases, to support these functions. Changed +functions are: ``atleast_1d``, ``atleast_2d``, ``atleast_3d``, ``broadcast_arrays``, +``array_split``, ``split``, ``hsplit``, ``vsplit``, ``dsplit``, ``meshgrid``, +``ogrid``, ``histogramdd``. From 760836fc5c0ec3c2eabce0b893e25ad3fd04669f Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Sun, 21 Jan 2024 19:31:44 +0100 Subject: [PATCH 5/5] BUG: fix type annotations for list/tuple Also fix two remaining docstrings for list/tuple change [skip cirrus] --- numpy/_core/shape_base.pyi | 6 ++--- numpy/lib/_function_base_impl.pyi | 2 +- numpy/lib/_histograms_impl.pyi | 2 +- numpy/lib/_index_tricks_impl.py | 5 ++-- numpy/lib/_index_tricks_impl.pyi | 2 +- numpy/lib/_shape_base_impl.py | 27 +++++++++---------- numpy/lib/_shape_base_impl.pyi | 20 +++++++------- numpy/lib/_stride_tricks_impl.pyi | 2 +- .../tests/data/reveal/array_constructors.pyi | 10 +++---- numpy/typing/tests/data/reveal/histograms.pyi | 12 ++++++--- .../typing/tests/data/reveal/index_tricks.pyi | 4 +-- .../tests/data/reveal/lib_function_base.pyi | 4 +-- numpy/typing/tests/data/reveal/shape_base.pyi | 20 +++++++------- .../tests/data/reveal/stride_tricks.pyi | 4 +-- 14 files changed, 61 insertions(+), 59 deletions(-) diff --git a/numpy/_core/shape_base.pyi b/numpy/_core/shape_base.pyi index b9220ff84157..8cf604b7358d 100644 --- a/numpy/_core/shape_base.pyi +++ b/numpy/_core/shape_base.pyi @@ -20,21 +20,21 @@ def atleast_1d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_1d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_1d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... +def atleast_1d(*arys: ArrayLike) -> tuple[NDArray[Any], ...]: ... @overload def atleast_2d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_2d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_2d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... +def atleast_2d(*arys: ArrayLike) -> tuple[NDArray[Any], ...]: ... @overload def atleast_3d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload def atleast_3d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload -def atleast_3d(*arys: ArrayLike) -> tuple[NDArray[Any]]: ... +def atleast_3d(*arys: ArrayLike) -> tuple[NDArray[Any], ...]: ... @overload def vstack( diff --git a/numpy/lib/_function_base_impl.pyi b/numpy/lib/_function_base_impl.pyi index 97a35e1d1ca0..bd15bc0c8239 100644 --- a/numpy/lib/_function_base_impl.pyi +++ b/numpy/lib/_function_base_impl.pyi @@ -626,7 +626,7 @@ def meshgrid( copy: bool = ..., sparse: bool = ..., indexing: L["xy", "ij"] = ..., -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def delete( diff --git a/numpy/lib/_histograms_impl.pyi b/numpy/lib/_histograms_impl.pyi index 60ca2172b121..138cdb115ef5 100644 --- a/numpy/lib/_histograms_impl.pyi +++ b/numpy/lib/_histograms_impl.pyi @@ -44,4 +44,4 @@ def histogramdd( range: Sequence[tuple[float, float]] = ..., density: None | bool = ..., weights: None | ArrayLike = ..., -) -> tuple[NDArray[Any], tuple[NDArray[Any]]]: ... +) -> tuple[NDArray[Any], tuple[NDArray[Any], ...]]: ... diff --git a/numpy/lib/_index_tricks_impl.py b/numpy/lib/_index_tricks_impl.py index 8d2e11278c46..2ea961879e65 100644 --- a/numpy/lib/_index_tricks_impl.py +++ b/numpy/lib/_index_tricks_impl.py @@ -304,11 +304,12 @@ class OGridClass(nd_grid): >>> ogrid[-1:1:5j] array([-1. , -0.5, 0. , 0.5, 1. ]) >>> ogrid[0:5, 0:5] - [array([[0], + (array([[0], [1], [2], [3], - [4]]), array([[0, 1, 2, 3, 4]])] + [4]]), + array([[0, 1, 2, 3, 4]])) """ diff --git a/numpy/lib/_index_tricks_impl.pyi b/numpy/lib/_index_tricks_impl.pyi index 82485c00d0c0..f13ab4d96e48 100644 --- a/numpy/lib/_index_tricks_impl.pyi +++ b/numpy/lib/_index_tricks_impl.pyi @@ -74,7 +74,7 @@ class nd_grid(Generic[_BoolType]): def __getitem__( self: nd_grid[Literal[True]], key: slice | Sequence[slice], - ) -> tuple[NDArray[Any]]: ... + ) -> tuple[NDArray[Any], ...]: ... class MGridClass(nd_grid[Literal[False]]): def __init__(self) -> None: ... diff --git a/numpy/lib/_shape_base_impl.py b/numpy/lib/_shape_base_impl.py index ed61e5f57bf9..87e6c1d13476 100644 --- a/numpy/lib/_shape_base_impl.py +++ b/numpy/lib/_shape_base_impl.py @@ -908,24 +908,21 @@ def hsplit(ary, indices_or_sections): [ 8., 9., 10., 11.], [12., 13., 14., 15.]]) >>> np.hsplit(x, 2) - [array([[ 0., 1.], - [ 4., 5.], - [ 8., 9.], - [12., 13.]]), - array([[ 2., 3.], - [ 6., 7.], - [10., 11.], - [14., 15.]])] + (array([[ 0., 1.], + [ 4., 5.], + [ 8., 9.], + [12., 13.]]), array([[ 2., 3.], + [ 6., 7.], + [10., 11.], + [14., 15.]])) >>> np.hsplit(x, np.array([3, 6])) - [array([[ 0., 1., 2.], - [ 4., 5., 6.], - [ 8., 9., 10.], - [12., 13., 14.]]), - array([[ 3.], + (array([[ 0., 1., 2.], + [ 4., 5., 6.], + [ 8., 9., 10.], + [12., 13., 14.]]), array([[ 3.], [ 7.], [11.], - [15.]]), - array([], shape=(4, 0), dtype=float64)] + [15.]]), array([], shape=(4, 0), dtype=float64)) With a higher dimensional array the split is still along the second axis. diff --git a/numpy/lib/_shape_base_impl.pyi b/numpy/lib/_shape_base_impl.pyi index 4a5736ff1005..72c876225580 100644 --- a/numpy/lib/_shape_base_impl.pyi +++ b/numpy/lib/_shape_base_impl.pyi @@ -115,59 +115,59 @@ def array_split( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> tuple[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT], ...]: ... @overload def array_split( ary: ArrayLike, indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def split( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> tuple[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT], ...]: ... @overload def split( ary: ArrayLike, indices_or_sections: _ShapeLike, axis: SupportsIndex = ..., -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def hsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> tuple[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT], ...]: ... @overload def hsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def vsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> tuple[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT], ...]: ... @overload def vsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def dsplit( ary: _ArrayLike[_SCT], indices_or_sections: _ShapeLike, -) -> tuple[NDArray[_SCT]]: ... +) -> tuple[NDArray[_SCT], ...]: ... @overload def dsplit( ary: ArrayLike, indices_or_sections: _ShapeLike, -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... @overload def get_array_wrap(*args: _SupportsArrayWrap) -> _ArrayWrap: ... diff --git a/numpy/lib/_stride_tricks_impl.pyi b/numpy/lib/_stride_tricks_impl.pyi index b15d2548ba37..cf635f1fb640 100644 --- a/numpy/lib/_stride_tricks_impl.pyi +++ b/numpy/lib/_stride_tricks_impl.pyi @@ -77,4 +77,4 @@ def broadcast_shapes(*args: _ShapeLike) -> _Shape: ... def broadcast_arrays( *args: ArrayLike, subok: bool = ..., -) -> tuple[NDArray[Any]]: ... +) -> tuple[NDArray[Any], ...]: ... diff --git a/numpy/typing/tests/data/reveal/array_constructors.pyi b/numpy/typing/tests/data/reveal/array_constructors.pyi index ba1ba823150c..814da1b9d639 100644 --- a/numpy/typing/tests/data/reveal/array_constructors.pyi +++ b/numpy/typing/tests/data/reveal/array_constructors.pyi @@ -186,15 +186,15 @@ assert_type(np.identity(10, dtype=int), npt.NDArray[Any]) assert_type(np.atleast_1d(A), npt.NDArray[np.float64]) assert_type(np.atleast_1d(C), npt.NDArray[Any]) -assert_type(np.atleast_1d(A, A), tuple[npt.NDArray[Any]]) -assert_type(np.atleast_1d(A, C), tuple[npt.NDArray[Any]]) -assert_type(np.atleast_1d(C, C), tuple[npt.NDArray[Any]]) +assert_type(np.atleast_1d(A, A), tuple[npt.NDArray[Any], ...]) +assert_type(np.atleast_1d(A, C), tuple[npt.NDArray[Any], ...]) +assert_type(np.atleast_1d(C, C), tuple[npt.NDArray[Any], ...]) assert_type(np.atleast_2d(A), npt.NDArray[np.float64]) -assert_type(np.atleast_2d(A, A), tuple[npt.NDArray[Any]]) +assert_type(np.atleast_2d(A, A), tuple[npt.NDArray[Any], ...]) assert_type(np.atleast_3d(A), npt.NDArray[np.float64]) -assert_type(np.atleast_3d(A, A), tuple[npt.NDArray[Any]]) +assert_type(np.atleast_3d(A, A), tuple[npt.NDArray[Any], ...]) assert_type(np.vstack([A, A]), np.ndarray[Any, Any]) assert_type(np.vstack([A, A], dtype=np.float64), npt.NDArray[np.float64]) diff --git a/numpy/typing/tests/data/reveal/histograms.pyi b/numpy/typing/tests/data/reveal/histograms.pyi index b968771518ea..67067eb7d63f 100644 --- a/numpy/typing/tests/data/reveal/histograms.pyi +++ b/numpy/typing/tests/data/reveal/histograms.pyi @@ -21,7 +21,11 @@ assert_type(np.histogram(AR_i8, bins="rice", range=(0, 3)), tuple[npt.NDArray[An assert_type(np.histogram(AR_i8, bins="scott", weights=AR_f8), tuple[npt.NDArray[Any], npt.NDArray[Any]]) assert_type(np.histogram(AR_f8, bins=1, density=True), tuple[npt.NDArray[Any], npt.NDArray[Any]]) -assert_type(np.histogramdd(AR_i8, bins=[1]), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_i8, range=[(0, 3)]), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_i8, weights=AR_f8), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) -assert_type(np.histogramdd(AR_f8, density=True), tuple[npt.NDArray[Any], tuple[npt.NDArray[Any]]]) +assert_type(np.histogramdd(AR_i8, bins=[1]), + tuple[npt.NDArray[Any], tuple[npt.NDArray[Any], ...]]) +assert_type(np.histogramdd(AR_i8, range=[(0, 3)]), + tuple[npt.NDArray[Any], tuple[npt.NDArray[Any], ...]]) +assert_type(np.histogramdd(AR_i8, weights=AR_f8), + tuple[npt.NDArray[Any], tuple[npt.NDArray[Any], ...]]) +assert_type(np.histogramdd(AR_f8, density=True), + tuple[npt.NDArray[Any], tuple[npt.NDArray[Any], ...]]) diff --git a/numpy/typing/tests/data/reveal/index_tricks.pyi b/numpy/typing/tests/data/reveal/index_tricks.pyi index d98f9b1e1a8f..029c8228cae7 100644 --- a/numpy/typing/tests/data/reveal/index_tricks.pyi +++ b/numpy/typing/tests/data/reveal/index_tricks.pyi @@ -51,8 +51,8 @@ assert_type(np.ravel_multi_index((3, 1, 4, 1), (6, 7, 8, 9)), np.intp) assert_type(np.mgrid[1:1:2], npt.NDArray[Any]) 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.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]) diff --git a/numpy/typing/tests/data/reveal/lib_function_base.pyi b/numpy/typing/tests/data/reveal/lib_function_base.pyi index 675b02c7e484..72974dce64bf 100644 --- a/numpy/typing/tests/data/reveal/lib_function_base.pyi +++ b/numpy/typing/tests/data/reveal/lib_function_base.pyi @@ -159,8 +159,8 @@ assert_type(np.quantile(AR_f8, [0.5], keepdims=True), Any) assert_type(np.quantile(AR_f8, [0.5], axis=[1]), Any) assert_type(np.quantile(AR_f8, [0.5], out=AR_c16), npt.NDArray[np.complex128]) -assert_type(np.meshgrid(AR_f8, AR_i8, copy=False), tuple[npt.NDArray[Any]]) -assert_type(np.meshgrid(AR_f8, AR_i8, AR_c16, indexing="ij"), tuple[npt.NDArray[Any]]) +assert_type(np.meshgrid(AR_f8, AR_i8, copy=False), tuple[npt.NDArray[Any], ...]) +assert_type(np.meshgrid(AR_f8, AR_i8, AR_c16, indexing="ij"), tuple[npt.NDArray[Any], ...]) assert_type(np.delete(AR_f8, np.s_[:5]), npt.NDArray[np.float64]) assert_type(np.delete(AR_LIKE_f8, [0, 4, 9], axis=0), npt.NDArray[Any]) diff --git a/numpy/typing/tests/data/reveal/shape_base.pyi b/numpy/typing/tests/data/reveal/shape_base.pyi index 86f0ef2442c1..362d705aeccd 100644 --- a/numpy/typing/tests/data/reveal/shape_base.pyi +++ b/numpy/typing/tests/data/reveal/shape_base.pyi @@ -32,20 +32,20 @@ assert_type(np.column_stack([AR_LIKE_f8]), npt.NDArray[Any]) assert_type(np.dstack([AR_i8]), npt.NDArray[np.int64]) assert_type(np.dstack([AR_LIKE_f8]), npt.NDArray[Any]) -assert_type(np.array_split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) -assert_type(np.array_split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) +assert_type(np.array_split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64], ...]) +assert_type(np.array_split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any], ...]) -assert_type(np.split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) -assert_type(np.split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) +assert_type(np.split(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64], ...]) +assert_type(np.split(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any], ...]) -assert_type(np.hsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) -assert_type(np.hsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) +assert_type(np.hsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64], ...]) +assert_type(np.hsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any], ...]) -assert_type(np.vsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) -assert_type(np.vsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) +assert_type(np.vsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64], ...]) +assert_type(np.vsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any], ...]) -assert_type(np.dsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64]]) -assert_type(np.dsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any]]) +assert_type(np.dsplit(AR_i8, [3, 5, 6, 10]), tuple[npt.NDArray[np.int64], ...]) +assert_type(np.dsplit(AR_LIKE_f8, [3, 5, 6, 10]), tuple[npt.NDArray[Any], ...]) assert_type(np.kron(AR_b, AR_b), npt.NDArray[np.bool]) assert_type(np.kron(AR_b, AR_i8), npt.NDArray[np.signedinteger[Any]]) diff --git a/numpy/typing/tests/data/reveal/stride_tricks.pyi b/numpy/typing/tests/data/reveal/stride_tricks.pyi index d62e16c12737..893e1bc314bc 100644 --- a/numpy/typing/tests/data/reveal/stride_tricks.pyi +++ b/numpy/typing/tests/data/reveal/stride_tricks.pyi @@ -29,5 +29,5 @@ assert_type(np.broadcast_to(AR_f8, [4, 6], subok=True), npt.NDArray[np.float64]) assert_type(np.broadcast_shapes((1, 2), [3, 1], (3, 2)), tuple[int, ...]) assert_type(np.broadcast_shapes((6, 7), (5, 6, 1), 7, (5, 1, 7)), tuple[int, ...]) -assert_type(np.broadcast_arrays(AR_f8, AR_f8), tuple[npt.NDArray[Any]]) -assert_type(np.broadcast_arrays(AR_f8, AR_LIKE_f), tuple[npt.NDArray[Any]]) +assert_type(np.broadcast_arrays(AR_f8, AR_f8), tuple[npt.NDArray[Any], ...]) +assert_type(np.broadcast_arrays(AR_f8, AR_LIKE_f), tuple[npt.NDArray[Any], ...])