Skip to content

Commit

Permalink
Merge pull request dandi#23 from candleindark/published-dandiset-pyda…
Browse files Browse the repository at this point in the history
…ntic-validation

Use `PublishedDandiset` to validate metadata of published dandiset
  • Loading branch information
candleindark authored Oct 30, 2024
2 parents 3d0e498 + 5d0a4f4 commit 52689d7
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions src/dandisets_linkml_status_tools/cli/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
from typing import Any, NamedTuple, Optional

from dandi.dandiapi import RemoteDandiset
from dandischema.models import Dandiset
from dandischema.models import Dandiset, PublishedDandiset
from linkml.validator import Validator
from linkml.validator.plugins import JsonschemaValidationPlugin, ValidationPlugin
from linkml.validator.report import ValidationResult
from linkml_runtime.dumpers import yaml_dumper
from linkml_runtime.linkml_model import SchemaDefinition
from pydantic import TypeAdapter, ValidationError
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic2linkml.gen_linkml import translate_defs
from yaml import dump as yaml_dump

Expand Down Expand Up @@ -46,18 +46,19 @@
isorted = partial(sorted, key=str.casefold)


def pydantic_validate(dandiset_metadata: dict[str, Any]) -> str:
def pydantic_validate(data: dict[str, Any], model: type[BaseModel]) -> str:
"""
Validate the given dandiset metadata against the Pydantic dandiset metadata model
:param dandiset_metadata: The dandiset metadata to validate.
:return: A JSON string that is an array of errors encountered in the validation
(The JSON string returned in a case of any validation failure is one returned by
the Pydantic `ValidationError.json()` method. In the case of no validation
error, the empty array JSON expression, `"[]"`, is returned.)
Validate the given data against a Pydantic model
:param data: The data to be validated
:param model: The Pydantic model to validate the data against
:return: A JSON string that specifies an array of errors encountered in
the validation (The JSON string returned in a case of any validation failure
is one returned by the Pydantic `ValidationError.json()` method. In the case
of no validation error, the empty array JSON expression, `"[]"`, is returned.)
"""
try:
Dandiset.model_validate(dandiset_metadata)
model.model_validate(data)
except ValidationError as e:
return e.json()

Expand Down Expand Up @@ -141,6 +142,14 @@ def compile_dandiset_validation_report(
Note: This function should only be called in the context of a `DandiAPIClient`
context manager associated with the given dandiset.
"""
# Determine validation targets
if is_dandiset_published:
pydantic_validation_target = PublishedDandiset # Specified as a Pydantic model
linkml_validation_target = "PublishedDandiset" # Specified as a LinkML class
else:
pydantic_validation_target = Dandiset # Specified as a Pydantic model
linkml_validation_target = "Dandiset" # Specified as a LinkML class

dandi_model_linkml_validator = DandiModelLinkmlValidator()

dandiset_id = dandiset.identifier
Expand Down Expand Up @@ -170,7 +179,9 @@ def compile_dandiset_validation_report(
dandiset_version_modified = dandiset_version_info.modified

# Validate the raw metadata using the Pydantic model
pydantic_validation_errs = pydantic_validate(raw_metadata)
pydantic_validation_errs = pydantic_validate(
raw_metadata, pydantic_validation_target
)
if pydantic_validation_errs != "[]":
logger.info(
"Captured Pydantic validation errors for dandiset %s @ %s",
Expand All @@ -180,7 +191,7 @@ def compile_dandiset_validation_report(

# Validate the raw metadata using the LinkML schema
linkml_validation_errs = dandi_model_linkml_validator.validate(
raw_metadata, "PublishedDandiset" if is_dandiset_published else "Dandiset"
raw_metadata, linkml_validation_target
)
if linkml_validation_errs:
logger.info(
Expand Down

0 comments on commit 52689d7

Please sign in to comment.