From bd6f30605014f070efe9704e11e2b0af196f6200 Mon Sep 17 00:00:00 2001 From: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:18:03 +0100 Subject: [PATCH] Reduce duplication in cf.py spanning checks. (#6196) Reduce duplication in cf.py spanning checks. --- docs/src/whatsnew/latest.rst | 3 ++ lib/iris/fileformats/cf.py | 79 +++++++++++++++--------------------- 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index ff4babc025..edc6ebfe2d 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -126,6 +126,9 @@ This document explains the changes made to Iris for this release #. `@trexfeathers`_ adapted Iris to work with Cartopy v0.24. (:pull:`6171`, :pull:`6172`) +#. `@trexfeathers`_ refactored spanning checks in :mod:`iris.fileformats.cf` + to reduce code duplication. (:pull:`6196`) + .. comment Whatsnew author names (@github name) in alphabetical order. Note that, diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index 024bcb6f1d..e7b0d8063e 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -18,7 +18,7 @@ from collections.abc import Iterable, MutableMapping import os import re -from typing import ClassVar +from typing import ClassVar, Optional import warnings import numpy as np @@ -1448,6 +1448,35 @@ def _build(cf_variable): coordinate_names = list(self.cf_group.coordinates.keys()) cf_group = self.CFGroup() + def _span_check( + var_name: str, via_formula_terms: Optional[str] = None + ) -> None: + """Sanity check dimensionality.""" + var = self.cf_group[var_name] + # No span check is necessary if variable is attached to a mesh. + if is_mesh_var or var.spans(cf_variable): + cf_group[var_name] = var + else: + # Register the ignored variable. + # N.B. 'ignored' variable from enclosing scope. + ignored.add(var_name) + + text_formula = text_via = "" + if via_formula_terms: + text_formula = " formula terms" + text_via = f" via variable {via_formula_terms}" + + message = ( + f"Ignoring{text_formula} variable {var_name} " + f"referenced by variable {cf_variable.cf_name}" + f"{text_via}: Dimensions {var.dimensions} do not span " + f"{cf_variable.dimensions}" + ) + warnings.warn( + message, + category=iris.warnings.IrisCfNonSpanningVarWarning, + ) + # Build CF variable relationships. for variable_type in self._variable_types: ignore = [] @@ -1466,28 +1495,8 @@ def _build(cf_variable): warn=False, ) # Sanity check dimensionality coverage. - for cf_name, cf_var in match.items(): - # No span check is necessary if variable is attached to a mesh. - if is_mesh_var or cf_var.spans(cf_variable): - cf_group[cf_name] = self.cf_group[cf_name] - else: - # Register the ignored variable. - # N.B. 'ignored' variable from enclosing scope. - ignored.add(cf_name) - msg = ( - "Ignoring variable {!r} referenced " - "by variable {!r}: Dimensions {!r} do not " - "span {!r}".format( - cf_name, - cf_variable.cf_name, - cf_var.dimensions, - cf_variable.dimensions, - ) - ) - warnings.warn( - msg, - category=iris.warnings.IrisCfNonSpanningVarWarning, - ) + for cf_name in match: + _span_check(cf_name) # Build CF data variable relationships. if isinstance(cf_variable, CFDataVariable): @@ -1514,29 +1523,7 @@ def _build(cf_variable): for cf_var in self.cf_group.formula_terms.values(): for cf_root in cf_var.cf_terms_by_root: if cf_root in cf_group and cf_var.cf_name not in cf_group: - # Sanity check dimensionality. - if cf_var.spans(cf_variable): - cf_group[cf_var.cf_name] = cf_var - else: - # Register the ignored variable. - # N.B. 'ignored' variable from enclosing scope. - ignored.add(cf_var.cf_name) - msg = ( - "Ignoring formula terms variable {!r} " - "referenced by data variable {!r} via " - "variable {!r}: Dimensions {!r} do not " - "span {!r}".format( - cf_var.cf_name, - cf_variable.cf_name, - cf_root, - cf_var.dimensions, - cf_variable.dimensions, - ) - ) - warnings.warn( - msg, - category=iris.warnings.IrisCfNonSpanningVarWarning, - ) + _span_check(cf_var.cf_name, cf_root) # Add the CF group to the variable. cf_variable.cf_group = cf_group