@@ -10,13 +10,16 @@ class Attribute(BaseObject):
1010 """
1111 """
1212
13- def __init__ (self , name , label , description , value , advanced , semantic , group , enabled , invalidate = True ,
14- uidIgnoreValue = None , validValue = True , errorMessage = "" , visible = True , exposed = False ):
13+ def __init__ (self , name , label , description , value , advanced , semantic , group , enabled ,
14+ keyable = False , keyType = None , invalidate = True , uidIgnoreValue = None ,
15+ validValue = True , errorMessage = "" , visible = True , exposed = False ):
1516 super (Attribute , self ).__init__ ()
1617 self ._name = name
1718 self ._label = label
1819 self ._description = description
1920 self ._value = value
21+ self ._keyable = keyable
22+ self ._keyType = keyType
2023 self ._group = group
2124 self ._advanced = advanced
2225 self ._enabled = enabled
@@ -46,6 +49,15 @@ def validateValue(self, value):
4649 """
4750 raise NotImplementedError ("Attribute.validateValue is an abstract function that should be "
4851 "implemented in the derived class." )
52+
53+ def validateKeyValues (self , keyValues ):
54+ """ Return validated/conformed 'keyValues'.
55+
56+ Raises:
57+ ValueError: if a value does not have the proper type
58+ """
59+ return isinstance (keyValues , dict ) and \
60+ all (isinstance (k , str ) and self .validateValue (v ) for k ,v in keyValues .items ())
4961
5062 def checkValueTypes (self ):
5163 """ Returns the attribute's name if the default value's type is invalid or if the range's type (when available)
@@ -65,7 +77,10 @@ def matchDescription(self, value, strict=True):
6577 strict: strict test for the match (for instance, regarding a group with some parameter changes)
6678 """
6779 try :
68- self .validateValue (value )
80+ if self ._keyable :
81+ self .validateKeyValues (value )
82+ else :
83+ self .validateValue (value )
6984 except ValueError :
7085 return False
7186 return True
@@ -82,6 +97,14 @@ def matchDescription(self, value, strict=True):
8297 # The default value of the attribute's descriptor is None, so it is not an input value,
8398 # but an output value that is computed during the Node's process execution.
8499 isDynamicValue = Property (bool , lambda self : self ._isDynamicValue , constant = True )
100+ # keyable:
101+ # Whether the attribute can have a distinct value per key.
102+ # By default, atribute value is not keyable.
103+ keyable = Property (bool , lambda self : self ._keyable , constant = True )
104+ # keyType:
105+ # The type of key corresponding to the attribute value.
106+ # This property only makes sense for keyable attributes.
107+ keyType = Property (str , lambda self : self ._keyType , constant = True )
85108 group = Property (str , lambda self : self ._group , constant = True )
86109 advanced = Property (bool , lambda self : self ._advanced , constant = True )
87110 enabled = Property (Variant , lambda self : self ._enabled , constant = True )
@@ -265,11 +288,13 @@ def retrieveChildrenInvalidations(self):
265288class Param (Attribute ):
266289 """
267290 """
268- def __init__ (self , name , label , description , value , group , advanced , semantic , enabled , invalidate = True ,
269- uidIgnoreValue = None , validValue = True , errorMessage = "" , visible = True , exposed = False ):
291+ def __init__ (self , name , label , description , value , group , advanced , semantic , enabled ,
292+ keyable = False , keyType = None , invalidate = True , uidIgnoreValue = None ,
293+ validValue = True , errorMessage = "" , visible = True , exposed = False ):
270294 super (Param , self ).__init__ (name = name , label = label , description = description , value = value ,
271- group = group , advanced = advanced , enabled = enabled , invalidate = invalidate ,
272- semantic = semantic , uidIgnoreValue = uidIgnoreValue , validValue = validValue ,
295+ keyable = keyable , keyType = keyType , group = group , advanced = advanced ,
296+ enabled = enabled , invalidate = invalidate , semantic = semantic ,
297+ uidIgnoreValue = uidIgnoreValue , validValue = validValue ,
273298 errorMessage = errorMessage , visible = visible , exposed = exposed )
274299
275300
@@ -302,11 +327,13 @@ def checkValueTypes(self):
302327class BoolParam (Param ):
303328 """
304329 """
305- def __init__ (self , name , label , description , value , group = "allParams" , advanced = False , enabled = True ,
306- invalidate = True , semantic = "" , visible = True , exposed = False ):
330+ def __init__ (self , name , label , description , value , keyable = False , keyType = None ,
331+ group = "allParams" , advanced = False , enabled = True , invalidate = True ,
332+ semantic = "" , visible = True , exposed = False ):
307333 super (BoolParam , self ).__init__ (name = name , label = label , description = description , value = value ,
308- group = group , advanced = advanced , enabled = enabled , invalidate = invalidate ,
309- semantic = semantic , visible = visible , exposed = exposed )
334+ keyable = keyable , keyType = keyType , group = group , advanced = advanced ,
335+ enabled = enabled , invalidate = invalidate , semantic = semantic ,
336+ visible = visible , exposed = exposed )
310337 self ._valueType = bool
311338
312339 def validateValue (self , value ):
@@ -330,12 +357,14 @@ def checkValueTypes(self):
330357class IntParam (Param ):
331358 """
332359 """
333- def __init__ (self , name , label , description , value , range = None , group = "allParams" , advanced = False , enabled = True ,
334- invalidate = True , semantic = "" , validValue = True , errorMessage = "" , visible = True , exposed = False ):
360+ def __init__ (self , name , label , description , value , range = None , keyable = False , keyType = None ,
361+ group = "allParams" , advanced = False , enabled = True , invalidate = True , semantic = "" ,
362+ validValue = True , errorMessage = "" , visible = True , exposed = False ):
335363 self ._range = range
336364 super (IntParam , self ).__init__ (name = name , label = label , description = description , value = value ,
337- group = group , advanced = advanced , enabled = enabled , invalidate = invalidate ,
338- semantic = semantic , validValue = validValue , errorMessage = errorMessage ,
365+ keyable = keyable , keyType = keyType , group = group , advanced = advanced ,
366+ enabled = enabled , invalidate = invalidate , semantic = semantic ,
367+ validValue = validValue , errorMessage = errorMessage ,
339368 visible = visible , exposed = exposed )
340369 self ._valueType = int
341370
@@ -360,12 +389,14 @@ def checkValueTypes(self):
360389class FloatParam (Param ):
361390 """
362391 """
363- def __init__ (self , name , label , description , value , range = None , group = "allParams" , advanced = False , enabled = True ,
364- invalidate = True , semantic = "" , validValue = True , errorMessage = "" , visible = True , exposed = False ):
392+ def __init__ (self , name , label , description , value , range = None , keyable = False , keyType = None ,
393+ group = "allParams" , advanced = False , enabled = True , invalidate = True , semantic = "" ,
394+ validValue = True , errorMessage = "" , visible = True , exposed = False ):
365395 self ._range = range
366396 super (FloatParam , self ).__init__ (name = name , label = label , description = description , value = value ,
367- group = group , advanced = advanced , enabled = enabled , invalidate = invalidate ,
368- semantic = semantic , validValue = validValue , errorMessage = errorMessage ,
397+ keyable = keyable , keyType = keyType , group = group , advanced = advanced ,
398+ enabled = enabled , invalidate = invalidate , semantic = semantic ,
399+ validValue = validValue , errorMessage = errorMessage ,
369400 visible = visible , exposed = exposed )
370401 self ._valueType = float
371402
0 commit comments