every ValidationError is defined to return a dictionary. In case of validation errors without such a call, a function enforces a default with an undefined key to ensure the correct format.

This commit is contained in:
Max Metz 2024-09-05 12:46:04 +02:00
parent 7ad8011c52
commit ab7b1ed34f
9 changed files with 115 additions and 99 deletions

View File

@ -38,7 +38,7 @@ def PostShip():
# as ParticipantType is an IntFlag, a user belonging to multiple groups is properly evaluated. # as ParticipantType is an IntFlag, a user belonging to multiple groups is properly evaluated.
is_bsmd = check_if_user_is_bsmd_type(user_data) is_bsmd = check_if_user_is_bsmd_type(user_data)
if not is_bsmd: if not is_bsmd:
raise ValidationError(f"current user does not belong to BSMD. Cannot post shipcalls. Found user data: {user_data}") raise ValidationError({"participant_type":f"current user does not belong to BSMD. Cannot post shipcalls. Found user data: {user_data}"})
content = request.get_json(force=True) content = request.get_json(force=True)
loadedModel = model.ShipSchema().load(data=content, many=False, partial=True) loadedModel = model.ShipSchema().load(data=content, many=False, partial=True)

View File

@ -177,7 +177,7 @@ class Participant(Schema):
valid_type = 0 <= value < max_int valid_type = 0 <= value < max_int
if not valid_type: if not valid_type:
raise ValidationError(f"the provided integer is not supported for default behaviour of the ParticipantType IntFlag. Your choice: {value}. Supported values are: 0 <= value {max_int}") raise ValidationError({"type":f"the provided integer is not supported for default behaviour of the ParticipantType IntFlag. Your choice: {value}. Supported values are: 0 <= value {max_int}"})
@validates("flags") @validates("flags")
@ -188,7 +188,7 @@ class Participant(Schema):
valid_type = 0 <= value < max_int valid_type = 0 <= value < max_int
if not valid_type: if not valid_type:
raise ValidationError(f"the provided integer is not supported for default behaviour of the ParticipantFlag IntFlag. Your choice: {value}. Supported values are: 0 <= value {max_int}") raise ValidationError({"flags":f"the provided integer is not supported for default behaviour of the ParticipantFlag IntFlag. Your choice: {value}. Supported values are: 0 <= value {max_int}"})
class ParticipantList(Participant): class ParticipantList(Participant):
@ -253,7 +253,7 @@ class ShipcallSchema(Schema):
valid_shipcall_type = int(value) in [item.value for item in ShipcallType] valid_shipcall_type = int(value) in [item.value for item in ShipcallType]
if not valid_shipcall_type: if not valid_shipcall_type:
raise ValidationError(f"the provided type is not a valid shipcall type.") raise ValidationError({"type":f"the provided type is not a valid shipcall type."})
@dataclass @dataclass
@ -393,7 +393,7 @@ class TimesSchema(Schema):
value = ParticipantType(value) value = ParticipantType(value)
if ParticipantType.BSMD in value: if ParticipantType.BSMD in value:
raise ValidationError(f"the participant_type must not be .BSMD") raise ValidationError({"participant_type":f"the participant_type must not be .BSMD"})
@validates("eta_berth") @validates("eta_berth")
def validate_eta_berth(self, value): def validate_eta_berth(self, value):
@ -471,12 +471,12 @@ class UserSchema(Schema):
def validate_user_phone(self, value): def validate_user_phone(self, value):
valid_characters = list(map(str,range(0,10)))+["+", " "] valid_characters = list(map(str,range(0,10)))+["+", " "]
if not all([v in valid_characters for v in value]): if not all([v in valid_characters for v in value]):
raise ValidationError(f"one of the phone number values is not valid.") raise ValidationError({"user_phone":f"one of the phone number values is not valid."})
@validates("user_email") @validates("user_email")
def validate_user_email(self, value): def validate_user_email(self, value):
if not "@" in value: if not "@" in value:
raise ValidationError(f"invalid email address") raise ValidationError({"user_email":f"invalid email address"})
@dataclass @dataclass
@ -565,12 +565,12 @@ class ShipSchema(Schema):
def validate_name(self, value): def validate_name(self, value):
character_length = len(str(value)) character_length = len(str(value))
if character_length<1: if character_length<1:
raise ValidationError(f"'name' argument should have at least one character") raise ValidationError({"name":f"'name' argument should have at least one character"})
elif character_length>=64: elif character_length>=64:
raise ValidationError(f"'name' argument should have at max. 63 characters") raise ValidationError({"name":f"'name' argument should have at max. 63 characters"})
if check_if_string_has_special_characters(value): if check_if_string_has_special_characters(value):
raise ValidationError(f"'name' argument should not have special characters.") raise ValidationError({"name":f"'name' argument should not have special characters."})
return return
@validates("imo") @validates("imo")
@ -578,7 +578,7 @@ class ShipSchema(Schema):
value = str(value).zfill(7) # 1 becomes '0000001' (7 characters). 12345678 becomes '12345678' (8 characters) value = str(value).zfill(7) # 1 becomes '0000001' (7 characters). 12345678 becomes '12345678' (8 characters)
imo_length = len(value) imo_length = len(value)
if imo_length != 7: if imo_length != 7:
raise ValidationError(f"'imo' should be a 7-digit number") raise ValidationError({"imo":f"'imo' should be a 7-digit number"})
return return
@validates("callsign") @validates("callsign")
@ -586,10 +586,10 @@ class ShipSchema(Schema):
if value is not None: if value is not None:
callsign_length = len(str(value)) callsign_length = len(str(value))
if callsign_length>8: if callsign_length>8:
raise ValidationError(f"'callsign' argument should not have more than 8 characters") raise ValidationError({"callsign":f"'callsign' argument should not have more than 8 characters"})
if check_if_string_has_special_characters(value): if check_if_string_has_special_characters(value):
raise ValidationError(f"'callsign' argument should not have special characters.") raise ValidationError({"callsign":f"'callsign' argument should not have special characters."})
return return

View File

