Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/api/private/deposit_check.py
Show All 11 Lines | |||||
from rest_framework import status | from rest_framework import status | ||||
from swh.scheduler.utils import create_oneshot_task_dict | from swh.scheduler.utils import create_oneshot_task_dict | ||||
from . import APIPrivateView, DepositReadMixin | from . import APIPrivateView, DepositReadMixin | ||||
from ...config import ARCHIVE_TYPE, DEPOSIT_STATUS_REJECTED, DEPOSIT_STATUS_VERIFIED | from ...config import ARCHIVE_TYPE, DEPOSIT_STATUS_REJECTED, DEPOSIT_STATUS_VERIFIED | ||||
from ...models import Deposit, DepositRequest | from ...models import Deposit, DepositRequest | ||||
from ..checks import check_metadata | |||||
from ..common import APIGet | from ..common import APIGet | ||||
MANDATORY_FIELDS_MISSING = "Mandatory fields are missing" | |||||
ALTERNATE_FIELDS_MISSING = "Mandatory alternate fields are missing" | |||||
MANDATORY_ARCHIVE_UNREADABLE = ( | MANDATORY_ARCHIVE_UNREADABLE = ( | ||||
"At least one of its associated archives is not readable" # noqa | "At least one of its associated archives is not readable" # noqa | ||||
) | ) | ||||
MANDATORY_ARCHIVE_INVALID = ( | MANDATORY_ARCHIVE_INVALID = ( | ||||
"Mandatory archive is invalid (i.e contains only one archive)" # noqa | "Mandatory archive is invalid (i.e contains only one archive)" # noqa | ||||
) | ) | ||||
MANDATORY_ARCHIVE_UNSUPPORTED = "Mandatory archive type is not supported" | MANDATORY_ARCHIVE_UNSUPPORTED = "Mandatory archive type is not supported" | ||||
MANDATORY_ARCHIVE_MISSING = "Deposit without archive is rejected" | MANDATORY_ARCHIVE_MISSING = "Deposit without archive is rejected" | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | ) -> Tuple[bool, Optional[str]]: | ||||
if len(files) > 1: | if len(files) > 1: | ||||
return True, None | return True, None | ||||
element = files[0] | element = files[0] | ||||
if PATTERN_ARCHIVE_EXTENSION.match(element): | if PATTERN_ARCHIVE_EXTENSION.match(element): | ||||
# archive in archive! | # archive in archive! | ||||
return False, MANDATORY_ARCHIVE_INVALID | return False, MANDATORY_ARCHIVE_INVALID | ||||
return True, None | return True, None | ||||
def _check_metadata(self, metadata: Dict) -> Tuple[bool, Optional[Dict]]: | |||||
"""Check to execute on all metadata for mandatory field presence. | |||||
Args: | |||||
metadata (dict): Metadata dictionary to check for mandatory fields | |||||
Returns: | |||||
tuple (status, error_detail): True, None if metadata are | |||||
ok (False, <detailed-error>) otherwise. | |||||
""" | |||||
required_fields = { | |||||
"author": False, | |||||
} | |||||
alternate_fields = { | |||||
("name", "title"): False, # alternate field, at least one | |||||
# of them must be present | |||||
} | |||||
for field, value in metadata.items(): | |||||
for name in required_fields: | |||||
if name in field: | |||||
required_fields[name] = True | |||||
for possible_names in alternate_fields: | |||||
for possible_name in possible_names: | |||||
if possible_name in field: | |||||
alternate_fields[possible_names] = True | |||||
continue | |||||
mandatory_result = [k for k, v in required_fields.items() if not v] | |||||
optional_result = [" or ".join(k) for k, v in alternate_fields.items() if not v] | |||||
moranegg: here it seems that the software (title/name) are optional, because of the name `optional`.
I… | |||||
Done Inline ActionsI'm not modifying that code today, i'm just moving it around so we have consistent behavior everywhere we use it.
It is. The docstring indeed mentions that the checks are about "all" mandatory metadata. ardumont: I'm not modifying that code today, i'm just moving it around so we have consistent behavior… | |||||
if mandatory_result == [] and optional_result == []: | |||||
return True, None | |||||
detail = [] | |||||
if mandatory_result != []: | |||||
detail.append( | |||||
{"summary": MANDATORY_FIELDS_MISSING, "fields": mandatory_result} | |||||
) | |||||
if optional_result != []: | |||||
detail.append( | |||||
{"summary": ALTERNATE_FIELDS_MISSING, "fields": optional_result,} | |||||
) | |||||
return False, {"metadata": detail} | |||||
Done Inline Actionshere is our old check metadata code that i've moved around so it's reusable in our new scenario. ardumont: here is our old check metadata code that i've moved around so it's reusable in our new scenario. | |||||
def process_get( | def process_get( | ||||
self, req, collection_name: str, deposit_id: int | self, req, collection_name: str, deposit_id: int | ||||
) -> Tuple[int, Dict, str]: | ) -> Tuple[int, Dict, str]: | ||||
"""Build a unique tarball from the multiple received and stream that | """Build a unique tarball from the multiple received and stream that | ||||
content to the client. | content to the client. | ||||
Args: | Args: | ||||
req (Request): | req (Request): | ||||
Show All 9 Lines | ) -> Tuple[int, Dict, str]: | ||||
problems: Dict = {} | problems: Dict = {} | ||||
# will check each deposit's associated request (both of type | # will check each deposit's associated request (both of type | ||||
# archive and metadata) for errors | # archive and metadata) for errors | ||||
archives_status, error_detail = self._check_deposit_archives(deposit) | archives_status, error_detail = self._check_deposit_archives(deposit) | ||||
if not archives_status: | if not archives_status: | ||||
assert error_detail is not None | assert error_detail is not None | ||||
problems.update(error_detail) | problems.update(error_detail) | ||||
metadata_status, error_detail = self._check_metadata(metadata) | metadata_status, error_detail = check_metadata(metadata) | ||||
if not metadata_status: | if not metadata_status: | ||||
assert error_detail is not None | assert error_detail is not None | ||||
problems.update(error_detail) | problems.update(error_detail) | ||||
deposit_status = archives_status and metadata_status | deposit_status = archives_status and metadata_status | ||||
# if any problems arose, the deposit is rejected | # if any problems arose, the deposit is rejected | ||||
if not deposit_status: | if not deposit_status: | ||||
Show All 22 Lines |
here it seems that the software (title/name) are optional, because of the name optional.
I see below that the and makes it mandatory.
Could you check if that's the behavior?
I would suggest to change this to alternate_mandatory_result.