Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement three levels of CMOR checks strictness #374

Merged
merged 64 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
547c9c5
ported Javi's functionality from dry checks to mainstream to be used …
valeriupredoi Nov 13, 2019
b693bc0
started work, committing quickly, laptop seems to be dying soon
valeriupredoi Nov 13, 2019
861a91c
talk to the Check
valeriupredoi Nov 13, 2019
b5b96b1
communication with the cmor checker
valeriupredoi Nov 13, 2019
9a6b264
implemented tiered errors
valeriupredoi Nov 13, 2019
a5b7680
rephrased a bit the error messages
valeriupredoi Nov 13, 2019
15919a7
Bouwe suggestion
valeriupredoi Nov 15, 2019
edd1f94
Bouwe suggestion
valeriupredoi Nov 15, 2019
0cabd66
replaced config key
valeriupredoi Nov 15, 2019
1c4701c
added default opt to cmd line
valeriupredoi Nov 15, 2019
30eee1d
fixed tests
valeriupredoi Nov 15, 2019
e71b6dc
fixed missing func arg
valeriupredoi Nov 15, 2019
694411b
fixed opt retrieval
valeriupredoi Nov 15, 2019
b1dfb51
Do not report anything in fix_metadata step
sloosvel Nov 15, 2019
bb70373
Relax some check_metadata checks
sloosvel Nov 15, 2019
3dee4ae
putting command line args dependent options in fix
valeriupredoi Nov 18, 2019
c7d75a3
making the implementation actually work
valeriupredoi Nov 18, 2019
847e8f1
adding func args
valeriupredoi Nov 18, 2019
c7971a5
fixed lines too long
valeriupredoi Nov 18, 2019
23e14de
fixed recipe tests
valeriupredoi Nov 18, 2019
0f9479d
fixed call to fix test
valeriupredoi Nov 18, 2019
f59418e
removed debug messgae
valeriupredoi Nov 18, 2019
f4ac790
Merge branch 'development' into cmor_checks_tiers
valeriupredoi Nov 18, 2019
bd9b4c9
Remove condition for regular errors
sloosvel Nov 25, 2019
4f6b6a4
Add unit tests
sloosvel Nov 26, 2019
06410b2
fixed linter
valeriupredoi Nov 29, 2019
57dd77b
fixed rank check
valeriupredoi Nov 29, 2019
3e27e49
Relax check on presence of some coordinates
sloosvel Dec 2, 2019
8f2e8dc
Fix style issues
sloosvel Dec 2, 2019
84ded5a
Add support for diferent error levels in checker
Dec 3, 2019
6addf1f
Remove unused import
Dec 3, 2019
c55a1ed
Fix codacy issues
Dec 3, 2019
ecc1062
fixed func attr
valeriupredoi Dec 3, 2019
aa48d92
fixed mock test
valeriupredoi Dec 3, 2019
70f64ce
proper fixed attr case is string
valeriupredoi Dec 3, 2019
f8584ce
fixed typo in func name
valeriupredoi Dec 3, 2019
a5885da
add time aux coords only if time in coords
valeriupredoi Dec 3, 2019
10ff62c
Clean a bit
Dec 3, 2019
d7d0561
added documentation on check levels
valeriupredoi Dec 3, 2019
9cbd895
added more meat to the check levels doc
valeriupredoi Dec 3, 2019
b9375aa
Doc update
Dec 3, 2019
dfb1e34
Rename check levels, keep only one ignore option
sloosvel Jan 27, 2020
2237941
Remove debug file
sloosvel Jan 27, 2020
7f04bae
Update documentation with name changes
sloosvel Jan 27, 2020
8c8b05c
Report warnings when converting units
sloosvel Jan 31, 2020
df2c681
Update doc/esmvalcore/fixing_data.rst
sloosvel Jan 31, 2020
8f33f02
Merge branch 'master' of https://github.com/ESMValGroup/ESMValCore in…
Feb 4, 2020
e27617c
Update docstrings
sloosvel Feb 19, 2020
9bcbf21
Merge branch 'master' into cmor_checks_tiers
sloosvel Feb 19, 2020
b218fb1
Attemp to fix conflicts
sloosvel Feb 25, 2020
1f45441
Update esmvalcore/cmor/check.py
sloosvel Feb 27, 2020
24c4cad
Update esmvalcore/cmor/check.py
sloosvel Feb 27, 2020
c0f4556
Update esmvalcore/cmor/check.py
sloosvel Feb 27, 2020
c3315a8
Update esmvalcore/cmor/check.py
sloosvel Feb 27, 2020
913e9b0
Update esmvalcore/cmor/fix.py
sloosvel Feb 27, 2020
8f83249
Update esmvalcore/cmor/fix.py
sloosvel Feb 27, 2020
91a205e
Update esmvalcore/cmor/check.py
sloosvel Feb 27, 2020
4e102d0
Apply suggestions from code review
sloosvel Feb 27, 2020
e0d9340
Improve warning message
sloosvel Feb 27, 2020
56ce2c2
Report missing coordinates with levels as critical
sloosvel Feb 27, 2020
1d5a0eb
Improve docstring
sloosvel Feb 27, 2020
87f34b8
Merge remote-tracking branch 'origin/master' into cmor_checks_tiers
sloosvel Feb 27, 2020
4c96139
Fix identation
sloosvel Feb 27, 2020
275d65c
Fix tests
sloosvel Feb 27, 2020
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
10 changes: 10 additions & 0 deletions esmvalcore/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ def get_args():
'--diagnostics',
nargs='*',
help="Only run the named diagnostics from the recipe.")
parser.add_argument(
'--cmor-checks',
type=str,
action='store_true',
help="Metadata CMOR checks strictness; \
Optional: true; possible values: \
none: no checks performed \
relaxed: checks are performed but no errors raised; \
default: full checks and errors raised.")
args = parser.parse_args()
return args

