[core] Add new desc parameters to flag attributes with erroneous values

This commit adds two new description parameters:

- `validValue`, which is true if the value of the attribute is not
erroneous (i.e. valid for the type of the attribute but invalid in the
context of that specific attribute) and false otherwise. This holds a
different significance than the "validateValue" method, which only checks
if the parameter's value is expected with respect to the attribute's type.
For example, we could want an IntParam that flags any value that is not
even: an odd integer value would successfully go through the
"validateValue" method, but would then be flagged as an invalid value
at the attribute's level.

- `errorMessage`, an attribute-specific string that contains a message
explaining why the attribute's `validValue` parameter might be set to
false.

By default, all the attributes' values are valid, and they have no error
message.
This commit is contained in:
Candice Bentéjac 2023-08-02 14:37:46 +02:00 committed by Loïc Vital
parent 04388eff5d
commit 63bd6d61cd
2 changed files with 37 additions and 9 deletions

View file

@ -62,6 +62,7 @@ class Attribute(BaseObject):
self._value = copy.copy(attributeDesc.value) self._value = copy.copy(attributeDesc.value)
self._label = attributeDesc.label self._label = attributeDesc.label
self._enabled = True self._enabled = True
self._validValue = True
# invalidation value for output attributes # invalidation value for output attributes
self._invalidationValue = "" self._invalidationValue = ""
@ -147,6 +148,24 @@ class Attribute(BaseObject):
""" Value for which the attribute should be ignored during the UID computation. """ """ Value for which the attribute should be ignored during the UID computation. """
return self.attributeDesc.uidIgnoreValue return self.attributeDesc.uidIgnoreValue
def getValidValue(self):
"""
Get the status of _validValue:
- If it is a function, execute it and return the result
- Otherwise, simply return its value
"""
if isinstance(self.desc.validValue, types.FunctionType):
try:
return self.desc.validValue(self.node)
except Exception:
return True
return self._validValue
def setValidValue(self, value):
if self._validValue == value:
return
self._validValue = value
def _get_value(self): def _get_value(self):
if self.isLink: if self.isLink:
return self.getLinkParam().value return self.getLinkParam().value
@ -338,6 +357,8 @@ class Attribute(BaseObject):
enabledChanged = Signal() enabledChanged = Signal()
enabled = Property(bool, getEnabled, setEnabled, notify=enabledChanged) enabled = Property(bool, getEnabled, setEnabled, notify=enabledChanged)
uidIgnoreValue = Property(Variant, getUidIgnoreValue, constant=True) uidIgnoreValue = Property(Variant, getUidIgnoreValue, constant=True)
validValueChanged = Signal()
validValue = Property(bool, getValidValue, setValidValue, notify=validValueChanged)
def raiseIfLink(func): def raiseIfLink(func):

View file

@ -14,7 +14,8 @@ class Attribute(BaseObject):
""" """
""" """
def __init__(self, name, label, description, value, advanced, semantic, uid, group, enabled, uidIgnoreValue=None): def __init__(self, name, label, description, value, advanced, semantic, uid, group, enabled, uidIgnoreValue=None,
validValue=True, errorMessage=""):
super(Attribute, self).__init__() super(Attribute, self).__init__()
self._name = name self._name = name
self._label = label self._label = label
@ -26,6 +27,8 @@ class Attribute(BaseObject):
self._enabled = enabled self._enabled = enabled
self._semantic = semantic self._semantic = semantic
self._uidIgnoreValue = uidIgnoreValue self._uidIgnoreValue = uidIgnoreValue
self._validValue = validValue
self._errorMessage = errorMessage
name = Property(str, lambda self: self._name, constant=True) name = Property(str, lambda self: self._name, constant=True)
label = Property(str, lambda self: self._label, constant=True) label = Property(str, lambda self: self._label, constant=True)
@ -37,6 +40,8 @@ class Attribute(BaseObject):
enabled = Property(Variant, lambda self: self._enabled, constant=True) enabled = Property(Variant, lambda self: self._enabled, constant=True)
semantic = Property(str, lambda self: self._semantic, constant=True) semantic = Property(str, lambda self: self._semantic, constant=True)
uidIgnoreValue = Property(Variant, lambda self: self._uidIgnoreValue, constant=True) uidIgnoreValue = Property(Variant, lambda self: self._uidIgnoreValue, constant=True)
validValue = Property(Variant, lambda self: self._validValue, constant=True)
errorMessage = Property(str, lambda self: self._errorMessage, constant=True)
type = Property(str, lambda self: self.__class__.__name__, constant=True) type = Property(str, lambda self: self.__class__.__name__, constant=True)
def validateValue(self, value): def validateValue(self, value):
@ -205,9 +210,9 @@ class GroupAttribute(Attribute):
class Param(Attribute): class Param(Attribute):
""" """
""" """
def __init__(self, name, label, description, value, uid, group, advanced, semantic, enabled, uidIgnoreValue=None): def __init__(self, name, label, description, value, uid, group, advanced, semantic, enabled, uidIgnoreValue=None, validValue=True, errorMessage=""):
super(Param, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled, super(Param, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled,
uidIgnoreValue=uidIgnoreValue) uidIgnoreValue=uidIgnoreValue, validValue=validValue, errorMessage=errorMessage)
class File(Attribute): class File(Attribute):
@ -253,9 +258,10 @@ class BoolParam(Param):
class IntParam(Param): class IntParam(Param):
""" """
""" """
def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, semantic='', enabled=True): def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, semantic='', enabled=True, validValue=True, errorMessage=""):
self._range = range self._range = range
super(IntParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled) super(IntParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled,
validValue=validValue, errorMessage=errorMessage)
def validateValue(self, value): def validateValue(self, value):
# handle unsigned int values that are translated to int by shiboken and may overflow # handle unsigned int values that are translated to int by shiboken and may overflow
@ -275,9 +281,10 @@ class IntParam(Param):
class FloatParam(Param): class FloatParam(Param):
""" """
""" """
def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, semantic='', enabled=True): def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, semantic='', enabled=True, validValue=True, errorMessage=""):
self._range = range self._range = range
super(FloatParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled) super(FloatParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled,
validValue=validValue, errorMessage=errorMessage)
def validateValue(self, value): def validateValue(self, value):
try: try:
@ -334,9 +341,9 @@ class ChoiceParam(Param):
class StringParam(Param): class StringParam(Param):
""" """
""" """
def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, semantic='', enabled=True, uidIgnoreValue=None): def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, semantic='', enabled=True, uidIgnoreValue=None, validValue=True, errorMessage=""):
super(StringParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled, super(StringParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled,
uidIgnoreValue=uidIgnoreValue) uidIgnoreValue=uidIgnoreValue, validValue=validValue, errorMessage=errorMessage)
def validateValue(self, value): def validateValue(self, value):
if not isinstance(value, str): if not isinstance(value, str):