Skip to content

Commit 37fc7f5

Browse files
committed
Ensure that cube.shape can only be a tuple (or None).
1 parent b1be959 commit 37fc7f5

File tree

2 files changed

+75
-6
lines changed

2 files changed

+75
-6
lines changed

lib/iris/_data_manager.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@ def __init__(self, data, shape=None):
3434
dataless.
3535
3636
"""
37-
if (shape is None) and (data is None):
38-
msg = 'one of "shape" or "data" should be provided; both are None'
39-
raise ValueError(msg)
40-
elif (shape is not None) and (data is not None):
41-
msg = '"shape" should only be provided if "data" is None'
42-
raise ValueError(msg)
37+
if shape is None:
38+
if data is None:
39+
msg = 'one of "shape" or "data" should be provided; both are None'
40+
raise ValueError(msg)
41+
else:
42+
if data is not None:
43+
msg = '"shape" should only be provided if "data" is None'
44+
raise ValueError(msg)
45+
# Normalise how shape is recorded
46+
shape = tuple(shape)
4347

4448
# Initialise the instance.
4549
self._shape = shape
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright Iris contributors
2+
#
3+
# This file is part of Iris and is released under the BSD license.
4+
# See LICENSE in the root of the repository for full licensing details.
5+
"""Basic integration tests for merging with dataless cubes."""
6+
7+
import numpy as np
8+
9+
from iris.coords import AuxCoord, DimCoord
10+
from iris.cube import Cube, CubeList
11+
12+
13+
class TestMergeDataless:
14+
def _testcube(self, z=1, name="this", dataless=False):
15+
# Create a testcube with a scalar Z coord, for merge testing.
16+
cube = Cube(
17+
[1, 2, 3],
18+
long_name=name,
19+
dim_coords_and_dims=[(DimCoord([0.0, 1.0, 2], long_name="x"), 0)],
20+
aux_coords_and_dims=[(AuxCoord([z], long_name="z"), ())],
21+
)
22+
if dataless:
23+
cube.data = None
24+
return cube
25+
26+
def test_mixed_passthrough(self):
27+
# Check that normal merge can handle dataless alongside dataful cubes.
28+
cubes = CubeList(
29+
[
30+
self._testcube(name="this", dataless=False),
31+
self._testcube(name="that", dataless=True),
32+
]
33+
)
34+
result = cubes.merge()
35+
assert len(result) == 2
36+
cube1, cube2 = [result.extract_cube(name) for name in ("this", "that")]
37+
assert not cube1.is_dataless()
38+
assert cube2.is_dataless()
39+
40+
def test_dataless_merge(self):
41+
# Check that dataless cubes can be merged.
42+
cubes = CubeList(
43+
[
44+
self._testcube(z=1, dataless=True),
45+
self._testcube(z=2, dataless=True),
46+
]
47+
)
48+
cube = cubes.merge_cube()
49+
assert cube.is_dataless()
50+
assert np.all(cube.coord("z").points == [1, 2])
51+
52+
def test_dataless_dataful_merge(self):
53+
# Check that dataless cubes can merge **with** regular ones.
54+
# Check that dataless cubes can be merged correctly.
55+
cubes = CubeList(
56+
[
57+
self._testcube(z=1, dataless=False),
58+
self._testcube(z=2, dataless=True),
59+
]
60+
)
61+
cube = cubes.merge_cube()
62+
assert not cube.is_dataless()
63+
data_z1, data_z2 = cube[0].data, cube[1].data
64+
assert np.all(data_z1 == [1, 2, 3])
65+
assert np.all(np.ma.getmaskarray(data_z2) == True) # noqa: E712

0 commit comments

Comments
 (0)