[tests] Harmonize and clean-up syntax across test files

Also comply more with PEP8 linting rules.
This commit is contained in:
Candice Bentéjac 2025-05-12 17:31:59 +02:00
parent 441ba37c24
commit 28042dd2ad
11 changed files with 218 additions and 189 deletions

View file

@ -39,4 +39,3 @@ class AppendFiles(desc.CommandLineNode):
value='{nodeCacheFolder}/appendText.txt', value='{nodeCacheFolder}/appendText.txt',
) )
] ]

View file

@ -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",
) )
] ]

View file

@ -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)

View file

@ -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__)

View file

@ -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

View file

@ -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("")

View file

@ -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()

View file

@ -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

View file

@ -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("")

View file

@ -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()

View file

@ -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,