diff --git a/esmvalcore/preprocessor/_derive/__init__.py b/esmvalcore/preprocessor/_derive/__init__.py index 27bffa38d7..42eac77aa3 100644 --- a/esmvalcore/preprocessor/_derive/__init__.py +++ b/esmvalcore/preprocessor/_derive/__init__.py @@ -7,6 +7,8 @@ import iris +from esmvalcore.preprocessor._units import convert_units + logger = logging.getLogger(__name__) @@ -18,7 +20,6 @@ def _get_all_derived_variables(): dict All derived variables with `short_name` (keys) and the associated python classes (values). - """ derivers = {} for path in Path(__file__).parent.glob('[a-z]*.py'): @@ -50,7 +51,6 @@ def get_required(short_name, project): ------- list List of dictionaries (including at least the key `short_name`). - """ if short_name.lower() not in ALL_DERIVED_VARIABLES: raise NotImplementedError( @@ -82,7 +82,6 @@ def derive(cubes, short_name, long_name, units, standard_name=None): ------- iris.cube.Cube The new derived variable. - """ if short_name == cubes[0].var_name: return cubes[0] @@ -116,11 +115,13 @@ def derive(cubes, short_name, long_name, units, standard_name=None): "'%s', automatically setting them to '%s'. This might lead to " "incorrect data", short_name, cube.units, units) cube.units = units - elif cube.units.is_convertible(units): - cube.convert_units(units) else: - raise ValueError( - f"Units '{cube.units}' after executing derivation script of " - f"'{short_name}' cannot be converted to target units '{units}'") + try: + convert_units(cube, units) + except ValueError as exc: + raise ValueError( + f"Units '{cube.units}' after executing derivation script of " + f"'{short_name}' cannot be converted to target units '{units}'" + ) from exc return cube diff --git a/tests/integration/preprocessor/_derive/test_interface.py b/tests/integration/preprocessor/_derive/test_interface.py index 14ea1d6c9a..5a466f6028 100644 --- a/tests/integration/preprocessor/_derive/test_interface.py +++ b/tests/integration/preprocessor/_derive/test_interface.py @@ -27,10 +27,12 @@ def patched_derive(mocker): mocker.patch.object(_derive, 'logger', autospec=True) -def mock_all_derived_variables(returned_units): +def mock_all_derived_variables(returned_units, fail_unit_conversion=False): """Mock the :obj:`dict` containing all derived variables accordingly.""" cube = mock.create_autospec(Cube, instance=True) cube.units = returned_units + if fail_unit_conversion: + cube.convert_units.side_effect = [ValueError] calculate_function = mock.Mock(return_value=cube) derived_var = mock.Mock(name='DerivedVariable') derived_var.return_value.calculate = calculate_function @@ -127,7 +129,7 @@ def test_check_units_convertible(mock_cubes): @pytest.mark.usefixtures("patched_derive") def test_check_units_fail(mock_cubes): """Test units after derivation if derivation scripts returns None.""" - mock_all_derived_variables(Unit('kg')) + mock_all_derived_variables(Unit('kg'), fail_unit_conversion=True) with pytest.raises(ValueError) as err: derive(mock_cubes, SHORT_NAME, mock.sentinel.long_name, 'm', standard_name=mock.sentinel.standard_name)