@ -35,24 +35,24 @@ def validate_posted_shipcall_data(user_data:dict, loadedModel:dict, content:dict
# as ParticipantType is an IntFlag, a user belonging to multiple groups is properly evaluated. # as ParticipantType is an IntFlag, a user belonging to multiple groups is properly evaluated.
is_bsmd = check_if_user_is_bsmd_type(user_data) is_bsmd = check_if_user_is_bsmd_type(user_data)
if not is_bsmd: if not is_bsmd:
raise ValidationError(f"current user does not belong to BSMD. Cannot post shipcalls. Found user data: {user_data}") raise ValidationError({"user_participant_type":f"current user does not belong to BSMD. Cannot post shipcalls. Found user data: {user_data}"})
##### Section 2: check loadedModel ##### ##### Section 2: check loadedModel #####
valid_ship_id = check_if_ship_id_is_valid(ship_id=loadedModel.get("ship_id", None)) valid_ship_id = check_if_ship_id_is_valid(ship_id=loadedModel.get("ship_id", None))
if not valid_ship_id: if not valid_ship_id:
raise ValidationError(f"provided an invalid ship id, which is not found in the database: {loadedModel.get('ship_id', None)}") raise ValidationError({"ship_id":f"provided an invalid ship id, which is not found in the database: {loadedModel.get('ship_id', None)}"})
valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=loadedModel.get("arrival_berth_id", None)) valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=loadedModel.get("arrival_berth_id", None))
if not valid_arrival_berth_id: if not valid_arrival_berth_id:
raise ValidationError(f"provided an invalid arrival berth id, which is not found in the database: {loadedModel.get('arrival_berth_id', None)}") raise ValidationError({"arrival_berth_id":f"provided an invalid arrival berth id, which is not found in the database: {loadedModel.get('arrival_berth_id', None)}"})
valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=loadedModel.get("departure_berth_id", None)) valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=loadedModel.get("departure_berth_id", None))
if not valid_departure_berth_id: if not valid_departure_berth_id:
raise ValidationError(f"provided an invalid departure berth id, which is not found in the database: {loadedModel.get('departure_berth_id', None)}") raise ValidationError({"departure_berth_id":f"provided an invalid departure berth id, which is not found in the database: {loadedModel.get('departure_berth_id', None)}"})
valid_participant_ids = check_if_participant_ids_are_valid(participants=loadedModel.get("participants",[])) valid_participant_ids = check_if_participant_ids_are_valid(participants=loadedModel.get("participants",[]))
if not valid_participant_ids: if not valid_participant_ids:
raise ValidationError(f"one of the provided participant ids is invalid. Could not find one of these in the database: {loadedModel.get('participants', None)}") raise ValidationError({"participants":f"one of the provided participant ids is invalid. Could not find one of these in the database: {loadedModel.get('participants', None)}"})
##### Section 3: check content ##### ##### Section 3: check content #####
@ -62,11 +62,11 @@ def validate_posted_shipcall_data(user_data:dict, loadedModel:dict, content:dict
for forbidden_key in ["canceled", "evaluation", "evaluation_message"]: for forbidden_key in ["canceled", "evaluation", "evaluation_message"]:
value = content.get(forbidden_key, None) value = content.get(forbidden_key, None)
if value is not None: if value is not None:
raise ValidationError(f"'{forbidden_key}' may not be set on POST. Found: {value}") raise ValidationError({"forbidden_key":f"'{forbidden_key}' may not be set on POST. Found: {value}"})
voyage_str_is_invalid = check_if_string_has_special_characters(text=content.get("voyage","")) voyage_str_is_invalid = check_if_string_has_special_characters(text=content.get("voyage",""))
if voyage_str_is_invalid: if voyage_str_is_invalid:
raise ValidationError(f"there are invalid characters in the 'voyage'-string. Please use only digits and ASCII letters. Allowed: {ascii_letters+digits}. Found: {content.get('voyage')}") raise ValidationError({"voyage":f"there are invalid characters in the 'voyage'-string. Please use only digits and ASCII letters. Allowed: {ascii_letters+digits}. Found: {content.get('voyage')}"})
##### Section 4: check loadedModel & content ##### ##### Section 4: check loadedModel & content #####
@ -77,43 +77,43 @@ def validate_posted_shipcall_data(user_data:dict, loadedModel:dict, content:dict
time_now = datetime.datetime.now() time_now = datetime.datetime.now()
type_ = loadedModel.get("type", int(ShipcallType.undefined)) type_ = loadedModel.get("type", int(ShipcallType.undefined))
if int(type_)==int(ShipcallType.undefined): if int(type_)==int(ShipcallType.undefined):
raise ValidationError(f"providing 'type' is mandatory. Missing key!") raise ValidationError({"type":f"providing 'type' is mandatory. Missing key!"})
elif int(type_)==int(ShipcallType.arrival): elif int(type_)==int(ShipcallType.arrival):
eta = loadedModel.get("eta") eta = loadedModel.get("eta")
if (content.get("eta", None) is None): if (content.get("eta", None) is None):
raise ValidationError(f"providing 'eta' is mandatory. Missing key!") raise ValidationError({"eta":f"providing 'eta' is mandatory. Missing key!"})
if content.get("arrival_berth_id", None) is None: if content.get("arrival_berth_id", None) is None:
raise ValidationError(f"providing 'arrival_berth_id' is mandatory. Missing key!") raise ValidationError({"arrival_berth_id":f"providing 'arrival_berth_id' is mandatory. Missing key!"})
if not eta >= time_now: if not eta >= time_now:
raise ValidationError(f"'eta' must be in the future. Incorrect datetime provided.") raise ValidationError({"eta":f"'eta' must be in the future. Incorrect datetime provided."})
elif int(type_)==int(ShipcallType.departure): elif int(type_)==int(ShipcallType.departure):
etd = loadedModel.get("etd") etd = loadedModel.get("etd")
if (content.get("etd", None) is None): if (content.get("etd", None) is None):
raise ValidationError(f"providing 'etd' is mandatory. Missing key!") raise ValidationError({"etd":f"providing 'etd' is mandatory. Missing key!"})
if content.get("departure_berth_id", None) is None: if content.get("departure_berth_id", None) is None:
raise ValidationError(f"providing 'departure_berth_id' is mandatory. Missing key!") raise ValidationError({"departure_berth_id":f"providing 'departure_berth_id' is mandatory. Missing key!"})
if not etd >= time_now: if not etd >= time_now:
raise ValidationError(f"'etd' must be in the future. Incorrect datetime provided.") raise ValidationError({"etd":f"'etd' must be in the future. Incorrect datetime provided."})
elif int(type_)==int(ShipcallType.shifting): elif int(type_)==int(ShipcallType.shifting):
eta = loadedModel.get("eta") eta = loadedModel.get("eta")
etd = loadedModel.get("etd") etd = loadedModel.get("etd")
# * arrival_berth_id / departure_berth_id (depending on type, see above) # * arrival_berth_id / departure_berth_id (depending on type, see above)
if (content.get("eta", None) is None) or (content.get("etd", None) is None): if (content.get("eta", None) is None) or (content.get("etd", None) is None):
raise ValidationError(f"providing 'eta' and 'etd' is mandatory. Missing one of those keys!") raise ValidationError({"eta_or_etd":f"providing 'eta' and 'etd' is mandatory. Missing one of those keys!"})
if (content.get("arrival_berth_id", None) is None) or (content.get("departure_berth_id", None) is None): if (content.get("arrival_berth_id", None) is None) or (content.get("departure_berth_id", None) is None):
raise ValidationError(f"providing 'arrival_berth_id' & 'departure_berth_id' is mandatory. Missing key!") raise ValidationError({"arrival_berth_id_or_departure_berth_id":f"providing 'arrival_berth_id' & 'departure_berth_id' is mandatory. Missing key!"})
if (not eta >= time_now) or (not etd >= time_now) or (not eta >= etd): if (not eta >= time_now) or (not etd >= time_now) or (not eta >= etd):
raise ValidationError(f"'eta' and 'etd' must be in the future. Incorrect datetime provided.") raise ValidationError({"eta_or_etd":f"'eta' and 'etd' must be in the future. Incorrect datetime provided."})
tidal_window_from = loadedModel.get("tidal_window_from", None) tidal_window_from = loadedModel.get("tidal_window_from", None)
tidal_window_to = loadedModel.get("tidal_window_to", None) tidal_window_to = loadedModel.get("tidal_window_to", None)
if tidal_window_to is not None: if tidal_window_to is not None:
if not tidal_window_to >= time_now: if not tidal_window_to >= time_now:
raise ValidationError(f"'tidal_window_to' must be in the future. Incorrect datetime provided.") raise ValidationError({"tidal_window_to":f"'tidal_window_to' must be in the future. Incorrect datetime provided."})
if tidal_window_from is not None: if tidal_window_from is not None:
if not tidal_window_from >= time_now: if not tidal_window_from >= time_now:
raise ValidationError(f"'tidal_window_from' must be in the future. Incorrect datetime provided.") raise ValidationError({"tidal_window_from":f"'tidal_window_from' must be in the future. Incorrect datetime provided."})
# #TODO: assert tidal_window_from > tidal_window_to # #TODO: assert tidal_window_from > tidal_window_to

View File

@ -75,16 +75,16 @@ class InputValidationShip():
if bollard_pull is not None: if bollard_pull is not None:
if not is_tug: if not is_tug:
raise ValidationError(f"'bollard_pull' is only allowed, when a ship is a tug ('is_tug').") raise ValidationError({"bollard_pull":f"'bollard_pull' is only allowed, when a ship is a tug ('is_tug')."})
if (not (0 < bollard_pull < 500)) & (is_tug): if (not (0 < bollard_pull < 500)) & (is_tug):
raise ValidationError(f"when a ship is a tug, the bollard pull must be 0 < value < 500. ") raise ValidationError({"bollard_pull":f"when a ship is a tug, the bollard pull must be 0 < value < 500. "})
@staticmethod @staticmethod
def check_user_is_bsmd_type(user_data:dict): def check_user_is_bsmd_type(user_data:dict):
is_bsmd = check_if_user_is_bsmd_type(user_data) is_bsmd = check_if_user_is_bsmd_type(user_data)
if not is_bsmd: if not is_bsmd:
raise ValidationError(f"current user does not belong to BSMD. Cannot post, put or delete ships. Found user data: {user_data}") raise ValidationError({"participant_type":f"current user does not belong to BSMD. Cannot post, put or delete ships. Found user data: {user_data}"})
@staticmethod @staticmethod
def check_ship_imo_already_exists(loadedModel:dict): def check_ship_imo_already_exists(loadedModel:dict):
@ -98,7 +98,7 @@ class InputValidationShip():
# check, if the imo in the POST-request already exists in the list # check, if the imo in the POST-request already exists in the list
imo_already_exists = loadedModel.get("imo") in ship_imos imo_already_exists = loadedModel.get("imo") in ship_imos
if imo_already_exists: if imo_already_exists:
raise ValidationError(f"the provided ship IMO {loadedModel.get('imo')} already exists. A ship may only be added, if there is no other ship with the same IMO number.") raise ValidationError({"imo":f"the provided ship IMO {loadedModel.get('imo')} already exists. A ship may only be added, if there is no other ship with the same IMO number."})
return return
@staticmethod @staticmethod
@ -112,14 +112,14 @@ class InputValidationShip():
ship = execute_sql_query_standalone(SQLQuery.get_ship_by_id(), param={"id":content.get("id")}, command_type="single", model=Ship) ship = execute_sql_query_standalone(SQLQuery.get_ship_by_id(), param={"id":content.get("id")}, command_type="single", model=Ship)
if put_data_ship_imo != ship.imo: if put_data_ship_imo != ship.imo:
raise ValidationError(f"The IMO number field may not be changed since it serves the purpose of a primary (matching) key.") raise ValidationError({"imo":f"The IMO number field may not be changed since it serves the purpose of a primary (matching) key."})
return return
@staticmethod @staticmethod
def content_contains_ship_id(content:dict): def content_contains_ship_id(content:dict):
put_data_ship_id = content.get('id',None) put_data_ship_id = content.get('id',None)
if put_data_ship_id is None: if put_data_ship_id is None:
raise ValidationError(f"The id field is required.") raise ValidationError({"id":f"The id field is required."})
return return
@staticmethod @staticmethod
@ -130,19 +130,19 @@ class InputValidationShip():
database entry may not have a deletion state already. database entry may not have a deletion state already.
""" """
if ship_id is None: if ship_id is None:
raise ValidationError(f"The ship_id must be provided.") raise ValidationError({"id":f"The ship id must be provided."})
response, status_code, header = GetShips(token=None) response, status_code, header = GetShips(token=None)
ships = json.loads(response) ships = json.loads(response)
existing_database_entries = [ship for ship in ships if ship.get("id")==ship_id] existing_database_entries = [ship for ship in ships if ship.get("id")==ship_id]
if len(existing_database_entries)==0: if len(existing_database_entries)==0:
raise ValidationError(f"Could not find a ship with the specified ID. Selected: {ship_id}") raise ValidationError({"id":f"Could not find a ship with the specified ID. Selected: {ship_id}"})
existing_database_entry = existing_database_entries[0] existing_database_entry = existing_database_entries[0]
deletion_state = existing_database_entry.get("deleted",None) deletion_state = existing_database_entry.get("deleted",None)
if deletion_state: if deletion_state:
raise ValidationError(f"The selected ship entry is already deleted.") raise ValidationError({"deleted":f"The selected ship entry is already deleted."})
return return

View File

@ -113,12 +113,12 @@ class InputValidationShipcall():
# voyage shall not contain special characters # voyage shall not contain special characters
voyage_str_is_invalid = check_if_string_has_special_characters(text=content.get("voyage","")) voyage_str_is_invalid = check_if_string_has_special_characters(text=content.get("voyage",""))
if voyage_str_is_invalid: if voyage_str_is_invalid:
raise ValidationError(f"there are invalid characters in the 'voyage'-string. Please use only digits and ASCII letters. Allowed: {ascii_letters+digits}. Found: {content.get('voyage')}") raise ValidationError({"voyage":f"there are invalid characters in the 'voyage'-string. Please use only digits and ASCII letters. Allowed: {ascii_letters+digits}. Found: {content.get('voyage')}"})
# the 'flags' integer must be valid # the 'flags' integer must be valid
flags_value = content.get("flags", 0) flags_value = content.get("flags", 0)
if check_if_int_is_valid_flag(flags_value, enum_object=ParticipantFlag): if check_if_int_is_valid_flag(flags_value, enum_object=ParticipantFlag):
raise ValidationError(f"incorrect value provided for 'flags'. Must be a valid combination of the flags.") raise ValidationError({"flags":f"incorrect value provided for 'flags'. Must be a valid combination of the flags."})
# time values must use future-dates # time values must use future-dates
InputValidationShipcall.check_times_are_in_future(loadedModel, content) InputValidationShipcall.check_times_are_in_future(loadedModel, content)
@ -212,7 +212,7 @@ class InputValidationShipcall():
is_bsmd_or_agency = (is_bsmd) or (is_agency) is_bsmd_or_agency = (is_bsmd) or (is_agency)
if not is_bsmd_or_agency: if not is_bsmd_or_agency:
raise ValidationError(f"current user must be either of participant type BSMD or AGENCY. Cannot post or put shipcalls. Found user data: {user_data} and participant_type: {participant_type}") raise ValidationError({"participant_type":f"current user must be either of participant type BSMD or AGENCY. Cannot post or put shipcalls. Found user data: {user_data} and participant_type: {participant_type}"})
return return
@staticmethod @staticmethod
@ -232,23 +232,23 @@ class InputValidationShipcall():
valid_ship_id = check_if_ship_id_is_valid(ship_id=ship_id) valid_ship_id = check_if_ship_id_is_valid(ship_id=ship_id)
if not valid_ship_id: if not valid_ship_id:
raise ValidationError(f"provided an invalid ship id, which is not found in the database: {ship_id}") raise ValidationError({"ship_id":f"provided an invalid ship id, which is not found in the database: {ship_id}"})
valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=arrival_berth_id) valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=arrival_berth_id)
if not valid_arrival_berth_id: if not valid_arrival_berth_id:
raise ValidationError(f"provided an invalid arrival berth id, which is not found in the database: {arrival_berth_id}") raise ValidationError({"arrival_berth_id":f"provided an invalid arrival berth id, which is not found in the database: {arrival_berth_id}"})
valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=departure_berth_id) valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=departure_berth_id)
if not valid_departure_berth_id: if not valid_departure_berth_id:
raise ValidationError(f"provided an invalid departure berth id, which is not found in the database: {departure_berth_id}") raise ValidationError({"departure_berth_id":f"provided an invalid departure berth id, which is not found in the database: {departure_berth_id}"})
valid_participant_ids = check_if_participant_ids_are_valid(participants=participants) valid_participant_ids = check_if_participant_ids_are_valid(participants=participants)
if not valid_participant_ids: if not valid_participant_ids:
raise ValidationError(f"one of the provided participant ids is invalid. Could not find one of these in the database: {participants}") raise ValidationError({"participants":f"one of the provided participant ids is invalid. Could not find one of these in the database: {participants}"})
valid_participant_types = check_if_participant_ids_and_types_are_valid(participants=participants) valid_participant_types = check_if_participant_ids_and_types_are_valid(participants=participants)
if not valid_participant_types: # #TODO: according to Daniel, there may eventually be multi-assignment of participants for the same role if not valid_participant_types: # #TODO: according to Daniel, there may eventually be multi-assignment of participants for the same role
raise ValidationError(f"every participant id and type should be listed only once. Found multiple entries for one of the participants.") raise ValidationError({"participants":f"every participant id and type should be listed only once. Found multiple entries for one of the participants."})
@staticmethod @staticmethod
def check_shipcall_type_is_unchanged(loadedModel:dict): def check_shipcall_type_is_unchanged(loadedModel:dict):
@ -257,7 +257,7 @@ class InputValidationShipcall():
shipcall = execute_sql_query_standalone(query=query, model=Shipcall, param={"id":loadedModel.get("id")}, command_type="single") shipcall = execute_sql_query_standalone(query=query, model=Shipcall, param={"id":loadedModel.get("id")}, command_type="single")
if int(loadedModel["type"]) != int(shipcall.type): if int(loadedModel["type"]) != int(shipcall.type):
raise ValidationError(f"The shipcall type may only be set in the initial POST-request. Afterwards, changing the shipcall type is not allowed.") # @pytest.raises raise ValidationError({"type":f"The shipcall type may only be set in the initial POST-request. Afterwards, changing the shipcall type is not allowed."}) # @pytest.raises
return return
@staticmethod @staticmethod
@ -271,7 +271,7 @@ class InputValidationShipcall():
for forbidden_key in forbidden_keys: for forbidden_key in forbidden_keys:
value = content.get(forbidden_key, None) value = content.get(forbidden_key, None)
if value is not None: if value is not None:
raise ValidationError(f"'{forbidden_key}' may not be set on POST. Found: {value}") raise ValidationError({"forbidden_key":f"'{forbidden_key}' may not be set on POST. Found: {value}"})
return return
@staticmethod @staticmethod
@ -287,36 +287,36 @@ class InputValidationShipcall():
departure_berth_id = content.get("departure_berth_id", None) departure_berth_id = content.get("departure_berth_id", None)
if ship_id is None: if ship_id is None:
raise ValidationError(f"providing 'ship_id' is mandatory. Missing key!") raise ValidationError({"ship_id":f"providing 'ship_id' is mandatory. Missing key!"})
if int(type_)==int(ShipcallType.undefined): if int(type_)==int(ShipcallType.undefined):
raise ValidationError(f"providing 'type' is mandatory. Missing key!") raise ValidationError({"type":f"providing 'type' is mandatory. Missing key!"})
# arrival: arrival_berth_id & eta must exist # arrival: arrival_berth_id & eta must exist
elif int(type_)==int(ShipcallType.arrival): elif int(type_)==int(ShipcallType.arrival):
if eta is None: if eta is None:
raise ValidationError(f"providing 'eta' is mandatory. Missing key!") raise ValidationError({"eta":f"providing 'eta' is mandatory. Missing key!"})
if arrival_berth_id is None: if arrival_berth_id is None:
raise ValidationError(f"providing 'arrival_berth_id' is mandatory. Missing key!") raise ValidationError({"arrival_berth_id":f"providing 'arrival_berth_id' is mandatory. Missing key!"})
# departure: departive_berth_id and etd must exist # departure: departive_berth_id and etd must exist
elif int(type_)==int(ShipcallType.departure): elif int(type_)==int(ShipcallType.departure):
if etd is None: if etd is None:
raise ValidationError(f"providing 'etd' is mandatory. Missing key!") raise ValidationError({"etd":f"providing 'etd' is mandatory. Missing key!"})
if departure_berth_id is None: if departure_berth_id is None:
raise ValidationError(f"providing 'departure_berth_id' is mandatory. Missing key!") raise ValidationError({"departure_berth_id":f"providing 'departure_berth_id' is mandatory. Missing key!"})
# shifting: arrival_berth_id, departure_berth_id, eta and etd must exist # shifting: arrival_berth_id, departure_berth_id, eta and etd must exist
elif int(type_)==int(ShipcallType.shifting): elif int(type_)==int(ShipcallType.shifting):
if (eta is None) or (etd is None): if (eta is None) or (etd is None):
raise ValidationError(f"providing 'eta' and 'etd' is mandatory. Missing one of those keys!") raise ValidationError({"eta_or_etd":f"providing 'eta' and 'etd' is mandatory. Missing one of those keys!"})
if (arrival_berth_id is None) or (departure_berth_id is None): if (arrival_berth_id is None) or (departure_berth_id is None):
raise ValidationError(f"providing 'arrival_berth_id' & 'departure_berth_id' is mandatory. Missing key!") raise ValidationError({"arrival_berth_id_or_departure_berth_id":f"providing 'arrival_berth_id' & 'departure_berth_id' is mandatory. Missing key!"})
else: else:
raise ValidationError(f"incorrect 'type' provided!") raise ValidationError({"type":f"incorrect 'type' provided!"})
return return
@staticmethod @staticmethod
@ -363,32 +363,32 @@ class InputValidationShipcall():
return return
if type_ is None: if type_ is None:
raise ValidationError(f"when providing 'eta' or 'etd', one must provide the type of the shipcall, so the datetimes can be verified.") raise ValidationError({"type":f"when providing 'eta' or 'etd', one must provide the type of the shipcall, so the datetimes can be verified."})
if not isinstance(type_, (int, ShipcallType)): if not isinstance(type_, (int, ShipcallType)):
type_ = ShipcallType[type_] type_ = ShipcallType[type_]
# #TODO: properly handle what happens, when eta or etd (or both) are None # #TODO: properly handle what happens, when eta or etd (or both) are None
if int(type_)==int(ShipcallType.undefined): if int(type_)==int(ShipcallType.undefined):
raise ValidationError(f"providing 'type' is mandatory. Missing key!") raise ValidationError({"type":f"providing 'type' is mandatory. Missing key!"})
elif int(type_)==int(ShipcallType.arrival): elif int(type_)==int(ShipcallType.arrival):
if eta is None: # null values -> no violation if eta is None: # null values -> no violation
return return
if not eta > time_now: if not eta > time_now:
raise ValidationError(f"'eta' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETA: {eta}.") raise ValidationError({"eta":f"'eta' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETA: {eta}."})
if etd is not None: if etd is not None:
raise ValidationError(f"'etd' should not be set when the shipcall type is 'arrival'.") raise ValidationError({"etd":f"'etd' should not be set when the shipcall type is 'arrival'."})
elif int(type_)==int(ShipcallType.departure): elif int(type_)==int(ShipcallType.departure):
if etd is None: # null values -> no violation if etd is None: # null values -> no violation
return return
if not etd > time_now: if not etd > time_now:
raise ValidationError(f"'etd' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETD: {etd}.") raise ValidationError({"etd":f"'etd' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETD: {etd}."})
if eta is not None: if eta is not None:
raise ValidationError(f"'eta' should not be set when the shipcall type is 'departure'.") raise ValidationError({"eta":f"'eta' should not be set when the shipcall type is 'departure'."})
elif int(type_)==int(ShipcallType.shifting): elif int(type_)==int(ShipcallType.shifting):
if (eta is None) and (etd is None): # null values -> no violation if (eta is None) and (etd is None): # null values -> no violation
@ -397,30 +397,30 @@ class InputValidationShipcall():
if not ((eta is not None) and (etd is not None)): if not ((eta is not None) and (etd is not None)):
# for PUT-requests, a user could try modifying only 'eta' or only 'etd'. To simplify the # for PUT-requests, a user could try modifying only 'eta' or only 'etd'. To simplify the
# rules, a user is only allowed to provide *both* values. # rules, a user is only allowed to provide *both* values.
raise ValidationError(f"For shifting shipcalls one should always provide, both, eta and etd.") raise ValidationError({"eta_or_etd":f"For shifting shipcalls one should always provide, both, eta and etd."})
if (not eta > time_now) or (not etd > time_now): if (not eta > time_now) or (not etd > time_now):
raise ValidationError(f"'eta' and 'etd' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETA: {eta}. ETD: {etd}") raise ValidationError({"eta_or_etd":f"'eta' and 'etd' must be in the future. Incorrect datetime provided. Current Time: {time_now}. ETA: {eta}. ETD: {etd}"})
if (not etd < eta): if (not etd < eta):
raise ValidationError(f"The estimated time of departure ('etd') must take place *before the estimated time of arrival ('eta'). The ship cannot arrive, before it has departed. Found: ETD: {etd}, ETA: {eta}") raise ValidationError({"eta_or_etd":f"The estimated time of departure ('etd') must take place *before the estimated time of arrival ('eta'). The ship cannot arrive, before it has departed. Found: ETD: {etd}, ETA: {eta}"})
if (eta is not None and etd is None) or (eta is None and etd is not None): if (eta is not None and etd is None) or (eta is None and etd is not None):
raise ValidationError(f"'eta' and 'etd' must both be provided when the shipcall type is 'shifting'.") raise ValidationError({"eta_or_etd":f"'eta' and 'etd' must both be provided when the shipcall type is 'shifting'."})
return return
@staticmethod @staticmethod
def check_tidal_window_in_future(type_, time_now, tidal_window_from, tidal_window_to): def check_tidal_window_in_future(type_, time_now, tidal_window_from, tidal_window_to):
if tidal_window_to is not None: if tidal_window_to is not None:
if not tidal_window_to >= time_now: if not tidal_window_to >= time_now:
raise ValidationError(f"'tidal_window_to' must be in the future. Incorrect datetime provided.") raise ValidationError({"tidal_window_to":f"'tidal_window_to' must be in the future. Incorrect datetime provided."})
if tidal_window_from is not None: if tidal_window_from is not None:
if not tidal_window_from >= time_now: if not tidal_window_from >= time_now:
raise ValidationError(f"'tidal_window_from' must be in the future. Incorrect datetime provided.") raise ValidationError({"tidal_window_from":f"'tidal_window_from' must be in the future. Incorrect datetime provided."})
if (tidal_window_to is not None) and (tidal_window_from is not None): if (tidal_window_to is not None) and (tidal_window_from is not None):
if tidal_window_to < tidal_window_from: if tidal_window_to < tidal_window_from:
raise ValidationError(f"'tidal_window_to' must take place after 'tidal_window_from'. Incorrect datetime provided. Found 'tidal_window_to': {tidal_window_to}, 'tidal_window_from': {tidal_window_to}.") raise ValidationError({"tidal_window_to_or_tidal_window_from":f"'tidal_window_to' must take place after 'tidal_window_from'. Incorrect datetime provided. Found 'tidal_window_to': {tidal_window_to}, 'tidal_window_from': {tidal_window_to}."})
return return
@staticmethod @staticmethod
@ -432,7 +432,7 @@ class InputValidationShipcall():
is_agency_participant = [ParticipantType.AGENCY in ParticipantType(participant.get("type")) for participant in participants] is_agency_participant = [ParticipantType.AGENCY in ParticipantType(participant.get("type")) for participant in participants]
if not any(is_agency_participant): if not any(is_agency_participant):
raise ValidationError(f"One of the assigned participants *must* be of type 'ParticipantType.AGENCY'. Found list of participants: {participants}") raise ValidationError({"participants":f"One of the assigned participants *must* be of type 'ParticipantType.AGENCY'. Found list of participants: {participants}"})
return return
@staticmethod @staticmethod
@ -448,14 +448,14 @@ class InputValidationShipcall():
# if the *existing* shipcall in the database is canceled, it may not be changed # if the *existing* shipcall in the database is canceled, it may not be changed
if shipcall.get("canceled", False): if shipcall.get("canceled", False):
raise ValidationError(f"The shipcall with id 'shipcall_id' is canceled. A canceled shipcall may not be changed.") raise ValidationError({"canceled":f"The shipcall with id 'shipcall_id' is canceled. A canceled shipcall may not be changed."})
return return
@staticmethod @staticmethod
def check_required_fields_of_put_request(content:dict): def check_required_fields_of_put_request(content:dict):
shipcall_id = content.get("id", None) shipcall_id = content.get("id", None)
if shipcall_id is None: if shipcall_id is None:
raise ValidationError(f"A PUT request requires an 'id' to refer to.") raise ValidationError({"id":f"A PUT request requires an 'id' to refer to."})
@staticmethod @staticmethod
def check_shipcall_id_exists(loadedModel): def check_shipcall_id_exists(loadedModel):
@ -464,7 +464,7 @@ class InputValidationShipcall():
query = 'SELECT * FROM shipcall where (id = ?shipcall_id?)' query = 'SELECT * FROM shipcall where (id = ?shipcall_id?)'
shipcalls = execute_sql_query_standalone(query=query, model=Shipcall, param={"shipcall_id" : shipcall_id}) shipcalls = execute_sql_query_standalone(query=query, model=Shipcall, param={"shipcall_id" : shipcall_id})
if len(shipcalls)==0: if len(shipcalls)==0:
raise ValidationError(f"unknown shipcall_id. There are no shipcalls with the ID {shipcall_id}") raise ValidationError({"id":f"unknown shipcall_id. There are no shipcalls with the ID {shipcall_id}"})
return return
@staticmethod @staticmethod
@ -497,7 +497,7 @@ class InputValidationShipcall():
an_agency_is_assigned = len(assigned_agency)==1 an_agency_is_assigned = len(assigned_agency)==1
if len(assigned_agency)>1: if len(assigned_agency)>1:
raise ValidationError(f"Internal error? Found more than one assigned agency for the shipcall with ID {shipcall_id}. Found: {assigned_agency}") raise ValidationError({"internal_error":f"Internal error? Found more than one assigned agency for the shipcall with ID {shipcall_id}. Found: {assigned_agency}"})
if an_agency_is_assigned: if an_agency_is_assigned:
# Agency assigned? User must belong to the assigned agency or be a BSMD user, in case the flag is set # Agency assigned? User must belong to the assigned agency or be a BSMD user, in case the flag is set

