diff --git a/eark_validator/mets.py b/eark_validator/mets.py index 78f69ac..b405900 100644 --- a/eark_validator/mets.py +++ b/eark_validator/mets.py @@ -166,7 +166,7 @@ def validate_mets(self, mets: str) -> bool: self._validation_errors.append( Result.model_validate({ 'rule_id': 'XML-1', - 'location': synt_err.filename + str(synt_err.lineno) + str(synt_err.offset), + 'location': str(synt_err.filename) + str(synt_err.lineno) + str(synt_err.offset), 'message': f'File {mets} is not valid XML. {synt_err.msg}', 'severity': 'Error' }) diff --git a/eark_validator/model/validation_report.py b/eark_validator/model/validation_report.py index bbddebe..64ec8dc 100644 --- a/eark_validator/model/validation_report.py +++ b/eark_validator/model/validation_report.py @@ -133,10 +133,8 @@ def convert_status(cls, data: Any) -> Any: return data class MetatdataResultSet(BaseModel): - model_config = ConfigDict(populate_by_name=True) - schema_results: MetadataResults = Field(validation_alias='schemaResults') - model_config = ConfigDict(populate_by_name=True) - schematron_results: MetadataResults = Field(validation_alias='schematronResults') + schema_results: Optional[MetadataResults] = None + schematron_results: Optional[MetadataResults] = None class ValidationReport(BaseModel): uid: Annotated[str, Field(default_factory=lambda: uuid4().hex)] diff --git a/eark_validator/packages.py b/eark_validator/packages.py index 6bb28fd..2b8954f 100644 --- a/eark_validator/packages.py +++ b/eark_validator/packages.py @@ -93,7 +93,14 @@ def validate(cls, version: SpecificationVersion, to_validate: Path) -> Validatio if not is_struct_valid: return ValidationReport.model_validate({'structure': struct_results}) validator = MetsValidator(str(to_validate)) - validator.validate_mets(METS) + is_mets_valid = validator.validate_mets(METS) + if not is_mets_valid: + metadata: MetatdataResultSet = MetatdataResultSet.model_validate({ + 'schema_results': MetadataResults.model_validate({ 'status': _validity_from_messages(validator.validation_errors), 'messages': validator.validation_errors })}) + return ValidationReport.model_validate({ + 'structure': struct_results, + 'metadata': metadata + }) csip_profile = SC.ValidationProfile(SpecificationType.CSIP, version) csip_profile.validate(to_validate.joinpath(METS)) diff --git a/eark_validator/structure.py b/eark_validator/structure.py index 0d78d59..3070659 100644 --- a/eark_validator/structure.py +++ b/eark_validator/structure.py @@ -89,6 +89,20 @@ def has_metadata(self) -> bool: """Returns True if the package/representation has a metadata folder.""" return DIR_NAMES['META'] in self.folders + def has_other(self) -> bool: + """Returns True if the package/representation has extra folders + after metadata, representations, schemas and documentation.""" + folder_count = len(self.folders) + if self.has_metadata(): + folder_count-=1 + if self.has_representations_folder(): + folder_count-=1 + if self.has_schemas(): + folder_count-=1 + if self.has_documentation(): + folder_count-=1 + return folder_count > 0 + def has_other_md(self) -> bool: """Returns True if the package/representation has extra metadata folders after preservation and descriptive.""" @@ -162,12 +176,16 @@ def get_root_results(self) -> List[Result]: results.extend(self._get_metadata_results(location=location)) if not self.parser.has_representations_folder(): results.append(test_result_from_id(9, location)) - elif len(self.representations) < 1: + elif len(self.representations) == 0 or not all(parser.is_parsable for _, parser in self.representations.items()): results.append(test_result_from_id(10, location)) return results def get_package_results(self) -> List[Result]: results: List[Result] = [] + if not self.parser.has_other(): + result = self._get_other_results() + if result: + results.append(result) if not self.parser.has_schemas(): result = self._get_schema_results() if result: @@ -191,6 +209,12 @@ def _get_metadata_results(self, location: str) -> List[Result]: results.append(test_result_from_id(8, location)) return results + def _get_other_results(self) -> Optional[Result]: + for tests in self.representations.values(): + if tests.has_other(): + return None + return test_result_from_id(14, _root_loc(self.name)) + def _get_schema_results(self) -> Optional[Result]: for tests in self.representations.values(): if tests.has_schemas(): diff --git a/tests/structure_test.py b/tests/structure_test.py index 631bde1..613a92f 100644 --- a/tests/structure_test.py +++ b/tests/structure_test.py @@ -240,9 +240,9 @@ def test_str10_emptyreps(self): _, details = STRUCT.validate(ip_path) self.assertEqual(details.status, STRUCT.StructureStatus.WELLFORMED, EXP_WELLFORMED.format(details.status)) - err_count = 1 - self.assertEqual(len(details.messages), err_count, - EXP_ERRORS.format(err_count, len(details.warnings))) + warn_count = 1 + self.assertEqual(len(details.warnings), warn_count, + EXP_ERRORS.format(warn_count, len(details.warnings))) self.assertTrue(contains_rule_id(details.warnings, 'CSIPSTR10', severity=Severity.WARNING)) @@ -254,7 +254,7 @@ def test_str11_nodata(self): self.assertEqual(details.status, STRUCT.StructureStatus.WELLFORMED, EXP_WELLFORMED.format(details.status)) warn_count = 1 - self.assertEqual(len(details.messages), warn_count, + self.assertEqual(len(details.warnings), warn_count, EXP_ERRORS.format(warn_count, len(details.warnings))) self.assertTrue(contains_rule_id(details.warnings, 'CSIPSTR11', severity=Severity.WARNING))