Skip to content

Commit

Permalink
#3392: Add basic function and basic tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbillowsMO committed May 23, 2024
1 parent e5705db commit d68e821
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pprint

import yaml
from esmvalcore.config._config_validators import ValidationError, _validators


def main():
Expand All @@ -17,6 +18,9 @@ def main():
# 'configure' task.
config_values = get_config_values_from_task_env()

# Validate the user config file content.
validate_user_config_file(config_values)

# Update the configuration from OS environment.
user_config_path = os.environ["USER_CONFIG_PATH"]
config_values["config_file"] = user_config_path
Expand Down Expand Up @@ -80,6 +84,46 @@ def get_config_values_from_task_env():
return config_values_from_task_env


def validate_user_config_file(user_config_file_content):
"""Validate a user config with ``ESMValCore.config._validators`` functions.
Parameters
----------
user_config_file_content: dict
An ESMValTool user configuration file loaded in memory as a Python
dictionary.
Raises
------
KeyError
If ``user_config_file_content`` includes a key for which there is no
validator listed in ``_validators``,
ValidationError
If any of the called validation functions raise a ValidationError.
"""
errors = []
for user_config_key, usr_config_value in user_config_file_content.items():
try:
validatation_function = _validators[user_config_key]
except KeyError as err:
errors.append(
f'Key Error for {user_config_key.upper()}. May not be a valid '
f'ESMValTool user configuration key\nERROR: {err}\n')
else:
try:
print(f'Validating {user_config_key.upper()} with value '
f'"{usr_config_value}" using function '
f'{validatation_function.__name__.upper()}.')
validatation_function(usr_config_value)
except ValidationError as err:
errors.append(
f'Validation error for {user_config_key.upper()} with '
f'value "{usr_config_value}"\nERROR: {err}\n')
if errors:
print(errors)
raise ValidationError("\n".join(errors))


def write_yaml(file_path, contents):
"""Write ``contents`` to the YAML file ``file_path``.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import pytest
from bin.configure import validate_user_config_file
from esmvalcore.config._config_validators import ValidationError

# Run tests with `pytest -c dev/null`.


def test_validate_user_config_file():
mock_valid_config = {
"output_dir": "~/esmvaltool_output",
"auxiliary_data_dir": "~/auxiliary_data",
"search_esgf": "never",
"download_dir": "~/climate_data",
"max_parallel_tasks": None,
"log_level": "info",
"exit_on_warning": True,
"output_file_type": "png",
}
result = validate_user_config_file(mock_valid_config)
assert result is None


def test_validate_user_config_file_one_validation_error():
mock_one_invalid_config = {
"output_dir": "~/esmvaltool_output",
"auxiliary_data_dir": "~/auxiliary_data",
"search_esgf": "never",
"download_dir": "~/climate_data",
"max_parallel_tasks": None,
"log_level": "info",
"exit_on_warning": 100,
"output_file_type": "png",
}
with pytest.raises(
ValidationError,
match='Validation error for EXIT_ON_WARNING with value "100"\n'
'ERROR: Could not convert `100` to `bool`\n'):
validate_user_config_file(mock_one_invalid_config)


def test_validate_user_config_file_two_validation_errors():
mock_two_invalids_config = {
"output_dir": 111,
"auxiliary_data_dir": "~/auxiliary_data",
"search_esgf": "never",
"download_dir": "~/climate_data",
"max_parallel_tasks": None,
"log_level": "info",
"exit_on_warning": 100,
"output_file_type": "png",
}
with pytest.raises(
ValidationError,
match='Validation error for OUTPUT_DIR with value "111"\nERROR: '
'Expected a path, but got 111\n\nValidation error for '
'EXIT_ON_WARNING with value "100"\nERROR: Could not convert `100` '
'to `bool`\n'):
validate_user_config_file(mock_two_invalids_config)


def test_validate_user_config_file_key_error():
mock_one_key_error = {
"output_dir": "~/esmvaltool_output",
"auxiliary_data_dir": "~/auxiliary_data",
"search_esgf": "never",
"download_dir": "~/climate_data",
"one_rogue_field": 90210,
"max_parallel_tasks": None,
"log_level": "info",
"exit_on_warning": True,
"output_file_type": "png",
}
with pytest.raises(
ValidationError,
match="Key Error for ONE_ROGUE_FIELD. May not be a valid "
"ESMValTool user configuration key\nERROR: 'one_rogue_field'\n"):
validate_user_config_file(mock_one_key_error)

0 comments on commit d68e821

Please sign in to comment.