mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-29 02:08:08 +02:00
[core] compatibility : List of groups update is more flexible
This commit is contained in:
parent
2e6990d2c6
commit
1f7663259a
2 changed files with 40 additions and 19 deletions
|
@ -38,8 +38,13 @@ class Attribute(BaseObject):
|
|||
"""
|
||||
return value
|
||||
|
||||
def matchDescription(self, value):
|
||||
""" Returns whether the value perfectly match attribute's description. """
|
||||
def matchDescription(self, value, conform=False):
|
||||
""" Returns whether the value perfectly match attribute's description.
|
||||
|
||||
Args:
|
||||
value: the value
|
||||
conform: try to adapt value to match the description
|
||||
"""
|
||||
try:
|
||||
self.validateValue(value)
|
||||
except ValueError:
|
||||
|
@ -66,13 +71,13 @@ class ListAttribute(Attribute):
|
|||
raise ValueError('ListAttribute only supports list/tuple input values (param:{}, value:{}, type:{})'.format(self.name, value, type(value)))
|
||||
return value
|
||||
|
||||
def matchDescription(self, value):
|
||||
def matchDescription(self, value, conform=False):
|
||||
""" Check that 'value' content matches ListAttribute's element description. """
|
||||
if not super(ListAttribute, self).matchDescription(value):
|
||||
if not super(ListAttribute, self).matchDescription(value, conform):
|
||||
return False
|
||||
# list must be homogeneous: only test first element
|
||||
if value:
|
||||
return self._elementDesc.matchDescription(value[0])
|
||||
return self._elementDesc.matchDescription(value[0], conform)
|
||||
return True
|
||||
|
||||
|
||||
|
@ -97,20 +102,32 @@ class GroupAttribute(Attribute):
|
|||
raise ValueError('Value contains key that does not match group description : {}'.format(invalidKeys))
|
||||
return value
|
||||
|
||||
def matchDescription(self, value):
|
||||
def matchDescription(self, value, conform=False):
|
||||
"""
|
||||
Check that 'value' contains the exact same set of keys as GroupAttribute's group description
|
||||
and that every child value match corresponding child attribute description.
|
||||
|
||||
Args:
|
||||
value: the value
|
||||
conform: remove entries that don't exist in the description.
|
||||
"""
|
||||
if not super(GroupAttribute, self).matchDescription(value):
|
||||
return False
|
||||
attrMap = {attr.name: attr for attr in self._groupDesc}
|
||||
# must have the exact same child attributes
|
||||
if sorted(value.keys()) != sorted(attrMap.keys()):
|
||||
return False
|
||||
|
||||
if conform:
|
||||
# remove invalid keys
|
||||
invalidKeys = set(value.keys()).difference([attr.name for attr in self._groupDesc])
|
||||
for k in invalidKeys:
|
||||
del self._groupDesc[k]
|
||||
else:
|
||||
# must have the exact same child attributes
|
||||
if sorted(value.keys()) != sorted(attrMap.keys()):
|
||||
return False
|
||||
|
||||
for k, v in value.items():
|
||||
# each child value must match corresponding child attribute description
|
||||
if not attrMap[k].matchDescription(v):
|
||||
if not attrMap[k].matchDescription(v, conform):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -880,14 +880,9 @@ class CompatibilityNode(BaseNode):
|
|||
self.splitCount = self.parallelization.get("split", 1)
|
||||
self.setSize(self.parallelization.get("size", 1))
|
||||
|
||||
# inputs matching current type description
|
||||
self._commonInputs = []
|
||||
# create input attributes
|
||||
for attrName, value in self._inputs.items():
|
||||
matchDesc = self._addAttribute(attrName, value, False)
|
||||
# store attributes that could be used during node upgrade
|
||||
if matchDesc:
|
||||
self._commonInputs.append(attrName)
|
||||
self._addAttribute(attrName, value, False)
|
||||
|
||||
# create outputs attributes
|
||||
for attrName, value in self.outputs.items():
|
||||
|
@ -951,7 +946,7 @@ class CompatibilityNode(BaseNode):
|
|||
return desc.StringParam(**params)
|
||||
|
||||
@staticmethod
|
||||
def attributeDescFromName(refAttributes, name, value):
|
||||
def attributeDescFromName(refAttributes, name, value, conform=False):
|
||||
"""
|
||||
Try to find a matching attribute description in refAttributes for given attribute 'name' and 'value'.
|
||||
|
||||
|
@ -968,8 +963,9 @@ class CompatibilityNode(BaseNode):
|
|||
# consider this value matches description:
|
||||
# - if it's a serialized link expression (no proper value to set/evaluate)
|
||||
# - or if it passes the 'matchDescription' test
|
||||
if attrDesc and (Attribute.isLinkExpression(value) or attrDesc.matchDescription(value)):
|
||||
if attrDesc and (Attribute.isLinkExpression(value) or attrDesc.matchDescription(value, conform)):
|
||||
return attrDesc
|
||||
|
||||
return None
|
||||
|
||||
def _addAttribute(self, name, val, isOutput):
|
||||
|
@ -1043,8 +1039,16 @@ class CompatibilityNode(BaseNode):
|
|||
if not self.canUpgrade:
|
||||
raise NodeUpgradeError(self.name, "no matching node type")
|
||||
# TODO: use upgrade method of node description if available
|
||||
|
||||
# inputs matching current type description
|
||||
commonInputs = []
|
||||
for attrName, value in self._inputs.items():
|
||||
if self.attributeDescFromName(self.nodeDesc.inputs, attrName, value, conform=True):
|
||||
# store attributes that could be used during node upgrade
|
||||
commonInputs.append(attrName)
|
||||
|
||||
return Node(self.nodeType, position=self.position,
|
||||
**{key: value for key, value in self.inputs.items() if key in self._commonInputs})
|
||||
**{key: value for key, value in self.inputs.items() if key in commonInputs})
|
||||
|
||||
compatibilityIssue = Property(int, lambda self: self.issue.value, constant=True)
|
||||
canUpgrade = Property(bool, canUpgrade.fget, constant=True)
|
||||
|
|
Loading…
Add table
Reference in a new issue