mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-02 08:18:25 +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
|
return value
|
||||||
|
|
||||||
def matchDescription(self, value):
|
def matchDescription(self, value, conform=False):
|
||||||
""" Returns whether the value perfectly match attribute's description. """
|
""" Returns whether the value perfectly match attribute's description.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: the value
|
||||||
|
conform: try to adapt value to match the description
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.validateValue(value)
|
self.validateValue(value)
|
||||||
except ValueError:
|
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)))
|
raise ValueError('ListAttribute only supports list/tuple input values (param:{}, value:{}, type:{})'.format(self.name, value, type(value)))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def matchDescription(self, value):
|
def matchDescription(self, value, conform=False):
|
||||||
""" Check that 'value' content matches ListAttribute's element description. """
|
""" 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
|
return False
|
||||||
# list must be homogeneous: only test first element
|
# list must be homogeneous: only test first element
|
||||||
if value:
|
if value:
|
||||||
return self._elementDesc.matchDescription(value[0])
|
return self._elementDesc.matchDescription(value[0], conform)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,20 +102,32 @@ class GroupAttribute(Attribute):
|
||||||
raise ValueError('Value contains key that does not match group description : {}'.format(invalidKeys))
|
raise ValueError('Value contains key that does not match group description : {}'.format(invalidKeys))
|
||||||
return value
|
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
|
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.
|
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):
|
if not super(GroupAttribute, self).matchDescription(value):
|
||||||
return False
|
return False
|
||||||
attrMap = {attr.name: attr for attr in self._groupDesc}
|
attrMap = {attr.name: attr for attr in self._groupDesc}
|
||||||
# must have the exact same child attributes
|
|
||||||
if sorted(value.keys()) != sorted(attrMap.keys()):
|
if conform:
|
||||||
return False
|
# 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():
|
for k, v in value.items():
|
||||||
# each child value must match corresponding child attribute description
|
# 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 False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -880,14 +880,9 @@ class CompatibilityNode(BaseNode):
|
||||||
self.splitCount = self.parallelization.get("split", 1)
|
self.splitCount = self.parallelization.get("split", 1)
|
||||||
self.setSize(self.parallelization.get("size", 1))
|
self.setSize(self.parallelization.get("size", 1))
|
||||||
|
|
||||||
# inputs matching current type description
|
|
||||||
self._commonInputs = []
|
|
||||||
# create input attributes
|
# create input attributes
|
||||||
for attrName, value in self._inputs.items():
|
for attrName, value in self._inputs.items():
|
||||||
matchDesc = self._addAttribute(attrName, value, False)
|
self._addAttribute(attrName, value, False)
|
||||||
# store attributes that could be used during node upgrade
|
|
||||||
if matchDesc:
|
|
||||||
self._commonInputs.append(attrName)
|
|
||||||
|
|
||||||
# create outputs attributes
|
# create outputs attributes
|
||||||
for attrName, value in self.outputs.items():
|
for attrName, value in self.outputs.items():
|
||||||
|
@ -951,7 +946,7 @@ class CompatibilityNode(BaseNode):
|
||||||
return desc.StringParam(**params)
|
return desc.StringParam(**params)
|
||||||
|
|
||||||
@staticmethod
|
@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'.
|
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:
|
# consider this value matches description:
|
||||||
# - if it's a serialized link expression (no proper value to set/evaluate)
|
# - if it's a serialized link expression (no proper value to set/evaluate)
|
||||||
# - or if it passes the 'matchDescription' test
|
# - 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 attrDesc
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _addAttribute(self, name, val, isOutput):
|
def _addAttribute(self, name, val, isOutput):
|
||||||
|
@ -1043,8 +1039,16 @@ class CompatibilityNode(BaseNode):
|
||||||
if not self.canUpgrade:
|
if not self.canUpgrade:
|
||||||
raise NodeUpgradeError(self.name, "no matching node type")
|
raise NodeUpgradeError(self.name, "no matching node type")
|
||||||
# TODO: use upgrade method of node description if available
|
# 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,
|
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)
|
compatibilityIssue = Property(int, lambda self: self.issue.value, constant=True)
|
||||||
canUpgrade = Property(bool, canUpgrade.fget, constant=True)
|
canUpgrade = Property(bool, canUpgrade.fget, constant=True)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue