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" |