[docs]classResourceStatistics:""" Base class for statistics. Subclasses should be created using mixins defined for each statistic type that the resource contains. """def__init__(self,resource_id:str):self.resource_id=resource_id
[docs]classGenomicResourceImplementation(ABC):""" Base class used by resource implementations. Resources are just a folder on a repository. Resource implementations are classes that know how to use the contents of the resource. """def__init__(self,genomic_resource:GenomicResource):self.resource=genomic_resourceself.config:dict=self.resource.get_config()self._statistics:ResourceStatistics|None=None@propertydefresource_id(self)->str:returnself.resource.resource_id
@propertydeffiles(self)->set[str]:"""Return a list of resource files the implementation utilises."""returnset()
[docs]@abstractmethoddefcalc_statistics_hash(self)->bytes:""" Compute the statistics hash. This hash is used to decide whether the resource statistics should be recomputed. """raiseNotImplementedError
[docs]@abstractmethoddefadd_statistics_build_tasks(self,task_graph:TaskGraph,**kwargs:Any)->list[Task]:"""Add tasks for calculating resource statistics to a task graph."""raiseNotImplementedError
[docs]@abstractmethoddefcalc_info_hash(self)->bytes:"""Compute and return the info hash."""raiseNotImplementedError
[docs]@abstractmethoddefget_info(self,**kwargs:Any)->str:"""Construct the contents of the implementation's HTML info page."""raiseNotImplementedError
[docs]@abstractmethoddefget_statistics_info(self,**kwargs:Any)->str:"""Construct the contents of the implementation's HTML statistics info page. """raiseNotImplementedError
[docs]defget_statistics(self)->ResourceStatistics|None:"""Try and load resource statistics."""returnNone
[docs]defget_template_data(self)->dict:""" Return a data dictionary to be used by the template. Will transform the description in the meta section using markdown. """template_data=self._get_template_data()template_data["resource_files"]=[self.FileEntry(entry.name,convert_size(entry.size),entry.md5)forentryinself.resource.get_manifest().entries.values()ifnotentry.name.startswith("statistics")andentry.name!="index.html"]template_data["resource_files"].append(self.FileEntry("statistics/","",""))returntemplate_data
[docs]defget_statistics_template_data(self)->dict:""" Return a data dictionary to be used by the statistics template. Will transform the description in the meta section using markdown. """template_data=self._get_template_data()template_data["statistic_files"]=[self.FileEntry(entry.name.removeprefix("statistics/"),convert_size(entry.size),entry.md5,)forentryinself.resource.get_manifest().entries.values()ifentry.name.startswith("statistics")]returntemplate_data
[docs]defget_info(self)->str:"""Construct the contents of the implementation's HTML info page."""template_data=self.get_template_data()returnself.get_template().render(resource=self.resource,markdown=markdown,data=template_data,base=RESOURCE_TEMPLATE,)
[docs]defget_statistics_info(self)->str:"""Construct the contents of the implementation's HTML info page."""template_data=self.get_statistics_template_data()returnself.get_template().render(resource=self.resource,markdown=markdown,data=template_data,base=STATISTICS_TEMPLATE,)
[docs]classResourceConfigValidationMixin:"""Mixin that provides validation of resource configuration."""
[docs]@staticmethod@abstractmethoddefget_schema()->dict:"""Return schema to be used for config validation."""raiseNotImplementedError
[docs]@classmethoddefvalidate_and_normalize_schema(cls,config:dict,resource:GenomicResource)->dict:"""Validate the resource schema and return the normalized version."""# pylint: disable=not-callablevalidator=Validator(cls.get_schema())ifnotvalidator.validate(config):logger.error("Resource %s of type %s has an invalid configuration. %s",resource.resource_id,resource.get_type(),validator.errors)raiseValueError(f"Invalid configuration: {resource.resource_id}")returncast(dict,validator.document)