Repository: numpy/numpy

Issue:
fill_value attribute gives TypeError for structured masked array fields with character dtype
For a structured masked array, when accessing a field with a character dtype, the `fill_value` is evidently not correctly set.  When `X` is a structured masked array with a structured dtype such that field `A` is a character array, accessing `X['A'].fill_value` gives `TypeError: byte indices must be integers or slices, not tuple`.  The offending line of code is:

`return self._fill_value[()]`

with a full example shown below.

```
$ ipython3 --pylab
Python 3.5.0 (default, Nov 20 2015, 16:20:41) 
Type "copyright", "credits" or "license" for more information.

IPython 4.0.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.
Using matplotlib backend: TkAgg
Python are go!

In [1]: print(numpy.version.version)
1.12.0.dev0+0de1234

In [2]: X = numpy.ma.empty(shape=1, dtype=[("A", "S1", 2)])

In [3]: Xa = X["A"]

In [5]: Xa.fill_value
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-d077d77d307b> in <module>()
----> 1 Xa.fill_value

/home/users/gholl/venv/stable-3.5/lib/python3.5/site-packages/numpy/ma/core.py in get_fill_value(self)
   3528         if self._fill_value is None:
   3529             self._fill_value = _check_fill_value(None, self.dtype)
-> 3530         return self._fill_value[()]
   3531 
   3532     def set_fill_value(self, value=None):

TypeError: byte indices must be integers or slices, not tuple
```

This problem is triggered, among other locations, upon calling `repr(Xa)`, so it has a rather high impact in practice.



Discussion:
It appears to be ultimately due to the fact that most numpy scalars are valid to be indexed with `()`, but `numpy.bytes_` is not:

```
In [36]: numpy.int64(10)[()]
Out[36]: 10

In [37]: numpy.bytes_("ABC")
Out[37]: b'ABC'

In [38]: numpy.bytes_("ABC")[()]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-4912a5675720> in <module>()
----> 1 numpy.bytes_("ABC")[()]

TypeError: byte indices must be integers or slices, not tuple
```

See also my comment on the commit triggering this problem: https://github.com/numpy/numpy/commit/f8f753b33fd77211227d5e5dad2d0b9c2e3dedad#commitcomment-16120218


Resolving patch:
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -3527,7 +3527,14 @@ def get_fill_value(self):
         """
         if self._fill_value is None:
             self._fill_value = _check_fill_value(None, self.dtype)
-        return self._fill_value[()]
+
+        # Temporary workaround to account for the fact that str and bytes
+        # scalars cannot be indexed with (), whereas all other numpy
+        # scalars can. See issues #7259 and #7267.
+        # The if-block can be removed after #7267 has been fixed.
+        if isinstance(self._fill_value, ndarray):
+            return self._fill_value[()]
+        return self._fill_value
 
     def set_fill_value(self, value=None):
         """


Test patch:
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -1819,6 +1819,13 @@ def test_fillvalue_in_view(self):
         y = x.view(dtype=np.int32)
         assert_(y.fill_value == 999999)
 
+    def test_fillvalue_bytes_or_str(self):
+        # Test whether fill values work as expected for structured dtypes
+        # containing bytes or str.  See issue #7259.
+        a = empty(shape=(3, ), dtype="(2)3S,(2)3U")
+        assert_equal(a["f0"].fill_value, default_fill_value(b"spam"))
+        assert_equal(a["f1"].fill_value, default_fill_value("eggs"))
+
 
 class TestUfuncs(TestCase):
     # Test class for the application of ufuncs on MaskedArrays.