diff --git a/meshroom/core/desc/node.py b/meshroom/core/desc/node.py index bd68e83605..cd667dadb6 100644 --- a/meshroom/core/desc/node.py +++ b/meshroom/core/desc/node.py @@ -1,5 +1,5 @@ import enum -from inspect import getfile +from inspect import getfile, getattr_static from pathlib import Path import logging import shlex @@ -427,7 +427,12 @@ def buildCommandLine(self, chunk) -> str: if chunk.node.isParallelized and chunk.node.size > 1: cmdSuffix = " " + self.commandLineRange.format(**chunk.range.toDict()) + " " + cmdSuffix - return cmdPrefix + chunk.node.nodeDesc.commandLine.format(**chunk.node._expVars, **chunk.node._staticExpVars, **cmdLineVars) + cmdSuffix + commandLineValue = getattr_static(self, 'commandLine') + if callable(commandLineValue): + cmd = commandLineValue(chunk.node) + else: + cmd = commandLineValue.format(**chunk.node._expVars, **chunk.node._staticExpVars, **cmdLineVars) + return cmdPrefix + cmd + cmdSuffix def processChunk(self, chunk): cmd = self.buildCommandLine(chunk) diff --git a/tests/test_nodeCommandLineFormatting.py b/tests/test_nodeCommandLineFormatting.py index 65f42ca4b0..612236f564 100644 --- a/tests/test_nodeCommandLineFormatting.py +++ b/tests/test_nodeCommandLineFormatting.py @@ -1,12 +1,64 @@ #!/usr/bin/env python # coding:utf-8 +from unittest.mock import patch, PropertyMock + from meshroom.core.graph import Graph from meshroom.core import desc from .utils import registerNodeDesc, unregisterNodeDesc +class NodeWithCommandLineLambda(desc.CommandLineNode): + """ + A node using a lambda for the commandLine member variable. + """ + commandLine = lambda node: f"myapp --input {node.input.value} --output {node.output.value}" + + inputs = [ + desc.File( + name="input", + label="Input File", + description="An input file.", + value="/some/input", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="Output file.", + value="{nodeCacheFolder}/output.txt", + ), + ] + + +class NodeWithCommandLineString(desc.CommandLineNode): + """ + A node using a string template for the commandLine member variable. + """ + commandLine = "myapp --input {inputValue} --output {outputValue}" + + inputs = [ + desc.File( + name="input", + label="Input File", + description="An input file.", + value="/some/input", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="Output file.", + value="{nodeCacheFolder}/output.txt", + ), + ] + + class NodeWithAttributesNeedingFormatting(desc.Node): """ A node containing list, file, choice and group attributes in order to test the @@ -187,3 +239,45 @@ def test_formatting_groups(self): assert node.secondGroup.getValueStr() == '"False,second_value,3.0"' assert node._expVars["secondGroupValue"] == 'False,second_value,3.0' + + +class TestCommandLineLambda: + + @classmethod + def setup_class(cls): + registerNodeDesc(NodeWithCommandLineLambda) + registerNodeDesc(NodeWithCommandLineString) + + @classmethod + def teardown_class(cls): + unregisterNodeDesc(NodeWithCommandLineLambda) + unregisterNodeDesc(NodeWithCommandLineString) + + def test_commandLine_lambda(self): + graph = Graph("") + node = graph.addNewNode("NodeWithCommandLineLambda") + chunk = node.chunks[0] + with patch("meshroom.core.plugins.NodePlugin.commandPrefix", new_callable=PropertyMock, return_value=""), \ + patch("meshroom.core.plugins.NodePlugin.commandSuffix", new_callable=PropertyMock, return_value=""): + cmd = node.nodeDesc.buildCommandLine(chunk) + assert "--input /some/input" in cmd + assert "--output" in cmd + + def test_commandLine_string(self): + graph = Graph("") + node = graph.addNewNode("NodeWithCommandLineString") + chunk = node.chunks[0] + with patch("meshroom.core.plugins.NodePlugin.commandPrefix", new_callable=PropertyMock, return_value=""), \ + patch("meshroom.core.plugins.NodePlugin.commandSuffix", new_callable=PropertyMock, return_value=""): + cmd = node.nodeDesc.buildCommandLine(chunk) + assert cmd == "myapp --input /some/input --output {}".format(node.output.value) + + def test_commandLine_lambda_uses_node_attribute(self): + graph = Graph("") + node = graph.addNewNode("NodeWithCommandLineLambda") + node.input.value = "/custom/path/file.txt" + chunk = node.chunks[0] + with patch("meshroom.core.plugins.NodePlugin.commandPrefix", new_callable=PropertyMock, return_value=""), \ + patch("meshroom.core.plugins.NodePlugin.commandSuffix", new_callable=PropertyMock, return_value=""): + cmd = node.nodeDesc.buildCommandLine(chunk) + assert "--input /custom/path/file.txt" in cmd