121 lines
6.4 KiB
Python
121 lines
6.4 KiB
Python
from datetime import datetime
|
|
import re
|
|
from typing import List, Optional
|
|
from definitions.attribute import textAttribute, intAttribute, dateAttribute, selectAttribute
|
|
|
|
def _is_int(value) -> bool:
|
|
"""Check if a value is a valid integer."""
|
|
return isinstance(value, int)
|
|
|
|
def _is_date(value) -> bool:
|
|
"""Check if a value is a valid date in YYYY-MM-DD format."""
|
|
if not isinstance(value, str):
|
|
return False
|
|
try:
|
|
datetime.strptime(value, "%Y-%m-%d")
|
|
return True
|
|
except ValueError:
|
|
return False
|
|
|
|
def _validate_number(attrib: intAttribute) -> Optional[str]:
|
|
"""Validate number-specific attributes. Returns an error message if invalid, otherwise None."""
|
|
if attrib.min_val is not None and not _is_int(attrib.min_val):
|
|
return f"min_val must be an integer for attribute '{attrib.attrib_name}'."
|
|
if attrib.max_val is not None and not _is_int(attrib.max_val):
|
|
return f"max_val must be an integer for attribute '{attrib.attrib_name}'."
|
|
if attrib.min_val is not None and attrib.max_val is not None and attrib.min_val > attrib.max_val:
|
|
return f"min_val cannot be greater than max_val for attribute '{attrib.attrib_name}'."
|
|
if attrib.default_val is not None and not _is_int(attrib.default_val):
|
|
return f"default_val must be an integer for attribute '{attrib.attrib_name}'."
|
|
if attrib.default_val is not None:
|
|
if attrib.min_val is not None and attrib.default_val < attrib.min_val:
|
|
return f"default_val cannot be less than min_val for attribute '{attrib.attrib_name}'."
|
|
if attrib.max_val is not None and attrib.default_val > attrib.max_val:
|
|
return f"default_val cannot be greater than max_val for attribute '{attrib.attrib_name}'."
|
|
return None
|
|
|
|
def _validate_date(attrib: dateAttribute) -> Optional[str]:
|
|
"""Validate date-specific attributes. Returns an error message if invalid, otherwise None."""
|
|
if attrib.min_val is not None and not _is_date(attrib.min_val):
|
|
return f"min_val must be a valid date (YYYY-MM-DD) for attribute '{attrib.attrib_name}'."
|
|
if attrib.max_val is not None and not _is_date(attrib.max_val):
|
|
return f"max_val must be a valid date (YYYY-MM-DD) for attribute '{attrib.attrib_name}'."
|
|
if attrib.min_val is not None and attrib.max_val is not None:
|
|
min_date = datetime.strptime(attrib.min_val, "%Y-%m-%d")
|
|
max_date = datetime.strptime(attrib.max_val, "%Y-%m-%d")
|
|
if max_date < min_date:
|
|
return f"max_val cannot be earlier than min_val for attribute '{attrib.attrib_name}'."
|
|
if attrib.default_val is not None and not _is_date(attrib.default_val):
|
|
return f"default_val must be a valid date (YYYY-MM-DD) for attribute '{attrib.attrib_name}'."
|
|
if attrib.default_val is not None:
|
|
default_date = datetime.strptime(attrib.default_val, "%Y-%m-%d")
|
|
if attrib.min_val is not None:
|
|
min_date = datetime.strptime(attrib.min_val, "%Y-%m-%d")
|
|
if default_date < min_date:
|
|
return f"default_val cannot be earlier than min_val for attribute '{attrib.attrib_name}'."
|
|
if attrib.max_val is not None:
|
|
max_date = datetime.strptime(attrib.max_val, "%Y-%m-%d")
|
|
if default_date > max_date:
|
|
return f"default_val cannot be later than max_val for attribute '{attrib.attrib_name}'."
|
|
return None
|
|
|
|
def _validate_text(attrib: textAttribute) -> Optional[str]:
|
|
"""Validate text-specific attributes. Returns an error message if invalid, otherwise None."""
|
|
if attrib.default_val is not None and attrib.regex is not None:
|
|
if not re.match(attrib.regex, str(attrib.default_val)):
|
|
return f"default_val does not match the regex pattern for attribute '{attrib.attrib_name}'."
|
|
return None
|
|
|
|
def _validate_select(attrib: selectAttribute) -> Optional[str]:
|
|
"""Validate select-specific attributes. Returns an error message if invalid, otherwise None."""
|
|
if not attrib.options:
|
|
return f"options cannot be empty for attribute '{attrib.attrib_name}'."
|
|
if attrib.default_val is not None and attrib.default_val not in attrib.options:
|
|
return f"default_val must be one of the options for attribute '{attrib.attrib_name}'."
|
|
return None
|
|
|
|
def validate_config(item_attributes: List) -> str:
|
|
"""
|
|
Validate the configuration file to ensure all attributes are properly defined.
|
|
Returns "Ok" if everything is valid, otherwise returns an error message.
|
|
"""
|
|
for attrib in item_attributes:
|
|
# Validate essential properties
|
|
if not attrib.attrib_name:
|
|
return f"Missing attribute name for the {item_attributes.index(attrib) + 1}th attribute."
|
|
if not attrib.display_name:
|
|
return f"Missing display name for attribute '{attrib.attrib_name}'."
|
|
if not attrib.html_input_type:
|
|
return f"Missing input type for attribute '{attrib.attrib_name}'."
|
|
if attrib.html_input_type not in ["text", "number", "date", "select"]:
|
|
return f"Invalid input type for attribute '{attrib.attrib_name}'."
|
|
|
|
# Validate type-specific attributes
|
|
if isinstance(attrib, intAttribute):
|
|
error = _validate_number(attrib)
|
|
if error:
|
|
return error
|
|
elif isinstance(attrib, dateAttribute):
|
|
error = _validate_date(attrib)
|
|
if error:
|
|
return error
|
|
elif isinstance(attrib, textAttribute):
|
|
error = _validate_text(attrib)
|
|
if error:
|
|
return error
|
|
elif isinstance(attrib, selectAttribute):
|
|
error = _validate_select(attrib)
|
|
if error:
|
|
return error
|
|
|
|
# Validate comparison (if applicable)
|
|
if attrib.compareto:
|
|
if not isinstance(attrib.compareto, list) or not all(isinstance(pair, tuple) and len(pair) == 2 for pair in attrib.compareto):
|
|
return f"Invalid comparison format for attribute '{attrib.attrib_name}'. Expected a list of tuples."
|
|
for cmp, ref_attr in attrib.compareto:
|
|
if cmp not in ["lt", "gt", "le", "ge", "eq"]:
|
|
return f"Invalid comparison operator '{cmp}' for attribute '{attrib.attrib_name}'."
|
|
if ref_attr not in [a.attrib_name for a in item_attributes]:
|
|
return f"Invalid reference attribute '{ref_attr}' for comparison in attribute '{attrib.attrib_name}'."
|
|
|
|
return "Ok" |