Skip to content

Commit f0eb0a8

Browse files
Deprecate positional out argument in dpnp.minimum and dpnp.maximum (#2659)
This PR suggests raising a `DeprecationWarning` when `out` is passed positionally to `dpnp.minimum` and `dpnp.maximum`. Align with NumPy 2.4
1 parent 486b00d commit f0eb0a8

File tree

8 files changed

+73
-6
lines changed

8 files changed

+73
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Also, that release drops support for Python 3.9, making Python 3.10 the minimum
3838
### Deprecated
3939

4040
* `dpnp.asfarray` is deprecated. Use `dpnp.asarray` with an appropriate dtype instead [#2650](https://github.com/IntelPython/dpnp/pull/2650)
41+
* Passing the output array ``out`` positionally to `dpnp.minimum` and `dpnp.maximum` is deprecated. Pass the output with the keyword form, e.g. ``dpnp.minimum(a, b, out=c)`` [#2659](https://github.com/IntelPython/dpnp/pull/2659)
4142

4243
### Removed
4344

doc/conf.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from dpnp.dpnp_algo.dpnp_elementwise_common import (
1414
DPNPBinaryFunc,
15+
DPNPBinaryFuncOutKw,
1516
DPNPUnaryFunc,
1617
DPNPUnaryTwoOutputsFunc,
1718
)
@@ -210,7 +211,13 @@
210211
# -- Options for todo extension ----------------------------------------------
211212
def _can_document_member(member, *args, **kwargs):
212213
if isinstance(
213-
member, (DPNPBinaryFunc, DPNPUnaryFunc, DPNPUnaryTwoOutputsFunc)
214+
member,
215+
(
216+
DPNPBinaryFunc,
217+
DPNPBinaryFuncOutKw,
218+
DPNPUnaryFunc,
219+
DPNPUnaryTwoOutputsFunc,
220+
),
214221
):
215222
return True
216223
return orig(member, *args, **kwargs)

dpnp/dpnp_algo/dpnp_elementwise_common.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
# THE POSSIBILITY OF SUCH DAMAGE.
2727
# *****************************************************************************
2828

29+
import warnings
30+
from functools import wraps
31+
2932
import dpctl.tensor as dpt
3033
import dpctl.tensor._copy_utils as dtc
3134
import dpctl.tensor._tensor_impl as dti
@@ -48,6 +51,7 @@
4851
"DPNPI0",
4952
"DPNPAngle",
5053
"DPNPBinaryFunc",
54+
"DPNPBinaryFuncOutKw",
5155
"DPNPFix",
5256
"DPNPImag",
5357
"DPNPReal",
@@ -775,6 +779,22 @@ def outer(
775779
)
776780

777781

782+
class DPNPBinaryFuncOutKw(DPNPBinaryFunc):
783+
"""DPNPBinaryFunc that deprecates positional `out` argument."""
784+
785+
@wraps(DPNPBinaryFunc.__call__)
786+
def __call__(self, *args, **kwargs):
787+
if len(args) > self.nin:
788+
warnings.warn(
789+
"Passing more than 2 positional arguments is deprecated. "
790+
"If you meant to use the third argument as an output, "
791+
"use the `out` keyword argument instead.",
792+
DeprecationWarning,
793+
stacklevel=2,
794+
)
795+
return super().__call__(*args, **kwargs)
796+
797+
778798
class DPNPAngle(DPNPUnaryFunc):
779799
"""Class that implements dpnp.angle unary element-wise functions."""
780800

dpnp/dpnp_iface_mathematical.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
DPNPI0,
6666
DPNPAngle,
6767
DPNPBinaryFunc,
68+
DPNPBinaryFuncOutKw,
6869
DPNPFix,
6970
DPNPImag,
7071
DPNPReal,
@@ -3244,6 +3245,16 @@ def interp(x, xp, fp, left=None, right=None, period=None):
32443245
32453246
Default: ``"K"``.
32463247
3248+
Warning
3249+
-------
3250+
Passing more than 2 positional arguments is deprecated.
3251+
If you meant to use the third argument as an output,
3252+
use the `out` keyword argument instead.
3253+
3254+
For example, ``dpnp.maximum(a, b, c)`` will emit a ``DeprecationWarning``.
3255+
Always pass the output array as the keyword argument instead, that is
3256+
``dpnp.maximum(a, b, out=c)``.
3257+
32473258
Returns
32483259
-------
32493260
out : dpnp.ndarray
@@ -3297,7 +3308,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
32973308
32983309
"""
32993310

3300-
maximum = DPNPBinaryFunc(
3311+
maximum = DPNPBinaryFuncOutKw(
33013312
"maximum",
33023313
ti._maximum_result_type,
33033314
ti._maximum,
@@ -3341,6 +3352,16 @@ def interp(x, xp, fp, left=None, right=None, period=None):
33413352
An array containing the element-wise minima. The data type of
33423353
the returned array is determined by the Type Promotion Rules.
33433354
3355+
Warning
3356+
-------
3357+
Passing more than 2 positional arguments is deprecated.
3358+
If you meant to use the third argument as an output,
3359+
use the `out` keyword argument instead.
3360+
3361+
For example, ``dpnp.minimum(a, b, c)`` will emit a ``DeprecationWarning``.
3362+
Always pass the output array as the keyword argument instead, that is
3363+
``dpnp.minimum(a, b, out=c)``.
3364+
33443365
Limitations
33453366
-----------
33463367
Parameters `where` and `subok` are supported with their default values.
@@ -3387,7 +3408,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
33873408
array(-inf)
33883409
"""
33893410

3390-
minimum = DPNPBinaryFunc(
3411+
minimum = DPNPBinaryFuncOutKw(
33913412
"minimum",
33923413
ti._minimum_result_type,
33933414
ti._minimum,

dpnp/tests/test_binary_ufuncs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def test_invalid_shape(self, func, shape):
183183
)
184184
def test_invalid_out_type(self, func, xp, out):
185185
a = xp.arange(10)
186-
assert_raises(TypeError, getattr(xp, func), a, 2, out)
186+
assert_raises(TypeError, getattr(xp, func), a, 2, out=out)
187187

188188

189189
class TestDivide:

dpnp/tests/test_mathematical.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,3 +2795,15 @@ def test_elemenwise_outer_scalar():
27952795
expected = dpnp.add.outer(x, y)
27962796
result = dpnp.add.outer(x, s)
27972797
assert dpnp.allclose(result, expected)
2798+
2799+
2800+
@testing.with_requires("numpy>=2.4")
2801+
@pytest.mark.parametrize("xp", [dpnp, numpy])
2802+
@pytest.mark.parametrize("func", ["minimum", "maximum"])
2803+
def test_minimum_maximum_out_deprecated(xp, func):
2804+
a = xp.array([1, 3, 2])
2805+
b = xp.array([2, 2, 2])
2806+
out = xp.empty_like(a)
2807+
2808+
with pytest.warns(DeprecationWarning, match="deprecated"):
2809+
_ = getattr(xp, func)(a, b, out)

dpnp/tests/test_sycl_queue.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,10 @@ def test_invalid_stream(self, stream):
10161016
"asarray_chkfinite",
10171017
"asanyarray",
10181018
"ascontiguousarray",
1019-
"asfarray",
1019+
pytest.param(
1020+
"asfarray",
1021+
marks=pytest.mark.filterwarnings("ignore::DeprecationWarning"),
1022+
),
10201023
"asfortranarray",
10211024
],
10221025
)

dpnp/tests/test_usm_type.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,10 @@ def test_copy_operation(usm_type):
286286
"asarray_chkfinite",
287287
"asanyarray",
288288
"ascontiguousarray",
289-
"asfarray",
289+
pytest.param(
290+
"asfarray",
291+
marks=pytest.mark.filterwarnings("ignore::DeprecationWarning"),
292+
),
290293
"asfortranarray",
291294
],
292295
)

0 commit comments

Comments
 (0)