Skip to content
Merged
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
66 changes: 29 additions & 37 deletions lib/iris/tests/integration/netcdf/test_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,30 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for attribute-related loading and saving netcdf files."""

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests # isort:skip

from contextlib import contextmanager
from unittest import mock

from cf_units import Unit
import pytest

import iris
from iris.cube import Cube, CubeList
from iris.fileformats.netcdf import CF_CONVENTIONS_VERSION
from iris.tests import _shared_utils


class TestUmVersionAttribute(tests.IrisTest):
def test_single_saves_as_global(self):
class TestUmVersionAttribute:
def test_single_saves_as_global(self, tmp_path, request):
cube = Cube(
[1.0],
standard_name="air_temperature",
units="K",
attributes={"um_version": "4.3"},
)
with self.temp_filename(".nc") as nc_path:
iris.save(cube, nc_path)
self.assertCDL(nc_path)
nc_path = tmp_path / "test.nc"
iris.save(cube, nc_path)
_shared_utils.assert_CDL(request, nc_path)

def test_multiple_same_saves_as_global(self):
def test_multiple_same_saves_as_global(self, tmp_path, request):
cube_a = Cube(
[1.0],
standard_name="air_temperature",
Expand All @@ -44,11 +40,11 @@ def test_multiple_same_saves_as_global(self):
units="hPa",
attributes={"um_version": "4.3"},
)
with self.temp_filename(".nc") as nc_path:
iris.save(CubeList([cube_a, cube_b]), nc_path)
self.assertCDL(nc_path)
nc_path = tmp_path / "test.nc"
iris.save(CubeList([cube_a, cube_b]), nc_path)
_shared_utils.assert_CDL(request, nc_path)

def test_multiple_different_saves_on_variables(self):
def test_multiple_different_saves_on_variables(self, tmp_path, request):
cube_a = Cube(
[1.0],
standard_name="air_temperature",
Expand All @@ -61,19 +57,19 @@ def test_multiple_different_saves_on_variables(self):
units="hPa",
attributes={"um_version": "4.4"},
)
with self.temp_filename(".nc") as nc_path:
iris.save(CubeList([cube_a, cube_b]), nc_path)
self.assertCDL(nc_path)
nc_path = tmp_path / "test.nc"
iris.save(CubeList([cube_a, cube_b]), nc_path)
_shared_utils.assert_CDL(request, nc_path)


@contextmanager
def _patch_site_configuration():
def _patch_site_configuration(mocker):
def cf_patch_conventions(conventions):
return ", ".join([conventions, "convention1, convention2"])

def update(config):
config["cf_profile"] = mock.Mock(name="cf_profile")
config["cf_patch"] = mock.Mock(name="cf_patch")
config["cf_profile"] = mocker.Mock(name="cf_profile")
config["cf_patch"] = mocker.Mock(name="cf_patch")
config["cf_patch_conventions"] = cf_patch_conventions

orig_site_config = iris.site_configuration.copy()
Expand All @@ -82,8 +78,8 @@ def update(config):
iris.site_configuration = orig_site_config


class TestConventionsAttributes(tests.IrisTest):
def test_patching_conventions_attribute(self):
class TestConventionsAttributes:
def test_patching_conventions_attribute(self, tmp_path, mocker):
# Ensure that user defined conventions are wiped and those which are
# saved patched through site_config can be loaded without an exception
# being raised.
Expand All @@ -95,24 +91,24 @@ def test_patching_conventions_attribute(self):
)

# Patch the site configuration dictionary.
with _patch_site_configuration(), self.temp_filename(".nc") as nc_path:
nc_path = tmp_path / "test.nc"
with _patch_site_configuration(mocker):
iris.save(cube, nc_path)
res = iris.load_cube(nc_path)

self.assertEqual(
res.attributes["Conventions"],
"{}, {}, {}".format(CF_CONVENTIONS_VERSION, "convention1", "convention2"),
assert res.attributes["Conventions"] == "{}, {}, {}".format(
CF_CONVENTIONS_VERSION, "convention1", "convention2"
)


class TestStandardName(tests.IrisTest):
def test_standard_name_roundtrip(self):
class TestStandardName:
def test_standard_name_roundtrip(self, tmp_path):
standard_name = "air_temperature detection_minimum"
cube = iris.cube.Cube(1, standard_name=standard_name)
with self.temp_filename(suffix=".nc") as fout:
iris.save(cube, fout)
detection_limit_cube = iris.load_cube(fout)
self.assertEqual(detection_limit_cube.standard_name, standard_name)
fout = tmp_path / "standard_name.nc"
iris.save(cube, fout)
detection_limit_cube = iris.load_cube(fout)
assert detection_limit_cube.standard_name == standard_name


class TestCalendar:
Expand All @@ -126,7 +122,3 @@ def test_calendar_roundtrip(self, tmp_path):
iris.save(self.cube, fout)
detection_limit_cube = iris.load_cube(fout)
assert detection_limit_cube.units == self.calendar


if __name__ == "__main__":
tests.main()
113 changes: 52 additions & 61 deletions lib/iris/tests/integration/netcdf/test_aux_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for aux-factory-related loading and saving netcdf files."""

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests # isort:skip
import pytest

