flask_crud_app/definitions/attribute.py

137 lines
5.7 KiB
Python

from datetime import datetime
from typing import Optional, List, Tuple
# Base Attribute class
class Attribute:
def __init__(
self,
attrib_name: str, # Attribute name and id.
display_name: str, # Input label or table column header.
html_input_type: str = "text", # HTML form input type. Determines MySQL data type.
placeholder: str = "", # HTML form input placeholder.
required: bool = False, # HTML form input "required" attribute and MySQL "Not Null" constraint
unique: bool = False, # MySQL "unique" constraint
primary: bool = False, # MySQL "primary key" constraint
index: bool = False, # bool: MySQL index
compareto: Optional[List[Tuple[str, str]]] = None, # Compare to another attribute of the item for validation
title: str = None, # Description text, HTML "title" attribute
):
if not attrib_name:
raise ValueError("Attribute name cannot be empty.")
if not display_name:
raise ValueError(f"Display name cannot be empty for attribute '{attrib_name}'.")
self.attrib_name = attrib_name
self.display_name = display_name
self.html_input_type = html_input_type
self.placeholder = placeholder
self.required = required
self.unique = unique
self.primary = primary
self.index = index
self.compareto = compareto
self.title = title
# Validate compareto
if self.compareto is not None:
validate_comparison(self)
# Text Attribute
class textAttribute(Attribute):
def __init__(
self,
regex: Optional[str] = None, # Regex for value validation
default_val: str = None, # Default value
compareto: Optional[List[Tuple[str, str]]] = None,
**kwargs # Additional arguments for the base class
):
super().__init__(html_input_type="text", **kwargs)
self.regex = regex
self.default_val = default_val
self.compareto = compareto
# Integer Attribute
class intAttribute(Attribute):
def __init__(
self,
min_val: Optional[int] = None, # Min value
max_val: Optional[int] = None, # Max value
step_val: Optional[int] = None, # Increment step
default_val: Optional[int] = None, # Default value
auto_increment: bool = False, # bool: MySQL autoincrement
compareto: Optional[List[Tuple[str, str]]] = None,
**kwargs # Additional arguments for the base class
):
super().__init__(html_input_type="number", **kwargs)
self.min_val = min_val
self.max_val = max_val
self.step_val = step_val
self.default_val = default_val
self.auto_increment = auto_increment
self.compareto = compareto
# Validate min_val and max_val
if self.min_val is not None and self.max_val is not None and self.min_val > self.max_val:
raise ValueError(f"min_val ({self.min_val}) cannot be greater than max_val ({self.max_val}).")
# Float Attribute
class floatAttribute(Attribute):
def __init__(
self,
min_val: Optional[float] = None, # Min value
max_val: Optional[float] = None, # Max value
step_val: Optional[float] = None, # Increment step
default_val: Optional[float] = None, # Default value
auto_increment: bool = False, # bool: MySQL autoincrement
compareto: Optional[List[Tuple[str, str]]] = None,
**kwargs # Additional arguments for the base class
):
super().__init__(html_input_type="number", **kwargs)
self.min_val = min_val
self.max_val = max_val
self.step_val = step_val
self.default_val = default_val
self.auto_increment = auto_increment
self.compareto = compareto
# Validate min_val and max_val
if self.min_val is not None and self.max_val is not None and self.min_val > self.max_val:
raise ValueError(f"min_val ({self.min_val}) cannot be greater than max_val ({self.max_val}).")
# Date Attribute
class dateAttribute(Attribute):
def __init__(
self,
min_val: Optional[str] = None, # Min value (string in "YYYY-MM-DD" format)
max_val: Optional[str] = None, # Max value (string in "YYYY-MM-DD" format)
default_val: Optional[str] = None, # Default value (string in "YYYY-MM-DD" format)
compareto: Optional[List[Tuple[str, str]]] = None,
**kwargs # Additional arguments for the base class
):
super().__init__(html_input_type="date", **kwargs)
self.min_val = self._parse_date(min_val) if min_val else None
self.max_val = self._parse_date(max_val) if max_val else None
self.default_val = self._parse_date(default_val) if default_val else None
self.compareto = compareto
def _parse_date(self, date_str: str) -> datetime:
"""Parse a date string into a datetime object."""
try:
return datetime.strptime(date_str, "%Y-%m-%d")
except ValueError as e:
raise ValueError(f"Invalid date format for '{date_str}'. Expected 'YYYY-MM-DD'.") from e
# Select Attribute
class selectAttribute(Attribute):
def __init__(
self,
options: Optional[List[str]] = None, # List of options
default_val: Optional[str] = None, # Default value
**kwargs # Additional arguments for the base class
):
super().__init__(html_input_type="select", **kwargs)
self.options = options if options else []
self.default_val = default_val if default_val else (self.options[0] if self.options else None)
# Validate default_val
if self.default_val and self.default_val not in self.options:
raise ValueError(f"Default value '{self.default_val}' is not in the options list.")