From f2dee4278c4ff70b0e7742e2d27aa94ce89c3649 Mon Sep 17 00:00:00 2001
From: David Hassell <david.hassell@ncas.ac.uk>
Date: Wed, 27 Apr 2022 09:26:11 +0100
Subject: [PATCH 1/3] Data.isscalar

---
 cf/data/data.py      | 13 +++++++------
 cf/test/test_Data.py |  5 +++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/cf/data/data.py b/cf/data/data.py
index c3d0cd1449..b73e476e6e 100644
--- a/cf/data/data.py
+++ b/cf/data/data.py
@@ -4894,18 +4894,19 @@ def is_masked(a):
         return bool(dx.any())
 
     @property
+    @daskified(_DASKIFIED_VERBOSE)
     def isscalar(self):
-        """True if the data array is a 0-d scalar array.
+        """True if the data is a 0-d scalar array.
 
         **Examples**
 
-        >>> d.ndim
-        0
+        >>> d = cf.Data(9, 'm')
         >>> d.isscalar
         True
-
-        >>> d.ndim >= 1
-        True
+        >>> d = cf.Data([9], 'm')
+        >>> d.isscalar
+        False
+        >>> d = cf.Data([9, 10], 'm')
         >>> d.isscalar
         False
 
diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py
index 0f22111145..fab8102415 100644
--- a/cf/test/test_Data.py
+++ b/cf/test/test_Data.py
@@ -3845,6 +3845,11 @@ def test_Data_override_calendar(self):
 
         self.assertIsNone(d.override_calendar("all_leap", inplace=True))
 
+    def test_Data_isscalar(self):
+        self.assertTrue(cf.Data(9, "m").isscalar)
+        self.assertFalse(cf.Data([9], "m").isscalar)
+        self.assertFalse(cf.Data([9, 10], "m").isscalar)
+
 
 if __name__ == "__main__":
     print("Run date:", datetime.datetime.now())

From dc22fb64789b13550084fb9e019818b295c306b0 Mon Sep 17 00:00:00 2001
From: David Hassell <david.hassell@ncas.ac.uk>
Date: Wed, 27 Apr 2022 10:16:20 +0100
Subject: [PATCH 2/3] Data.masked_all

---
 cf/data/data.py      | 60 +++++++++++++++++++++++++++++++-------------
 cf/test/test_Data.py | 17 ++++++++++---
 2 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/cf/data/data.py b/cf/data/data.py
index b73e476e6e..d485656321 100644
--- a/cf/data/data.py
+++ b/cf/data/data.py
@@ -53,7 +53,6 @@
     cf_soften_mask,
     cf_where,
 )
-from .filledarray import FilledArray
 from .mixin import DataClassDeprecationsMixin
 from .utils import (  # is_small,; is_very_small,
     YMDhms,
@@ -9396,43 +9395,68 @@ def del_units(self, default=ValueError()):
         )
 
     @classmethod
-    def masked_all(cls, shape, dtype=None, units=None, chunk=True):
-        """Return a new data array of given shape and type with all
-        elements masked.
+    def masked_all(
+        cls,
+        shape,
+        dtype=None,
+        units=None,
+        calendar=None,
+        chunks=_DEFAULT_CHUNKS,
+    ):
+        """Return an empty masked array with all elements masked.
 
-        .. seealso:: `empty`, `ones`, `zeros`
+        .. seealso:: `empty`, `ones`, `zeros`, `masked_invalid`
 
         :Parameters:
 
             shape: `int` or `tuple` of `int`
-                The shape of the new array.
+                The shape of the new array. e.g. ``(2, 3)`` or ``2``.
 
             dtype: data-type
-                The data-type of the new array. By default the data-type
-                is ``float``.
+                The desired output data-type for the array, e.g.
+                `numpy.int8`. The default is `numpy.float64`.
 
             units: `str` or `Units`
                 The units for the new data array.
 
+            calendar: `str`, optional
+                The calendar for reference time units.
+
+            {{chunks: `int`, `tuple`, `dict` or `str`, optional}}
+
+                .. versionadded:: 4.0.0
+
         :Returns:
 
             `Data`
-                The new data array having all elements masked.
+                A masked array with all data masked.
 
         **Examples**
 
-        >>> d = cf.Data.masked_all((96, 73))
+        >>> d = cf.Data.masked_all((2, 2))
+        >>> print(d.array)
+        [[-- --]
+         [-- --]]
+
+        >>> d = cf.Data.masked_all((), dtype=bool)
+        >>> print(d.array)
+        masked_array(data=--,
+                     mask=True,
+               fill_value=True,
+                    dtype=bool)
 
         """
-        array = FilledArray(
-            shape=tuple(shape),
-            size=reduce(mul, shape, 1),
-            ndim=len(shape),
-            dtype=np.dtype(dtype),
-            fill_value=cf_masked,
+        d = cls.empty(
+            shape=shape,
+            dtype=dtype,
+            units=units,
+            calendar=calendar,
+            chunks=chunks,
         )
-
-        return cls(array, units=units, chunk=chunk)
+        dx = d.to_dask_array()
+        dx = dx.map_blocks(partial(np.ma.array, mask=True, copy=False))
+        d._set_dask(dx, reset_mask_hardness=False)
+        return d
 
     @daskified(_DASKIFIED_VERBOSE)
     @_inplace_enabled(default=False)
diff --git a/cf/test/test_Data.py b/cf/test/test_Data.py
index fab8102415..916af722be 100644
--- a/cf/test/test_Data.py
+++ b/cf/test/test_Data.py
@@ -3845,10 +3845,19 @@ def test_Data_override_calendar(self):
 
         self.assertIsNone(d.override_calendar("all_leap", inplace=True))
 
-    def test_Data_isscalar(self):
-        self.assertTrue(cf.Data(9, "m").isscalar)
-        self.assertFalse(cf.Data([9], "m").isscalar)
-        self.assertFalse(cf.Data([9, 10], "m").isscalar)
+    def test_Data_masked_all(self):
+        # shape
+        for shape in ((), (2,), (2, 3)):
+            a = np.ma.masked_all(shape)
+            d = cf.Data.masked_all(shape)
+            self.assertEqual(d.shape, a.shape)
+            self.assertTrue((d.array.mask == a.mask).all())
+
+        # dtype
+        for dtype in "fibUS":
+            a = np.ma.masked_all((), dtype=dtype)
+            d = cf.Data.masked_all((), dtype=dtype)
+            self.assertEqual(d.dtype, a.dtype)
 
 
 if __name__ == "__main__":

From d34f4d710ab0faf96327535b49693bfa55c3b73f Mon Sep 17 00:00:00 2001
From: David Hassell <davidhassell@users.noreply.github.com>
Date: Mon, 9 May 2022 08:26:31 +0100
Subject: [PATCH 3/3] Typo

Co-authored-by: Sadie L. Bartholomew <sadie.bartholomew@ncas.ac.uk>
---
 cf/data/data.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cf/data/data.py b/cf/data/data.py
index b22c1ceb9d..5ead348dcc 100644
--- a/cf/data/data.py
+++ b/cf/data/data.py
@@ -9419,7 +9419,7 @@ def masked_all(
          [-- --]]
 
         >>> d = cf.Data.masked_all((), dtype=bool)
-        >>> print(d.array)
+        >>> d.array
         masked_array(data=--,
                      mask=True,
                fill_value=True,
