From 628f7b6c8ab806b2ded7ba6b7d802a964395ca91 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 26 Apr 2017 17:49:29 +0100 Subject: DEP: Deprecate calling the `out` argument `y` Fixes gh-8995 --- numpy/lib/tests/test_ufunclike.py | 9 ++++- numpy/lib/ufunclike.py | 70 ++++++++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 20 deletions(-) (limited to 'numpy/lib') diff --git a/numpy/lib/tests/test_ufunclike.py b/numpy/lib/tests/test_ufunclike.py index 97d608ecf..2f671739e 100644 --- a/numpy/lib/tests/test_ufunclike.py +++ b/numpy/lib/tests/test_ufunclike.py @@ -3,7 +3,8 @@ from __future__ import division, absolute_import, print_function import numpy.core as nx import numpy.lib.ufunclike as ufl from numpy.testing import ( - run_module_suite, TestCase, assert_, assert_equal, assert_array_equal + run_module_suite, TestCase, assert_, assert_equal, assert_array_equal, + assert_warns ) @@ -61,5 +62,11 @@ class TestUfunclike(TestCase): assert_(isinstance(f, MyArray)) assert_equal(f.metadata, 'foo') + def test_deprecated(self): + # NumPy 1.13.0, 2017-04-26 + assert_warns(DeprecationWarning, ufl.fix, [1, 2], y=nx.empty(2)) + assert_warns(DeprecationWarning, ufl.isposinf, [1, 2], y=nx.empty(2)) + assert_warns(DeprecationWarning, ufl.isneginf, [1, 2], y=nx.empty(2)) + if __name__ == "__main__": run_module_suite() diff --git a/numpy/lib/ufunclike.py b/numpy/lib/ufunclike.py index b6c017b96..773525db4 100644 --- a/numpy/lib/ufunclike.py +++ b/numpy/lib/ufunclike.py @@ -8,8 +8,36 @@ from __future__ import division, absolute_import, print_function __all__ = ['fix', 'isneginf', 'isposinf'] import numpy.core.numeric as nx +import warnings +import functools -def fix(x, y=None): +def _deprecate_out_named_y(f): + """ + Allow the out argument to be passed as the name `y` (deprecated) + + In future, this decorator should be removed. + """ + @functools.wraps(f) + def func(x, out=None, **kwargs): + if 'y' in kwargs: + if 'out' in kwargs: + raise TypeError( + "{} got multiple values for argument 'out'/'y'" + .format(f.__name__) + ) + out = kwargs.pop('y') + # NumPy 1.13.0, 2017-04-26 + warnings.warn( + "The name of the out argument to {} has changed from `y` to " + "`out`, to match other ufuncs.".format(f.__name__), + DeprecationWarning, stacklevel=3) + return f(x, out=out, **kwargs) + + return func + + +@_deprecate_out_named_y +def fix(x, out=None): """ Round to nearest integer towards zero. @@ -46,12 +74,14 @@ def fix(x, y=None): x = nx.asanyarray(x) y1 = nx.floor(x) y2 = nx.ceil(x) - if y is None: - y = nx.asanyarray(y1) - y[...] = nx.where(x >= 0, y1, y2) - return y + if out is None: + out = nx.asanyarray(y1) + out[...] = nx.where(x >= 0, y1, y2) + return out -def isposinf(x, y=None): + +@_deprecate_out_named_y +def isposinf(x, out=None): """ Test element-wise for positive infinity, return result as bool array. @@ -64,7 +94,7 @@ def isposinf(x, y=None): Returns ------- - y : ndarray + out : ndarray A boolean array with the same dimensions as the input. If second argument is not supplied then a boolean array is returned with values True where the corresponding element of the input is @@ -74,7 +104,7 @@ def isposinf(x, y=None): If a second argument is supplied the result is stored there. If the type of that array is a numeric type the result is represented as zeros and ones, if the type is boolean then as False and True. - The return value `y` is then a reference to that array. + The return value `out` is then a reference to that array. See Also -------- @@ -109,11 +139,13 @@ def isposinf(x, y=None): """ if y is None: x = nx.asarray(x) - y = nx.empty(x.shape, dtype=nx.bool_) - nx.logical_and(nx.isinf(x), ~nx.signbit(x), y) - return y + out = nx.empty(x.shape, dtype=nx.bool_) + nx.logical_and(nx.isinf(x), ~nx.signbit(x), out) + return out + -def isneginf(x, y=None): +@_deprecate_out_named_y +def isneginf(x, out=None): """ Test element-wise for negative infinity, return result as bool array. @@ -121,13 +153,13 @@ def isneginf(x, y=None): ---------- x : array_like The input array. - y : array_like, optional + out : array_like, optional A boolean array with the same shape and type as `x` to store the result. Returns ------- - y : ndarray + out : ndarray A boolean array with the same dimensions as the input. If second argument is not supplied then a numpy boolean array is returned with values True where the corresponding element of the @@ -137,7 +169,7 @@ def isneginf(x, y=None): If a second argument is supplied the result is stored there. If the type of that array is a numeric type the result is represented as zeros and ones, if the type is boolean then as False and True. The - return value `y` is then a reference to that array. + return value `out` is then a reference to that array. See Also -------- @@ -170,8 +202,8 @@ def isneginf(x, y=None): array([1, 0, 0]) """ - if y is None: + if out is None: x = nx.asarray(x) - y = nx.empty(x.shape, dtype=nx.bool_) - nx.logical_and(nx.isinf(x), nx.signbit(x), y) - return y + out = nx.empty(x.shape, dtype=nx.bool_) + nx.logical_and(nx.isinf(x), nx.signbit(x), out) + return out -- cgit v1.2.1 From 05f422827b3317ad3774cbd1859edbf6bc196f75 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 26 Apr 2017 19:17:08 +0100 Subject: BUG: Return scalars from ufunclike objects No need to reinvent the wheel here - the ufunc machinery will handle the out arguments Fixes #8993 --- numpy/lib/tests/test_ufunclike.py | 25 +++++++++++++++++++++++++ numpy/lib/ufunclike.py | 27 ++++++++++----------------- 2 files changed, 35 insertions(+), 17 deletions(-) (limited to 'numpy/lib') diff --git a/numpy/lib/tests/test_ufunclike.py b/numpy/lib/tests/test_ufunclike.py index 2f671739e..0b152540f 100644 --- a/numpy/lib/tests/test_ufunclike.py +++ b/numpy/lib/tests/test_ufunclike.py @@ -1,5 +1,6 @@ from __future__ import division, absolute_import, print_function +import numpy as np import numpy.core as nx import numpy.lib.ufunclike as ufl from numpy.testing import ( @@ -62,11 +63,35 @@ class TestUfunclike(TestCase): assert_(isinstance(f, MyArray)) assert_equal(f.metadata, 'foo') + # check 0d arrays don't decay to scalars + m0d = m[0,...] + m0d.metadata = 'bar' + f0d = ufl.fix(m0d) + assert_(isinstance(f0d, MyArray)) + assert_equal(f0d.metadata, 'bar') + def test_deprecated(self): # NumPy 1.13.0, 2017-04-26 assert_warns(DeprecationWarning, ufl.fix, [1, 2], y=nx.empty(2)) assert_warns(DeprecationWarning, ufl.isposinf, [1, 2], y=nx.empty(2)) assert_warns(DeprecationWarning, ufl.isneginf, [1, 2], y=nx.empty(2)) + def test_scalar(self): + x = np.inf + actual = np.isposinf(x) + expected = np.True_ + assert_equal(actual, expected) + assert_equal(type(actual), type(expected)) + + x = -3.4 + actual = np.fix(x) + expected = np.float64(-3.0) + assert_equal(actual, expected) + assert_equal(type(actual), type(expected)) + + out = np.array(0.0) + actual = np.fix(x, out=out) + assert_(actual is out) + if __name__ == "__main__": run_module_suite() diff --git a/numpy/lib/ufunclike.py b/numpy/lib/ufunclike.py index 773525db4..ad7c85e59 100644 --- a/numpy/lib/ufunclike.py +++ b/numpy/lib/ufunclike.py @@ -71,14 +71,15 @@ def fix(x, out=None): array([ 2., 2., -2., -2.]) """ - x = nx.asanyarray(x) - y1 = nx.floor(x) - y2 = nx.ceil(x) - if out is None: - out = nx.asanyarray(y1) - out[...] = nx.where(x >= 0, y1, y2) - return out + # promote back to an array if flattened + res = nx.asanyarray(nx.ceil(x, out=out)) + res = nx.floor(x, out=res, where=nx.greater_equal(x, 0)) + # when no out argument is passed and no subclasses are involved, flatten + # scalars + if out is None and type(res) is nx.ndarray: + res = res[()] + return res @_deprecate_out_named_y def isposinf(x, out=None): @@ -137,11 +138,7 @@ def isposinf(x, out=None): array([0, 0, 1]) """ - if y is None: - x = nx.asarray(x) - out = nx.empty(x.shape, dtype=nx.bool_) - nx.logical_and(nx.isinf(x), ~nx.signbit(x), out) - return out + return nx.logical_and(nx.isinf(x), ~nx.signbit(x), out) @_deprecate_out_named_y @@ -202,8 +199,4 @@ def isneginf(x, out=None): array([1, 0, 0]) """ - if out is None: - x = nx.asarray(x) - out = nx.empty(x.shape, dtype=nx.bool_) - nx.logical_and(nx.isinf(x), nx.signbit(x), out) - return out + return nx.logical_and(nx.isinf(x), nx.signbit(x), out) -- cgit v1.2.1