Expand Down Expand Up @@ -143,6 +152,7 @@ def main(args):
pattern if TASKSEP in pattern else pattern + TASKSEP + '*'
for pattern in args.diagnostics or ()
}
cfg['cmor_checks_type'] = args.cmor_checks
cfg['synda_download'] = args.synda_download
for limit in ('max_datasets', 'max_years'):
value = getattr(args, limit)
Expand Down
8 changes: 8 additions & 0 deletions esmvalcore/_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,19 @@ def _get_default_settings(variable, config_user, derive=False):

# Configure CMOR metadata check
if variable.get('cmor_table'):
raise_exception = True
report_only_warning = False
if config_user['cmor_checks_type'] in ['none', 'relaxed']:
raise_exception = False
if config_user['cmor_checks_type'] == 'relaxed':
report_only_warning = True
settings['cmor_check_metadata'] = {
'cmor_table': variable['cmor_table'],
'mip': variable['mip'],
'short_name': variable['short_name'],
'frequency': variable['frequency'],
'raise_exception': raise_exception,
'report_only_warning': report_only_warning,
}
# Configure final CMOR data check
if variable.get('cmor_table'):
Expand Down
77 changes: 69 additions & 8 deletions esmvalcore/cmor/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,16 @@ def __init__(self,
var_info,
frequency=None,
fail_on_error=False,
raise_exception=True,
report_only_warning=False,
automatic_fixes=False):

self._cube = cube
self._failerr = fail_on_error
self._raise_exception = raise_exception
self._report_only_warning = report_only_warning
self._errors = list()
self._strict_errors = list()
self._warnings = list()
self._debug_messages = list()
self._cmor_var = var_info
Expand Down Expand Up @@ -104,13 +109,16 @@ def check_metadata(self, logger=None):

self.report_debug_messages(logger)
self.report_warnings(logger)
self.report_errors()
self.report_errors(logger)

