Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAINT: Structure rules test coverage #27

Merged
merged 3 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions eark_validator/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __init__(self, package_path: Path, check_metadata=True):
self._name = os.path.basename(self._to_proc)
else:
# If not an archive we can't process
self._report = _report_from_bad_path(self.name, package_path)
self._report = _report_from_bad_path(package_path)
return
self._report = validate(self._to_proc, check_metadata)

Expand All @@ -96,13 +96,6 @@ def validation_report(self) -> ValidationReport:
"""Returns the valdiation report for the package."""
return self._report

def _report_from_unpack_except(name: str, package_path: Path) -> ValidationReport:
struct_results = structure.get_multi_root_results(package_path)
return ValidationReport.model_validate({ 'structure': struct_results })

def _report_from_bad_path(name: str, package_path: Path) -> ValidationReport:
def _report_from_bad_path(package_path: Path) -> ValidationReport:
struct_results = structure.get_bad_path_results(package_path)
return ValidationReport.model_validate({ 'structure': struct_results })

def _get_info_pack(name: str, profile=None) -> PackageDetails:
return PackageDetails.model_validate({ 'name': name })
71 changes: 43 additions & 28 deletions eark_validator/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@ class StructureParser():
_package_handler = PackageHandler()
"""Encapsulates the set of tests carried out on folder structure."""
def __init__(self, package_path: Path):
self._is_archive = package_path.is_file() and PackageHandler.is_archive(package_path)
to_process = self._package_handler.prepare_package(package_path)
self.folders, self.files = _folders_and_files(to_process)
if DIR_NAMES['META'] in self.folders:
self.md_folders, _ = _folders_and_files(os.path.join(to_process, DIR_NAMES['META']))
else:
self.md_folders = set()
self._is_archive = PackageHandler.is_archive(package_path)
self.md_folders: set[str]= set()
self.folders: set[str] = set()
self.files : set[str] = set()
self.is_parsable = False
if self._is_archive or package_path.is_dir():
self.is_parsable = True
self.resolved_path = self._package_handler.prepare_package(package_path)
self.folders, self.files = _folders_and_files(self.resolved_path)
if DIR_NAMES['META'] in self.folders:
self.md_folders, _ = _folders_and_files(os.path.join(self.resolved_path, DIR_NAMES['META']))

def has_data(self) -> bool:
"""Returns True if the package/representation has a structure folder."""
Expand Down Expand Up @@ -97,7 +101,7 @@ def has_preservation_md(self) -> bool:
"""Returns True if the package/representation has a preservation metadata folder."""
return DIR_NAMES['PRES'] in self.md_folders

def has_representations(self) -> bool:
def has_representations_folder(self) -> bool:
"""Returns True if the package/representation has a representations folder."""
return DIR_NAMES['REPS'] in self.folders

Expand All @@ -112,18 +116,21 @@ def is_archive(self) -> bool:

class StructureChecker():
def __init__(self, dir_to_scan: Path):
self.name: Path = os.path.basename(dir_to_scan)
self.name: str = os.path.basename(dir_to_scan)
self.parser: StructureParser = StructureParser(dir_to_scan)
self.representations: Dict[Representation, StructureParser] = {}
_reps = os.path.join(dir_to_scan, DIR_NAMES['REPS'])
if os.path.isdir(_reps):
for entry in os.listdir(_reps):
self.representations[entry] = StructureParser(Path(os.path.join(_reps, entry)))
if self.parser.is_parsable:
_reps = os.path.join(self.parser.resolved_path, DIR_NAMES['REPS'])
if os.path.isdir(_reps):
for entry in os.listdir(_reps):
self.representations[entry] = StructureParser(Path(os.path.join(_reps, entry)))

def get_test_results(self) -> StructResults:
if not self.parser.is_parsable:
return get_bad_path_results(self.name)

results: List[Result] = self.get_root_results()
results = results + self.get_package_results()