import iris
from iris.tests import _shared_utils
from iris.tests import stock as stock


@tests.skip_data
class TestAtmosphereSigma(tests.IrisTest):
def setUp(self):
@_shared_utils.skip_data
class TestAtmosphereSigma:
@pytest.fixture(autouse=True)
def _setup(self):
# Modify stock cube so it is suitable to have a atmosphere sigma
# factory added to it.
cube = stock.realistic_4d_no_derived()
Expand All @@ -33,23 +33,24 @@ def setUp(self):
cube.add_aux_factory(factory)
self.cube = cube

def test_save(self):
with self.temp_filename(suffix=".nc") as filename:
iris.save(self.cube, filename)
self.assertCDL(filename)
def test_save(self, request, tmp_path):
filename = tmp_path / "fn.nc"
iris.save(self.cube, filename)
_shared_utils.assert_CDL(request, filename)

def test_save_load_loop(self):
def test_save_load_loop(self, tmp_path):
# Ensure that the AtmosphereSigmaFactory is automatically loaded
# when loading the file.
with self.temp_filename(suffix=".nc") as filename:
iris.save(self.cube, filename)
cube = iris.load_cube(filename, "air_potential_temperature")
assert cube.coords("air_pressure")
filename = tmp_path / "fn.nc"
iris.save(self.cube, filename)
cube = iris.load_cube(filename, "air_potential_temperature")
assert cube.coords("air_pressure")


@tests.skip_data
class TestHybridPressure(tests.IrisTest):
def setUp(self):
@_shared_utils.skip_data
class TestHybridPressure:
@pytest.fixture(autouse=True)
def _setup(self):
# Modify stock cube so it is suitable to have a
# hybrid pressure factory added to it.
cube = stock.realistic_4d_no_derived()
Expand All @@ -66,29 +67,27 @@ def setUp(self):
cube.add_aux_factory(factory)
self.cube = cube

def test_save(self):
with self.temp_filename(suffix=".nc") as filename:
iris.save(self.cube, filename)
self.assertCDL(filename)
def test_save(self, request, tmp_path):
filename = tmp_path / "fn.nc"
iris.save(self.cube, filename)
_shared_utils.assert_CDL(request, filename)

def test_save_load_loop(self):
def test_save_load_loop(self, tmp_path):
# Tests an issue where the variable names in the formula
# terms changed to the standard_names instead of the variable names
# when loading a previously saved cube.
with (
self.temp_filename(suffix=".nc") as filename,
self.temp_filename(suffix=".nc") as other_filename,
):
iris.save(self.cube, filename)
cube = iris.load_cube(filename, "air_potential_temperature")
iris.save(cube, other_filename)
other_cube = iris.load_cube(other_filename, "air_potential_temperature")
self.assertEqual(cube, other_cube)


@tests.skip_data
class TestSaveMultipleAuxFactories(tests.IrisTest):
def test_hybrid_height_and_pressure(self):
filename = tmp_path / "fn.nc"
other_filename = tmp_path / "ofn.nc"
iris.save(self.cube, filename)
cube = iris.load_cube(filename, "air_potential_temperature")
iris.save(cube, other_filename)
other_cube = iris.load_cube(other_filename, "air_potential_temperature")
assert cube == other_cube


@_shared_utils.skip_data
class TestSaveMultipleAuxFactories:
def test_hybrid_height_and_pressure(self, request, tmp_path):
cube = stock.realistic_4d()
cube.add_aux_coord(
iris.coords.DimCoord(1200.0, long_name="level_pressure", units="hPa")
Expand All @@ -105,11 +104,11 @@ def test_hybrid_height_and_pressure(self):
cube.coord("surface_air_pressure"),
)
cube.add_aux_factory(factory)
with self.temp_filename(suffix=".nc") as filename:
iris.save(cube, filename)
self.assertCDL(filename)
filename = tmp_path / "fn.nc"
iris.save(cube, filename)
_shared_utils.assert_CDL(request, filename)

def test_shared_primary(self):
def test_shared_primary(self, tmp_path):
cube = stock.realistic_4d()
factory = iris.aux_factory.HybridHeightFactory(
cube.coord("level_height"),
Expand All @@ -118,37 +117,29 @@ def test_shared_primary(self):
)
factory.rename("another altitude")
cube.add_aux_factory(factory)
with (
self.temp_filename(suffix=".nc") as filename,
self.assertRaisesRegex(ValueError, "multiple aux factories"),
):
filename = tmp_path / "fn.nc"
with pytest.raises(ValueError, match="multiple aux factories"):
iris.save(cube, filename)