if self.frequency != 'fx':
self._add_auxiliar_time_coordinates()
return self._cube
if self.has_errors():
return None
else:
return self._cube

def report_errors(self):
def report_errors(self, logger):
"""Report detected errors.

Raises
Expand All @@ -120,10 +128,22 @@ def report_errors(self):

"""
if self.has_errors():
msg = 'There were errors in variable {}:\n{}\nin cube:\n{}'
msg = 'There are REGULAR CMOR errors in var {}:\n{}\nin cube:\n{}'
msg = msg.format(self._cube.var_name, '\n '.join(self._errors),
self._cube)
raise CMORCheckError(msg)
if self._raise_exception:
logger.error(msg)
raise CMORCheckError(msg)
if self._report_only_warning:
logger.warning(msg)
if self.has_strict_errors():
msg = 'There are STRICT CMOR errors in var {}:\n{}\nin cube:\n{}'
msg = msg.format(
self._cube.var_name, '\n '.join(self._strict_errors),
self._cube)
if self._raise_exception:
raise CMORCheckError(msg)
logger.error(msg)

def report_warnings(self, logger):
"""Report detected warnings to the given logger.
Expand Down Expand Up @@ -179,7 +199,7 @@ def check_data(self, logger=None):
self._check_coords_data()

self.report_warnings(logger)
self.report_errors()
self.report_errors(logger)
return self._cube

def _check_fill_value(self):
Expand Down Expand Up @@ -576,6 +596,17 @@ def has_errors(self):
"""
return len(self._errors) > 0

def has_strict_errors(self):
"""Check if there are reported errors of strict nature.

Returns
-------
bool:
True if there are pending errors, False otherwise.

"""
return len(self._strict_errors) > 0

def has_warnings(self):
"""Check if there are reported warnings.

Expand Down Expand Up @@ -617,6 +648,25 @@ def report_error(self, message, *args):
raise CMORCheckError(msg + '\nin cube:\n{}'.format(self._cube))
self._errors.append(msg)

def report_strict_error(self, message, *args):
"""Report a STRICT error.

If fail_on_error is set to True, raises automatically.
If fail_on_error is set to False, stores it for later reports.

Parameters
----------
message: str: unicode
Message for the error.
*args:
arguments to format the message string.

"""
msg = message.format(*args)
if self._failerr:
raise CMORCheckError(msg + '\nin cube:\n{}'.format(self._cube))
self._strict_errors.append(msg)

def report_warning(self, message, *args):
"""Report a warning.

Expand Down Expand Up @@ -668,6 +718,7 @@ def _get_cmor_checker(table,
short_name,
frequency,
fail_on_error=True,
raise_exception=True,
automatic_fixes=False):
"""Get a CMOR checker/fixer."""
if table not in CMOR_TABLES:
Expand All @@ -687,12 +738,16 @@ def _checker(cube):
var_info,
frequency=frequency,
fail_on_error=fail_on_error,
raise_exception=raise_exception,
report_only_warning=report_only_warning,
automatic_fixes=automatic_fixes)

return _checker


def cmor_check_metadata(cube, cmor_table, mip, short_name, frequency):
def cmor_check_metadata(cube, cmor_table, mip,
short_name, frequency,
raise_exception, report_only_warning):
"""Check if metadata conforms to variable's CMOR definiton.

None of the checks at this step will force the cube to load the data.
Expand All @@ -709,9 +764,15 @@ def cmor_check_metadata(cube, cmor_table, mip, short_name, frequency):
Variable's short name.
frequency: basestring
Data frequency.
raise_exception: bool
Boolean operator that raises or not
the exception resulted from checker.

"""
checker = _get_cmor_checker(cmor_table, mip, short_name, frequency)
checker = _get_cmor_checker(cmor_table, mip,
short_name, frequency,
raise_exception=raise_exception,
report_only_warning=report_only_warning)
checker(cube).check_metadata()
return cube

Expand Down