diff options
author | RenaRuirui <renaxu@umich.edu> | 2020-04-25 14:23:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-25 21:23:58 +0300 |
commit | 619422b493eaf88c42373af1725ac0aa2297fa91 (patch) | |
tree | b4a735be467d23efca13e77b897a16fcd421fe59 | |
parent | 59984a3596e00e088b10c58f02856e8088fcd4df (diff) | |
download | numpy-619422b493eaf88c42373af1725ac0aa2297fa91.tar.gz |
BUG: fix AttributeError on accessing object in nested MaskedArray. (#15949)
* BUG: fix AttributeError on accessing object in nested MaskedArray
Co-authored-by: Rena Xu <renaxu@Renas-MacBook-Pro.local>
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
Co-authored-by: vagrant <vagrant@vagrant.vm>
-rw-r--r-- | numpy/ma/core.py | 11 | ||||
-rw-r--r-- | numpy/ma/tests/test_extras.py | 22 |
2 files changed, 31 insertions, 2 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 00e6bbd98..a5e59bb74 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -3297,6 +3297,10 @@ class MaskedArray(ndarray): if self._fill_value is not None: dout._fill_value = self._fill_value[indx] + # Something like gh-15895 has happened if this check fails. + # _fill_value should always be an ndarray. + if not isinstance(dout._fill_value, np.ndarray): + raise RuntimeError('Internal NumPy error.') # If we're indexing a multidimensional field in a # structured array (such as dtype("(2,)i2,(2,)i1")), # dimensionality goes up (M[field].ndim == M.ndim + @@ -3304,7 +3308,7 @@ class MaskedArray(ndarray): # M[field] but problematic for M[field].fill_value # which should have shape () to avoid breaking several # methods. There is no great way out, so set to - # first element. See issue #6723. + # first element. See issue #6723. if dout._fill_value.ndim > 0: if not (dout._fill_value == dout._fill_value.flat[0]).all(): @@ -3315,7 +3319,10 @@ class MaskedArray(ndarray): "heterogeneous fill_value and setting " f"all to {dout._fill_value[0]!s}.", stacklevel=2) - dout._fill_value = dout._fill_value.flat[0] + # Need to use `.flat[0:1].squeeze(...)` instead of just + # `.flat[0]` to ensure the result is a 0d array and not + # a scalar. + dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) dout._isfield = True # Update the mask if needed if mout is not nomask: diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py index 1c8610625..d237829cb 100644 --- a/numpy/ma/tests/test_extras.py +++ b/numpy/ma/tests/test_extras.py @@ -64,6 +64,28 @@ class TestGeneric: control = array([[(1, (1, 1))]], mask=[[(1, (1, 1))]], dtype=dt) assert_equal(test, control) + def test_masked_all_with_object_nested(self): + # Test masked_all works with nested array with dtype of an 'object' + # refers to issue #15895 + my_dtype = np.dtype([('b', ([('c', object)], (1,)))]) + masked_arr = np.ma.masked_all((1,), my_dtype) + + assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray) + assert_equal(type(masked_arr['b']['c']), np.ma.core.MaskedArray) + assert_equal(len(masked_arr['b']['c']), 1) + assert_equal(masked_arr['b']['c'].shape, (1, 1)) + assert_equal(masked_arr['b']['c']._fill_value.shape, ()) + + def test_masked_all_with_object(self): + # same as above except that the array is not nested + my_dtype = np.dtype([('b', (object, (1,)))]) + masked_arr = np.ma.masked_all((1,), my_dtype) + + assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray) + assert_equal(len(masked_arr['b']), 1) + assert_equal(masked_arr['b'].shape, (1, 1)) + assert_equal(masked_arr['b']._fill_value.shape, ()) + def test_masked_all_like(self): # Tests masked_all # Standard dtype |