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',
|
||||
)
|
||||
]
|
||||
|
||||
|
|
|
@ -2,21 +2,21 @@ from meshroom.core import desc
|
|||
|
||||
|
||||
class Ls(desc.CommandLineNode):
|
||||
commandLine = 'ls {inputValue} > {outputValue}'
|
||||
commandLine = "ls {inputValue} > {outputValue}"
|
||||
inputs = [
|
||||
desc.File(
|
||||
name='input',
|
||||
label='Input',
|
||||
description='''''',
|
||||
value='',
|
||||
name="input",
|
||||
label="Input",
|
||||
description="",
|
||||
value="",
|
||||
)
|
||||
]
|
||||
|
||||
outputs = [
|
||||
desc.File(
|
||||
name='output',
|
||||
label='Output',
|
||||
description='''''',
|
||||
value='{nodeCacheFolder}/ls.txt',
|
||||
name="output",
|
||||
label="Output",
|
||||
description="",
|
||||
value="{nodeCacheFolder}/ls.txt",
|
||||
)
|
||||
]
|
||||
|
|
|
@ -20,7 +20,8 @@ SampleGroupV1 = [
|
|||
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
||||
desc.ListAttribute(
|
||||
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",
|
||||
description="",
|
||||
)
|
||||
|
@ -30,7 +31,8 @@ SampleGroupV2 = [
|
|||
desc.IntParam(name="a", label="a", description="", value=0, range=None),
|
||||
desc.ListAttribute(
|
||||
name="b",
|
||||
elementDesc=desc.GroupAttribute(name="p", label="", description="", groupDesc=SampleGroupV1),
|
||||
elementDesc=desc.GroupAttribute(name="p", label="",
|
||||
description="", groupDesc=SampleGroupV1),
|
||||
label="b",
|
||||
description="",
|
||||
)
|
||||
|
@ -39,10 +41,12 @@ SampleGroupV2 = [
|
|||
# SampleGroupV3 is SampleGroupV2 with one more int parameter
|
||||
SampleGroupV3 = [
|
||||
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(
|
||||
name="b",
|
||||
elementDesc=desc.GroupAttribute(name="p", label="", description="", groupDesc=SampleGroupV1),
|
||||
elementDesc=desc.GroupAttribute(name="p", label="",
|
||||
description="", groupDesc=SampleGroupV1),
|
||||
label="b",
|
||||
description="",
|
||||
)
|
||||
|
@ -52,11 +56,12 @@ SampleGroupV3 = [
|
|||
class SampleNodeV1(desc.Node):
|
||||
""" Version 1 Sample Node """
|
||||
inputs = [
|
||||
desc.File(name='input', label='Input', description='', value='',),
|
||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False) # No impact on UID
|
||||
desc.File(name="input", label="Input", description="", value=""),
|
||||
desc.StringParam(name="paramA", label="ParamA", description="",
|
||||
value="", invalidate=False) # No impact on UID
|
||||
]
|
||||
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'
|
||||
"""
|
||||
inputs = [
|
||||
desc.File(name='in', label='Input', description='', value='',),
|
||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False), # No impact on UID
|
||||
desc.File(name="in", label="Input", description="", value=""),
|
||||
desc.StringParam(name="paramA", label="ParamA", description="",
|
||||
value="", invalidate=False), # No impact on UID
|
||||
]
|
||||
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'
|
||||
"""
|
||||
inputs = [
|
||||
desc.File(name='in', label='Input', description='', value='',),
|
||||
desc.File(name="in", label="Input", description="", value=""),
|
||||
]
|
||||
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
|
||||
"""
|
||||
inputs = [
|
||||
desc.File(name='in', label='Input', description='', value='',),
|
||||
desc.ListAttribute(name='paramA', label='ParamA',
|
||||
desc.File(name="in", label="Input", description="", value=""),
|
||||
desc.ListAttribute(name="paramA", label="ParamA",
|
||||
elementDesc=desc.GroupAttribute(
|
||||
groupDesc=SampleGroupV1, name='gA', label='gA', description=''),
|
||||
description='')
|
||||
groupDesc=SampleGroupV1, name="gA", label="gA", description=""),
|
||||
description="")
|
||||
]
|
||||
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
|
||||
"""
|
||||
inputs = [
|
||||
desc.File(name='in', label='Input', description='', value=''),
|
||||
desc.ListAttribute(name='paramA', label='ParamA',
|
||||
desc.File(name="in", label="Input", description="", value=""),
|
||||
desc.ListAttribute(name="paramA", label="ParamA",
|
||||
elementDesc=desc.GroupAttribute(
|
||||
groupDesc=SampleGroupV2, name='gA', label='gA', description=''),
|
||||
description='')
|
||||
groupDesc=SampleGroupV2, name="gA", label="gA", description=""),
|
||||
description="")
|
||||
]
|
||||
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
|
||||
"""
|
||||
inputs = [
|
||||
desc.File(name='in', label='Input', description='', value=''),
|
||||
desc.ListAttribute(name='paramA', label='ParamA',
|
||||
desc.File(name="in", label="Input", description="", value=""),
|
||||
desc.ListAttribute(name="paramA", label="ParamA",
|
||||
elementDesc=desc.GroupAttribute(
|
||||
groupDesc=SampleGroupV3, name='gA', label='gA', description=''),
|
||||
description='')
|
||||
groupDesc=SampleGroupV3, name="gA", label="gA", description=""),
|
||||
description="")
|
||||
]
|
||||
outputs = [
|
||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
||||
desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")
|
||||
]
|
||||
|
||||
|
||||
class SampleInputNodeV1(desc.InputNode):
|
||||
""" Version 1 Sample Input Node """
|
||||
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 = [
|
||||
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'
|
||||
"""
|
||||
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 = [
|
||||
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.
|
||||
"""
|
||||
registerNodeType(SampleNodeV1)
|
||||
g = Graph('')
|
||||
g = Graph("")
|
||||
n = g.addNewNode("SampleNodeV1", input="/dev/null", paramA="foo")
|
||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_unknown_node_type.mg")
|
||||
g.save(graphFile)
|
||||
|
@ -178,24 +186,25 @@ def test_unknown_node_type():
|
|||
nodeName = n.name
|
||||
unregisterNodeType(SampleNodeV1)
|
||||
|
||||
# reload file
|
||||
|
||||
# Reload file
|
||||
g = loadGraph(graphFile)
|
||||
os.remove(graphFile)
|
||||
|
||||
assert len(g.nodes) == 1
|
||||
n = g.node(nodeName)
|
||||
# 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 n.issue == CompatibilityIssue.UnknownNodeType
|
||||
# check if attributes are properly restored
|
||||
# Check if attributes are properly restored
|
||||
assert len(n.attributes) == 3
|
||||
assert n.input.isInput
|
||||
assert n.output.isOutput
|
||||
# check if internal folder
|
||||
# Check if internal folder
|
||||
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
|
||||
with pytest.raises(NodeUpgradeError):
|
||||
g.upgradeNode(nodeName)
|
||||
|
@ -205,20 +214,20 @@ def test_description_conflict():
|
|||
"""
|
||||
Test compatibility behavior for conflicting node descriptions.
|
||||
"""
|
||||
# copy registered node types to be able to restore them
|
||||
originalNodeTypes = copy.copy(meshroom.core.nodesDesc)
|
||||
# Copy registered node types to be able to restore them
|
||||
originalNodeTypes = copy.deepcopy(pluginManager.getNodePlugins())
|
||||
|
||||
nodeTypes = [SampleNodeV1, SampleNodeV2, SampleNodeV3, SampleNodeV4, SampleNodeV5]
|
||||
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]:
|
||||
registerNodeType(nt)
|
||||
pluginManager.registerNode(NodePlugin(nt))
|
||||
n = g.addNewNode(nt.__name__)
|
||||
|
||||
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]}]
|
||||
|
||||
nodes.append(n)
|
||||
|
@ -226,15 +235,15 @@ def test_description_conflict():
|
|||
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
||||
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)
|
||||
|
||||
# offset node types register to create description conflicts
|
||||
# each node type name now reference the next one's implementation
|
||||
# Offset node types register to create description conflicts
|
||||
# Each node type name now reference the next one's implementation
|
||||
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)
|
||||
os.remove(graphFile)
|
||||
|
||||
|
@ -246,7 +255,7 @@ def test_description_conflict():
|
|||
assert isinstance(compatNode, CompatibilityNode)
|
||||
assert srcNode.internalFolder == compatNode.internalFolder
|
||||
|
||||
# case by case description conflict verification
|
||||
# Case by case description conflict verification
|
||||
if isinstance(srcNode.nodeDesc, SampleNodeV1):
|
||||
# V1 => V2: 'input' has been renamed to 'in'
|
||||
assert len(compatNode.attributes) == 3
|
||||
|
@ -254,27 +263,29 @@ def test_description_conflict():
|
|||
assert hasattr(compatNode, "input")
|
||||
assert not hasattr(compatNode, "in")
|
||||
|
||||
# perform upgrade
|
||||
# Perform upgrade
|
||||
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 not hasattr(upgradedNode, "input")
|
||||
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
|
||||
|
||||
elif isinstance(srcNode.nodeDesc, SampleNodeV2):
|
||||
# V2 => V3: 'paramA' has been removed'
|
||||
# V2 => V3: 'paramA' has been removed
|
||||
assert len(compatNode.attributes) == 3
|
||||
assert hasattr(compatNode, "paramA")
|
||||
|
||||
# perform upgrade
|
||||
# Perform upgrade
|
||||
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")
|
||||
# check uid is identical (paramA not part of uid)
|
||||
# Check UID is identical (paramA not part of UID)
|
||||
assert upgradedNode.internalFolder == srcNode.internalFolder
|
||||
|
||||
elif isinstance(srcNode.nodeDesc, SampleNodeV3):
|
||||
|
@ -282,9 +293,10 @@ def test_description_conflict():
|
|||
assert len(compatNode.attributes) == 2
|
||||
assert not hasattr(compatNode, "paramA")
|
||||
|
||||
# perform upgrade
|
||||
# Perform upgrade
|
||||
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 isinstance(upgradedNode.paramA.attributeDesc, desc.ListAttribute)
|
||||
|
@ -298,22 +310,24 @@ def test_description_conflict():
|
|||
groupAttribute = compatNode.paramA.attributeDesc.elementDesc
|
||||
|
||||
assert isinstance(groupAttribute, desc.GroupAttribute)
|
||||
# check that Compatibility node respect SampleGroupV1 description
|
||||
# Check that Compatibility node respect SampleGroupV1 description
|
||||
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)
|
||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV5)
|
||||
assert isinstance(upgradedNode, Node) and \
|
||||
isinstance(upgradedNode.nodeDesc, SampleNodeV5)
|
||||
|
||||
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.internalFolder != srcNode.internalFolder
|
||||
else:
|
||||
raise ValueError("Unexpected node type: " + srcNode.nodeType)
|
||||
|
||||
# restore original node types
|
||||
# Restore original node types
|
||||
meshroom.core.nodesDesc = originalNodeTypes
|
||||
|
||||
|
||||
|
@ -323,7 +337,7 @@ def test_upgradeAllNodes():
|
|||
registerNodeType(SampleInputNodeV1)
|
||||
registerNodeType(SampleInputNodeV2)
|
||||
|
||||
g = Graph('')
|
||||
g = Graph("")
|
||||
n1 = g.addNewNode("SampleNodeV1")
|
||||
n2 = g.addNewNode("SampleNodeV2")
|
||||
n3 = g.addNewNode("SampleInputNodeV1")
|
||||
|
@ -335,28 +349,28 @@ def test_upgradeAllNodes():
|
|||
graphFile = os.path.join(tempfile.mkdtemp(), "test_description_conflict.mg")
|
||||
g.save(graphFile)
|
||||
|
||||
# make SampleNodeV2 and SampleInputNodeV2 an unknown type
|
||||
# Make SampleNodeV2 and SampleInputNodeV2 an unknown type
|
||||
unregisterNodeType(SampleNodeV2)
|
||||
unregisterNodeType(SampleInputNodeV2)
|
||||
# replace SampleNodeV1 by SampleNodeV2 and SampleInputNodeV1 by SampleInputNodeV2
|
||||
meshroom.core.nodesDesc[SampleNodeV1.__name__] = SampleNodeV2
|
||||
meshroom.core.nodesDesc[SampleInputNodeV1.__name__] = SampleInputNodeV2
|
||||
# Replace SampleNodeV1 by SampleNodeV2 and SampleInputNodeV1 by SampleInputNodeV2
|
||||
|
||||
# reload file
|
||||
# Reload file
|
||||
g = loadGraph(graphFile)
|
||||
os.remove(graphFile)
|
||||
|
||||
# both nodes are CompatibilityNodes
|
||||
# Both nodes are CompatibilityNodes
|
||||
assert len(g.compatibilityNodes) == 4
|
||||
assert g.node(n1Name).canUpgrade # description conflict
|
||||
assert not g.node(n2Name).canUpgrade # unknown type
|
||||
assert g.node(n3Name).canUpgrade # description conflict
|
||||
assert not g.node(n4Name).canUpgrade # unknown type
|
||||
|
||||
# upgrade all upgradable nodes
|
||||
# Upgrade all upgradable nodes
|
||||
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 n2Name in g.compatibilityNodes.keys()
|
||||
assert n4Name in g.compatibilityNodes.keys()
|
||||
|
@ -369,36 +383,36 @@ def test_conformUpgrade():
|
|||
registerNodeType(SampleNodeV5)
|
||||
registerNodeType(SampleNodeV6)
|
||||
|
||||
g = Graph('')
|
||||
g = Graph("")
|
||||
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
|
||||
graphFile = os.path.join(tempfile.mkdtemp(), "test_conform_upgrade.mg")
|
||||
g.save(graphFile)
|
||||
|
||||
# replace SampleNodeV5 by SampleNodeV6
|
||||
# Replace SampleNodeV5 by SampleNodeV6
|
||||
meshroom.core.nodesDesc[SampleNodeV5.__name__] = SampleNodeV6
|
||||
|
||||
# reload file
|
||||
# Reload file
|
||||
g = loadGraph(graphFile)
|
||||
os.remove(graphFile)
|
||||
|
||||
# node is a CompatibilityNode
|
||||
# Node is a CompatibilityNode
|
||||
assert len(g.compatibilityNodes) == 1
|
||||
assert g.node(n1Name).canUpgrade
|
||||
|
||||
# upgrade all upgradable nodes
|
||||
# Upgrade all upgradable nodes
|
||||
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
|
||||
|
||||
upgradedNode = g.node(n1Name)
|
||||
|
||||
# check upgrade
|
||||
# Check upgrade
|
||||
assert isinstance(upgradedNode, Node) and isinstance(upgradedNode.nodeDesc, SampleNodeV6)
|
||||
|
||||
# check conformation
|
||||
# Check conformation
|
||||
assert len(upgradedNode.paramA.value) == 1
|
||||
|
||||
unregisterNodeType(SampleNodeV5)
|
||||
|
@ -508,7 +522,8 @@ class UidTestingNodeV1(desc.Node):
|
|||
inputs = [
|
||||
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):
|
||||
|
@ -554,7 +569,8 @@ class UidTestingNodeV3(desc.Node):
|
|||
description="",
|
||||
),
|
||||
]
|
||||
outputs = [desc.File(name="output", label="Output", description="", value="{nodeCacheFolder}")]
|
||||
outputs = [desc.File(name="output", label="Output",
|
||||
description="", value="{nodeCacheFolder}")]
|
||||
|
||||
|
||||
class TestUidConflict:
|
||||
|
@ -626,7 +642,8 @@ class TestUidConflict:
|
|||
assert len(loadedGraph.compatibilityNodes) == 0
|
||||
|
||||
|
||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughConnection(self, graphSavedOnDisk):
|
||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughConnection(
|
||||
self, graphSavedOnDisk):
|
||||
with registeredNodeTypes([UidTestingNodeV1, UidTestingNodeV2]):
|
||||
graph: Graph = graphSavedOnDisk
|
||||
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
||||
|
@ -640,7 +657,8 @@ class TestUidConflict:
|
|||
loadedGraph = loadGraph(graph.filepath)
|
||||
assert len(loadedGraph.compatibilityNodes) == 1
|
||||
|
||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughListConnection(self, graphSavedOnDisk):
|
||||
def test_uidConflictDoesNotPropagateToValidDownstreamNodeThroughListConnection(
|
||||
self,graphSavedOnDisk):
|
||||
with registeredNodeTypes([UidTestingNodeV2, UidTestingNodeV3]):
|
||||
graph: Graph = graphSavedOnDisk
|
||||
nodeA = graph.addNewNode(UidTestingNodeV2.__name__)
|
||||
|
|
|
@ -2,11 +2,11 @@ from meshroom.core.graph import Graph
|
|||
|
||||
|
||||
def test_depth():
|
||||
graph = Graph('Tests tasks depth')
|
||||
graph = Graph("Tests tasks depth")
|
||||
|
||||
tA = graph.addNewNode('Ls', input='/tmp')
|
||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
||||
tA = graph.addNewNode("Ls", input="/tmp")
|
||||
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||
|
||||
graph.addEdges(
|
||||
(tA.output, tB.input),
|
||||
|
@ -19,12 +19,12 @@ def test_depth():
|
|||
|
||||
|
||||
def test_depth_diamond_graph():
|
||||
graph = Graph('Tests tasks depth')
|
||||
graph = Graph("Tests tasks depth")
|
||||
|
||||
tA = graph.addNewNode('Ls', input='/tmp')
|
||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
||||
tD = graph.addNewNode('AppendFiles')
|
||||
tA = graph.addNewNode("Ls", input="/tmp")
|
||||
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||
tD = graph.addNewNode("AppendFiles")
|
||||
|
||||
graph.addEdges(
|
||||
(tA.output, tB.input),
|
||||
|
@ -58,13 +58,13 @@ def test_depth_diamond_graph():
|
|||
|
||||
|
||||
def test_depth_diamond_graph2():
|
||||
graph = Graph('Tests tasks depth')
|
||||
graph = Graph("Tests tasks depth")
|
||||
|
||||
tA = graph.addNewNode('Ls', input='/tmp')
|
||||
tB = graph.addNewNode('AppendText', inputText='echo B')
|
||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
||||
tD = graph.addNewNode('AppendText', inputText='echo D')
|
||||
tE = graph.addNewNode('AppendFiles')
|
||||
tA = graph.addNewNode("Ls", input="/tmp")
|
||||
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||
tD = graph.addNewNode("AppendText", inputText="echo D")
|
||||
tE = graph.addNewNode("AppendFiles")
|
||||
# C
|
||||
# / \
|
||||
# /---/---->\
|
||||
|
@ -116,14 +116,13 @@ def test_depth_diamond_graph2():
|
|||
|
||||
|
||||
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')
|
||||
tC = graph.addNewNode('AppendText', inputText='echo C')
|
||||
tD = graph.addNewNode('AppendText', inputText='echo D')
|
||||
tE = graph.addNewNode('AppendFiles')
|
||||
tA = graph.addNewNode("Ls", input="/tmp")
|
||||
tB = graph.addNewNode("AppendText", inputText="echo B")
|
||||
tC = graph.addNewNode("AppendText", inputText="echo C")
|
||||
tD = graph.addNewNode("AppendText", inputText="echo D")
|
||||
tE = graph.addNewNode("AppendFiles")
|
||||
# C
|
||||
# / \
|
||||
# /---/---->\
|
||||
|
@ -153,24 +152,24 @@ def test_transitive_reduction():
|
|||
assert set(flowEdgesRes) == set(flowEdges)
|
||||
|
||||
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
|
||||
|
||||
|
||||
def test_graph_reverse_dfsOnDiscover():
|
||||
graph = Graph('Test dfsOnDiscover(reverse=True)')
|
||||
graph = Graph("Test dfsOnDiscover(reverse=True)")
|
||||
|
||||
# ------------\
|
||||
# / ~ C - E - F
|
||||
# A - B
|
||||
# ~ D
|
||||
|
||||
A = graph.addNewNode('Ls', input='/tmp')
|
||||
B = graph.addNewNode('AppendText', inputText=A.output)
|
||||
C = graph.addNewNode('AppendText', inputText=B.output)
|
||||
D = graph.addNewNode('AppendText', inputText=B.output)
|
||||
E = graph.addNewNode('Ls', input=C.output)
|
||||
F = graph.addNewNode('AppendText', input=A.output, inputText=E.output)
|
||||
A = graph.addNewNode("Ls", input="/tmp")
|
||||
B = graph.addNewNode("AppendText", inputText=A.output)
|
||||
C = graph.addNewNode("AppendText", inputText=B.output)
|
||||
D = graph.addNewNode("AppendText", inputText=B.output)
|
||||
E = graph.addNewNode("Ls", input=C.output)
|
||||
F = graph.addNewNode("AppendText", input=A.output, inputText=E.output)
|
||||
|
||||
# Get all nodes from A (use set, order not guaranteed)
|
||||
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]
|
||||
assert set(nodes) == {B, D, C, E, F}
|
||||
# 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}
|
||||
# Get all nodes from C (order guaranteed)
|
||||
nodes = graph.dfsOnDiscover(startNodes=[C], reverse=True)[0]
|
||||
|
@ -190,7 +189,7 @@ def test_graph_reverse_dfsOnDiscover():
|
|||
|
||||
|
||||
def test_graph_dfsOnDiscover():
|
||||
graph = Graph('Test dfsOnDiscover(reverse=False)')
|
||||
graph = Graph("Test dfsOnDiscover(reverse=False)")
|
||||
|
||||
# ------------\
|
||||
# / ~ C - E - F
|
||||
|
@ -198,13 +197,13 @@ def test_graph_dfsOnDiscover():
|
|||
# ~ D
|
||||
# G
|
||||
|
||||
G = graph.addNewNode('Ls', input='/tmp')
|
||||
A = graph.addNewNode('Ls', input='/tmp')
|
||||
B = graph.addNewNode('AppendText', inputText=A.output)
|
||||
C = graph.addNewNode('AppendText', inputText=B.output)
|
||||
D = graph.addNewNode('AppendText', input=G.output, inputText=B.output)
|
||||
E = graph.addNewNode('Ls', input=C.output)
|
||||
F = graph.addNewNode('AppendText', input=A.output, inputText=E.output)
|
||||
G = graph.addNewNode("Ls", input="/tmp")
|
||||
A = graph.addNewNode("Ls", input="/tmp")
|
||||
B = graph.addNewNode("AppendText", inputText=A.output)
|
||||
C = graph.addNewNode("AppendText", inputText=B.output)
|
||||
D = graph.addNewNode("AppendText", input=G.output, inputText=B.output)
|
||||
E = graph.addNewNode("Ls", input=C.output)
|
||||
F = graph.addNewNode("AppendText", input=A.output, inputText=E.output)
|
||||
|
||||
# Get all nodes from A (use set, order not guaranteed)
|
||||
nodes = graph.dfsOnDiscover(startNodes=[A], reverse=False)[0]
|
||||
|
@ -219,7 +218,7 @@ def test_graph_dfsOnDiscover():
|
|||
nodes = graph.dfsOnDiscover(startNodes=[F], reverse=False)[0]
|
||||
assert set(nodes) == {A, B, C, E, F}
|
||||
# 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}
|
||||
# Get all nodes from D (order guaranteed)
|
||||
nodes = graph.dfsOnDiscover(startNodes=[D], longestPathFirst=True, reverse=False)[0]
|
||||
|
@ -230,21 +229,21 @@ def test_graph_dfsOnDiscover():
|
|||
|
||||
|
||||
def test_graph_nodes_sorting():
|
||||
graph = Graph('')
|
||||
graph = Graph("")
|
||||
|
||||
ls0 = graph.addNewNode('Ls')
|
||||
ls1 = graph.addNewNode('Ls')
|
||||
ls2 = graph.addNewNode('Ls')
|
||||
ls0 = graph.addNewNode("Ls")
|
||||
ls1 = 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)
|
||||
ls2 = graph.addNewNode('Ls', name='Ls_2')
|
||||
ls0 = graph.addNewNode('Ls', name='Ls_0')
|
||||
ls1 = graph.addNewNode('Ls', name='Ls_1')
|
||||
ls2 = graph.addNewNode("Ls", name="Ls_2")
|
||||
ls0 = graph.addNewNode("Ls", name="Ls_0")
|
||||
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():
|
||||
|
@ -256,24 +255,25 @@ def test_duplicate_nodes():
|
|||
# \ \
|
||||
# ---------- n3
|
||||
|
||||
g = Graph('')
|
||||
n0 = g.addNewNode('Ls', input='/tmp')
|
||||
n1 = g.addNewNode('Ls', input=n0.output)
|
||||
n2 = g.addNewNode('Ls', input=n1.output)
|
||||
n3 = g.addNewNode('AppendFiles', input=n1.output, input2=n2.output)
|
||||
g = Graph("")
|
||||
n0 = g.addNewNode("Ls", input="/tmp")
|
||||
n1 = g.addNewNode("Ls", input=n0.output)
|
||||
n2 = g.addNewNode("Ls", input=n1.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)
|
||||
nMap = g.duplicateNodes(srcNodes=nodes_to_duplicate)
|
||||
for s, duplicated in nMap.items():
|
||||
for d in duplicated:
|
||||
assert s.nodeType == d.nodeType
|
||||
|
||||
# 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()])
|
||||
# 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()])
|
||||
|
||||
# check connections
|
||||
# access directly index 0 because we know there is a single duplicate for each parent node
|
||||
# Check connections
|
||||
# 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[n2][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._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):
|
||||
graph = Graph("")
|
||||
|
|
|
@ -7,8 +7,10 @@ from meshroom.core import desc, registerNodeType
|
|||
class SampleNode(desc.Node):
|
||||
""" Sample Node for unit testing """
|
||||
inputs = [
|
||||
desc.File(name='input', label='Input', description='', value='',),
|
||||
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False) # No impact on UID
|
||||
desc.File(name="input", label="Input", description="", value="",),
|
||||
desc.StringParam(name="paramA", label="ParamA",
|
||||
description="", value="",
|
||||
invalidate=False) # No impact on UID
|
||||
]
|
||||
outputs = [
|
||||
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
|
||||
|
@ -19,10 +21,10 @@ registerNodeType(SampleNode)
|
|||
|
||||
|
||||
def test_output_invalidation():
|
||||
graph = Graph('')
|
||||
n1 = graph.addNewNode('SampleNode', input='/tmp')
|
||||
n2 = graph.addNewNode('SampleNode')
|
||||
n3 = graph.addNewNode('SampleNode')
|
||||
graph = Graph("")
|
||||
n1 = graph.addNewNode("SampleNode", input="/tmp")
|
||||
n2 = graph.addNewNode("SampleNode")
|
||||
n3 = graph.addNewNode("SampleNode")
|
||||
|
||||
graph.addEdges(
|
||||
(n1.output, n2.input),
|
||||
|
@ -52,9 +54,9 @@ def test_inputLinkInvalidation():
|
|||
"""
|
||||
Input links should not change the invalidation.
|
||||
"""
|
||||
graph = Graph('')
|
||||
n1 = graph.addNewNode('SampleNode')
|
||||
n2 = graph.addNewNode('SampleNode')
|
||||
graph = Graph("")
|
||||
n1 = graph.addNewNode("SampleNode")
|
||||
n2 = graph.addNewNode("SampleNode")
|
||||
|
||||
graph.addEdges((n1.input, n2.input))
|
||||
assert n1.input.uid() == n2.input.uid()
|
||||
|
|
|
@ -313,7 +313,8 @@ class TestAttributeCallbackBehaviorWithUpstreamCompoundAttributes:
|
|||
|
||||
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 = [
|
||||
|
@ -390,7 +391,6 @@ class TestAttributeCallbackBehaviorWithUpstreamDynamicOutputs:
|
|||
assert nodeB.input.value == 20
|
||||
assert nodeB.affectedInput.value == 0
|
||||
|
||||
|
||||
def test_clearingDynamicOutputValueDoesNotTriggerDownstreamAttributeChangedCallback(
|
||||
self, graphSavedOnDisk
|
||||
):
|
||||
|
@ -455,4 +455,3 @@ class TestAttributeCallbackBehaviorOnGraphImport:
|
|||
otherGraph.importGraphContent(graph)
|
||||
|
||||
assert otherGraph.node(nodeB.name).affectedInput.value == 2
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ from meshroom.core.node import 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 = [
|
||||
desc.ListAttribute(
|
||||
|
@ -128,11 +129,14 @@ class TestCommandLineFormatting:
|
|||
|
||||
# Assert that extending values when the list is not empty is working
|
||||
node.images.extend(inputImages)
|
||||
assert node.images.getValueStr() == '"single value with space" "{}" "{}"'.format(inputImages[0],
|
||||
assert node.images.getValueStr() == \
|
||||
'"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
|
||||
assert node._cmdVars["imagesValue"] == 'single value with space {} {}'.format(inputImages[0],
|
||||
# Values are not retrieved as strings in the command line, so quotes around them are
|
||||
# not expected
|
||||
assert node._cmdVars["imagesValue"] == \
|
||||
'single value with space {} {}'.format(inputImages[0],
|
||||
inputImages[1])
|
||||
|
||||
def test_formatting_strings(self):
|
||||
|
@ -140,11 +144,13 @@ class TestCommandLineFormatting:
|
|||
node = graph.addNewNode("NodeWithAttributesNeedingFormatting")
|
||||
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._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._cmdVars["methodValue"] == "MethodC"
|
||||
|
||||
|
@ -154,14 +160,18 @@ class TestCommandLineFormatting:
|
|||
|
||||
# Assert that the list with one empty value generates empty quotes
|
||||
node.images.extend("")
|
||||
assert node.images.getValueStr() == '""', "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 node.images.getValueStr() == '""', \
|
||||
"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
|
||||
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"] == ' ', \
|
||||
"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):
|
||||
graph = Graph("")
|
||||
|
|
|
@ -18,7 +18,7 @@ def registeredNodeTypes(nodeTypes: list[Type[desc.Node]]):
|
|||
|
||||
@contextmanager
|
||||
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
|
||||
with patch.object(
|
||||
meshroom.core,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue