summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-04-06 16:08:30 -0600
committerGitHub <noreply@github.com>2018-04-06 16:08:30 -0600
commit1f9c30ef0f4f7a0c3e0227c3de681a11fcc24861 (patch)
tree0f69a88b9e69636bb034a50f4ebdacff1357f7cf
parenta3c28010ca5427cf67346c928f7319c111d84fd8 (diff)
parent2ee7c72e56b5ef16f3838f86de8ad0d435b9b4e0 (diff)
downloadnumpy-1f9c30ef0f4f7a0c3e0227c3de681a11fcc24861.tar.gz
Merge pull request #10826 from tylerjereddy/issue_10779_squeeze
BUG: np.squeeze() now respects older API axis expectation
-rw-r--r--doc/release/1.15.0-notes.rst10
-rw-r--r--numpy/core/fromnumeric.py9
-rw-r--r--numpy/core/tests/test_regression.py61
3 files changed, 74 insertions, 6 deletions
diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst
index 2a8c57351..cff75c477 100644
--- a/doc/release/1.15.0-notes.rst
+++ b/doc/release/1.15.0-notes.rst
@@ -55,6 +55,16 @@ All downstream users seem to use detect the `None` result from
``flatnotmasked_contiguous`` and replace it with ``[]``.
These callers will continue to work as before.
+``np.squeeze`` now respects the API expectation of objects that do not handle an ``axis`` argument
+--------------------------------------------------------------------------------------------------
+Prior to version ``1.7.0`` ``np.squeeze`` did not have an ``axis`` argument and all empty axes were removed
+by default. After incorporation of an ``axis`` argument, it was possible to selectively squeeze single
+or multiple empty axes, but the old API expectation was not respected because the axes could still be
+selectively removed (silent success) in an object depending on the old API. The silent success is no
+longer possible, and objects expecting the old API are respected. The silent success was prevented
+by removing the interception of an otherwise-normal Exception when ``axis`` was provided to an object
+using the old API.
+
C API changes
=============
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 63279ffb3..5f1aadbf5 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1280,13 +1280,10 @@ def squeeze(a, axis=None):
squeeze = a.squeeze
except AttributeError:
return _wrapit(a, 'squeeze')
- try:
- # First try to use the new axis= parameter
- return squeeze(axis=axis)
- except TypeError:
- # For backwards compatibility
+ if axis is None:
return squeeze()
-
+ else:
+ return squeeze(axis=axis)
def diagonal(a, offset=0, axis1=0, axis2=1):
"""
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 016b720f3..119594668 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1675,6 +1675,67 @@ class TestRegression(object):
assert_(a.flags.f_contiguous)
assert_(b.flags.f_contiguous)
+ def test_squeeze_axis_handling(self):
+ # Issue #10779
+ # Ensure proper handling of objects
+ # that don't support axis specification
+ # when squeezing
+
+ class OldSqueeze(np.ndarray):
+
+ def __new__(cls,
+ input_array):
+ obj = np.asarray(input_array).view(cls)
+ return obj
+
+ # it is perfectly reasonable that prior
+ # to numpy version 1.7.0 a subclass of ndarray
+ # might have been created that did not expect
+ # squeeze to have an axis argument
+ # NOTE: this example is somewhat artificial;
+ # it is designed to simulate an old API
+ # expectation to guard against regression
+ def squeeze(self):
+ return super(OldSqueeze, self).squeeze()
+
+ oldsqueeze = OldSqueeze(np.array([[1],[2],[3]]))
+
+ # if no axis argument is specified the old API
+ # expectation should give the correct result
+ assert_equal(np.squeeze(oldsqueeze),
+ np.array([1,2,3]))
+
+ # likewise, axis=None should work perfectly well
+ # with the old API expectation
+ assert_equal(np.squeeze(oldsqueeze, axis=None),
+ np.array([1,2,3]))
+
+ # however, specification of any particular axis
+ # should raise a TypeError in the context of the
+ # old API specification, even when using a valid
+ # axis specification like 1 for this array
+ with assert_raises(TypeError):
+ # this would silently succeed for array
+ # subclasses / objects that did not support
+ # squeeze axis argument handling before fixing
+ # Issue #10779
+ np.squeeze(oldsqueeze, axis=1)
+
+ # check for the same behavior when using an invalid
+ # axis specification -- in this case axis=0 does not
+ # have size 1, but the priority should be to raise
+ # a TypeError for the axis argument and NOT a
+ # ValueError for squeezing a non-empty dimension
+ with assert_raises(TypeError):
+ np.squeeze(oldsqueeze, axis=0)
+
+ # the new API knows how to handle the axis
+ # argument and will return a ValueError if
+ # attempting to squeeze an axis that is not
+ # of length 1
+ with assert_raises(ValueError):
+ np.squeeze(np.array([[1],[2],[3]]), axis=0)
+
def test_reduce_contiguous(self):
# GitHub issue #387
a = np.add.reduce(np.zeros((2, 1, 2)), (0, 1))