Source code for linkml.validator.plugins.recommended_slots_plugin

from typing import Iterator, List, Optional

from linkml.validator.plugins.validation_plugin import ValidationPlugin
from linkml.validator.report import Severity, ValidationResult
from linkml.validator.validation_context import ValidationContext


[docs]class RecommendedSlotsPlugin(ValidationPlugin): """A validation plugin which validates that recommended slots are populated""" def process(self, instance: dict, context: ValidationContext) -> Iterator[ValidationResult]: def _do_process( instance: dict, class_name: str, location: Optional[List[str]] = None ) -> Iterator[ValidationResult]: if not isinstance(instance, dict): return if location is None: location = [] for slot_def in context.schema_view.class_induced_slots(class_name): slot_value = instance.get(slot_def.name, None) if slot_def.recommended and slot_value is None: loc = "/".join(location) yield ValidationResult( type="recommended slots", severity=Severity.WARN, instance=instance, instantiates=class_name, message=f"Slot '{slot_def.name}' is recommended on class '{class_name}' in /{loc}", ) slot_range_class = context.schema_view.get_class(slot_def.range) if slot_range_class is not None and slot_value is not None: location += [slot_def.name] if slot_def.multivalued: if slot_def.inlined and isinstance(slot_value, dict): for k, v in slot_value.items(): yield from _do_process(v, slot_range_class.name, location + [k]) elif slot_def.inlined_as_list and isinstance(slot_value, list): for i, v in enumerate(slot_value): yield from _do_process(v, slot_range_class.name, location + [str(i)]) else: yield from _do_process(instance[slot_def.name], slot_range_class.name, location) yield from _do_process(instance, context.target_class)