Skip to content

Commit 70630eb

Browse files
Rationalise CML (#6713)
* Removed `assert_CML_approx_data` and added its functionality to `assert_CML` * Updated tests to call `assert_CML` with new `approx_data` keyword instead of `assert_CML_approx_data` * Added "What's New" entry * Removed commented out code. * Format fix - double backticks. Co-authored-by: Bill Little <[email protected]> * Docstring formatting - correct use of double backticks. Co-authored-by: Bill Little <[email protected]> * Prefer f-string --------- Co-authored-by: Bill Little <[email protected]>
1 parent ecab3df commit 70630eb

File tree

12 files changed

+242
-152
lines changed

12 files changed

+242
-152
lines changed

docs/src/whatsnew/latest.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ This document explains the changes made to Iris for this release
9595
#. `@melissaKG`_ upgraded Iris' tests to no longer use the deprecated
9696
``git whatchanged`` command. (:pull:`6672`)
9797

98+
#. `@ukmo-ccbunney` merged functionality of ``assert_CML_approx_data`` into
99+
``assert_CML`` via the use of a new ``approx_data`` keyword. (:pull:`6713`)
100+
98101

99102
.. comment
100103
Whatsnew author names (@github name) in alphabetical order. Note that,

lib/iris/tests/_shared_utils.py

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -291,28 +291,6 @@ def remove_test(string: str):
291291
return str(output_path)
292292

293293

294-
def assert_CML_approx_data(
295-
request: pytest.FixtureRequest, cubes, reference_filename=None, **kwargs
296-
):
297-
# passes args and kwargs on to approx equal
298-
# See result_path() Examples for how to access the ``request`` fixture.
299-
300-
_check_for_request_fixture(request, "assert_CML_approx_data")
301-
302-
if isinstance(cubes, iris.cube.Cube):
303-
cubes = [cubes]
304-
if reference_filename is None:
305-
reference_filename = result_path(request, None, "cml")
306-
reference_filename = [get_result_path(reference_filename)]
307-
for i, cube in enumerate(cubes):
308-
fname = list(reference_filename)
309-
# don't want the ".cml" for the json stats file
310-
fname[-1] = fname[-1].removesuffix(".cml")
311-
fname[-1] += ".data.%d.json" % i
312-
assert_data_almost_equal(cube.data, fname, **kwargs)
313-
assert_CML(request, cubes, reference_filename, checksum=False)
314-
315-
316294
def assert_CDL(
317295
request: pytest.FixtureRequest, netcdf_filename, reference_filename=None, flags="-h"
318296
):
@@ -385,14 +363,30 @@ def sort_key(line):
385363

386364

387365
def assert_CML(
388-
request: pytest.FixtureRequest, cubes, reference_filename=None, checksum=True
366+
request: pytest.FixtureRequest,
367+
cubes,
368+
reference_filename=None,
369+
checksum=True,
370+
approx_data=False,
371+
**kwargs,
389372
):
390373
"""Test that the CML for the given cubes matches the contents of
391374
the reference file.
392375
393376
If the environment variable IRIS_TEST_CREATE_MISSING is
394377
non-empty, the reference file is created if it doesn't exist.
395378
379+
The data payload of individual cubes is not compared unless ``checksum``
380+
or ``approx_data`` are True.
381+
382+
Notes
383+
-----
384+
The ``approx_data`` keyword provides functionality equivalent to the
385+
old ``assert_CML_approx_data`` function.
386+
387+
``**kwargs`` are passed through to :func:`assert_data_almost_equal` if
388+
``approx_data`` is True.
389+
396390
Parameters
397391
----------
398392
request : pytest.FixtureRequest
@@ -409,6 +403,10 @@ def assert_CML(
409403
checksum : bool, optional
410404
When True, causes the CML to include a checksum for each
411405
Cube's data. Defaults to True.
406+
approx_data : bool, optional, default=False
407+
When True, the cube's data will be compared with the reference
408+
data and asserted to be within a specified tolerance. Implies
409+
``checksum=False``.
412410
413411
"""
414412
_check_for_request_fixture(request, "assert_CML")
@@ -417,15 +415,23 @@ def assert_CML(
417415
cubes = [cubes]
418416
if reference_filename is None:
419417
reference_filename = result_path(request, None, "cml")
420-
418+
# Note: reference_path could be a tuple of path parts
419+
reference_path = get_result_path(reference_filename)
420+
if approx_data:
421+
# compare data payload stats against known good stats
422+
checksum = False # ensure we are not comparing data checksums
423+
for i, cube in enumerate(cubes):
424+
# Build the json stats filename based on CML file path:
425+
fname = reference_path.removesuffix(".cml")
426+
fname += f".data.{i}.json"
427+
assert_data_almost_equal(cube.data, fname, **kwargs)
421428
if isinstance(cubes, (list, tuple)):
422-
xml = iris.cube.CubeList(cubes).xml(
429+
cml = iris.cube.CubeList(cubes).xml(
423430
checksum=checksum, order=False, byteorder=False
424431
)
425432
else:
426-
xml = cubes.xml(checksum=checksum, order=False, byteorder=False)
427-
reference_path = get_result_path(reference_filename)
428-
_check_same(xml, reference_path)
433+
cml = cubes.xml(checksum=checksum, order=False, byteorder=False)
434+
_check_same(cml, reference_path)
429435

430436

431437
def assert_text_file(source_filename, reference_filename, desc="text file"):

lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,9 @@ def test_regrid_to_same_grid(self, request):
242242
src = self.simple_cube
243243
res = regrid_area_weighted(src, src)
244244
assert res == src
245-
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("simple.cml",))
245+
_shared_utils.assert_CML(
246+
request, res, RESULT_DIR + ("simple.cml",), approx_data=True
247+
)
246248

247249
def test_equal_area_numbers(self):
248250
# Remove coords system and units so it is no longer spherical.
@@ -321,8 +323,8 @@ def test_regrid_latlon_reduced_res(self, request):
321323
# Reduce from (3, 4) to (2, 2).
322324
dest = _subsampled_grid(src, 2, 2)
323325
res = regrid_area_weighted(src, dest)
324-
_shared_utils.assert_CML_approx_data(
325-
request, res, RESULT_DIR + ("latlonreduced.cml",)
326+
_shared_utils.assert_CML(
327+
request, res, RESULT_DIR + ("latlonreduced.cml",), approx_data=True
326328
)
327329

328330
def test_regrid_reorder_axis(self):
@@ -360,8 +362,8 @@ def test_regrid_lon_to_half_res(self, request):
360362
src = self.simple_cube
361363
dest = _resampled_grid(src, 0.5, 1.0)
362364
res = regrid_area_weighted(src, dest)
363-
_shared_utils.assert_CML_approx_data(
364-
request, res, RESULT_DIR + ("lonhalved.cml",)
365+
_shared_utils.assert_CML(
366+
request, res, RESULT_DIR + ("lonhalved.cml",), approx_data=True
365367
)
366368

367369
def test_regrid_to_non_int_frac(self, request):
@@ -370,21 +372,25 @@ def test_regrid_to_non_int_frac(self, request):
370372
src = self.simple_cube
371373
dest = _resampled_grid(src, 0.75, 0.67)
372374
res = regrid_area_weighted(src, dest)
373-
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("lower.cml",))
375+
_shared_utils.assert_CML(
376+
request, res, RESULT_DIR + ("lower.cml",), approx_data=True
377+
)
374378

375379
def test_regrid_to_higher_res(self, request):
376380
src = self.simple_cube
377381
frac = 3.5
378382
dest = _resampled_grid(src, frac, frac)
379383
res = regrid_area_weighted(src, dest)
380-
_shared_utils.assert_CML_approx_data(request, res, RESULT_DIR + ("higher.cml",))
384+
_shared_utils.assert_CML(
385+
request, res, RESULT_DIR + ("higher.cml",), approx_data=True
386+
)
381387

382388
def test_hybrid_height(self, request):
383389
src = self.realistic_cube
384390
dest = _resampled_grid(src, 0.7, 0.8)
385391
res = regrid_area_weighted(src, dest)
386-
_shared_utils.assert_CML_approx_data(
387-
request, res, RESULT_DIR + ("hybridheight.cml",)
392+
_shared_utils.assert_CML(
393+
request, res, RESULT_DIR + ("hybridheight.cml",), approx_data=True
388394
)
389395

390396
def test_missing_data(self):
@@ -483,8 +489,11 @@ def test_cross_section(self, request):
483489
dest.add_dim_coord(lon, 1)
484490
dest.add_aux_coord(src.coord("grid_latitude").copy(), None)
485491
res = regrid_area_weighted(src, dest)
486-
_shared_utils.assert_CML_approx_data(
487-
request, res, RESULT_DIR + ("const_lat_cross_section.cml",)
492+
_shared_utils.assert_CML(
493+
request,
494+
res,
495+
RESULT_DIR + ("const_lat_cross_section.cml",),
496+
approx_data=True,
488497
)
489498
# Constant latitude, data order [x, z]
490499
# Using original and transposing the result should give the
@@ -493,8 +502,11 @@ def test_cross_section(self, request):
493502
dest.transpose()
494503
res = regrid_area_weighted(src, dest)
495504
res.transpose()
496-
_shared_utils.assert_CML_approx_data(
497-
request, res, RESULT_DIR + ("const_lat_cross_section.cml",)
505+
_shared_utils.assert_CML(
506+
request,
507+
res,
508+
RESULT_DIR + ("const_lat_cross_section.cml",),
509+
approx_data=True,
498510
)
499511

500512
# Constant longitude
@@ -507,8 +519,11 @@ def test_cross_section(self, request):
507519
dest.add_dim_coord(lat, 1)
508520
dest.add_aux_coord(src.coord("grid_longitude").copy(), None)
509521
res = regrid_area_weighted(src, dest)
510-
_shared_utils.assert_CML_approx_data(
511-
request, res, RESULT_DIR + ("const_lon_cross_section.cml",)
522+
_shared_utils.assert_CML(
523+
request,
524+
res,
525+
RESULT_DIR + ("const_lon_cross_section.cml",),
526+
approx_data=True,
512527
)
513528
# Constant longitude, data order [y, z]
514529
# Using original and transposing the result should give the
@@ -517,8 +532,11 @@ def test_cross_section(self, request):
517532
dest.transpose()
518533
res = regrid_area_weighted(src, dest)
519534
res.transpose()
520-
_shared_utils.assert_CML_approx_data(
521-
request, res, RESULT_DIR + ("const_lon_cross_section.cml",)
535+
_shared_utils.assert_CML(
536+
request,
537+
res,
538+
RESULT_DIR + ("const_lon_cross_section.cml",),
539+
approx_data=True,
522540
)
523541

524542
def test_scalar_source_cube(self):

lib/iris/tests/test_analysis.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,17 +213,17 @@ def test_weighted_mean_little(self):
213213
if a.dtype > np.float32:
214214
cast_data = a.data.astype(np.float32)
215215
a.data = cast_data
216-
_shared_utils.assert_CML_approx_data(
217-
self.request, a, ("analysis", "weighted_mean_lat.cml")
216+
_shared_utils.assert_CML(
217+
self.request, a, ("analysis", "weighted_mean_lat.cml"), approx_data=True
218218
)
219219

220220
b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights)
221221
if b.dtype > np.float32:
222222
cast_data = b.data.astype(np.float32)
223223
b.data = cast_data
224224
b.data = np.asarray(b.data)
225-
_shared_utils.assert_CML_approx_data(
226-
self.request, b, ("analysis", "weighted_mean_lon.cml")
225+
_shared_utils.assert_CML(
226+
self.request, b, ("analysis", "weighted_mean_lon.cml"), approx_data=True
227227
)
228228
assert b.coord("dummy").shape == (1,)
229229

@@ -234,8 +234,8 @@ def test_weighted_mean_little(self):
234234
if c.dtype > np.float32:
235235
cast_data = c.data.astype(np.float32)
236236
c.data = cast_data
237-
_shared_utils.assert_CML_approx_data(
238-
self.request, c, ("analysis", "weighted_mean_latlon.cml")
237+
_shared_utils.assert_CML(
238+
self.request, c, ("analysis", "weighted_mean_latlon.cml"), approx_data=True
239239
)
240240
assert c.coord("dummy").shape == (1,)
241241

@@ -331,25 +331,32 @@ def _common(
331331
_shared_utils.assert_CML(self.request, self.cube, ("analysis", original_name))
332332

333333
a = self.cube.collapsed("grid_latitude", aggregate)
334-
_shared_utils.assert_CML_approx_data(
335-
self.request, a, ("analysis", "%s_latitude.cml" % name), *args, **kwargs
334+
_shared_utils.assert_CML(
335+
self.request,
336+
a,
337+
("analysis", "%s_latitude.cml" % name),
338+
*args,
339+
approx_data=True,
340+
**kwargs,
336341
)
337342

338343
b = a.collapsed("grid_longitude", aggregate)
339-
_shared_utils.assert_CML_approx_data(
344+
_shared_utils.assert_CML(
340345
self.request,
341346
b,
342347
("analysis", "%s_latitude_longitude.cml" % name),
343348
*args,
349+
approx_data=True,
344350
**kwargs,
345351
)
346352

347353
c = self.cube.collapsed(["grid_latitude", "grid_longitude"], aggregate)
348-
_shared_utils.assert_CML_approx_data(
354+
_shared_utils.assert_CML(
349355
self.request,
350356
c,
351357
("analysis", "%s_latitude_longitude_1call.cml" % name),
352358
*args,
359+
approx_data=True,
353360
**kwargs,
354361
)
355362

0 commit comments

Comments
 (0)