Skip to content

Commit

Permalink
Merge pull request dandi#18 from candleindark/published-dandisets
Browse files Browse the repository at this point in the history
Use correct model to validate published datasets
  • Loading branch information
candleindark authored Oct 23, 2024
2 parents 6ba722e + 2ec2d59 commit a3845f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
10 changes: 7 additions & 3 deletions src/dandisets_linkml_status_tools/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pydantic2linkml.cli.tools import LogLevel

from dandisets_linkml_status_tools.cli.tools import (
compile_validation_report,
compile_dandiset_validation_report,
output_reports,
)

Expand Down Expand Up @@ -64,15 +64,19 @@ def main(
dandiset_latest = dandiset.for_version(most_recent_published_version)

# Handle the latest published version
report_on_latest = compile_validation_report(dandiset_latest)
report_on_latest = compile_dandiset_validation_report(
dandiset_latest, is_dandiset_published=True
)
validation_reports.append(report_on_latest)
else:
# === The dandiset has never been published ===
# === Only a draft version is available ===
dandiset_draft = dandiset

# Handle the draft version
report_on_draft = compile_validation_report(dandiset_draft)
report_on_draft = compile_dandiset_validation_report(
dandiset_draft, is_dandiset_published=False
)
validation_reports.append(report_on_draft)

# Print summary of validation reports
Expand Down
39 changes: 23 additions & 16 deletions src/dandisets_linkml_status_tools/cli/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ def pydantic_validate(dandiset_metadata: dict[str, Any]) -> str:
return "[]"


class DandisetLinkmlValidator:
class DandiModelLinkmlValidator:
"""
A class to validate dandiset metadata against the dandiset metadata model in
A class to validate DANDI metadata against the DANDI metadata models in
the LinkML schema produced by the pydantic2linkml translator for DANDI models
expressed in Pydantic
"""
Expand All @@ -76,7 +76,7 @@ class DandisetLinkmlValidator:

def __init__(self, validation_plugins: Optional[list[ValidationPlugin]] = None):
"""
Initialize a `DandisetLinkmlValidator` instance that wraps a LinkML validator
Initialize a `DandiModelLinkmlValidator` instance that wraps a LinkML validator
instance set up with schema produced by the pydantic2linkml translator,
for DANDI models expressed in Pydantic, and given validation plugins.
Expand All @@ -97,7 +97,8 @@ def __init__(self, validation_plugins: Optional[list[ValidationPlugin]] = None):
@classmethod
def get_dandi_linkml_schema(cls) -> SchemaDefinition:
"""
Get the LinkML schema produced by the pydantic2linkml translator for DANDI models
Get the LinkML schema produced by the pydantic2linkml translator
for DANDI models
:return: The LinkML schema
"""
Expand All @@ -106,34 +107,38 @@ def get_dandi_linkml_schema(cls) -> SchemaDefinition:

return cls._dandi_linkml_schema

def validate(self, dandiset_metadata: dict[str, Any]) -> list[ValidationResult]:
def validate(
self, dandi_metadata: dict[str, Any], dandi_metadata_class: str
) -> list[ValidationResult]:
"""
Validate the given dandiset metadata against the dandiset metadata model in
LinkML
Validate given DANDI metadata against a DANDI metadata model
specified by its class name in the LinkML schema
:param dandiset_metadata: The dandiset metadata to validate
:param dandi_metadata: The DANDI metadata to validate
:param dandi_metadata_class: The class name of the DANDI metadata model
:return: A list of validation errors encountered
"""
# The name of the class in the LinkML schema representing Dandiset metadata
dandiset_metadata_class = "Dandiset"

validation_report = self._inner_validator.validate(
dandiset_metadata, target_class=dandiset_metadata_class
dandi_metadata, target_class=dandi_metadata_class
)
return validation_report.results


def compile_validation_report(dandiset: RemoteDandiset) -> DandisetValidationReport:
def compile_dandiset_validation_report(
dandiset: RemoteDandiset, *, is_dandiset_published: bool
) -> DandisetValidationReport:
"""
Compile a validation report of the metadata of a given dandiset
:param dandiset: The given dandiset
:param is_dandiset_published: A boolean indicating whether the given dandiset
is published
:return: The compiled validation report
Note: This function should only be called in the context of a `DandiAPIClient`
context manager associated with the given dandiset.
"""
dandiset_linkml_validator = DandisetLinkmlValidator()
dandi_model_linkml_validator = DandiModelLinkmlValidator()

dandiset_id = dandiset.identifier
dandiset_version = dandiset.version_id
Expand All @@ -157,7 +162,9 @@ def compile_validation_report(dandiset: RemoteDandiset) -> DandisetValidationRep
)

# Validate the raw metadata using the LinkML schema
linkml_validation_errs = dandiset_linkml_validator.validate(raw_metadata)
linkml_validation_errs = dandi_model_linkml_validator.validate(
raw_metadata, "PublishedDandiset" if is_dandiset_published else "Dandiset"
)
if linkml_validation_errs:
logger.info(
"Captured LinkML validation errors for dandiset %s @ %s",
Expand Down Expand Up @@ -309,7 +316,7 @@ def output_dandi_linkml_schema(output_path: Path) -> None:
"""
# Output the LinkML schema used in the validations
dandi_linkml_schema_yml = yaml_dumper.dumps(
DandisetLinkmlValidator.get_dandi_linkml_schema()
DandiModelLinkmlValidator.get_dandi_linkml_schema()
)
with output_path.open("w") as f:
f.write(dandi_linkml_schema_yml)
Expand Down

0 comments on commit a3845f9

Please sign in to comment.