added 'is_value_valid' implementation for attribute definitions

This commit is contained in:
Jakub Trllo 2024-10-09 15:17:16 +02:00
parent b0001f9a58
commit ed36077292

View file

@ -228,8 +228,21 @@ class AbstractAttrDef(metaclass=AbstractAttrDefMeta):
and (ignore_enabled or self.enabled == other.enabled)
)
def _def_type_compare(self, other: "AbstractAttrDef") -> bool:
return True
@abstractmethod
def is_value_valid(self, value: Any) -> bool:
"""Check if value is valid.
This should return False if value is not valid based
on definition type.
Args:
value (Any): Value to validate based on definition type.
Returns:
bool: True if value is valid.
"""
pass
@property
@abstractmethod
@ -286,6 +299,9 @@ class AbstractAttrDef(metaclass=AbstractAttrDefMeta):
return cls(**data)
def _def_type_compare(self, other: "AbstractAttrDef") -> bool:
return True
# -----------------------------------------
# UI attribute definitions won't hold value
@ -297,6 +313,9 @@ class UIDef(AbstractAttrDef):
def __init__(self, key=None, default=None, *args, **kwargs):
super().__init__(key, default, *args, **kwargs)
def is_value_valid(self, value: Any) -> bool:
return True
def convert_value(self, value):
return value
@ -332,6 +351,9 @@ class UnknownDef(AbstractAttrDef):
kwargs["default"] = default
super().__init__(key, **kwargs)
def is_value_valid(self, value: Any) -> bool:
return True
def convert_value(self, value):
return value
@ -352,6 +374,9 @@ class HiddenDef(AbstractAttrDef):
kwargs["visible"] = False
super().__init__(key, **kwargs)
def is_value_valid(self, value: Any) -> bool:
return True
def convert_value(self, value):
return value
@ -407,12 +432,15 @@ class NumberDef(AbstractAttrDef):
self.maximum = maximum
self.decimals = 0 if decimals is None else decimals
def _def_type_compare(self, other: "NumberDef") -> bool:
return (
self.decimals == other.decimals
and self.maximum == other.maximum
and self.maximum == other.maximum
)
def is_value_valid(self, value: Any) -> bool:
if self.decimals == 0:
if not isinstance(value, int):
return False
elif not isinstance(value, float):
return False
if self.minimum > value > self.maximum:
return False
return True
def convert_value(self, value):
if isinstance(value, str):
@ -428,6 +456,13 @@ class NumberDef(AbstractAttrDef):
return int(value)
return round(float(value), self.decimals)
def _def_type_compare(self, other: "NumberDef") -> bool:
return (
self.decimals == other.decimals
and self.maximum == other.maximum
and self.maximum == other.maximum
)
class TextDef(AbstractAttrDef):
"""Text definition.
@ -474,11 +509,12 @@ class TextDef(AbstractAttrDef):
self.placeholder = placeholder
self.regex = regex
def _def_type_compare(self, other: "TextDef") -> bool:
return (
self.multiline == other.multiline
and self.regex == other.regex
)
def is_value_valid(self, value: Any) -> bool:
if not isinstance(value, str):
return False
if self.regex and not self.regex.match(value):
return False
return True
def convert_value(self, value):
if isinstance(value, str):
@ -492,6 +528,12 @@ class TextDef(AbstractAttrDef):
data["placeholder"] = self.placeholder
return data
def _def_type_compare(self, other: "TextDef") -> bool:
return (
self.multiline == other.multiline
and self.regex == other.regex
)
class EnumDef(AbstractAttrDef):
"""Enumeration of items.
@ -536,12 +578,6 @@ class EnumDef(AbstractAttrDef):
self._item_values = item_values_set
self.multiselection = multiselection
def _def_type_compare(self, other: "EnumDef") -> bool:
return (
self.items == other.items
and self.multiselection == other.multiselection
)
def convert_value(self, value):
if not self.multiselection:
if value in self._item_values:
@ -552,6 +588,17 @@ class EnumDef(AbstractAttrDef):
return copy.deepcopy(self.default)
return list(self._item_values.intersection(value))
def is_value_valid(self, value: Any) -> bool:
"""Check if item is available in possible values."""
if isinstance(value, list):
if not self.multiselection:
return False
return all(value in self._item_values for value in value)
if self.multiselection:
return False
return value in self._item_values
def serialize(self):
data = super().serialize()
data["items"] = copy.deepcopy(self.items)
@ -620,6 +667,12 @@ class EnumDef(AbstractAttrDef):
return output
def _def_type_compare(self, other: "EnumDef") -> bool:
return (
self.items == other.items
and self.multiselection == other.multiselection
)
class BoolDef(AbstractAttrDef):
"""Boolean representation.
@ -635,6 +688,9 @@ class BoolDef(AbstractAttrDef):
default = False
super().__init__(key, default=default, **kwargs)
def is_value_valid(self, value: Any) -> bool:
return isinstance(value, bool)
def convert_value(self, value):
if isinstance(value, bool):
return value
@ -944,6 +1000,29 @@ class FileDef(AbstractAttrDef):
and self.allow_sequences == other.allow_sequences
)
def is_value_valid(self, value: Any) -> bool:
if self.single_item:
if not isinstance(value, dict):
return False
try:
FileDefItem.from_dict(value)
return True
except (ValueError, KeyError):
return False
if not isinstance(value, list):
return False
for item in value:
if not isinstance(item, dict):
return False
try:
FileDefItem.from_dict(item)
except (ValueError, KeyError):
return False
return True
def convert_value(self, value):
if isinstance(value, (str, dict)):
value = [value]