diff options
author | Eric Wieser <wieser.eric@gmail.com> | 2018-05-18 23:27:23 -0700 |
---|---|---|
committer | Eric Wieser <wieser.eric@gmail.com> | 2018-06-10 11:12:27 -0700 |
commit | 4116089c94fe7112b71409adeecff009b654966f (patch) | |
tree | 979704a1cc35420f2b8926352e1e5bb3765ab6e5 /numpy/ma/core.py | |
parent | 3bb11d6f1758e4d3d6ca812749cc5145f82713b3 (diff) | |
download | numpy-4116089c94fe7112b71409adeecff009b654966f.tar.gz |
BUG: Prevent crashes on 0-length structured void scalars
Diffstat (limited to 'numpy/ma/core.py')
-rw-r--r-- | numpy/ma/core.py | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 5ed086db3..d4c4c4437 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -215,7 +215,7 @@ def _recursive_fill_value(dtype, f): """ Recursively produce a fill value for `dtype`, calling f on scalar dtypes """ - if dtype.names: + if dtype.names is not None: vals = tuple(_recursive_fill_value(dtype[name], f) for name in dtype.names) return np.array(vals, dtype=dtype)[()] # decay to void scalar from 0d elif dtype.subdtype: @@ -433,7 +433,7 @@ def _recursive_set_fill_value(fillvalue, dt): if cdtype.subdtype: cdtype = cdtype.subdtype[0] - if cdtype.names: + if cdtype.names is not None: output_value.append(tuple(_recursive_set_fill_value(fval, cdtype))) else: output_value.append(np.array(fval, dtype=cdtype).item()) @@ -1282,7 +1282,7 @@ def _replace_dtype_fields_recursive(dtype, primitive_dtype): _recurse = _replace_dtype_fields_recursive # Do we have some name fields ? - if dtype.names: + if dtype.names is not None: descr = [] for name in dtype.names: field = dtype.fields[name] @@ -1547,7 +1547,7 @@ def _shrink_mask(m): """ Shrink a mask to nomask if possible """ - if not m.dtype.names and not m.any(): + if m.dtype.names is None and not m.any(): return nomask else: return m @@ -1733,7 +1733,7 @@ def mask_or(m1, m2, copy=False, shrink=True): names = m1.dtype.names for name in names: current1 = m1[name] - if current1.dtype.names: + if current1.dtype.names is not None: _recursive_mask_or(current1, m2[name], newmask[name]) else: umath.logical_or(current1, m2[name], newmask[name]) @@ -1750,7 +1750,7 @@ def mask_or(m1, m2, copy=False, shrink=True): (dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None)) if (dtype1 != dtype2): raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2)) - if dtype1.names: + if dtype1.names is not None: # Allocate an output mask array with the properly broadcast shape. newmask = np.empty(np.broadcast(m1, m2).shape, dtype1) _recursive_mask_or(m1, m2, newmask) @@ -1793,7 +1793,7 @@ def flatten_mask(mask): def _flatmask(mask): "Flatten the mask and returns a (maybe nested) sequence of booleans." mnames = mask.dtype.names - if mnames: + if mnames is not None: return [flatten_mask(mask[name]) for name in mnames] else: return mask @@ -2429,7 +2429,7 @@ def _recursive_printoption(result, mask, printopt): """ names = result.dtype.names - if names: + if names is not None: for name in names: curdata = result[name] curmask = mask[name] @@ -2481,7 +2481,7 @@ def _recursive_filled(a, mask, fill_value): names = a.dtype.names for name in names: current = a[name] - if current.dtype.names: + if current.dtype.names is not None: _recursive_filled(current, mask[name], fill_value[name]) else: np.copyto(current, fill_value[name], where=mask[name]) @@ -2868,12 +2868,12 @@ class MaskedArray(ndarray): _data._mask = mask _data._sharedmask = not copy else: - if _data.dtype.names: + if _data.dtype.names is not None: def _recursive_or(a, b): "do a|=b on each field of a, recursively" for name in a.dtype.names: (af, bf) = (a[name], b[name]) - if af.dtype.names: + if af.dtype.names is not None: _recursive_or(af, bf) else: af |= bf @@ -2960,7 +2960,7 @@ class MaskedArray(ndarray): if isinstance(obj, ndarray): # XX: This looks like a bug -- shouldn't it check self.dtype # instead? - if obj.dtype.names: + if obj.dtype.names is not None: _mask = getmaskarray(obj) else: _mask = getmask(obj) @@ -3009,7 +3009,7 @@ class MaskedArray(ndarray): # When _mask.shape is not writable (because it's a void) pass # Finalize the fill_value for structured arrays - if self.dtype.names: + if self.dtype.names is not None: if self._fill_value is None: self._fill_value = _check_fill_value(None, self.dtype) return @@ -3293,15 +3293,14 @@ class MaskedArray(ndarray): return _dtype = _data.dtype - nbfields = len(_dtype.names or ()) if value is masked: # The mask wasn't set: create a full version. if _mask is nomask: _mask = self._mask = make_mask_none(self.shape, _dtype) # Now, set the mask to its value. - if nbfields: - _mask[indx] = tuple([True] * nbfields) + if _dtype.names is not None: + _mask[indx] = tuple([True] * len(_dtype.names)) else: _mask[indx] = True return @@ -3310,8 +3309,8 @@ class MaskedArray(ndarray): dval = getattr(value, '_data', value) # Get the _mask part of the new value mval = getmask(value) - if nbfields and mval is nomask: - mval = tuple([False] * nbfields) + if _dtype.names is not None and mval is nomask: + mval = tuple([False] * len(_dtype.names)) if _mask is nomask: # Set the data, then the mask _data[indx] = dval @@ -3326,7 +3325,7 @@ class MaskedArray(ndarray): indx = indx * umath.logical_not(_mask) _data[indx] = dval else: - if nbfields: + if _dtype.names is not None: err_msg = "Flexible 'hard' masks are not yet supported." raise NotImplementedError(err_msg) mindx = mask_or(_mask[indx], mval, copy=True) @@ -3707,7 +3706,7 @@ class MaskedArray(ndarray): if self is masked_singleton: return np.asanyarray(fill_value) - if m.dtype.names: + if m.dtype.names is not None: result = self._data.copy('K') _recursive_filled(result, self._mask, fill_value) elif not m.any(): @@ -3977,7 +3976,7 @@ class MaskedArray(ndarray): mask = mask_or(smask, omask, copy=True) odata = getdata(other) - if mask.dtype.names: + if mask.dtype.names is not None: # For possibly masked structured arrays we need to be careful, # since the standard structured array comparison will use all # fields, masked or not. To avoid masked fields influencing the |