for name, tests in self.representations.items():
location = Location.model_validate({ 'context': str(name), 'description': 'representation' })
if not tests.has_data():
Expand All @@ -147,16 +154,11 @@ def get_root_results(self) -> List[Result]:
results.append(test_result_from_id(3, location))
if not self.parser.has_mets():
results.append(test_result_from_id(4, location))
if not self.parser.has_metadata():
results.append(test_result_from_id(5, location))
if not self.parser.has_preservation_md():
results.append(test_result_from_id(6, location))
if not self.parser.has_descriptive_md():
results.append(test_result_from_id(7, location))
if not self.parser.has_other_md():
results.append(test_result_from_id(8, location))
if not self.parser.has_representations():
results.extend(self._get_metadata_results(location=location))
if not self.parser.has_representations_folder():
results.append(test_result_from_id(9, location))
elif not len(self.representations) > 0:
results.append(test_result_from_id(10, location))
return results

def get_package_results(self) -> List[Result]:
Expand All @@ -171,6 +173,19 @@ def get_package_results(self) -> List[Result]:
results.append(result)
return results

def _get_metadata_results(self, location: str) -> List[Result]:
results: List[Result] = []
if not self.parser.has_metadata():
results.append(test_result_from_id(5, location))
else:
if not self.parser.has_preservation_md():
results.append(test_result_from_id(6, location))
if not self.parser.has_descriptive_md():
results.append(test_result_from_id(7, location))
if not self.parser.has_other_md():
results.append(test_result_from_id(8, location))
return results

def _get_schema_results(self) -> Optional[Result]:
for tests in self.representations.values():
if tests.has_schemas():
Expand Down Expand Up @@ -213,15 +228,15 @@ def test_result_from_id(requirement_id, location, message=None) -> Result:
'severity': Severity.from_level(req['level'])
})

def get_multi_root_results(name) -> StructResults:
return StructResults.model_validate({ 'status': StructureStatus.NotWellFormed, 'messages': [ test_result_from_id(1, Location.model_validate({ 'context': 'root', 'description': str(name) })) ] })

def get_bad_path_results(path) -> StructResults:
return StructResults.model_validate({ 'status': StructureStatus.NotWellFormed, 'messages': [ test_result_from_id(1, Location.model_validate({ 'context': 'root', 'description': str(path) })) ] })
return StructResults.model_validate({ 'status': StructureStatus.NotWellFormed, 'messages': _get_str1_result_list(path) })

def _get_str1_result_list(name: str) -> List[Result]:
return [ test_result_from_id(1, Location.model_validate({ 'context': 'root', 'description': str(name) })) ]

def validate(to_validate) -> Tuple[bool, StructResults]:
try:
struct_tests = StructureChecker(to_validate).get_test_results()
return struct_tests.status == StructureStatus.WellFormed, struct_tests
except PackageError:
return False, get_multi_root_results(to_validate)
return False, get_bad_path_results(to_validate)
3 changes: 2 additions & 1 deletion tests/manifests_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from eark_validator.model.manifest import Manifest, SourceType
from eark_validator.model.manifest import ManifestEntry

import tests.resources as RES
import tests.resources.xml as XML
import tests.resources.ips.unpacked as UNPACKED

Expand Down Expand Up @@ -202,7 +203,7 @@ def test_no_dir(self):
Manifests.from_directory(missing)

def test_file_path(self):
file_path = str(files(UNPACKED).joinpath('single_file').joinpath('empty.file'))
file_path = str(files(RES).joinpath('empty.file'))
with self.assertRaises(ValueError):
Manifests.from_directory(file_path)
with self.assertRaises(ValueError):
Expand Down
Binary file added tests/resources/ips/bad/multi_file.zip
Binary file not shown.
Binary file added tests/resources/ips/bad/multi_var.zip
Binary file not shown.
Binary file added tests/resources/ips/struct/empty_reps.tar.gz
Binary file not shown.
Binary file modified tests/resources/ips/struct/no_data.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_desc.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_docs.tar.gz
Binary file not shown.
Binary file modified tests/resources/ips/struct/no_md.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_messages.tar.gz
Binary file not shown.
Binary file modified tests/resources/ips/struct/no_mets.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_other.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_pres.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_repmd.tar.gz
Binary file not shown.
Binary file added tests/resources/ips/struct/no_repmets.tar.gz
Binary file not shown.
Binary file modified tests/resources/ips/struct/no_reps.tar.gz
Binary file not shown.
Binary file modified tests/resources/ips/struct/no_schemas.tar.gz
Binary file not shown.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Loading
Loading