[core] Add a property to ignore an attribute during the UID computation

By default, an attribute that belongs to the UID group 0 is taken into
the node's UID computation independently from its value, as long as it is
enabled.

When such an attribute is added to a node's list of attributes, it
automatically invalidates all computations made for this node prior to
its addition.

This commits adds a new attribute property, "uidIgnoreValue". This property
determines whether the attribute must be taken into consideration during
the node's UID computation: if the value of the attribute is the same as
"uidIgnoreValue", then it should be ignored; otherwise, it should be taken
into account. By default, "uidIgnoreValue" is set to "None", meaning that
any attribute that may be considered during the UID computation will be
taken into account.

In the context of the internal attributes, "uidIgnoreValue" is set to empty
string, so the "invalidation" attribute will not automatically
invalidate 100% of the nodes from existing graphs until its value is set
to a non-empty string.
This commit is contained in:
Candice Bentéjac 2023-02-17 15:34:39 +01:00
parent 6381371e7d
commit 311ab9cb40
3 changed files with 16 additions and 6 deletions

View file

@ -143,6 +143,10 @@ class Attribute(BaseObject):
self._enabled = v self._enabled = v
self.enabledChanged.emit() self.enabledChanged.emit()
def getUidIgnoreValue(self):
""" Value for which the attribute should be ignored during the UID computation. """
return self.attributeDesc.uidIgnoreValue
def _get_value(self): def _get_value(self):
if self.isLink: if self.isLink:
return self.getLinkParam().value return self.getLinkParam().value
@ -333,6 +337,7 @@ class Attribute(BaseObject):
node = Property(BaseObject, node.fget, constant=True) node = Property(BaseObject, node.fget, constant=True)
enabledChanged = Signal() enabledChanged = Signal()
enabled = Property(bool, getEnabled, setEnabled, notify=enabledChanged) enabled = Property(bool, getEnabled, setEnabled, notify=enabledChanged)
uidIgnoreValue = Property(Variant, getUidIgnoreValue, constant=True)
def raiseIfLink(func): def raiseIfLink(func):

View file

@ -14,7 +14,7 @@ class Attribute(BaseObject):
""" """
""" """
def __init__(self, name, label, description, value, advanced, semantic, uid, group, enabled): def __init__(self, name, label, description, value, advanced, semantic, uid, group, enabled, uidIgnoreValue=None):
super(Attribute, self).__init__() super(Attribute, self).__init__()
self._name = name self._name = name
self._label = label self._label = label
@ -25,6 +25,7 @@ class Attribute(BaseObject):
self._advanced = advanced self._advanced = advanced
self._enabled = enabled self._enabled = enabled
self._semantic = semantic self._semantic = semantic
self._uidIgnoreValue = uidIgnoreValue
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)
@ -35,6 +36,7 @@ class Attribute(BaseObject):
advanced = Property(bool, lambda self: self._advanced, constant=True) advanced = Property(bool, lambda self: self._advanced, constant=True)
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)
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):
@ -201,8 +203,9 @@ class GroupAttribute(Attribute):
class Param(Attribute): class Param(Attribute):
""" """
""" """
def __init__(self, name, label, description, value, uid, group, advanced, semantic, enabled): def __init__(self, name, label, description, value, uid, group, advanced, semantic, enabled, uidIgnoreValue=None):
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)
class File(Attribute): class File(Attribute):
@ -329,8 +332,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): def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, semantic='', enabled=True, uidIgnoreValue=None):
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)
def validateValue(self, value): def validateValue(self, value):
if not isinstance(value, str): if not isinstance(value, str):
@ -509,6 +513,7 @@ class Node(object):
semantic="multiline", semantic="multiline",
uid=[0], uid=[0],
advanced=True, advanced=True,
uidIgnoreValue="", # If the invalidation string is empty, it does not participate to the node's UID
), ),
StringParam( StringParam(
name="comment", name="comment",

View file

@ -691,7 +691,7 @@ class BaseNode(BaseObject):
""" Compute node uids by combining associated attributes' uids. """ """ Compute node uids by combining associated attributes' uids. """
for uidIndex, associatedAttributes in self.attributesPerUid.items(): for uidIndex, associatedAttributes in self.attributesPerUid.items():
# uid is computed by hashing the sorted list of tuple (name, value) of all attributes impacting this uid # uid is computed by hashing the sorted list of tuple (name, value) of all attributes impacting this uid
uidAttributes = [(a.getName(), a.uid(uidIndex)) for a in associatedAttributes if a.enabled] uidAttributes = [(a.getName(), a.uid(uidIndex)) for a in associatedAttributes if a.enabled and a.value != a.uidIgnoreValue]
uidAttributes.sort() uidAttributes.sort()
self._uids[uidIndex] = hashValue(uidAttributes) self._uids[uidIndex] = hashValue(uidAttributes)