refactor: Modularize attribute class definitions
- Split `definitions/attribute.py` into separate files under `definitions/attributes/`. - Added `__init__.py` for simplified imports. - Improved code organization and maintainability.
This commit is contained in:
parent
f398c9e35b
commit
3acbb85b08
@ -1,4 +1,4 @@
|
|||||||
from definitions.attribute import textAttribute, intAttribute, dateAttribute, selectAttribute
|
from definitions.attributes import *
|
||||||
|
|
||||||
app_secret_key = "test_phase_secret_key"
|
app_secret_key = "test_phase_secret_key"
|
||||||
|
|
||||||
|
@ -1,219 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
import re
|
|
||||||
from typing import List, Optional, Tuple, Set
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
|
|
||||||
ALLOWED_INPUT_TYPES = {"text", "number", "date", "select"}
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Attribute:
|
|
||||||
"""Base class for all attribute types."""
|
|
||||||
attrib_name: str
|
|
||||||
display_name: str
|
|
||||||
html_input_type: Optional[str] = "text"
|
|
||||||
required: bool = False
|
|
||||||
unique: bool = False
|
|
||||||
primary: bool = False
|
|
||||||
default_val: Optional[str] = None
|
|
||||||
compareto: Optional[List[Tuple[str, str]]] = None
|
|
||||||
valid_comparisons: Optional[Set[str]] = None
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate common attributes. Returns an error message if invalid, otherwise None."""
|
|
||||||
if not self.attrib_name:
|
|
||||||
return "Missing attribute name."
|
|
||||||
if not self.display_name:
|
|
||||||
return f"Missing display name for attribute '{self.attrib_name}'."
|
|
||||||
if not self.html_input_type:
|
|
||||||
return f"Missing input type for attribute '{self.attrib_name}'."
|
|
||||||
if self.html_input_type not in ALLOWED_INPUT_TYPES:
|
|
||||||
return f"Invalid input type '{self.html_input_type}' for attribute '{self.attrib_name}'."
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class textAttribute(Attribute):
|
|
||||||
"""Class for text attributes."""
|
|
||||||
regex: Optional[str] = None
|
|
||||||
min_length: Optional[int] = None
|
|
||||||
max_length: Optional[int] = 50
|
|
||||||
allowed_chars: Optional[str] = None
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
"""Post-initialization to set the HTML input type."""
|
|
||||||
self.html_input_type = "text"
|
|
||||||
self.valid_comparisons = {"lt", "st", "eq", "ne"}, # longer than, shorter than, eq, or not eq, to the ref attrib
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate text-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
if self.min_length is not None and self.max_length is not None:
|
|
||||||
if not isinstance(self.min_length, int) or not isinstance(self.max_length, int):
|
|
||||||
return f"Min and max lengths must be integers for '{self.attrib_name}'."
|
|
||||||
if int(self.min_length) > int(self.max_length):
|
|
||||||
return f"Max length must be greater than min length for '{self.attrib_name}'."
|
|
||||||
if self.default_val is not None:
|
|
||||||
if self.regex is not None:
|
|
||||||
compiled_regex = re.compile(self.regex)
|
|
||||||
if not compiled_regex.match(str(self.default_val)):
|
|
||||||
return f"Default value for '{self.attrib_name}' must match the pattern: {self.regex}"
|
|
||||||
if self.allowed_chars is not None:
|
|
||||||
for char in self.default_val:
|
|
||||||
if char not in self.allowed_chars:
|
|
||||||
return f"Invalid character '{char}' in default value for '{self.attrib_name}'. Allowed characters are: {self.allowed_chars}"
|
|
||||||
if self.min_length is not None:
|
|
||||||
if len(self.default_val) < int(self.min_length):
|
|
||||||
return f"Invalid default value for '{self.attrib_name}'. The minimum length is: {self.min_length}"
|
|
||||||
if self.max_length is not None:
|
|
||||||
if len(self.default_val) > int(self.max_length):
|
|
||||||
return f"Invalid default value for '{self.attrib_name}'. The maximum length is: {self.max_length}"
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class numAttribute(Attribute):
|
|
||||||
"""Base class for numeric attributes (int and float)."""
|
|
||||||
min_val: Optional[float] = None
|
|
||||||
max_val: Optional[float] = None
|
|
||||||
step: float = 1.0
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
"""Post-initialization to set the HTML input type."""
|
|
||||||
self.html_input_type = "number"
|
|
||||||
self.valid_comparisons = {"lt", "gt", "le", "ge", "eq", "ne"} # <, >, <=, >=, ==, !=
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate numeric-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
|
|
||||||
# Validate min_val and max_val
|
|
||||||
if self.min_val is not None and not isinstance(self.min_val, (int, float)):
|
|
||||||
return f"min_val must be a number for attribute '{self.attrib_name}'."
|
|
||||||
if self.max_val is not None and not isinstance(self.max_val, (int, float)):
|
|
||||||
return f"max_val must be a number for attribute '{self.attrib_name}'."
|
|
||||||
if self.min_val is not None and self.max_val is not None and self.min_val > self.max_val:
|
|
||||||
return f"min_val cannot be greater than max_val for attribute '{self.attrib_name}'."
|
|
||||||
|
|
||||||
# Validate step
|
|
||||||
if self.step is not None:
|
|
||||||
if not isinstance(self.step, (int, float)):
|
|
||||||
return f"Step must be a number for attribute '{self.attrib_name}'."
|
|
||||||
if self.step <= 0:
|
|
||||||
return f"Step must be a positive number for attribute '{self.attrib_name}'."
|
|
||||||
if self.min_val is not None and self.max_val is not None:
|
|
||||||
range_val = self.max_val - self.min_val
|
|
||||||
if self.step > range_val:
|
|
||||||
return f"Step value is too large for attribute '{self.attrib_name}'."
|
|
||||||
|
|
||||||
# Validate default_val
|
|
||||||
if self.default_val is not None:
|
|
||||||
if not isinstance(self.default_val, (int, float)):
|
|
||||||
return f"default_val must be a number for attribute '{self.attrib_name}'."
|
|
||||||
if self.min_val is not None and self.default_val < self.min_val:
|
|
||||||
return f"default_val cannot be less than min_val for attribute '{self.attrib_name}'."
|
|
||||||
if self.max_val is not None and self.default_val > self.max_val:
|
|
||||||
return f"default_val cannot be greater than max_val for attribute '{self.attrib_name}'."
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class intAttribute(numAttribute):
|
|
||||||
"""Class for integer attributes."""
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate integer-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
|
|
||||||
# Ensure default_val is an integer
|
|
||||||
if self.default_val is not None and not isinstance(self.default_val, int):
|
|
||||||
return f"default_val must be an integer for attribute '{self.attrib_name}'."
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class floatAttribute(numAttribute):
|
|
||||||
"""Class for float attributes."""
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate float-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
|
|
||||||
# Ensure default_val is a float
|
|
||||||
if self.default_val is not None and not isinstance(self.default_val, float):
|
|
||||||
return f"default_val must be a float for attribute '{self.attrib_name}'."
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class dateAttribute(Attribute):
|
|
||||||
"""Class for date attributes."""
|
|
||||||
min_val: Optional[str] = None
|
|
||||||
max_val: Optional[str] = None
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
"""Post-initialization to set the HTML input type."""
|
|
||||||
self.html_input_type = "date"
|
|
||||||
self.valid_comparisons = {"lt", "gt", "le", "ge", "eq", "ne"}, # <, >, <=, >=, ==, !=
|
|
||||||
|
|
||||||
def _is_date(self, value: str) -> bool:
|
|
||||||
"""Check if a value is a valid date in YYYY-MM-DD format."""
|
|
||||||
try:
|
|
||||||
datetime.strptime(value, "%Y-%m-%d")
|
|
||||||
return True
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate date-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
if self.min_val is not None and not self._is_date(self.min_val):
|
|
||||||
return f"min_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
|
||||||
if self.max_val is not None and not self._is_date(self.max_val):
|
|
||||||
return f"max_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
|
||||||
if self.min_val is not None and self.max_val is not None:
|
|
||||||
min_date = datetime.strptime(self.min_val, "%Y-%m-%d")
|
|
||||||
max_date = datetime.strptime(self.max_val, "%Y-%m-%d")
|
|
||||||
if max_date < min_date:
|
|
||||||
return f"max_val cannot be earlier than min_val for attribute '{self.attrib_name}'."
|
|
||||||
if self.default_val is not None and not self._is_date(self.default_val):
|
|
||||||
return f"default_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
|
||||||
if self.default_val is not None:
|
|
||||||
default_date = datetime.strptime(self.default_val, "%Y-%m-%d")
|
|
||||||
if self.min_val is not None:
|
|
||||||
min_date = datetime.strptime(self.min_val, "%Y-%m-%d")
|
|
||||||
if default_date < min_date:
|
|
||||||
return f"default_val cannot be earlier than min_val for attribute '{self.attrib_name}'."
|
|
||||||
if self.max_val is not None:
|
|
||||||
max_date = datetime.strptime(self.max_val, "%Y-%m-%d")
|
|
||||||
if default_date > max_date:
|
|
||||||
return f"default_val cannot be later than max_val for attribute '{self.attrib_name}'."
|
|
||||||
return None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class selectAttribute(Attribute):
|
|
||||||
"""Class for select attributes."""
|
|
||||||
options: List[str] = None
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
"""Post-initialization to set the HTML input type."""
|
|
||||||
self.html_input_type = "select"
|
|
||||||
self.valid_comparisons = {"eq", "ne"} # eq, or not eq, to the ref attrib
|
|
||||||
|
|
||||||
def validate(self) -> Optional[str]:
|
|
||||||
"""Validate select-specific attributes."""
|
|
||||||
error = super().validate()
|
|
||||||
if error:
|
|
||||||
return error
|
|
||||||
if not self.options:
|
|
||||||
return f"options cannot be empty for attribute '{self.attrib_name}'."
|
|
||||||
if self.default_val is not None and self.default_val not in self.options:
|
|
||||||
return f"default_val must be one of the options for attribute '{self.attrib_name}'."
|
|
||||||
return None
|
|
29
definitions/attributes/Attribute.py
Normal file
29
definitions/attributes/Attribute.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from typing import List, Optional, Tuple, Set
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
ALLOWED_INPUT_TYPES = {"text", "number", "date", "select"}
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Attribute:
|
||||||
|
"""Base class for all attribute types."""
|
||||||
|
attrib_name: str
|
||||||
|
display_name: str
|
||||||
|
html_input_type: Optional[str] = "text"
|
||||||
|
required: bool = False
|
||||||
|
unique: bool = False
|
||||||
|
primary: bool = False
|
||||||
|
default_val: Optional[str] = None
|
||||||
|
compareto: Optional[List[Tuple[str, str]]] = None
|
||||||
|
valid_comparisons: Optional[Set[str]] = None
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate common attributes. Returns an error message if invalid, otherwise None."""
|
||||||
|
if not self.attrib_name:
|
||||||
|
return "Missing attribute name."
|
||||||
|
if not self.display_name:
|
||||||
|
return f"Missing display name for attribute '{self.attrib_name}'."
|
||||||
|
if not self.html_input_type:
|
||||||
|
return f"Missing input type for attribute '{self.attrib_name}'."
|
||||||
|
if self.html_input_type not in ALLOWED_INPUT_TYPES:
|
||||||
|
return f"Invalid input type '{self.html_input_type}' for attribute '{self.attrib_name}'."
|
||||||
|
return None
|
16
definitions/attributes/__init__.py
Normal file
16
definitions/attributes/__init__.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from .Attribute import Attribute
|
||||||
|
from .textAttribute import textAttribute
|
||||||
|
from .numAttribute import numAttribute, intAttribute, floatAttribute
|
||||||
|
from .dateAttribute import dateAttribute
|
||||||
|
from .selectAttribute import selectAttribute
|
||||||
|
|
||||||
|
# Export all classes in a list for easier introspection
|
||||||
|
__all__ = [
|
||||||
|
"Attribute",
|
||||||
|
"textAttribute",
|
||||||
|
"numAttribute",
|
||||||
|
"intAttribute",
|
||||||
|
"floatAttribute",
|
||||||
|
"dateAttribute",
|
||||||
|
"selectAttribute",
|
||||||
|
]
|
51
definitions/attributes/dateAttribute.py
Normal file
51
definitions/attributes/dateAttribute.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from .Attribute import Attribute
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class dateAttribute(Attribute):
|
||||||
|
"""Class for date attributes."""
|
||||||
|
min_val: Optional[str] = None
|
||||||
|
max_val: Optional[str] = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
"""Post-initialization to set the HTML input type."""
|
||||||
|
self.html_input_type = "date"
|
||||||
|
self.valid_comparisons = {"lt", "gt", "le", "ge", "eq", "ne"}, # <, >, <=, >=, ==, !=
|
||||||
|
|
||||||
|
def _is_date(self, value: str) -> bool:
|
||||||
|
"""Check if a value is a valid date in YYYY-MM-DD format."""
|
||||||
|
try:
|
||||||
|
datetime.strptime(value, "%Y-%m-%d")
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate date-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
if self.min_val is not None and not self._is_date(self.min_val):
|
||||||
|
return f"min_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
||||||
|
if self.max_val is not None and not self._is_date(self.max_val):
|
||||||
|
return f"max_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
||||||
|
if self.min_val is not None and self.max_val is not None:
|
||||||
|
min_date = datetime.strptime(self.min_val, "%Y-%m-%d")
|
||||||
|
max_date = datetime.strptime(self.max_val, "%Y-%m-%d")
|
||||||
|
if max_date < min_date:
|
||||||
|
return f"max_val cannot be earlier than min_val for attribute '{self.attrib_name}'."
|
||||||
|
if self.default_val is not None and not self._is_date(self.default_val):
|
||||||
|
return f"default_val must be a valid date (YYYY-MM-DD) for attribute '{self.attrib_name}'."
|
||||||
|
if self.default_val is not None:
|
||||||
|
default_date = datetime.strptime(self.default_val, "%Y-%m-%d")
|
||||||
|
if self.min_val is not None:
|
||||||
|
min_date = datetime.strptime(self.min_val, "%Y-%m-%d")
|
||||||
|
if default_date < min_date:
|
||||||
|
return f"default_val cannot be earlier than min_val for attribute '{self.attrib_name}'."
|
||||||
|
if self.max_val is not None:
|
||||||
|
max_date = datetime.strptime(self.max_val, "%Y-%m-%d")
|
||||||
|
if default_date > max_date:
|
||||||
|
return f"default_val cannot be later than max_val for attribute '{self.attrib_name}'."
|
||||||
|
return None
|
83
definitions/attributes/numAttribute.py
Normal file
83
definitions/attributes/numAttribute.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from .Attribute import Attribute
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class numAttribute(Attribute):
|
||||||
|
"""Base class for numeric attributes (int and float)."""
|
||||||
|
min_val: Optional[float] = None
|
||||||
|
max_val: Optional[float] = None
|
||||||
|
step: float = 1.0
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
"""Post-initialization to set the HTML input type."""
|
||||||
|
self.html_input_type = "number"
|
||||||
|
self.valid_comparisons = {"lt", "gt", "le", "ge", "eq", "ne"} # <, >, <=, >=, ==, !=
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate numeric-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
|
||||||
|
# Validate min_val and max_val
|
||||||
|
if self.min_val is not None and not isinstance(self.min_val, (int, float)):
|
||||||
|
return f"min_val must be a number for attribute '{self.attrib_name}'."
|
||||||
|
if self.max_val is not None and not isinstance(self.max_val, (int, float)):
|
||||||
|
return f"max_val must be a number for attribute '{self.attrib_name}'."
|
||||||
|
if self.min_val is not None and self.max_val is not None and self.min_val > self.max_val:
|
||||||
|
return f"min_val cannot be greater than max_val for attribute '{self.attrib_name}'."
|
||||||
|
|
||||||
|
# Validate step
|
||||||
|
if self.step is not None:
|
||||||
|
if not isinstance(self.step, (int, float)):
|
||||||
|
return f"Step must be a number for attribute '{self.attrib_name}'."
|
||||||
|
if self.step <= 0:
|
||||||
|
return f"Step must be a positive number for attribute '{self.attrib_name}'."
|
||||||
|
if self.min_val is not None and self.max_val is not None:
|
||||||
|
range_val = self.max_val - self.min_val
|
||||||
|
if self.step > range_val:
|
||||||
|
return f"Step value is too large for attribute '{self.attrib_name}'."
|
||||||
|
|
||||||
|
# Validate default_val
|
||||||
|
if self.default_val is not None:
|
||||||
|
if not isinstance(self.default_val, (int, float)):
|
||||||
|
return f"default_val must be a number for attribute '{self.attrib_name}'."
|
||||||
|
if self.min_val is not None and self.default_val < self.min_val:
|
||||||
|
return f"default_val cannot be less than min_val for attribute '{self.attrib_name}'."
|
||||||
|
if self.max_val is not None and self.default_val > self.max_val:
|
||||||
|
return f"default_val cannot be greater than max_val for attribute '{self.attrib_name}'."
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class intAttribute(numAttribute):
|
||||||
|
"""Class for integer attributes."""
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate integer-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
|
||||||
|
# Ensure default_val is an integer
|
||||||
|
if self.default_val is not None and not isinstance(self.default_val, int):
|
||||||
|
return f"default_val must be an integer for attribute '{self.attrib_name}'."
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class floatAttribute(numAttribute):
|
||||||
|
"""Class for float attributes."""
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate float-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
|
||||||
|
# Ensure default_val is a float
|
||||||
|
if self.default_val is not None and not isinstance(self.default_val, float):
|
||||||
|
return f"default_val must be a float for attribute '{self.attrib_name}'."
|
||||||
|
|
||||||
|
return None
|
24
definitions/attributes/selectAttribute.py
Normal file
24
definitions/attributes/selectAttribute.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from typing import List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from .Attribute import Attribute
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class selectAttribute(Attribute):
|
||||||
|
"""Class for select attributes."""
|
||||||
|
options: List[str] = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
"""Post-initialization to set the HTML input type."""
|
||||||
|
self.html_input_type = "select"
|
||||||
|
self.valid_comparisons = {"eq", "ne"} # eq, or not eq, to the ref attrib
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate select-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
if not self.options:
|
||||||
|
return f"options cannot be empty for attribute '{self.attrib_name}'."
|
||||||
|
if self.default_val is not None and self.default_val not in self.options:
|
||||||
|
return f"default_val must be one of the options for attribute '{self.attrib_name}'."
|
||||||
|
return None
|
44
definitions/attributes/textAttribute.py
Normal file
44
definitions/attributes/textAttribute.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import re
|
||||||
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from .Attribute import Attribute
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class textAttribute(Attribute):
|
||||||
|
"""Class for text attributes."""
|
||||||
|
regex: Optional[str] = None
|
||||||
|
min_length: Optional[int] = None
|
||||||
|
max_length: Optional[int] = 50
|
||||||
|
allowed_chars: Optional[str] = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
"""Post-initialization to set the HTML input type."""
|
||||||
|
self.html_input_type = "text"
|
||||||
|
self.valid_comparisons = {"lt", "st", "eq", "ne"}, # longer than, shorter than, eq, or not eq, to the ref attrib
|
||||||
|
|
||||||
|
def validate(self) -> Optional[str]:
|
||||||
|
"""Validate text-specific attributes."""
|
||||||
|
error = super().validate()
|
||||||
|
if error:
|
||||||
|
return error
|
||||||
|
if self.min_length is not None and self.max_length is not None:
|
||||||
|
if not isinstance(self.min_length, int) or not isinstance(self.max_length, int):
|
||||||
|
return f"Min and max lengths must be integers for '{self.attrib_name}'."
|
||||||
|
if int(self.min_length) > int(self.max_length):
|
||||||
|
return f"Max length must be greater than min length for '{self.attrib_name}'."
|
||||||
|
if self.default_val is not None:
|
||||||
|
if self.regex is not None:
|
||||||
|
compiled_regex = re.compile(self.regex)
|
||||||
|
if not compiled_regex.match(str(self.default_val)):
|
||||||
|
return f"Default value for '{self.attrib_name}' must match the pattern: {self.regex}"
|
||||||
|
if self.allowed_chars is not None:
|
||||||
|
for char in self.default_val:
|
||||||
|
if char not in self.allowed_chars:
|
||||||
|
return f"Invalid character '{char}' in default value for '{self.attrib_name}'. Allowed characters are: {self.allowed_chars}"
|
||||||
|
if self.min_length is not None:
|
||||||
|
if len(self.default_val) < int(self.min_length):
|
||||||
|
return f"Invalid default value for '{self.attrib_name}'. The minimum length is: {self.min_length}"
|
||||||
|
if self.max_length is not None:
|
||||||
|
if len(self.default_val) > int(self.max_length):
|
||||||
|
return f"Invalid default value for '{self.attrib_name}'. The maximum length is: {self.max_length}"
|
||||||
|
return None
|
@ -1,7 +1,7 @@
|
|||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from sqlalchemy import Enum, Integer, Float, String, Date, Column, Boolean
|
from sqlalchemy import Enum, Integer, Float, String, Date, Column, Boolean
|
||||||
from config import item_attributes, sql_conf
|
from config import item_attributes, sql_conf
|
||||||
from definitions.attribute import textAttribute, intAttribute, floatAttribute, dateAttribute, selectAttribute
|
from definitions.attributes import *
|
||||||
|
|
||||||
# Initialize SQLAlchemy
|
# Initialize SQLAlchemy
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from definitions.attribute import Attribute
|
from definitions.attributes import *
|
||||||
|
|
||||||
def validate_config(item_attributes: List[Attribute]) -> str:
|
def validate_config(item_attributes: List[Attribute]) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -3,13 +3,7 @@ import re
|
|||||||
from marshmallow import Schema, fields, ValidationError
|
from marshmallow import Schema, fields, ValidationError
|
||||||
from typing import Dict, Any, Optional, Type
|
from typing import Dict, Any, Optional, Type
|
||||||
from config import item_attributes
|
from config import item_attributes
|
||||||
from definitions.attribute import (
|
from definitions.attributes import *
|
||||||
textAttribute,
|
|
||||||
intAttribute,
|
|
||||||
floatAttribute,
|
|
||||||
dateAttribute,
|
|
||||||
selectAttribute,
|
|
||||||
)
|
|
||||||
|
|
||||||
def create_dynamic_schema() -> Type[Schema]:
|
def create_dynamic_schema() -> Type[Schema]:
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user