#!/usr/bin/python3
r"""
Validate a file or files in a directory using a schema.
Input files can be metadata, schema, or data files in yaml, json, or ecsv format.
For model parameters, the schema files are taken from the simtools model parameter
schema directory by default.
Command line arguments
----------------------
file_name (str)
input file to be validated
file_directory (str)
directory with json files of model parameters to be validated
schema (str)
schema file (jsonschema format) used for validation
data_type (str)
type of input data (allowed types: metadata, schema, data, model_parameter)
Example
-------
Validate metadata of a file:
.. code-block:: console
simtools-validate-file-using-schema \\
--file_name tests/resources/MLTdata-preproduction.meta.yml \\
--schema simtools/schemas/metadata.metaschema.yml \\
--data_type metadata
Validate schema of a file:
.. code-block:: console
simtools-validate-file-using-schema \\
--file_name tests/resources/model_parameters/schema-0.3.0/num_gains-1.0.0.json \\
--schema src/simtools/schemas/model_parameter.metaschema.yml \\
--data_type schema
Validate all model parameter files in a directory:
.. code-block:: console
simtools-validate-file-using-schema \\
--file_directory tests/resources/model_parameters \\
--data_type model_parameter
"""
from simtools.application_control import get_application_label, startup_application
from simtools.configuration import configurator
from simtools.constants import MODEL_PARAMETER_SCHEMA_PATH
from simtools.data_model import metadata_collector, schema, validate_data
def _parse():
"""Parse command line configuration."""
config = configurator.Configurator(
label=get_application_label(__file__),
description="Validate a file (metadata, schema, or data file) using a schema.",
)
config.parser.add_argument(
"--file_name",
help="File to be validated (full path or name pattern, e.g., '*.json')",
default="*.json",
)
config.parser.add_argument(
"--file_directory",
help=(
"Directory with files to be validated. "
"If no schema file is provided, the assumption is that model "
"parameters are validated and the schema files are taken from "
f"{MODEL_PARAMETER_SCHEMA_PATH}."
),
)
config.parser.add_argument("--schema", help="Schema file", required=False)
config.parser.add_argument(
"--data_type",
help="Type of input data",
choices=["metadata", "schema", "data", "model_parameter"],
default="data",
)
config.parser.add_argument(
"--check_exact_data_type",
help="Require exact data type for validation",
action="store_true",
)
config.parser.add_argument(
"--ignore_software_version",
help="Ignore software version check.",
action="store_true",
)
return config.initialize(paths=False)
[docs]
def main():
"""Validate a file or files in a directory using a schema."""
app_context = startup_application(_parse)
file_name = app_context.args.get("file_name")
file_directory = app_context.args.get("file_directory")
schema_file = app_context.args.get("schema")
data_type = app_context.args.get("data_type").lower()
if data_type == "metadata":
# metadata_collector runs the metadata validation by default, no need to do anything else
metadata_collector.MetadataCollector(None, metadata_file_name=file_name)
app_context.logger.info(f"Successful validation of metadata {file_name}")
elif data_type == "schema":
schema.validate_schema_from_files(
file_directory=file_directory,
file_name=file_name,
schema_file=schema_file,
ignore_software_version=app_context.args.get("ignore_software_version", False),
)
else:
validate_data.DataValidator.validate_data_files(
file_name=file_name,
file_directory=file_directory,
is_model_parameter=(data_type == "model_parameter"),
check_exact_data_type=app_context.args.get("check_exact_data_type", False),
schema_file=schema_file,
)
if __name__ == "__main__":
main()