mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-06-20 19:47:22 +02:00
[tests] Harmonize and clean-up syntax across test files
Also comply more with PEP8 linting rules.
This commit is contained in:
parent
441ba37c24
commit
28042dd2ad
11 changed files with 218 additions and 189 deletions
|
@ -39,4 +39,3 @@ class AppendFiles(desc.CommandLineNode):
|
||||||
value='{nodeCacheFolder}/appendText.txt',
|
value='{nodeCacheFolder}/appendText.txt',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,21 @@ from meshroom.core import desc
|
||||||
|
|
||||||
|
|
||||||
class Ls(desc.CommandLineNode):
|
class Ls(desc.CommandLineNode):
|
||||||
commandLine = 'ls {inputValue} > {outputValue}'
|
commandLine = "ls {inputValue} > {outputValue}"
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(
|
desc.File(
|
||||||
name='input',
|
name="input",
|
||||||
label='Input',
|
label="Input",
|
||||||
description='''''',
|
description="",
|
||||||
value='',
|
value="",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(
|
desc.File(
|
||||||
name='output',
|
name="output",
|
||||||
label='Output',
|
label="Output",
|
||||||
description='''''',
|
description="",
|
||||||
value='{nodeCacheFolder}/ls.txt',
|
value="{nodeCacheFolder}/ls.txt",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -84,7 +84,7 @@ class TestChoiceParam:
|
||||||
graph: Graph = graphSavedOnDisk
|
graph: Graph = graphSavedOnDisk
|
||||||
node = graph.addNewNode(NodeWithChoiceParams.__name__)
|
node = graph.addNewNode(NodeWithChoiceParams.__name__)
|
||||||
node.choice.values = ["D", "E", "F"]
|
node.choice.values = ["D", "E", "F"]
|
||||||
|
|
||||||
graph.save()
|
graph.save()
|
||||||
loadedGraph = loadGraph(graph.filepath)
|
loadedGraph = loadGraph(graph.filepath)
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ class TestChoiceParamSavingCustomValues:
|
||||||
node = graph.addNewNode(NodeWithChoiceParamsSavingValuesOverride.__name__)
|
node = graph.addNewNode(NodeWithChoiceParamsSavingValuesOverride.__name__)
|
||||||
node.choice.values = ["D", "E", "F"]
|
node.choice.values = ["D", "E", "F"]
|
||||||
node.choiceMulti.values = ["D", "E", "F"]
|
node.choiceMulti.values = ["D", "E", "F"]
|
||||||
|
|
||||||
graph.save()
|
graph.save()
|
||||||
loadedGraph = loadGraph(graph.filepath)
|
loadedGraph = loadGraph(graph.filepath)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ SampleGroupV1 = [
|
||||||
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
||||||
desc.ListAttribute(
|
desc.ListAttribute(
|
||||||
name="b",
|
name="b",
|
||||||
elementDesc=desc.FloatParam(name="p", label="", description="", value=0.0, range=None),
|
elementDesc=desc.FloatParam(name="p", label="",
|
||||||
|
description="", value=0.0, range=None),
|
||||||
label="b",
|
label="b",
|
||||||
description="",
|
description="",
|
||||||
)
|
)
|
||||||
|
@ -30,7 +31,8 @@ SampleGroupV2 = [
|
||||||
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
||||||
desc.ListAttribute(
|
desc.ListAttribute(
|
||||||
name="b",
|
name="b",
|
||||||
elementDesc=desc.GroupAttribute(name="p", label="", description="", groupDesc=SampleGroupV1),
|
elementDesc=desc.GroupAttribute(name="p", label="",
|
||||||
|
description="", groupDesc=SampleGroupV1),
|
||||||
label="b",
|
label="b",
|
||||||
description="",
|
description="",
|
||||||
)
|
)
|
||||||
|
@ -39,10 +41,12 @@ SampleGroupV2 = [
|
||||||
# SampleGroupV3 is SampleGroupV2 with one more int parameter
|
# SampleGroupV3 is SampleGroupV2 with one more int parameter
|
||||||
SampleGroupV3 = [
|
SampleGroupV3 = [
|
||||||
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
||||||
desc.IntParam(name="notInSampleGroupV2", label="notInSampleGroupV2", description="", value=0, range=None),
|
desc.IntParam(name="notInSampleGroupV2", label="notInSampleGroupV2",
|
||||||
|
description="", value=0, range=None),
|
||||||
desc.ListAttribute(
|
desc.ListAttribute(
|
||||||
name="b",
|
name="b",
|
||||||
elementDesc=desc.GroupAttribute(name="p", label="", description="", groupDesc=SampleGroupV1),
|
elementDesc=desc.GroupAttribute(name="p", label="",
|
||||||
|
description="", groupDesc=SampleGroupV1),
|
||||||
label="b",
|
label="b",
|
||||||
description="",
|
description="",
|
||||||
)
|
)
|
||||||
|
@ -52,11 +56,12 @@ SampleGroupV3 = [
|
||||||
class SampleNodeV1(desc.Node):
|
class SampleNodeV1(desc.Node):
|
||||||
""" Version 1 Sample Node """
|
""" Version 1 Sample Node """
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='input', label='Input', description='', value='',),
|
desc.File(name="input", label="Input", description="", value=""),
|
||||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False) # No impact on UID
|
desc.StringParam(name="paramA", label="ParamA", description="",
|
||||||
|
value="", invalidate=False) # No impact on UID
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,11 +70,12 @@ class SampleNodeV2(desc.Node):
|
||||||
* 'input' has been renamed to 'in'
|
* 'input' has been renamed to 'in'
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='in', label='Input', description='', value='',),
|
desc.File(name="in", label="Input", description="", value=""),
|
||||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False), # No impact on UID
|
desc.StringParam(name="paramA", label="ParamA", description="",
|
||||||
|
value="", invalidate=False), # No impact on UID
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,10 +85,10 @@ class SampleNodeV3(desc.Node):
|
||||||
* 'paramA' has been removed'
|
* 'paramA' has been removed'
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='in', label='Input', description='', value='',),
|
desc.File(name="in", label="Input", description="", value=""),
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,14 +98,14 @@ class SampleNodeV4(desc.Node):
|
||||||
* 'paramA' has been added
|
* 'paramA' has been added
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='in', label='Input', description='', value='',),
|
desc.File(name="in", label="Input", description="", value=""),
|
||||||
desc.ListAttribute(name='paramA', label='ParamA',
|
desc.ListAttribute(name="paramA", label="ParamA",
|
||||||
elementDesc=desc.GroupAttribute(
|
elementDesc=desc.GroupAttribute(
|
||||||
groupDesc=SampleGroupV1, name='gA', label='gA', description=''),
|
groupDesc=SampleGroupV1, name="gA", label="gA", description=""),
|
||||||
description='')
|
description="")
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,14 +115,14 @@ class SampleNodeV5(desc.Node):
|
||||||
* 'paramA' elementDesc has changed from SampleGroupV1 to SampleGroupV2
|
* 'paramA' elementDesc has changed from SampleGroupV1 to SampleGroupV2
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='in', label='Input', description='', value=''),
|
desc.File(name="in", label="Input", description="", value=""),
|
||||||
desc.ListAttribute(name='paramA', label='ParamA',
|
desc.ListAttribute(name="paramA", label="ParamA",
|
||||||
elementDesc=desc.GroupAttribute(
|
elementDesc=desc.GroupAttribute(
|
||||||
groupDesc=SampleGroupV2, name='gA', label='gA', description=''),
|
groupDesc=SampleGroupV2, name="gA", label="gA", description=""),
|
||||||
description='')
|
description="")
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,24 +132,25 @@ class SampleNodeV6(desc.Node):
|
||||||
* 'paramA' elementDesc has changed from SampleGroupV2 to SampleGroupV3
|
* 'paramA' elementDesc has changed from SampleGroupV2 to SampleGroupV3
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='in', label='Input', description='', value=''),
|
desc.File(name="in", label="Input", description="", value=""),
|
||||||
desc.ListAttribute(name='paramA', label='ParamA',
|
desc.ListAttribute(name="paramA", label="ParamA",
|
||||||
elementDesc=desc.GroupAttribute(
|
elementDesc=desc.GroupAttribute(
|
||||||
groupDesc=SampleGroupV3, name='gA', label='gA', description=''),
|
groupDesc=SampleGroupV3, name="gA", label="gA", description=""),
|
||||||
description='')
|
description="")
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SampleInputNodeV1(desc.InputNode):
|
class SampleInputNodeV1(desc.InputNode):
|
||||||
""" Version 1 Sample Input Node """
|
""" Version 1 Sample Input Node """
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.StringParam(name='path', label='path', description='', value='', invalidate=False) # No impact on UID
|
desc.StringParam(name="path", label="Path", description="",
|
||||||
|
value="", invalidate=False) # No impact on UID
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,10 +159,11 @@ class SampleInputNodeV2(desc.InputNode):
|
||||||
* 'path' has been renamed to 'in'
|
* 'path' has been renamed to 'in'
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.StringParam(name='in', label='path', description='', value='', invalidate=False) # No impact on UID
|
desc.StringParam(name="in", label="path", description="",
|
||||||
|
value="", invalidate=False) # No impact on UID
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,7 +178,7 @@ def test_unknown_node_type():
|
||||||
Test compatibility behavior for unknown node type.
|
Test compatibility behavior for unknown node type.
|
||||||
"""
|
"""
|
||||||
registerNodeType(SampleNodeV1)
|
registerNodeType(SampleNodeV1)
|
||||||
g = Graph('')
|
g = Graph("")
|
||||||
n = g.addNewNode("SampleNodeV1", input="/dev/null", paramA="foo")
|
n = g.addNewNode("SampleNodeV1", input="/dev/null", paramA="foo")
|
||||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_unknown_node_type.mg")
|
graphFile = os.path.join(tempfile.mkdtemp(), "test_unknown_node_type.mg")
|
||||||
g.save(graphFile)
|
g.save(graphFile)
|
||||||
|
@ -178,24 +186,25 @@ def test_unknown_node_type():
|
||||||
nodeName = n.name
|
nodeName = n.name
|
||||||
unregisterNodeType(SampleNodeV1)
|
unregisterNodeType(SampleNodeV1)
|
||||||
|
|
||||||
# reload file
|
|
||||||
|
# Reload file
|
||||||
g = loadGraph(graphFile)
|
g = loadGraph(graphFile)
|
||||||
os.remove(graphFile)
|
os.remove(graphFile)
|
||||||
|
|
||||||
assert len(g.nodes) == 1
|
assert len(g.nodes) == 1
|
||||||
n = g.node(nodeName)
|
n = g.node(nodeName)
|
||||||
# SampleNodeV1 is now an unknown type
|
# SampleNodeV1 is now an unknown type
|
||||||
# check node instance type and compatibility issue type
|
# Check node instance type and compatibility issue type
|
||||||
assert isinstance(n, CompatibilityNode)
|
assert isinstance(n, CompatibilityNode)
|
||||||
assert n.issue == CompatibilityIssue.UnknownNodeType
|
assert n.issue == CompatibilityIssue.UnknownNodeType
|
||||||
# check if attributes are properly restored
|
# Check if attributes are properly restored
|
||||||
assert len(n.attributes) == 3
|
assert len(n.attributes) == 3
|
||||||
assert n.input.isInput
|
assert n.input.isInput
|
||||||
assert n.output.isOutput
|
assert n.output.isOutput
|
||||||
# check if internal folder
|
# Check if internal folder
|
||||||
assert n.internalFolder == internalFolder
|
assert n.internalFolder == internalFolder
|
||||||
|
|
||||||
# upgrade can't be perform on unknown node types
|
# Upgrade can't be perform on unknown node types
|
||||||
assert not n.canUpgrade
|
assert not n.canUpgrade
|
||||||
with pytest.raises(NodeUpgradeError):
|
with pytest.raises(NodeUpgradeError):
|
||||||
g.upgradeNode(nodeName)
|
g.upgradeNode(nodeName)
|
||||||
|
@ -205,20 +214,20 @@ def test_description_conflict():
|
||||||
"""
|
"""
|
||||||
Test compatibility behavior for conflicting node descriptions.
|
Test compatibility behavior for conflicting node descriptions.
|
||||||
"""
|
"""
|
||||||
# copy registered node types to be able to restore them
|
# Copy registered node types to be able to restore them
|
||||||
originalNodeTypes = copy.copy(meshroom.core.nodesDesc)
|
originalNodeTypes = copy.deepcopy(pluginManager.getNodePlugins())
|
||||||
|
|
||||||
nodeTypes = [SampleNodeV1, SampleNodeV2, SampleNodeV3, SampleNodeV4, SampleNodeV5]
|
nodeTypes = [SampleNodeV1, SampleNodeV2, SampleNodeV3, SampleNodeV4, SampleNodeV5]
|
||||||
nodes = []
|
nodes = []
|
||||||
g = Graph('')
|
g = Graph("")
|
||||||
|
|
||||||
# register and instantiate instances of all node types except last one
|
# Register and instantiate instances of all node types except last one
|
||||||
for nt in nodeTypes[:-1]:
|
for nt in nodeTypes[:-1]:
|
||||||
registerNodeType(nt)
|
pluginManager.registerNode(NodePlugin(nt))
|
||||||
n = g.addNewNode(nt.__name__)
|
n = g.addNewNode(nt.__name__)
|
||||||
|
|
||||||
if nt == SampleNodeV4:
|
if nt == SampleNodeV4:
|
||||||
# initialize list attribute with values to create a conflict with V5
|
# Initialize list attribute with values to create a conflict with V5
|
||||||
n.paramA.value = [{'a': 0, 'b': [1.0, 2.0]}]
|
n.paramA.value = [{'a': 0, 'b': [1.0, 2.0]}]
|
||||||
|
|
||||||
nodes.append(n)
|
nodes.append(n)
|
||||||
|
@ -226,15 +235,15 @@ def test_description_conflict():
|
||||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
||||||
g.save(graphFile)
|
g.save(graphFile)
|
||||||
|
|
||||||
# reload file as-is, ensure no compatibility issue is detected (no CompatibilityNode instances)
|
# Reload file as-is, ensure no compatibility issue is detected (no CompatibilityNode instances)
|
||||||
loadGraph(graphFile, strictCompatibility=True)
|
loadGraph(graphFile, strictCompatibility=True)
|
||||||
|
|
||||||
# offset node types register to create description conflicts
|
# Offset node types register to create description conflicts
|
||||||
# each node type name now reference the next one's implementation
|
# Each node type name now reference the next one's implementation
|
||||||
for i, nt in enumerate(nodeTypes[:-1]):
|
for i, nt in enumerate(nodeTypes[:-1]):
|
||||||
meshroom.core.nodesDesc[nt.__name__] = nodeTypes[i+1]
|
pluginManager.getNodePlugins()[nt.__name__] = NodePlugin(nodeTypes[i + 1])
|
||||||
|
|
||||||
# reload file
|
# Reload file
|
||||||
g = loadGraph(graphFile)
|
g = loadGraph(graphFile)
|
||||||
os.remove(graphFile)
|
os.remove(graphFile)
|
||||||
|
|
||||||
|
@ -246,7 +255,7 @@ def test_description_conflict():
|
||||||
assert isinstance(compatNode, CompatibilityNode)
|
assert isinstance(compatNode, CompatibilityNode)
|
||||||
assert srcNode.internalFolder == compatNode.internalFolder
|
assert srcNode.internalFolder == compatNode.internalFolder
|
||||||
|
|
||||||
# case by case description conflict verification
|
# Case by case description conflict verification
|
||||||
if isinstance(srcNode.nodeDesc, SampleNodeV1):
|
if isinstance(srcNode.nodeDesc, SampleNodeV1):
|
||||||
# V1 => V2: 'input' has been renamed to 'in'
|
# V1 => V2: 'input' has been renamed to 'in'
|
||||||
assert len(compatNode.attributes) == 3
|
assert len(compatNode.attributes) == 3
|
||||||
|
@ -254,27 +263,29 @@ def test_description_conflict():
|
||||||
assert hasattr(compatNode, "input")
|
assert hasattr(compatNode, "input")
|
||||||
assert not hasattr(compatNode, "in")
|
assert not hasattr(compatNode, "in")
|
||||||
|
|
||||||
# perform upgrade
|
# Perform upgrade
|
||||||
upgradedNode = g.upgradeNode(nodeName)
|
upgradedNode = g.upgradeNode(nodeName)
|
||||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV2)
|
assert isinstance(upgradedNode, Node) and \
|
||||||
|
isinstance(upgradedNode.nodeDesc, SampleNodeV2)
|
||||||
|
|
||||||
assert list(upgradedNode.attributes.keys()) == ["in", "paramA", "output"]
|
assert list(upgradedNode.attributes.keys()) == ["in", "paramA", "output"]
|
||||||
assert not hasattr(upgradedNode, "input")
|
assert not hasattr(upgradedNode, "input")
|
||||||
assert hasattr(upgradedNode, "in")
|
assert hasattr(upgradedNode, "in")
|
||||||
# check uid has changed (not the same set of attributes)
|
# Check UID has changed (not the same set of attributes)
|
||||||
assert upgradedNode.internalFolder != srcNode.internalFolder
|
assert upgradedNode.internalFolder != srcNode.internalFolder
|
||||||
|
|
||||||
elif isinstance(srcNode.nodeDesc, SampleNodeV2):
|
elif isinstance(srcNode.nodeDesc, SampleNodeV2):
|
||||||
# V2 => V3: 'paramA' has been removed'
|
# V2 => V3: 'paramA' has been removed
|
||||||
assert len(compatNode.attributes) == 3
|
assert len(compatNode.attributes) == 3
|
||||||
assert hasattr(compatNode, "paramA")
|
assert hasattr(compatNode, "paramA")
|
||||||
|
|
||||||
# perform upgrade
|
# Perform upgrade
|
||||||
upgradedNode = g.upgradeNode(nodeName)
|
upgradedNode = g.upgradeNode(nodeName)
|
||||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV3)
|
assert isinstance(upgradedNode, Node) and \
|
||||||
|
isinstance(upgradedNode.nodeDesc, SampleNodeV3)
|
||||||
|
|
||||||
assert not hasattr(upgradedNode, "paramA")
|
assert not hasattr(upgradedNode, "paramA")
|
||||||
# check uid is identical (paramA not part of uid)
|
# Check UID is identical (paramA not part of UID)
|
||||||
assert upgradedNode.internalFolder == srcNode.internalFolder
|
assert upgradedNode.internalFolder == srcNode.internalFolder
|
||||||
|
|
||||||
elif isinstance(srcNode.nodeDesc, SampleNodeV3):
|
elif isinstance(srcNode.nodeDesc, SampleNodeV3):
|
||||||
|
@ -282,9 +293,10 @@ def test_description_conflict():
|
||||||
assert len(compatNode.attributes) == 2
|
assert len(compatNode.attributes) == 2
|
||||||
assert not hasattr(compatNode, "paramA")
|
assert not hasattr(compatNode, "paramA")
|
||||||
|
|
||||||
# perform upgrade
|
# Perform upgrade
|
||||||
upgradedNode = g.upgradeNode(nodeName)
|
upgradedNode = g.upgradeNode(nodeName)
|
||||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV4)
|
assert isinstance(upgradedNode, Node) and \
|
||||||
|
isinstance(upgradedNode.nodeDesc, SampleNodeV4)
|
||||||
|
|
||||||
assert hasattr(upgradedNode, "paramA")
|
assert hasattr(upgradedNode, "paramA")
|
||||||
assert isinstance(upgradedNode.paramA.attributeDesc, desc.ListAttribute)
|
assert isinstance(upgradedNode.paramA.attributeDesc, desc.ListAttribute)
|
||||||
|
@ -298,22 +310,24 @@ def test_description_conflict():
|
||||||
groupAttribute = compatNode.paramA.attributeDesc.elementDesc
|
groupAttribute = compatNode.paramA.attributeDesc.elementDesc
|
||||||
|
|
||||||
assert isinstance(groupAttribute, desc.GroupAttribute)
|
assert isinstance(groupAttribute, desc.GroupAttribute)
|
||||||
# check that Compatibility node respect SampleGroupV1 description
|
# Check that Compatibility node respect SampleGroupV1 description
|
||||||
for elt in groupAttribute.groupDesc:
|
for elt in groupAttribute.groupDesc:
|
||||||
assert isinstance(elt, next(a for a in SampleGroupV1 if a.name == elt.name).__class__)
|
assert isinstance(elt,
|
||||||
|
next(a for a in SampleGroupV1 if a.name == elt.name).__class__)
|
||||||
|
|
||||||
# perform upgrade
|
# Perform upgrade
|
||||||
upgradedNode = g.upgradeNode(nodeName)
|
upgradedNode = g.upgradeNode(nodeName)
|
||||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV5)
|
assert isinstance(upgradedNode, Node) and \
|
||||||
|
isinstance(upgradedNode.nodeDesc, SampleNodeV5)
|
||||||
|
|
||||||
assert hasattr(upgradedNode, "paramA")
|
assert hasattr(upgradedNode, "paramA")
|
||||||
# parameter was incompatible, value could not be restored
|
# Parameter was incompatible, value could not be restored
|
||||||
assert upgradedNode.paramA.isDefault
|
assert upgradedNode.paramA.isDefault
|
||||||
assert upgradedNode.internalFolder != srcNode.internalFolder
|
assert upgradedNode.internalFolder != srcNode.internalFolder
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unexpected node type: " + srcNode.nodeType)
|
raise ValueError("Unexpected node type: " + srcNode.nodeType)
|
||||||
|
|
||||||
# restore original node types
|
# Restore original node types
|
||||||
meshroom.core.nodesDesc = originalNodeTypes
|
meshroom.core.nodesDesc = originalNodeTypes
|
||||||
|
|
||||||
|
|
||||||
|
@ -323,7 +337,7 @@ def test_upgradeAllNodes():
|
||||||
registerNodeType(SampleInputNodeV1)
|
registerNodeType(SampleInputNodeV1)
|
||||||
registerNodeType(SampleInputNodeV2)
|
registerNodeType(SampleInputNodeV2)
|
||||||
|
|
||||||
g = Graph('')
|
g = Graph("")
|
||||||
n1 = g.addNewNode("SampleNodeV1")
|
n1 = g.addNewNode("SampleNodeV1")
|
||||||
n2 = g.addNewNode("SampleNodeV2")
|
n2 = g.addNewNode("SampleNodeV2")
|
||||||
n3 = g.addNewNode("SampleInputNodeV1")
|
n3 = g.addNewNode("SampleInputNodeV1")
|
||||||
|
@ -335,28 +349,28 @@ def test_upgradeAllNodes():
|
||||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
||||||
g.save(graphFile)
|
g.save(graphFile)
|
||||||
|
|
||||||
# make SampleNodeV2 and SampleInputNodeV2 an unknown type
|
# Make SampleNodeV2 and SampleInputNodeV2 an unknown type
|
||||||
unregisterNodeType(SampleNodeV2)
|
unregisterNodeType(SampleNodeV2)
|
||||||
unregisterNodeType(SampleInputNodeV2)
|
unregisterNodeType(SampleInputNodeV2)
|
||||||
# replace SampleNodeV1 by SampleNodeV2 and SampleInputNodeV1 by SampleInputNodeV2
|
|
||||||
meshroom.core.nodesDesc[SampleNodeV1.__name__] = SampleNodeV2
|
meshroom.core.nodesDesc[SampleNodeV1.__name__] = SampleNodeV2
|
||||||
meshroom.core.nodesDesc[SampleInputNodeV1.__name__] = SampleInputNodeV2
|
meshroom.core.nodesDesc[SampleInputNodeV1.__name__] = SampleInputNodeV2
|
||||||
|
# Replace SampleNodeV1 by SampleNodeV2 and SampleInputNodeV1 by SampleInputNodeV2
|
||||||
|
|
||||||
# reload file
|
# Reload file
|
||||||
g = loadGraph(graphFile)
|
g = loadGraph(graphFile)
|
||||||
os.remove(graphFile)
|
os.remove(graphFile)
|
||||||
|
|
||||||
# both nodes are CompatibilityNodes
|
# Both nodes are CompatibilityNodes
|
||||||
assert len(g.compatibilityNodes) == 4
|
assert len(g.compatibilityNodes) == 4
|
||||||
assert g.node(n1Name).canUpgrade # description conflict
|
assert g.node(n1Name).canUpgrade # description conflict
|
||||||
assert not g.node(n2Name).canUpgrade # unknown type
|
assert not g.node(n2Name).canUpgrade # unknown type
|
||||||
assert g.node(n3Name).canUpgrade # description conflict
|
assert g.node(n3Name).canUpgrade # description conflict
|
||||||
assert not g.node(n4Name).canUpgrade # unknown type
|
assert not g.node(n4Name).canUpgrade # unknown type
|
||||||
|
|
||||||
# upgrade all upgradable nodes
|
# Upgrade all upgradable nodes
|
||||||
g.upgradeAllNodes()
|
g.upgradeAllNodes()
|
||||||
|
|
||||||
# only the nodes with an unknown type have not been upgraded
|
# Only the nodes with an unknown type have not been upgraded
|
||||||
assert len(g.compatibilityNodes) == 2
|
assert len(g.compatibilityNodes) == 2
|
||||||
assert n2Name in g.compatibilityNodes.keys()
|
assert n2Name in g.compatibilityNodes.keys()
|
||||||
assert n4Name in g.compatibilityNodes.keys()
|
assert n4Name in g.compatibilityNodes.keys()
|
||||||
|
@ -369,36 +383,36 @@ def test_conformUpgrade():
|
||||||
registerNodeType(SampleNodeV5)
|
registerNodeType(SampleNodeV5)
|
||||||
registerNodeType(SampleNodeV6)
|
registerNodeType(SampleNodeV6)
|
||||||
|
|
||||||
g = Graph('')
|
g = Graph("")
|
||||||
n1 = g.addNewNode("SampleNodeV5")
|
n1 = g.addNewNode("SampleNodeV5")
|
||||||
n1.paramA.value = [{'a': 0, 'b': [{'a': 0, 'b': [1.0, 2.0]}, {'a': 1, 'b': [1.0, 2.0]}]}]
|
n1.paramA.value = [{"a": 0, "b": [{"a": 0, "b": [1.0, 2.0]}, {"a": 1, "b": [1.0, 2.0]}]}]
|
||||||
n1Name = n1.name
|
n1Name = n1.name
|
||||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_conform_upgrade.mg")
|
graphFile = os.path.join(tempfile.mkdtemp(), "test_conform_upgrade.mg")
|
||||||
g.save(graphFile)
|
g.save(graphFile)
|
||||||
|
|
||||||
# replace SampleNodeV5 by SampleNodeV6
|
# Replace SampleNodeV5 by SampleNodeV6
|
||||||
meshroom.core.nodesDesc[SampleNodeV5.__name__] = SampleNodeV6
|
meshroom.core.nodesDesc[SampleNodeV5.__name__] = SampleNodeV6
|
||||||
|
|
||||||
# reload file
|
# Reload file
|
||||||
g = loadGraph(graphFile)
|
g = loadGraph(graphFile)
|
||||||
os.remove(graphFile)
|
os.remove(graphFile)
|
||||||
|
|
||||||
# node is a CompatibilityNode
|
# Node is a CompatibilityNode
|
||||||
assert len(g.compatibilityNodes) == 1
|
assert len(g.compatibilityNodes) == 1
|
||||||
assert g.node(n1Name).canUpgrade
|
assert g.node(n1Name).canUpgrade
|
||||||
|
|
||||||
# upgrade all upgradable nodes
|
# Upgrade all upgradable nodes
|
||||||
g.upgradeAllNodes()
|
g.upgradeAllNodes()
|
||||||
|
|
||||||
# only the node with an unknown type has not been upgraded
|
# Only the node with an unknown type has not been upgraded
|
||||||
assert len(g.compatibilityNodes) == 0
|
assert len(g.compatibilityNodes) == 0
|
||||||
|
|
||||||
upgradedNode = g.node(n1Name)
|
upgradedNode = g.node(n1Name)
|
||||||
|
|
||||||
# check upgrade
|
# Check upgrade
|
||||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV6)
|
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV6)
|
||||||
|
|
||||||
# check conformation
|
# Check conformation
|
||||||
assert len(upgradedNode.paramA.value) == 1
|
assert len(upgradedNode.paramA.value) == 1
|
||||||
|
|
||||||
unregisterNodeType(SampleNodeV5)
|
unregisterNodeType(SampleNodeV5)
|
||||||
|
@ -482,7 +496,7 @@ class TestVersionConflict:
|
||||||
with overrideNodeTypeVersion(SampleNodeV1, "1.0"):
|
with overrideNodeTypeVersion(SampleNodeV1, "1.0"):
|
||||||
node = graph.addNewNode(SampleNodeV1.__name__)
|
node = graph.addNewNode(SampleNodeV1.__name__)
|
||||||
graph.save()
|
graph.save()
|
||||||
|
|
||||||
with overrideNodeTypeVersion(SampleNodeV1, "2.0"):
|
with overrideNodeTypeVersion(SampleNodeV1, "2.0"):
|
||||||
otherGraph = Graph("")
|
otherGraph = Graph("")
|
||||||
otherGraph.load(graph.filepath)
|
otherGraph.load(graph.filepath)
|
||||||
|
@ -496,7 +510,7 @@ class TestVersionConflict:
|
||||||
with registeredNodeTypes([SampleNodeV1]):
|
with registeredNodeTypes([SampleNodeV1]):
|
||||||
graph.addNewNode(SampleNodeV1.__name__)
|
graph.addNewNode(SampleNodeV1.__name__)
|
||||||
graph.save()
|
graph.save()
|
||||||
|
|
||||||
with overrideNodeTypeVersion(SampleNodeV1, "2.0"):
|
with overrideNodeTypeVersion(SampleNodeV1, "2.0"):
|
||||||
otherGraph = Graph("")
|
otherGraph = Graph("")
|
||||||
otherGraph.load(graph.filepath)
|
otherGraph.load(graph.filepath)
|
||||||
|
@ -508,7 +522,8 @@ class UidTestingNodeV1(desc.Node):
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name="input", label="Input", description="", value="", invalidate=True),
|
desc.File(name="input", label="Input", description="", value="", invalidate=True),
|
||||||
]
|
]
|
||||||
outputs = [desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")]
|
outputs = [desc.File(name="output", label="Output",
|
||||||
|
description="", value="{nodeCacheFolder}")]
|
||||||
|
|
||||||
|
|
||||||
class UidTestingNodeV2(desc.Node):
|
class UidTestingNodeV2(desc.Node):
|
||||||
|
@ -554,7 +569,8 @@ class UidTestingNodeV3(desc.Node):
|
||||||
description="",
|
description="",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
outputs = [desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")]
|
outputs = [desc.File(name="output", label="Output",
|
||||||
|
description="", value="{nodeCacheFolder}")]
|
||||||
|
|
||||||
|
|
||||||
class TestUidConflict:
|
class TestUidConflict:
|
||||||
|
@ -626,7 +642,8 @@ class TestUidConflict:
|
||||||
assert len(loadedGraph.compatibilityNodes) == 0
|
assert len(loadedGraph.compatibilityNodes) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughConnection(self, graphSavedOnDisk):
|
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughConnection(
|
||||||
|
self, graphSavedOnDisk):
|
||||||
with registeredNodeTypes([UidTestingNodeV1, UidTestingNodeV2]):
|
with registeredNodeTypes([UidTestingNodeV1, UidTestingNodeV2]):
|
||||||
graph: Graph = graphSavedOnDisk
|
graph: Graph = graphSavedOnDisk
|
||||||
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
||||||
|
@ -640,7 +657,8 @@ class TestUidConflict:
|
||||||
loadedGraph = loadGraph(graph.filepath)
|
loadedGraph = loadGraph(graph.filepath)
|
||||||
assert len(loadedGraph.compatibilityNodes) == 1
|
assert len(loadedGraph.compatibilityNodes) == 1
|
||||||
|
|
||||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughListConnection(self, graphSavedOnDisk):
|
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughListConnection(
|
||||||
|
self,graphSavedOnDisk):
|
||||||
with registeredNodeTypes([UidTestingNodeV2, UidTestingNodeV3]):
|
with registeredNodeTypes([UidTestingNodeV2, UidTestingNodeV3]):
|
||||||
graph: Graph = graphSavedOnDisk
|
graph: Graph = graphSavedOnDisk
|
||||||
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
||||||
|
|
|
@ -2,11 +2,11 @@ from meshroom.core.graph import Graph
|
||||||
|
|
||||||
|
|
||||||
def test_depth():
|
def test_depth():
|
||||||
graph = Graph('Tests tasks depth')
|
graph = Graph("Tests tasks depth")
|
||||||
|
|
||||||
tA = graph.addNewNode('Ls', input='/tmp')
|
tA = graph.addNewNode("Ls", input="/tmp")
|
||||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||||
|
|
||||||
graph.addEdges(
|
graph.addEdges(
|
||||||
(tA.output, tB.input),
|
(tA.output, tB.input),
|
||||||
|
@ -19,19 +19,19 @@ def test_depth():
|
||||||
|
|
||||||
|
|
||||||
def test_depth_diamond_graph():
|
def test_depth_diamond_graph():
|
||||||
graph = Graph('Tests tasks depth')
|
graph = Graph("Tests tasks depth")
|
||||||
|
|
||||||
tA = graph.addNewNode('Ls', input='/tmp')
|
tA = graph.addNewNode("Ls", input="/tmp")
|
||||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||||
tD = graph.addNewNode('AppendFiles')
|
tD = graph.addNewNode("AppendFiles")
|
||||||
|
|
||||||
graph.addEdges(
|
graph.addEdges(
|
||||||
(tA.output, tB.input),
|
(tA.output, tB.input),
|
||||||
(tA.output, tC.input),
|
(tA.output, tC.input),
|
||||||
(tB.output, tD.input),
|
(tB.output, tD.input),
|
||||||
(tC.output, tD.input2),
|
(tC.output, tD.input2),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert tA.depth == 0
|
assert tA.depth == 0
|
||||||
assert tB.depth == 1
|
assert tB.depth == 1
|
||||||
|
@ -58,13 +58,13 @@ def test_depth_diamond_graph():
|
||||||
|
|
||||||
|
|
||||||
def test_depth_diamond_graph2():
|
def test_depth_diamond_graph2():
|
||||||
graph = Graph('Tests tasks depth')
|
graph = Graph("Tests tasks depth")
|
||||||
|
|
||||||
tA = graph.addNewNode('Ls', input='/tmp')
|
tA = graph.addNewNode("Ls", input="/tmp")
|
||||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||||
tD = graph.addNewNode('AppendText', inputText='echo D')
|
tD = graph.addNewNode("AppendText", inputText="echo D")
|
||||||
tE = graph.addNewNode('AppendFiles')
|
tE = graph.addNewNode("AppendFiles")
|
||||||
# C
|
# C
|
||||||
# / \
|
# / \
|
||||||
# /---/---->\
|
# /---/---->\
|
||||||
|
@ -81,7 +81,7 @@ def test_depth_diamond_graph2():
|
||||||
(tB.output, tE.input2),
|
(tB.output, tE.input2),
|
||||||
(tC.output, tE.input3),
|
(tC.output, tE.input3),
|
||||||
(tD.output, tE.input4),
|
(tD.output, tE.input4),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert tA.depth == 0
|
assert tA.depth == 0
|
||||||
assert tB.depth == 1
|
assert tB.depth == 1
|
||||||
|
@ -116,14 +116,13 @@ def test_depth_diamond_graph2():
|
||||||
|
|
||||||
|
|
||||||
def test_transitive_reduction():
|
def test_transitive_reduction():
|
||||||
|
graph = Graph("Tests tasks depth")
|
||||||
|
|
||||||
graph = Graph('Tests tasks depth')
|
tA = graph.addNewNode("Ls", input="/tmp")
|
||||||
|
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||||
tA = graph.addNewNode('Ls', input='/tmp')
|
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
tD = graph.addNewNode("AppendText", inputText="echo D")
|
||||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
tE = graph.addNewNode("AppendFiles")
|
||||||
tD = graph.addNewNode('AppendText', inputText='echo D')
|
|
||||||
tE = graph.addNewNode('AppendFiles')
|
|
||||||
# C
|
# C
|
||||||
# / \
|
# / \
|
||||||
# /---/---->\
|
# /---/---->\
|
||||||
|
@ -141,7 +140,7 @@ def test_transitive_reduction():
|
||||||
(tB.output, tE.input4),
|
(tB.output, tE.input4),
|
||||||
(tC.output, tE.input3),
|
(tC.output, tE.input3),
|
||||||
(tD.output, tE.input2),
|
(tD.output, tE.input2),
|
||||||
)
|
)
|
||||||
|
|
||||||
flowEdges = graph.flowEdges()
|
flowEdges = graph.flowEdges()
|
||||||
flowEdgesRes = [(tB, tA),
|
flowEdgesRes = [(tB, tA),
|
||||||
|
@ -153,24 +152,24 @@ def test_transitive_reduction():
|
||||||
assert set(flowEdgesRes) == set(flowEdges)
|
assert set(flowEdgesRes) == set(flowEdges)
|
||||||
|
|
||||||
assert len(graph._nodesMinMaxDepths) == len(graph.nodes)
|
assert len(graph._nodesMinMaxDepths) == len(graph.nodes)
|
||||||
for node, (minDepth, maxDepth) in graph._nodesMinMaxDepths.items():
|
for node, (_, maxDepth) in graph._nodesMinMaxDepths.items():
|
||||||
assert node.depth == maxDepth
|
assert node.depth == maxDepth
|
||||||
|
|
||||||
|
|
||||||
def test_graph_reverse_dfsOnDiscover():
|
def test_graph_reverse_dfsOnDiscover():
|
||||||
graph = Graph('Test dfsOnDiscover(reverse=True)')
|
graph = Graph("Test dfsOnDiscover(reverse=True)")
|
||||||
|
|
||||||
# ------------\
|
# ------------\
|
||||||
# / ~ C - E - F
|
# / ~ C - E - F
|
||||||
# A - B
|
# A - B
|
||||||
# ~ D
|
# ~ D
|
||||||
|
|
||||||
A = graph.addNewNode('Ls', input='/tmp')
|
A = graph.addNewNode("Ls", input="/tmp")
|
||||||
B = graph.addNewNode('AppendText', inputText=A.output)
|
B = graph.addNewNode("AppendText", inputText=A.output)
|
||||||
C = graph.addNewNode('AppendText', inputText=B.output)
|
C = graph.addNewNode("AppendText", inputText=B.output)
|
||||||
D = graph.addNewNode('AppendText', inputText=B.output)
|
D = graph.addNewNode("AppendText", inputText=B.output)
|
||||||
E = graph.addNewNode('Ls', input=C.output)
|
E = graph.addNewNode("Ls", input=C.output)
|
||||||
F = graph.addNewNode('AppendText', input=A.output, inputText=E.output)
|
F = graph.addNewNode("AppendText", input=A.output, inputText=E.output)
|
||||||
|
|
||||||
# Get all nodes from A (use set, order not guaranteed)
|
# Get all nodes from A (use set, order not guaranteed)
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[A], reverse=True)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[A], reverse=True)[0]
|
||||||
|
@ -179,7 +178,7 @@ def test_graph_reverse_dfsOnDiscover():
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[B], reverse=True)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[B], reverse=True)[0]
|
||||||
assert set(nodes) == {B, D, C, E, F}
|
assert set(nodes) == {B, D, C, E, F}
|
||||||
# Get all nodes of type AppendText from B
|
# Get all nodes of type AppendText from B
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[B], filterTypes=['AppendText'], reverse=True)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[B], filterTypes=["AppendText"], reverse=True)[0]
|
||||||
assert set(nodes) == {B, D, C, F}
|
assert set(nodes) == {B, D, C, F}
|
||||||
# Get all nodes from C (order guaranteed)
|
# Get all nodes from C (order guaranteed)
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[C], reverse=True)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[C], reverse=True)[0]
|
||||||
|
@ -190,7 +189,7 @@ def test_graph_reverse_dfsOnDiscover():
|
||||||
|
|
||||||
|
|
||||||
def test_graph_dfsOnDiscover():
|
def test_graph_dfsOnDiscover():
|
||||||
graph = Graph('Test dfsOnDiscover(reverse=False)')
|
graph = Graph("Test dfsOnDiscover(reverse=False)")
|
||||||
|
|
||||||
# ------------\
|
# ------------\
|
||||||
# / ~ C - E - F
|
# / ~ C - E - F
|
||||||
|
@ -198,13 +197,13 @@ def test_graph_dfsOnDiscover():
|
||||||
# ~ D
|
# ~ D
|
||||||
# G
|
# G
|
||||||
|
|
||||||
G = graph.addNewNode('Ls', input='/tmp')
|
G = graph.addNewNode("Ls", input="/tmp")
|
||||||
A = graph.addNewNode('Ls', input='/tmp')
|
A = graph.addNewNode("Ls", input="/tmp")
|
||||||
B = graph.addNewNode('AppendText', inputText=A.output)
|
B = graph.addNewNode("AppendText", inputText=A.output)
|
||||||
C = graph.addNewNode('AppendText', inputText=B.output)
|
C = graph.addNewNode("AppendText", inputText=B.output)
|
||||||
D = graph.addNewNode('AppendText', input=G.output, inputText=B.output)
|
D = graph.addNewNode("AppendText", input=G.output, inputText=B.output)
|
||||||
E = graph.addNewNode('Ls', input=C.output)
|
E = graph.addNewNode("Ls", input=C.output)
|
||||||
F = graph.addNewNode('AppendText', input=A.output, inputText=E.output)
|
F = graph.addNewNode("AppendText", input=A.output, inputText=E.output)
|
||||||
|
|
||||||
# Get all nodes from A (use set, order not guaranteed)
|
# Get all nodes from A (use set, order not guaranteed)
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[A], reverse=False)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[A], reverse=False)[0]
|
||||||
|
@ -219,7 +218,7 @@ def test_graph_dfsOnDiscover():
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[F], reverse=False)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[F], reverse=False)[0]
|
||||||
assert set(nodes) == {A, B, C, E, F}
|
assert set(nodes) == {A, B, C, E, F}
|
||||||
# Get all nodes of type AppendText from C
|
# Get all nodes of type AppendText from C
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[C], filterTypes=['AppendText'], reverse=False)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[C], filterTypes=["AppendText"], reverse=False)[0]
|
||||||
assert set(nodes) == {B, C}
|
assert set(nodes) == {B, C}
|
||||||
# Get all nodes from D (order guaranteed)
|
# Get all nodes from D (order guaranteed)
|
||||||
nodes = graph.dfsOnDiscover(startNodes=[D], longestPathFirst=True, reverse=False)[0]
|
nodes = graph.dfsOnDiscover(startNodes=[D], longestPathFirst=True, reverse=False)[0]
|
||||||
|
@ -230,21 +229,21 @@ def test_graph_dfsOnDiscover():
|
||||||
|
|
||||||
|
|
||||||
def test_graph_nodes_sorting():
|
def test_graph_nodes_sorting():
|
||||||
graph = Graph('')
|
graph = Graph("")
|
||||||
|
|
||||||
ls0 = graph.addNewNode('Ls')
|
ls0 = graph.addNewNode("Ls")
|
||||||
ls1 = graph.addNewNode('Ls')
|
ls1 = graph.addNewNode("Ls")
|
||||||
ls2 = graph.addNewNode('Ls')
|
ls2 = graph.addNewNode("Ls")
|
||||||
|
|
||||||
assert graph.nodesOfType('Ls', sortedByIndex=True) == [ls0, ls1, ls2]
|
assert graph.nodesOfType("Ls", sortedByIndex=True) == [ls0, ls1, ls2]
|
||||||
|
|
||||||
graph = Graph('')
|
graph = Graph("")
|
||||||
# 'Random' creation order (what happens when loading a file)
|
# 'Random' creation order (what happens when loading a file)
|
||||||
ls2 = graph.addNewNode('Ls', name='Ls_2')
|
ls2 = graph.addNewNode("Ls", name="Ls_2")
|
||||||
ls0 = graph.addNewNode('Ls', name='Ls_0')
|
ls0 = graph.addNewNode("Ls", name="Ls_0")
|
||||||
ls1 = graph.addNewNode('Ls', name='Ls_1')
|
ls1 = graph.addNewNode("Ls", name="Ls_1")
|
||||||
|
|
||||||
assert graph.nodesOfType('Ls', sortedByIndex=True) == [ls0, ls1, ls2]
|
assert graph.nodesOfType("Ls", sortedByIndex=True) == [ls0, ls1, ls2]
|
||||||
|
|
||||||
|
|
||||||
def test_duplicate_nodes():
|
def test_duplicate_nodes():
|
||||||
|
@ -256,24 +255,25 @@ def test_duplicate_nodes():
|
||||||
# \ \
|
# \ \
|
||||||
# ---------- n3
|
# ---------- n3
|
||||||
|
|
||||||
g = Graph('')
|
g = Graph("")
|
||||||
n0 = g.addNewNode('Ls', input='/tmp')
|
n0 = g.addNewNode("Ls", input="/tmp")
|
||||||
n1 = g.addNewNode('Ls', input=n0.output)
|
n1 = g.addNewNode("Ls", input=n0.output)
|
||||||
n2 = g.addNewNode('Ls', input=n1.output)
|
n2 = g.addNewNode("Ls", input=n1.output)
|
||||||
n3 = g.addNewNode('AppendFiles', input=n1.output, input2=n2.output)
|
n3 = g.addNewNode("AppendFiles", input=n1.output, input2=n2.output)
|
||||||
|
|
||||||
# duplicate from n1
|
# Duplicate from n1
|
||||||
nodes_to_duplicate, _ = g.dfsOnDiscover(startNodes=[n1], reverse=True, dependenciesOnly=True)
|
nodes_to_duplicate, _ = g.dfsOnDiscover(startNodes=[n1], reverse=True, dependenciesOnly=True)
|
||||||
nMap = g.duplicateNodes(srcNodes=nodes_to_duplicate)
|
nMap = g.duplicateNodes(srcNodes=nodes_to_duplicate)
|
||||||
for s, duplicated in nMap.items():
|
for s, duplicated in nMap.items():
|
||||||
for d in duplicated:
|
for d in duplicated:
|
||||||
assert s.nodeType == d.nodeType
|
assert s.nodeType == d.nodeType
|
||||||
|
|
||||||
# check number of duplicated nodes and that every parent node has been duplicated once
|
# Check number of duplicated nodes and that every parent node has been duplicated once
|
||||||
assert len(nMap) == 3 and all([len(nMap[i]) == 1 for i in nMap.keys()])
|
assert len(nMap) == 3 and \
|
||||||
|
all([len(nMap[i]) == 1 for i in nMap.keys()])
|
||||||
|
|
||||||
# check connections
|
# Check connections
|
||||||
# access directly index 0 because we know there is a single duplicate for each parent node
|
# Access directly index 0 because we know there is a single duplicate for each parent node
|
||||||
assert nMap[n1][0].input.getLinkParam() == n0.output
|
assert nMap[n1][0].input.getLinkParam() == n0.output
|
||||||
assert nMap[n2][0].input.getLinkParam() == nMap[n1][0].output
|
assert nMap[n2][0].input.getLinkParam() == nMap[n1][0].output
|
||||||
assert nMap[n3][0].input.getLinkParam() == nMap[n1][0].output
|
assert nMap[n3][0].input.getLinkParam() == nMap[n1][0].output
|
||||||
|
|
|
@ -255,7 +255,8 @@ class TestGraphPartialSerialization:
|
||||||
otherGraph = Graph("")
|
otherGraph = Graph("")
|
||||||
otherGraph._deserialize(graph.serializePartial([nodeA, nodeB]))
|
otherGraph._deserialize(graph.serializePartial([nodeA, nodeB]))
|
||||||
|
|
||||||
assert otherGraph.node(nodeB.name).listInput.linkParam == otherGraph.node(nodeA.name).listInput
|
assert otherGraph.node(nodeB.name).listInput.linkParam == \
|
||||||
|
otherGraph.node(nodeA.name).listInput
|
||||||
|
|
||||||
def test_singleNodeWithInputConnectionFromNonSerializedNodeRemovesEdge(self):
|
def test_singleNodeWithInputConnectionFromNonSerializedNodeRemovesEdge(self):
|
||||||
graph = Graph("")
|
graph = Graph("")
|
||||||
|
|
|
@ -7,8 +7,10 @@ from meshroom.core import desc, registerNodeType
|
||||||
class SampleNode(desc.Node):
|
class SampleNode(desc.Node):
|
||||||
""" Sample Node for unit testing """
|
""" Sample Node for unit testing """
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.File(name='input', label='Input', description='', value='',),
|
desc.File(name="input", label="Input", description="", value="",),
|
||||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False) # No impact on UID
|
desc.StringParam(name="paramA", label="ParamA",
|
||||||
|
description="", value="",
|
||||||
|
invalidate=False) # No impact on UID
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
||||||
|
@ -19,10 +21,10 @@ registerNodeType(SampleNode)
|
||||||
|
|
||||||
|
|
||||||
def test_output_invalidation():
|
def test_output_invalidation():
|
||||||
graph = Graph('')
|
graph = Graph("")
|
||||||
n1 = graph.addNewNode('SampleNode', input='/tmp')
|
n1 = graph.addNewNode("SampleNode", input="/tmp")
|
||||||
n2 = graph.addNewNode('SampleNode')
|
n2 = graph.addNewNode("SampleNode")
|
||||||
n3 = graph.addNewNode('SampleNode')
|
n3 = graph.addNewNode("SampleNode")
|
||||||
|
|
||||||
graph.addEdges(
|
graph.addEdges(
|
||||||
(n1.output, n2.input),
|
(n1.output, n2.input),
|
||||||
|
@ -52,9 +54,9 @@ def test_inputLinkInvalidation():
|
||||||
"""
|
"""
|
||||||
Input links should not change the invalidation.
|
Input links should not change the invalidation.
|
||||||
"""
|
"""
|
||||||
graph = Graph('')
|
graph = Graph("")
|
||||||
n1 = graph.addNewNode('SampleNode')
|
n1 = graph.addNewNode("SampleNode")
|
||||||
n2 = graph.addNewNode('SampleNode')
|
n2 = graph.addNewNode("SampleNode")
|
||||||
|
|
||||||
graph.addEdges((n1.input, n2.input))
|
graph.addEdges((n1.input, n2.input))
|
||||||
assert n1.input.uid() == n2.input.uid()
|
assert n1.input.uid() == n2.input.uid()
|
||||||
|
|
|
@ -313,7 +313,8 @@ class TestAttributeCallbackBehaviorWithUpstreamCompoundAttributes:
|
||||||
|
|
||||||
class NodeWithDynamicOutputValue(desc.BaseNode):
|
class NodeWithDynamicOutputValue(desc.BaseNode):
|
||||||
"""
|
"""
|
||||||
A Node containing an output attribute which value is computed dynamically during graph execution.
|
A Node containing an output attribute which value is computed dynamically
|
||||||
|
during graph execution.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
inputs = [
|
inputs = [
|
||||||
|
@ -390,7 +391,6 @@ class TestAttributeCallbackBehaviorWithUpstreamDynamicOutputs:
|
||||||
assert nodeB.input.value == 20
|
assert nodeB.input.value == 20
|
||||||
assert nodeB.affectedInput.value == 0
|
assert nodeB.affectedInput.value == 0
|
||||||
|
|
||||||
|
|
||||||
def test_clearingDynamicOutputValueDoesNotTriggerDownstreamAttributeChangedCallback(
|
def test_clearingDynamicOutputValueDoesNotTriggerDownstreamAttributeChangedCallback(
|
||||||
self, graphSavedOnDisk
|
self, graphSavedOnDisk
|
||||||
):
|
):
|
||||||
|
@ -450,9 +450,8 @@ class TestAttributeCallbackBehaviorOnGraphImport:
|
||||||
|
|
||||||
nodeA.input.value = 5
|
nodeA.input.value = 5
|
||||||
nodeB.affectedInput.value = 2
|
nodeB.affectedInput.value = 2
|
||||||
|
|
||||||
otherGraph = Graph("")
|
otherGraph = Graph("")
|
||||||
otherGraph.importGraphContent(graph)
|
otherGraph.importGraphContent(graph)
|
||||||
|
|
||||||
assert otherGraph.node(nodeB.name).affectedInput.value == 2
|
assert otherGraph.node(nodeB.name).affectedInput.value == 2
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ from meshroom.core.node import Node
|
||||||
|
|
||||||
class NodeWithAttributesNeedingFormatting(desc.Node):
|
class NodeWithAttributesNeedingFormatting(desc.Node):
|
||||||
"""
|
"""
|
||||||
A node containing list, file, choice and group attributes in order to test the formatting of the command line.
|
A node containing list, file, choice and group attributes in order to test the
|
||||||
|
formatting of the command line.
|
||||||
"""
|
"""
|
||||||
inputs = [
|
inputs = [
|
||||||
desc.ListAttribute(
|
desc.ListAttribute(
|
||||||
|
@ -128,23 +129,28 @@ class TestCommandLineFormatting:
|
||||||
|
|
||||||
# Assert that extending values when the list is not empty is working
|
# Assert that extending values when the list is not empty is working
|
||||||
node.images.extend(inputImages)
|
node.images.extend(inputImages)
|
||||||
assert node.images.getValueStr() == '"single value with space" "{}" "{}"'.format(inputImages[0],
|
assert node.images.getValueStr() == \
|
||||||
inputImages[1])
|
'"single value with space" "{}" "{}"'.format(inputImages[0],
|
||||||
|
inputImages[1])
|
||||||
|
|
||||||
# Values are not retrieved as strings in the command line, so quotes around them are not expected
|
# Values are not retrieved as strings in the command line, so quotes around them are
|
||||||
assert node._cmdVars["imagesValue"] == 'single value with space {} {}'.format(inputImages[0],
|
# not expected
|
||||||
inputImages[1])
|
assert node._cmdVars["imagesValue"] == \
|
||||||
|
'single value with space {} {}'.format(inputImages[0],
|
||||||
|
inputImages[1])
|
||||||
|
|
||||||
def test_formatting_strings(self):
|
def test_formatting_strings(self):
|
||||||
graph = Graph("")
|
graph = Graph("")
|
||||||
node = graph.addNewNode("NodeWithAttributesNeedingFormatting")
|
node = graph.addNewNode("NodeWithAttributesNeedingFormatting")
|
||||||
node._buildCmdVars()
|
node._buildCmdVars()
|
||||||
|
|
||||||
# Assert an empty File attribute generates empty quotes when requesting its value as a string
|
# Assert an empty File attribute generates empty quotes when requesting its value as
|
||||||
|
# a string
|
||||||
assert node.input.getValueStr() == '""'
|
assert node.input.getValueStr() == '""'
|
||||||
assert node._cmdVars["inputValue"] == ""
|
assert node._cmdVars["inputValue"] == ""
|
||||||
|
|
||||||
# Assert a Choice attribute with a non-empty default value is surrounded with quotes when requested as a string
|
# Assert a Choice attribute with a non-empty default value is surrounded with quotes
|
||||||
|
# when requested as a string
|
||||||
assert node.method.getValueStr() == '"MethodC"'
|
assert node.method.getValueStr() == '"MethodC"'
|
||||||
assert node._cmdVars["methodValue"] == "MethodC"
|
assert node._cmdVars["methodValue"] == "MethodC"
|
||||||
|
|
||||||
|
@ -154,14 +160,18 @@ class TestCommandLineFormatting:
|
||||||
|
|
||||||
# Assert that the list with one empty value generates empty quotes
|
# Assert that the list with one empty value generates empty quotes
|
||||||
node.images.extend("")
|
node.images.extend("")
|
||||||
assert node.images.getValueStr() == '""', "A list with one empty string should generate empty quotes"
|
assert node.images.getValueStr() == '""', \
|
||||||
assert node._cmdVars["imagesValue"] == "", "The value is always only the value, so empty here"
|
"A list with one empty string should generate empty quotes"
|
||||||
|
assert node._cmdVars["imagesValue"] == "", \
|
||||||
|
"The value is always only the value, so empty here"
|
||||||
|
|
||||||
# Assert that a list with 2 empty strings generates quotes
|
# Assert that a list with 2 empty strings generates quotes
|
||||||
node.images.extend("")
|
node.images.extend("")
|
||||||
assert node.images.getValueStr() == '"" ""', "A list with 2 empty strings should generate quotes"
|
assert node.images.getValueStr() == '"" ""', \
|
||||||
|
"A list with 2 empty strings should generate quotes"
|
||||||
assert node._cmdVars["imagesValue"] == ' ', \
|
assert node._cmdVars["imagesValue"] == ' ', \
|
||||||
"The value is always only the value, so 2 empty strings with the space separator in the middle"
|
"The value is always only the value, so 2 empty strings with the " \
|
||||||
|
"space separator in the middle"
|
||||||
|
|
||||||
def test_formatting_groups(self):
|
def test_formatting_groups(self):
|
||||||
graph = Graph("")
|
graph = Graph("")
|
||||||
|
|
|
@ -44,7 +44,7 @@ def test_pipeline():
|
||||||
if attr.isOutput and attr.enabled:
|
if attr.isOutput and attr.enabled:
|
||||||
otherAttr = otherNode.attribute(key)
|
otherAttr = otherNode.attribute(key)
|
||||||
assert attr.uid() != otherAttr.uid()
|
assert attr.uid() != otherAttr.uid()
|
||||||
|
|
||||||
# Test serialization/deserialization on both graphs
|
# Test serialization/deserialization on both graphs
|
||||||
for graph in [graph1, graph2]:
|
for graph in [graph1, graph2]:
|
||||||
filename = tempfile.mktemp()
|
filename = tempfile.mktemp()
|
||||||
|
|
|
@ -18,7 +18,7 @@ def registeredNodeTypes(nodeTypes: list[Type[desc.Node]]):
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def overrideNodeTypeVersion(nodeType: Type[desc.Node], version: str):
|
def overrideNodeTypeVersion(nodeType: Type[desc.Node], version: str):
|
||||||
"""Helper context manager to override the version of a given node type."""
|
""" Helper context manager to override the version of a given node type. """
|
||||||
unpatchedFunc = meshroom.core.nodeVersion
|
unpatchedFunc = meshroom.core.nodeVersion
|
||||||
with patch.object(
|
with patch.object(
|
||||||
meshroom.core,
|
meshroom.core,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue