"""CF-Convention Checking======================Utilities designed to verify the compliance of metadata with the CF-Convention."""from__future__importannotationsimportfnmatchimportrefromcollections.abcimportSequenceimportxarrayasxrfromxclim.core._exceptionsimportValidationErrorfromxclim.core._typesimportVARIABLESfromxclim.core.optionsimportcfcheck
[docs]@cfcheckdefcheck_valid(var:xr.DataArray,key:str,expected:str|Sequence[str]):r""" Check that a variable's attribute has one of the expected values and raise a ValidationError if otherwise. Parameters ---------- var : xr.DataArray The variable to check. key : str The attribute to check. expected : str or sequence of str The expected value(s). Raises ------ ValidationError If the attribute is not present or does not match the expected value(s). """att=getattr(var,key,None)ifattisNone:raiseValidationError(f"Variable does not have a `{key}` attribute.")ifisinstance(expected,str):expected=[expected]forexpinexpected:iffnmatch.fnmatch(att,exp):breakelse:raiseValidationError(f"Variable has a non-conforming {key}: Got `{att}`, expected `{expected}`",)
[docs]defcfcheck_from_name(varname:str,vardata:xr.DataArray,attrs:list[str]|None=None):""" Perform cfchecks on a DataArray using specifications from xclim's default variables. Parameters ---------- varname : str The name of the variable to check. vardata : xr.DataArray The variable to check. attrs : list of str, optional Attributes to check. Default is ["cell_methods", "standard_name"]. Raises ------ ValidationError If the variable does not meet the expected CF-Convention. """ifattrsisNone:attrs=["cell_methods","standard_name"]data=VARIABLES[varname]if"cell_methods"indataand"cell_methods"inattrs:_check_cell_methods(getattr(vardata,"cell_methods",None),data["cell_methods"])if"standard_name"indataand"standard_name"inattrs:check_valid(vardata,"standard_name",data["standard_name"])
[docs]@cfcheckdef_check_cell_methods(data_cell_methods:str,expected_method:str)->None:ifdata_cell_methodsisNone:raiseValidationError("Variable does not have a `cell_methods` attribute.")EXTRACT_CELL_METHOD_REGEX=r"(\s*\S+\s*:(\s+[\w()-]+)+)(?!\S*:)"forminre.compile(EXTRACT_CELL_METHOD_REGEX).findall(data_cell_methods):ifexpected_methodinm[0]:returnNoneraiseValidationError(f"Variable has a non-conforming cell_methods: "f"Got `{data_cell_methods}`, which do not include the expected "f"`{expected_method}`.")