From c5370b794cf894ad4ab08c96a78ab240738cd185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 28 Oct 2025 17:48:15 +0100 Subject: [PATCH 1/3] [nodes] Add new `InputFile` input node The node receives a file or directory as the input, and can be used as the entry point of a graph for `meshroom_batch` --- meshroom/nodes/general/InputFile.py | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 meshroom/nodes/general/InputFile.py diff --git a/meshroom/nodes/general/InputFile.py b/meshroom/nodes/general/InputFile.py new file mode 100644 index 0000000000..7777bcafcc --- /dev/null +++ b/meshroom/nodes/general/InputFile.py @@ -0,0 +1,48 @@ +__version__ = "1.0" + +import logging +import os + +from meshroom.core import desc + +class InputFile(desc.InputNode, desc.InitNode): + """ +This node is an input node that receives a File. +""" + category = "Other" + + inputs = [ + desc.File( + name="inputFile", + label="Input File", + description="A file or folder to use as the input.", + value="", + ) + ] + + def initialize(self, node, inputs, recursiveInputs): + self.resetAttributes(node, ["inputFile"]) + + if len(inputs) >= 1: + if os.path.isfile(inputs[0]) or os.path.isdir(inputs[0]): + self.setAttributes(node, {"inputFile": inputs[0]}) + + if len(inputs) > 1: + logging.warning(f"Several inputs were provided ({inputs}).") + logging.warning(f"Only the first one ({inputs[0]}) will be used.") + else: + raise RuntimeError(f"{inputs[0]} is not a valid file or directory.") + + elif len(recursiveInputs) >= 1: + if os.path.isfile(recursiveInputs[0]) or os.path.isdir(recursiveInputs[0]): + self.setAttributes(node, {"inputFile": recursiveInputs[0]}) + + if len(recursiveInputs) > 1: + logging.warning(f"Several recursive inputs were provided ({recursiveInputs}).") + logging.warning(f"Only the first valid one ({recursiveInputs[0]}) will be used.") + + else: + raise RuntimeError(f"{recursiveInputs[0]} is not a valid file or directory.") + + else: + raise RuntimeError("No file or directory has been set for 'inputFile'.") From 39151bea0544a3cadb89327603c27b0c9329c67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Fri, 31 Oct 2025 15:56:34 +0100 Subject: [PATCH 2/3] [tests] Add test for `InitNode` --- .../meshroom/pluginA/PluginAInputInitNode.py | 27 ++++++++++++++ tests/test_nodes.py | 35 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/plugins/meshroom/pluginA/PluginAInputInitNode.py diff --git a/tests/plugins/meshroom/pluginA/PluginAInputInitNode.py b/tests/plugins/meshroom/pluginA/PluginAInputInitNode.py new file mode 100644 index 0000000000..2e10187603 --- /dev/null +++ b/tests/plugins/meshroom/pluginA/PluginAInputInitNode.py @@ -0,0 +1,27 @@ +__version__ = "1.0" + +from meshroom.core import desc + + +class PluginAInputInitNode(desc.InputNode, desc.InitNode): + inputs = [ + desc.File( + name="input", + label="Input", + description="", + value="", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="", + value="", + ), + ] + + def initialize(self, node, inputs, recursiveInputs): + if len(inputs) >= 1: + self.setAttributes(node, {"input": inputs[0]}) diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 845193e7db..cfa2353af5 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -101,3 +101,38 @@ def test_expVariables(self): assert n._expVars["uid"] == n._uid assert n.internalFolder assert n.internalFolder == n._expVars["nodeCacheFolder"] + + +class TestInitNode: + plugin = None + + @classmethod + def setup_class(cls): + folder = os.path.join(os.path.dirname(__file__), "plugins", "meshroom") + package = "pluginA" + cls.plugin = Plugin(package, folder) + nodes = loadClassesNodes(folder, package) + for node in nodes: + cls.plugin.addNodePlugin(node) + pluginManager.addPlugin(cls.plugin) + + @classmethod + def teardown_class(cls): + for node in cls.plugin.nodes.values(): + pluginManager.unregisterNode(node) + pluginManager.removePlugin(cls.plugin) + cls.plugin = None + + def test_initNode(self): + g = Graph("") + + node = g.addNewNode("PluginAInputInitNode") + + # Check that the init node is correctly detected + initNodes = g.findInitNodes() + assert len(initNodes) == 1 and node in initNodes + + # Check that the init node's initialize method has been set + inputs = ["/path/to/file", "/path/to/file/2"] + node.nodeDesc.initialize(node, inputs, None) + assert node.input.value == inputs[0] From 06a83f6bb960649b82e6c19faa5b1468d2fd4e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Fri, 31 Oct 2025 15:56:53 +0100 Subject: [PATCH 3/3] [tests] Fix typo on the class name for PluginA's input node --- tests/plugins/meshroom/pluginA/PluginAInputNode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/meshroom/pluginA/PluginAInputNode.py b/tests/plugins/meshroom/pluginA/PluginAInputNode.py index 10d31a35de..c4efa8cf1e 100644 --- a/tests/plugins/meshroom/pluginA/PluginAInputNode.py +++ b/tests/plugins/meshroom/pluginA/PluginAInputNode.py @@ -3,7 +3,7 @@ from meshroom.core import desc -class PluginANodeA(desc.InputNode): +class PluginAInputNode(desc.InputNode): inputs = [ desc.File( name="input",