"""
The ``linkml.validator`` package contains a new LinkML validation framework that is more flexible
than the ``linkml.validators`` package. While that package still exists, it may become deprecated
in the future.
"""
import os
from pathlib import Path
from typing import Any, Optional, Union
from linkml_runtime.linkml_model import SchemaDefinition
from linkml_runtime.loaders import yaml_loader
from linkml.validator.loaders import default_loader_for_file
from linkml.validator.plugins import JsonschemaValidationPlugin
from linkml.validator.report import ValidationReport
from linkml.validator.validator import Validator
def _get_default_validator(
schema: Union[str, dict, Path, SchemaDefinition],
*,
strict: bool = False,
) -> Validator:
try:
if isinstance(schema, Path):
schema = str(schema)
if isinstance(schema, dict):
schema = SchemaDefinition(**schema)
elif isinstance(schema, str):
schema = yaml_loader.load(schema, target_class=SchemaDefinition)
if not isinstance(schema, SchemaDefinition):
raise ValueError(f"Schema could not be loaded from {schema}")
except ValueError as e:
raise ValueError(f"Invalid schema: {schema}") from e
validation_plugins = [JsonschemaValidationPlugin(closed=True)]
return Validator(schema, validation_plugins=validation_plugins, strict=strict)
[docs]def validate(
instance: Any,
schema: Union[str, dict, SchemaDefinition],
target_class: Optional[str] = None,
*,
strict: bool = False,
) -> ValidationReport:
"""Validate a data instance against a schema
This function provides a simple interface to do basic validation performed by a JSON Schema
validator on a single instance. To have more control over the type of validation performed,
see the :class:`Validator` class.
:param instance: The instance to validate
:param schema: The schema used to validate the instance. If a string is
it will be interpreted as a path, URL, or other loadable location.
If it is a dict it should be compatible with ``SchemaDefinition``,
otherwise it should be a ``SchemaDefinition`` instance.
:param target_class: Name of the class within the schema to validate
against. If ``None``, the class will be inferred from the schema by
looking for a class with ``tree_root: true``. Defaults to ``None``.
:param strict: If ``True``, validation will stop after the first validation
error is found, Otherwise all validation problems will be reported.
Defaults to ``False``.
:raises ValueError: If a valid ``SchemaDefinition`` cannot be constructed
from the ``schema`` parameter.
:return: A validation report
:rtype: ValidationReport
"""
validator = _get_default_validator(schema, strict=strict)
return validator.validate(instance, target_class)
[docs]def validate_file(
file: Union[str, bytes, os.PathLike],
schema: Union[str, dict, SchemaDefinition],
target_class: Optional[str] = None,
*,
strict: bool = False,
) -> ValidationReport:
"""Validate instances loaded from a file against a schema
This function provides a simple interface to do basic validation performed by a JSON Schema
validator on instances loaded from a file. Loading is done according to the file's extension.
Accepted file extensions are: ``.csv``, ``.tsv``, ``.yaml``, ``.yml``, and ``.json``.
Individual rows of CSV and TSV files are treated as instances to validate. Each document
within a YAML file is treated as an individual instance to validate. If the top-level of a
JSON file is an array, each element of the array is treated as an instance to validate.
Otherwise, if the top-level is an object it is treated as a single instance to validate.
To have more control over the type of validation performed, see the :class:`Validator` class.
:param file: Path-like object of the file to be read
:param schema: The schema used to validate the instance. If a string is
it will be interpreted as a path, URL, or other loadable location.
If it is a dict it should be compatible with ``SchemaDefinition``,
otherwise it should be a ``SchemaDefinition`` instance.
:param target_class: Name of the class within the schema to validate
against. If ``None``, the class will be inferred from the schema by
looking for a class with ``tree_root: true``. Defaults to ``None``.
:param strict: If ``True``, validation will stop after the first validation
error is found, Otherwise all validation problems will be reported.
Defaults to ``False``.
:return: A validation report
:rtype: ValidationReport
"""
loader = default_loader_for_file(file)
validator = _get_default_validator(schema, strict=strict)
return validator.validate_source(loader, target_class)
__all__ = ["Validator", "validate", "validate_file"]