summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenaRuirui <renaxu@umich.edu>2020-04-25 14:23:58 -0400
committerGitHub <noreply@github.com>2020-04-25 21:23:58 +0300
commit619422b493eaf88c42373af1725ac0aa2297fa91 (patch)
treeb4a735be467d23efca13e77b897a16fcd421fe59
parent59984a3596e00e088b10c58f02856e8088fcd4df (diff)
downloadnumpy-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.py11
-rw-r--r--numpy/ma/tests/test_extras.py22
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