[core] add validator per attribute type

This commit is contained in:
Fabien Castan 2017-10-31 16:48:51 +01:00
parent 11cfece411
commit 329dcba3a5
2 changed files with 67 additions and 1 deletions

View file

@ -1,5 +1,7 @@
from meshroom.common import BaseObject, Property, Variant
from enum import Enum # available by default in python3. For python2: "pip install enum34"
import collections
import os
class Attribute(BaseObject):
@ -23,6 +25,9 @@ class Attribute(BaseObject):
isOutput = Property(bool, lambda self: self._isOutput, constant=True)
isInput = Property(bool, lambda self: not self._isOutput, constant=True)
def validateValue(self, value):
return value
class ListAttribute(Attribute):
""" A list of Attributes """
@ -35,6 +40,11 @@ class ListAttribute(Attribute):
uid = Property(Variant, lambda self: self.elementDesc.uid, constant=True)
def validateValue(self, value):
if not (isinstance(value, collections.Iterable) and isinstance(value, basestring)):
raise ValueError('ListAttribute only supports iterable input values.')
return value
class GroupAttribute(Attribute):
""" A macro Attribute composed of several Attributes """
@ -45,6 +55,11 @@ class GroupAttribute(Attribute):
self.groupDesc = groupDesc
super(GroupAttribute, self).__init__(label=label, description=description, value=None, uid=(), group=group)
def validateValue(self, value):
if not (isinstance(value, collections.Iterable) and isinstance(value, basestring)):
raise ValueError('GroupAttribute only supports iterable input values.')
return value
def retrieveChildrenUids(self):
allUids = []
for desc in self.groupDesc.values():
@ -68,6 +83,11 @@ class File(Attribute):
super(File, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
self._isOutput = isOutput
def validateValue(self, value):
if not isinstance(value, basestring):
raise ValueError('File only supports string input: "{}".'.format(value))
return os.path.normpath(value).replace('\\', '/')
class BoolParam(Param):
"""
@ -75,6 +95,12 @@ class BoolParam(Param):
def __init__(self, label, description, value, uid, group='allParams'):
super(BoolParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
def validateValue(self, value):
try:
return bool(value)
except:
raise ValueError('BoolParam only supports bool value.')
class IntParam(Param):
"""
@ -83,6 +109,12 @@ class IntParam(Param):
self._range = range
super(IntParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
def validateValue(self, value):
try:
return int(value)
except:
raise ValueError('IntParam only supports int value.')
range = Property(Variant, lambda self: self._range, constant=True)
@ -93,6 +125,12 @@ class FloatParam(Param):
self._range = range
super(FloatParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
def validateValue(self, value):
try:
return float(value)
except:
raise ValueError('FloatParam only supports float value.')
range = Property(Variant, lambda self: self._range, constant=True)
@ -105,6 +143,19 @@ class ChoiceParam(Param):
self._joinChar = joinChar
super(ChoiceParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
def validateValue(self, value):
newValues = None
if self.exclusive:
newValues = [value]
else:
if not isinstance(value, collections.Iterable):
raise ValueError('Non exclusive ChoiceParam value "{}" should be iterable.'.format(value))
newValues = value
for newValue in newValues:
if newValue not in self.values:
raise ValueError('ChoiceParam value "{}" is not in "{}".'.format(newValue, str(self.values)))
return value
values = Property(Variant, lambda self: self._values, constant=True)
exclusive = Property(bool, lambda self: self._exclusive, constant=True)
joinChar = Property(str, lambda self: self._joinChar, constant=True)
@ -116,6 +167,11 @@ class StringParam(Param):
def __init__(self, label, description, value, uid, group='allParams'):
super(StringParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group)
def validateValue(self, value):
if not isinstance(value, basestring):
raise ValueError('StringParam value "{}" should be a string.'.format(value))
return value
class Level(Enum):
NONE = 0

View file

@ -14,6 +14,7 @@ from collections import defaultdict
from contextlib import contextmanager
from enum import Enum # available by default in python3. For python2: "pip install enum34"
import logging
import re
from . import stats
from . import desc
@ -48,6 +49,7 @@ else:
bytes = str
basestring = basestring
stringIsLinkRe = re.compile('^\{.+\}$')
@contextmanager
def GraphModification(graph):
@ -143,7 +145,15 @@ class Attribute(BaseObject):
def _set_value(self, value):
if self._value == value:
return
self._value = value
if isinstance(value, Attribute) or (isinstance(value, basestring) and stringIsLinkRe.match(value)):
# if we set a link to another attribute
self._value = value
else:
# if we set a new value, we use the attribute descriptor validator to check the validity of the value
# and apply some conversion if needed
convertedValue = self.desc.validateValue(value)
self._value = convertedValue
# Request graph update when input parameter value is set
# and parent node belongs to a graph
# Output attributes value are set internally during the update process,