Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions lib/iris/cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,25 @@ class CubeList(list):

"""

def __new__(cls, list_of_cubes=None):
"""Given a :class:`list` of cubes, return a CubeList instance."""
cube_list = list.__new__(cls, list_of_cubes)

# Check that all items in the incoming list are cubes. Note that this
# checking does not guarantee that a CubeList instance *always* has
# just cubes in its list as the append & __getitem__ methods have not
# been overridden.
if not all([isinstance(cube, Cube) for cube in cube_list]):
def __init__(self, iterable_of_cubes=None):
"""Given an iterable of cubes, return a CubeList instance."""
if iterable_of_cubes is None:
iterable_of_cubes = []
# Run the iterable, and capture as a list.
list_of_cubes = list(iterable_of_cubes)

# Check that all items in the incoming list (if any) are cubes.
# Note that this checking does not (yet) guarantee that a CubeList
# instance *always* contains only cubes, as the append & __setitem__ methods
# (for example), have not been overridden.
if not all(isinstance(cube, Cube) for cube in list_of_cubes):
raise ValueError(
"All items in list_of_cubes must be Cube " "instances."
"CubeList create arguments are not all Cube "
"instances : {}".format(list_of_cubes)
)
return cube_list

# Initialise "as a" list.
super().__init__(list_of_cubes)

def __str__(self):
"""Runs short :meth:`Cube.summary` on every cube."""
Expand Down
51 changes: 50 additions & 1 deletion lib/iris/tests/unit/cube/test_CubeList.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,53 @@
from iris.fileformats.pp import STASH


class TestCreateCubelist(tests.IrisTest):
def test_create_no_args(self):
result = CubeList()
self.assertIsInstance(result, CubeList)
self.assertEqual(len(result), 0)

def test_create_empty_arg(self):
# In principle, any iterable should do. So let's use a generator.
def empty_iter():
if False:
yield False

result = CubeList(empty_iter())
self.assertIsInstance(result, CubeList)
self.assertEqual(len(result), 0)

def test_create_single_cube(self):
cube = Cube([1])
result = CubeList([cube])
self.assertIsInstance(result, CubeList)
self.assertEqual(len(result), 1)
self.assertIs(result[0], cube)

def test_create_cubes(self):
cubes = (
Cube([1], long_name="a"),
Cube(np.arange(6).reshape((2, 3)), long_name="b"),
)
result = CubeList(cubes)
self.assertIsInstance(result, CubeList)
self.assertEqual(len(result), 2)
self.assertIs(result[0], cubes[0])
self.assertIs(result[1], cubes[1])

def test_create_fail_noncube_object(self):
with self.assertRaisesRegexp(ValueError, "Cube instance"):
CubeList([Cube([1]), []])

def test_create_fail_noncube_None(self):
with self.assertRaisesRegexp(ValueError, "Cube instance"):
CubeList([Cube([1]), None])

def test_create_fail_noncube_number(self):
with self.assertRaisesRegexp(ValueError, "Cube instance"):
CubeList([Cube([1]), 123.45])


class Test_concatenate_cube(tests.IrisTest):
def setUp(self):
self.units = Unit(
Expand Down Expand Up @@ -592,7 +639,9 @@ class TestRealiseData(tests.IrisTest):
def test_realise_data(self):
# Simply check that calling CubeList.realise_data is calling
# _lazy_data.co_realise_cubes.
mock_cubes_list = [mock.Mock(ident=count) for count in range(3)]
mock_cubes_list = [
mock.Mock(ident=count, spec=Cube) for count in range(3)
]
test_cubelist = CubeList(mock_cubes_list)
call_patch = self.patch("iris._lazy_data.co_realise_cubes")
test_cubelist.realise_data()
Expand Down