Repository: astropy/astropy

Issue:
masked Quantity fails on astropy master with numpy 1.17.2
Masked `Quantity` started failing with `astropy` master and `numpy 1.17.2`:

```python
>>> import numpy as np
>>> import astropy.units as u

>>> masked_quantity = np.ma.array([1, 2, 3 ,4] * u.kg,
...                               mask=[True, False, True, False])
>>> print(masked_quantity)
Traceback (most recent call last):
  File "/Users/lbradley/Dropbox/softw/packages/dev/astropy/astropy/units/quantity.py", line 1319, in _to_own_unit
    _value = value.to_value(self.unit)
AttributeError: '_MaskedPrintOption' object has no attribute 'to_value'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./ma.py", line 8, in <module>
    print(masked_quantity)
  File "/Users/lbradley/local/conda/envs/dev/lib/python3.7/site-packages/numpy/ma/core.py", line 3870, in __str__
    return str(self._insert_masked_print())
  File "/Users/lbradley/local/conda/envs/dev/lib/python3.7/site-packages/numpy/ma/core.py", line 3864, in _insert_masked_print
    _recursive_printoption(res, mask, masked_print_option)
  File "/Users/lbradley/local/conda/envs/dev/lib/python3.7/site-packages/numpy/ma/core.py", line 2443, in _recursive_printoption
    np.copyto(result, printopt, where=mask)
  File "<__array_function__ internals>", line 6, in copyto
  File "/Users/lbradley/Dropbox/softw/packages/dev/astropy/astropy/units/quantity.py", line 1475, in __array_function__
    args, kwargs, unit, out = function_helper(*args, **kwargs)
  File "/Users/lbradley/Dropbox/softw/packages/dev/astropy/astropy/units/quantity_helper/function_helpers.py", line 270, in copyto
    return ((dst.view(np.ndarray), dst._to_own_unit(src)) + args,
  File "/Users/lbradley/Dropbox/softw/packages/dev/astropy/astropy/units/quantity.py", line 1324, in _to_own_unit
    as_quantity = Quantity(value)
  File "/Users/lbradley/Dropbox/softw/packages/dev/astropy/astropy/units/quantity.py", line 374, in __new__
    raise TypeError("The value must be a valid Python or "
TypeError: The value must be a valid Python or Numpy numeric type.
```

It works fine with `astropy` master and `numpy <= 1.17.1`.  It also works fine with `astropy 3.2.1` and `numpy = 1.17.2`:

```python
>>> import numpy as np
>>> import astropy.units as u

>>> masked_quantity = np.ma.array([1, 2, 3 ,4] * u.kg,
...                               mask=[True, False, True, False])
>>> print(masked_quantity)
[-- 2.0 -- 4.0] kg
```

Ping: @mhvk

Discussion:

Patch:
diff --git a/astropy/units/quantity.py b/astropy/units/quantity.py
index 7aa4747fce..c8a3778bb8 100644
--- a/astropy/units/quantity.py
+++ b/astropy/units/quantity.py
@@ -369,8 +369,7 @@ class Quantity(np.ndarray):
         # check that array contains numbers or long int objects
         if (value.dtype.kind in 'OSU' and
             not (value.dtype.kind == 'O' and
-                 isinstance(value.item(() if value.ndim == 0 else 0),
-                            numbers.Number))):
+                 isinstance(value.item(0), numbers.Number))):
             raise TypeError("The value must be a valid Python or "
                             "Numpy numeric type.")
 
@@ -1321,9 +1320,19 @@ class Quantity(np.ndarray):
             # We're not a Quantity, so let's try a more general conversion.
             # Plain arrays will be converted to dimensionless in the process,
             # but anything with a unit attribute will use that.
-            as_quantity = Quantity(value)
             try:
+                as_quantity = Quantity(value)
                 _value = as_quantity.to_value(self.unit)
+            except TypeError:
+                # Could not make a Quantity.  Maybe masked printing?
+                # Note: masked quantities do not work very well, but no reason
+                # to break even repr and str.
+                if (value is np.ma.masked_print_option and
+                        self.dtype.kind == 'O'):
+                    return value
+                else:
+                    raise
+
             except UnitsError:
                 # last chance: if this was not something with a unit
                 # and is all 0, inf, or nan, we treat it as arbitrary unit.


Test patch:
diff --git a/astropy/units/tests/test_quantity.py b/astropy/units/tests/test_quantity.py
index 27fa999f55..6bb4885378 100644
--- a/astropy/units/tests/test_quantity.py
+++ b/astropy/units/tests/test_quantity.py
@@ -1616,3 +1616,13 @@ class TestQuantityMimics:
         assert np.all(q.value == [1., 2.])
         with pytest.raises(u.UnitTypeError):
             u.Quantity(mimic)
+
+
+def test_masked_quantity_str_repr():
+    """Ensure we don't break masked Quantity representation."""
+    # Really, masked quantities do not work well, but at least let the
+    # basics work.
+    masked_quantity = np.ma.array([1, 2, 3, 4] * u.kg,
+                                  mask=[True, False, True, False])
+    str(masked_quantity)
+    repr(masked_quantity)