Skip to content

Commit

Permalink
added is_dataless, and corrected data manager exceptions to not be cu…
Browse files Browse the repository at this point in the history
…be specific
  • Loading branch information
ESadek-MO committed Dec 17, 2024
1 parent 9b52067 commit 2f2b56a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
19 changes: 14 additions & 5 deletions lib/iris/_data_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ def __init__(self, data, shape=None):
data :
The :class:`~numpy.ndarray` or :class:`~numpy.ma.core.MaskedArray`
real data, or :class:`~dask.array.core.Array` lazy data to be
managed.
managed. If a value of None is given, the data manager will be
considered dataless.
shape :
A tuple, representing the shape of the data manager. This can only
be used in the case of `data=None`, and will render the data manager
dataless.
"""
if (shape is not None) and (data is not None):
msg = "A cube may not be created with both data and a custom shape."
raise iris.exceptions.InvalidCubeError(msg)
msg = "`shape` should only be provided if `data is None`"
raise ValueError(msg)

# Initialise the instance.
self._lazy_array = None
Expand Down Expand Up @@ -134,12 +140,12 @@ def _assert_axioms(self):
overfilled = self._lazy_array is not None and self._real_array is not None
if overfilled:
msg = "Unexpected data state, got both lazy and real data."
raise iris.exceptions.InvalidCubeError(msg)
raise ValueError(msg)
elif (
empty and self._shape is None
): # if I remove the second check, allows empty arrays, like old behaviour
msg = "Unexpected data state, got no lazy or real data, and no shape."
raise iris.exceptions.InvalidCubeError(msg)
raise ValueError(msg)

def _deepcopy(self, memo, data=None):
"""Perform a deepcopy of the :class:`~iris._data_manager.DataManager` instance.
Expand Down Expand Up @@ -290,6 +296,9 @@ def shape(self):
result = self.core_data().shape
return result

def is_dataless(self):
return (self.core_data() is None) and (self.shape is not None)

def copy(self, data=None):
"""Return a deep copy of this :class:`~iris._data_manager.DataManager` instance.
Expand Down
10 changes: 10 additions & 0 deletions lib/iris/cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -2887,6 +2887,16 @@ def has_lazy_data(self) -> bool:
"""
return self._data_manager.has_lazy_data()

def is_dataless(self) -> bool:
"""Detail whether this :class:`~iris.cube.Cube` is dataless.
Returns
-------
bool
"""
return self._data_manager.is_dataless()

@property
def dim_coords(self) -> tuple[DimCoord, ...]:
"""Return a tuple of all the dimension coordinates, ordered by dimension.
Expand Down
13 changes: 13 additions & 0 deletions lib/iris/tests/unit/data_manager/test_DataManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,19 @@ def test_with_lazy_array(self):
self.assertTrue(dm.has_lazy_data())
self.assertIs(result, dm._lazy_array)

class Test_is_dataless(tests.IrisTest):
def setUp(self):
self.data = np.array(0)
self.shape = (0)

def test_with_data(self):
dm = DataManager(self.data)
self.assertFalse(dm.is_dataless())

def test_without_data(self):
dm = DataManager(None, self.shape)
self.assertTrue(dm.is_dataless())


if __name__ == "__main__":
tests.main()

0 comments on commit 2f2b56a

Please sign in to comment.