def test_hybrid_height_cubes(self):
def test_hybrid_height_cubes(self, request, tmp_path):
hh1 = stock.simple_4d_with_hybrid_height()
hh1.attributes["cube"] = "hh1"
hh2 = stock.simple_4d_with_hybrid_height()
hh2.attributes["cube"] = "hh2"
sa = hh2.coord("surface_altitude")
sa.points = sa.points * 10
with self.temp_filename(".nc") as fname:
iris.save([hh1, hh2], fname)
cubes = iris.load(fname, "air_temperature")
cubes = sorted(cubes, key=lambda cube: cube.attributes["cube"])
self.assertCML(cubes)
filename = tmp_path / "fn.nc"
iris.save([hh1, hh2], filename)
cubes = iris.load(filename, "air_temperature")
cubes = sorted(cubes, key=lambda cube: cube.attributes["cube"])
_shared_utils.assert_CML(request, cubes)

def test_hybrid_height_cubes_on_dimension_coordinate(self):
def test_hybrid_height_cubes_on_dimension_coordinate(self, tmp_path):
hh1 = stock.hybrid_height()
hh2 = stock.hybrid_height()
sa = hh2.coord("surface_altitude")
sa.points = sa.points * 10
emsg = "Unable to create dimensonless vertical coordinate."
with (
self.temp_filename(".nc") as fname,
self.assertRaisesRegex(ValueError, emsg),
):
iris.save([hh1, hh2], fname)


if __name__ == "__main__":
tests.main()
filename = tmp_path / "fn.nc"
with pytest.raises(ValueError, match=emsg):
iris.save([hh1, hh2], filename)
12 changes: 4 additions & 8 deletions lib/iris/tests/integration/netcdf/test_coord_systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for coord-system-related loading and saving netcdf files."""

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests # isort:skip

import warnings

import numpy as np
Expand All @@ -16,8 +12,8 @@
import iris
from iris.coords import DimCoord
from iris.cube import Cube
from iris.tests import _shared_utils
from iris.tests import stock as stock
from iris.tests._shared_utils import assert_CML
from iris.tests.stock.netcdf import ncgen_from_cdl
from iris.tests.unit.fileformats.netcdf.loader import test_load_cubes as tlc

Expand Down Expand Up @@ -172,7 +168,7 @@ def multi_cs_osgb_wkt():
"""


@tests.skip_data
@_shared_utils.skip_data
class TestCoordSystem:
@pytest.fixture(autouse=True)
def _setup(self):
Expand All @@ -182,11 +178,11 @@ def _setup(self):

def test_load_laea_grid(self, request):
cube = iris.load_cube(
tests.get_data_path(
_shared_utils.get_data_path(
("NetCDF", "lambert_azimuthal_equal_area", "euro_air_temp.nc")
)
)
assert_CML(request, cube, ("netcdf", "netcdf_laea.cml"))
_shared_utils.assert_CML(request, cube, ("netcdf", "netcdf_laea.cml"))

def test_load_datum_wkt(self, datum_wkt_cdl):
expected = "OSGB 1936"
Expand Down
2 changes: 1 addition & 1 deletion lib/iris/tests/integration/netcdf/test_dataless.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

class TestDataless:
@pytest.fixture(autouse=True)
def setup(self, tmp_path_factory):
def _setup(self, tmp_path_factory):
ny, nx = 3, 4
self.testcube = Cube(
shape=(ny, nx),
Expand Down
8 changes: 4 additions & 4 deletions lib/iris/tests/integration/netcdf/test_delayed_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import iris
from iris.fileformats.netcdf._thread_safe_nc import default_fillvals
import iris.tests
from iris.tests import _shared_utils
from iris.tests.stock import realistic_4d


Expand All @@ -38,7 +38,7 @@ def all_saves_with_split_attrs(self):
def output_path(self, tmp_path):
# A temporary output netcdf-file path, **unique to each test call**.
self.temp_output_filepath = tmp_path / "tmp.nc"
yield self.temp_output_filepath
return self.temp_output_filepath

@pytest.fixture(autouse=True, scope="module")
def all_vars_lazy(self):
Expand Down Expand Up @@ -118,8 +118,8 @@ def fix_array(array):
cube.add_cell_measure(cm, cm_dims)
return cube

def test_realfile_loadsave_equivalence(self, save_is_delayed, output_path):
input_filepath = iris.tests.get_data_path(
def test_realfile_loadsave_equivalence(self, save_is_delayed, output_path, request):
input_filepath = _shared_utils.get_data_path(
["NetCDF", "global", "xyz_t", "GEMS_CO2_Apr2006.nc"]
)
original_cubes = iris.load(input_filepath)
Expand Down
Loading
Loading