View File

@ -137,7 +137,7 @@ class InputValidationTimes():
pdata = execute_sql_query_standalone(query=query, param={"id":times_id}, pooledConnection=None) pdata = execute_sql_query_standalone(query=query, param={"id":times_id}, pooledConnection=None)
if len(pdata)==0: if len(pdata)==0:
raise ValidationError(f"The selected time entry is already deleted. ID: {times_id}") raise ValidationError({"deleted":f"The selected time entry is already deleted. ID: {times_id}"})
return return
@staticmethod @staticmethod
@ -145,7 +145,7 @@ class InputValidationTimes():
"""a new dataset may only be created by a user who is *not* belonging to participant group BSMD""" """a new dataset may only be created by a user who is *not* belonging to participant group BSMD"""
is_bsmd = check_if_user_is_bsmd_type(user_data) is_bsmd = check_if_user_is_bsmd_type(user_data)
if is_bsmd: if is_bsmd:
raise ValidationError(f"current user belongs to BSMD. Cannot post 'times' datasets. Found user data: {user_data}") raise ValidationError({"participant_type":f"current user belongs to BSMD. Cannot post 'times' datasets. Found user data: {user_data}"})
return return
@staticmethod @staticmethod
@ -166,18 +166,18 @@ class InputValidationTimes():
loadedModel["participant_type"] = ParticipantType(loadedModel["participant_type"]) loadedModel["participant_type"] = ParticipantType(loadedModel["participant_type"])
if ParticipantType.BSMD in loadedModel["participant_type"]: if ParticipantType.BSMD in loadedModel["participant_type"]:
raise ValidationError(f"current user belongs to BSMD. Cannot post times datasets. Found user data: {user_data}") raise ValidationError({"participant_type":f"current user belongs to BSMD. Cannot post times datasets. Found user data: {user_data}"})
if (loadedModel["etd_interval_end"] is not None) and (loadedModel["etd_berth"] is not None): if (loadedModel["etd_interval_end"] is not None) and (loadedModel["etd_berth"] is not None):
time_end_after_time_start = loadedModel["etd_interval_end"] >= loadedModel["etd_berth"] time_end_after_time_start = loadedModel["etd_interval_end"] >= loadedModel["etd_berth"]
if not time_end_after_time_start: if not time_end_after_time_start:
raise ValidationError(f"The provided time interval for the estimated departure time is invalid. The interval end takes place before the interval start. Found interval data: {loadedModel['etd_berth']} to {loadedModel['etd_interval_end']}") raise ValidationError({"etd":f"The provided time interval for the estimated departure time is invalid. The interval end takes place before the interval start. Found interval data: {loadedModel['etd_berth']} to {loadedModel['etd_interval_end']}"})
if (loadedModel["eta_interval_end"] is not None) and (loadedModel["eta_berth"] is not None): if (loadedModel["eta_interval_end"] is not None) and (loadedModel["eta_berth"] is not None):
time_end_after_time_start = loadedModel["eta_interval_end"] >= loadedModel["eta_berth"] time_end_after_time_start = loadedModel["eta_interval_end"] >= loadedModel["eta_berth"]
if not time_end_after_time_start: if not time_end_after_time_start:
raise ValidationError(f"The provided time interval for the estimated arrival time is invalid. The interval begin takes place after the interval end. Found interval data: {loadedModel['eta_berth']} to {loadedModel['eta_interval_end']}") raise ValidationError({"eta":f"The provided time interval for the estimated arrival time is invalid. The interval begin takes place after the interval end. Found interval data: {loadedModel['eta_berth']} to {loadedModel['eta_interval_end']}"})
return return
@staticmethod @staticmethod
@ -189,19 +189,19 @@ class InputValidationTimes():
Note: whenever an ID is 'None', there is no exception, because a different method is supposed to capture non-existant mandatory fields. Note: whenever an ID is 'None', there is no exception, because a different method is supposed to capture non-existant mandatory fields.
""" """
# extract the IDs # extract the IDs
berth_id, participant_id, shipcall_id = content.get("berth_id"), content.get("participant_id"), content.get("shipcall_id") berth_id, shipcall_id, participant_id = content.get("berth_id"), content.get("shipcall_id"), content.get("participant_id")
valid_berth_id_reference = check_if_berth_id_is_valid(berth_id) valid_berth_id_reference = check_if_berth_id_is_valid(berth_id)
if not valid_berth_id_reference: if not valid_berth_id_reference:
raise ValidationError(f"The referenced berth_id '{berth_id}' does not exist in the database.") raise ValidationError({"berth_id":f"The referenced berth_id '{berth_id}' does not exist in the database."})
valid_shipcall_id_reference = check_if_shipcall_id_is_valid(shipcall_id) valid_shipcall_id_reference = check_if_shipcall_id_is_valid(shipcall_id)
if not valid_shipcall_id_reference: if not valid_shipcall_id_reference:
raise ValidationError(f"The referenced shipcall_id '{shipcall_id}' does not exist in the database.") raise ValidationError({"shipcall_id":f"The referenced shipcall_id '{shipcall_id}' does not exist in the database."})
valid_participant_id_reference = check_if_participant_id_is_valid_standalone(participant_id, participant_type=None) valid_participant_id_reference = check_if_participant_id_is_valid_standalone(participant_id, participant_type=None)
if not valid_participant_id_reference: if not valid_participant_id_reference:
raise ValidationError(f"The referenced participant_id '{participant_id}' does not exist in the database.") raise ValidationError({"participant_id":f"The referenced participant_id '{participant_id}' does not exist in the database."})
return return
@ -223,7 +223,7 @@ class InputValidationTimes():
shipcall_type = ShipcallType[shipcalls.get(shipcall_id,{}).get("type",ShipcallType.undefined.name)] shipcall_type = ShipcallType[shipcalls.get(shipcall_id,{}).get("type",ShipcallType.undefined.name)]
if (participant_type is None) or (int(shipcall_type) == int(ShipcallType.undefined)): if (participant_type is None) or (int(shipcall_type) == int(ShipcallType.undefined)):
raise ValidationError(f"At least one of the required fields is missing. Missing: 'participant_type' or 'shipcall_type'") raise ValidationError({"required_fields":f"At least one of the required fields is missing. Missing: 'participant_type' or 'shipcall_type'"})
# build a list of required fields based on shipcall and participant type, as well as type-independent fields # build a list of required fields based on shipcall and participant type, as well as type-independent fields
@ -240,14 +240,14 @@ class InputValidationTimes():
if any(missing_required_fields): if any(missing_required_fields):
# create a tuple of (field_key, bool) to describe to a user, which one of the fields may be missing # create a tuple of (field_key, bool) to describe to a user, which one of the fields may be missing
verbosity_tuple = [(field, missing) for field, missing in zip(required_fields, missing_required_fields) if missing] verbosity_tuple = [(field, missing) for field, missing in zip(required_fields, missing_required_fields) if missing]
raise ValidationError(f"At least one of the required fields is missing. Missing: {verbosity_tuple}") raise ValidationError({"required_fields":f"At least one of the required fields is missing. Missing: {verbosity_tuple}"})
return return
@staticmethod @staticmethod
def check_times_required_fields_put_data(content:dict): def check_times_required_fields_put_data(content:dict):
"""in a PUT request, only the 'id' is a required field. All other fields are simply ignored, when they are not provided.""" """in a PUT request, only the 'id' is a required field. All other fields are simply ignored, when they are not provided."""
if content.get("id") is None: if content.get("id") is None:
raise ValidationError(f"A PUT-request requires an 'id' reference, which was not found.") raise ValidationError({"id":f"A PUT-request requires an 'id' reference, which was not found."})
return return
@staticmethod @staticmethod
@ -337,7 +337,7 @@ class InputValidationTimes():
] ]
if not len(matching_spm)>0: if not len(matching_spm)>0:
raise ValidationError(f'The participant group with id {user_participant_id} is not assigned to the shipcall. Found ShipcallParticipantMap: {spm_shipcall_data}') # part of a pytest.raises raise ValidationError({"participant_id":f'The participant group with id {user_participant_id} is not assigned to the shipcall. Found ShipcallParticipantMap: {spm_shipcall_data}'}) # part of a pytest.raises
return return
@staticmethod @staticmethod
@ -356,7 +356,7 @@ class InputValidationTimes():
# check, if there is already a dataset for the participant type # check, if there is already a dataset for the participant type
participant_type_exists_already = any([ParticipantType(time_.get("participant_type",0)) in participant_type for time_ in times]) participant_type_exists_already = any([ParticipantType(time_.get("participant_type",0)) in participant_type for time_ in times])
if participant_type_exists_already: if participant_type_exists_already:
raise ValidationError(f"A dataset for the participant type is already present. Participant Type: {participant_type}. Times Datasets: {times}") raise ValidationError({"participant_type":f"A dataset for the participant type is already present. Participant Type: {participant_type}. Times Datasets: {times}"})
return return
@staticmethod @staticmethod
@ -399,7 +399,7 @@ class InputValidationTimes():
# extracts the participant_id from the first matching entry, if applicable # extracts the participant_id from the first matching entry, if applicable
if not len(pdata)>0: if not len(pdata)>0:
# this case is usually covered by the InputValidationTimes.check_if_entry_is_already_deleted method already # this case is usually covered by the InputValidationTimes.check_if_entry_is_already_deleted method already
raise ValidationError(f"Unknown times_id. Could not find a matching entry for ID: {times_id}") raise ValidationError({"times_id":f"Unknown times_id. Could not find a matching entry for ID: {times_id}"})
else: else:
participant_type = pdata[0].get("participant_type") participant_type = pdata[0].get("participant_type")
shipcall_id = pdata[0].get("shipcall_id") shipcall_id = pdata[0].get("shipcall_id")
@ -415,14 +415,14 @@ class InputValidationTimes():
if special_case__bsmd_may_edit_agency_dataset: if special_case__bsmd_may_edit_agency_dataset:
return return
else: else:
raise ValidationError(f"The dataset may only be changed by a user belonging to the same participant group as the times dataset is referring to. User participant_id: {user_participant_id}; Dataset participant_id: {participant_id_of_times_dataset}") raise ValidationError({"user_participant_type":f"The dataset may only be changed by a user belonging to the same participant group as the times dataset is referring to. User participant_id: {user_participant_id}; Dataset participant_id: {participant_id_of_times_dataset}"})
return return
@staticmethod @staticmethod
def get_participant_id_from_shipcall_participant_map(shipcall_id:int, participant_type:int, spm_shipcall_data=None)->int: def get_participant_id_from_shipcall_participant_map(shipcall_id:int, participant_type:int, spm_shipcall_data=None)->int:
"""use shipcall_id and participant_type to identify the matching participant_id""" """use shipcall_id and participant_type to identify the matching participant_id"""
if shipcall_id is None: if shipcall_id is None:
raise ValidationError(f"Could not find a referenced shipcall_id within the request.") raise ValidationError({"shipcall_id":f"Could not find a referenced shipcall_id within the request."})
if spm_shipcall_data is None: if spm_shipcall_data is None:
spm_shipcall_data = execute_sql_query_standalone( spm_shipcall_data = execute_sql_query_standalone(
@ -432,7 +432,7 @@ class InputValidationTimes():
# raise an error when there are no matches # raise an error when there are no matches
if len(spm_shipcall_data)==0: if len(spm_shipcall_data)==0:
raise ValidationError(f"Could not find a matching time dataset for the provided participant_type: {participant_type} at shipcall with id {shipcall_id}.") raise ValidationError({"participant_type":f"Could not find a matching time dataset for the provided participant_type: {participant_type} at shipcall with id {shipcall_id}."})
participant_id_of_times_dataset = spm_shipcall_data[0].get("participant_id") participant_id_of_times_dataset = spm_shipcall_data[0].get("participant_id")
return participant_id_of_times_dataset return participant_id_of_times_dataset

View File

@ -158,7 +158,7 @@ def check_if_participant_id_is_valid_standalone(participant_id:int, participant_
if participant_type is not None: if participant_type is not None:
if participant_id not in list(participants.keys()): if participant_id not in list(participants.keys()):
raise ValidationError(f"the provided participant_id {participant_id} does not exist in the database.") raise ValidationError({"participant_id":f"the provided participant_id {participant_id} does not exist in the database."})
# IntFlag object # IntFlag object
participant_type_in_db = ParticipantType(int(participants.get(participant_id).get("type", ParticipantType.undefined))) participant_type_in_db = ParticipantType(int(participants.get(participant_id).get("type", ParticipantType.undefined)))

View File

@ -36,10 +36,10 @@ def validate_time_is_in_not_too_distant_future(raise_validation_error:bool, valu
if raise_validation_error: if raise_validation_error:
if not is_in_future: if not is_in_future:
raise ValidationError(f"The provided value must be in the future. Current Time: {datetime.datetime.now()}, Value: {value}") raise ValidationError({"any_date":f"The provided value must be in the future. Current Time: {datetime.datetime.now()}, Value: {value}"})
if is_too_distant: if is_too_distant:
raise ValidationError(f"The provided value is in the too distant future and exceeds a threshold for 'reasonable' entries. Found: {value}") raise ValidationError({"any_date":f"The provided value is in the too distant future and exceeds a threshold for 'reasonable' entries. Found: {value}"})
return is_in_future & (not is_too_distant) return is_in_future & (not is_too_distant)

View File

@ -11,8 +11,24 @@ def create_validation_error_response(ex:ValidationError, status_code:int=400)->t
# generate an overview the errors # generate an overview the errors
#example: #example:
# {'lock_time': ['The provided value must be in the future. Current Time: 2024-09-02 08:23:32.600791, Value: 2024-09-01 08:20:41.853000']} # {'lock_time': ['The provided value must be in the future. Current Time: 2024-09-02 08:23:32.600791, Value: 2024-09-01 08:20:41.853000']}
# when the model schema returns an error, 'messages' is by default a dictionary.
# e.g., loadedModel = model.TimesSchema().load(data=content, many=False, partial=True)
# returns: {'eta_berth': ['The provided value must be in the future}
# when raising a custom ValidationError, it can return a string, list or dict.
# we would like to ensure, that the content of the .messages is a dictionary. This can be accomplished by calling
# raise ValidationError({"example_key_which_fails":"the respective error message"})
errors = ex.messages errors = ex.messages
# raise ValidationError("example error")
# creates a .messages object, which is an array. e.g., ex.messages = ["example error"]
# the following conversion snipped ensures a dictionary output
if isinstance(errors, (str,list)):
errors = {"undefined_schema":errors}
# hence, errors always has the following type: dict[str, list[str]]
# example: # example:
# "Valid Data": { # "Valid Data": {
# "id": 2894, # "id": 2894,