diff --git a/meshroom/core/attribute.py b/meshroom/core/attribute.py index f8135323..5274d3cf 100644 --- a/meshroom/core/attribute.py +++ b/meshroom/core/attribute.py @@ -339,9 +339,12 @@ class Attribute(BaseObject): elif self.isInput and Attribute.isLinkExpression(v): # value is a link to another attribute link = v[1:-1] - linkNode, linkAttr = link.split('.') + linkNodeName, linkAttrName = link.split('.') try: - g.addEdge(g.node(linkNode).attribute(linkAttr), self) + node = g.node(linkNodeName) + if not node: + raise KeyError(f"Node '{linkNodeName}' not found") + g.addEdge(node.attribute(linkAttrName), self) except KeyError as err: logging.warning('Connect Attribute from Expression failed.') logging.warning('Expression: "{exp}"\nError: "{err}".'.format(exp=v, err=err)) diff --git a/tests/test_graphIO.py b/tests/test_graphIO.py index cd51038c..95d72021 100644 --- a/tests/test_graphIO.py +++ b/tests/test_graphIO.py @@ -336,3 +336,15 @@ class TestImportGraphContentFromMinimalGraphData: assert len(graph.nodes) == 1 assert len(graph.compatibilityNodes) == 0 + def test_connectionsToMissingNodesAreDiscarded(self): + graph = Graph("") + + with registeredNodeTypes([SimpleNode]): + sampleGraphContent = dedent(""" + { + "SimpleNode_1": { + "nodeType": "SimpleNode", "inputs": { "input": "{NotSerializedNode.output}" } + } + } + """) + graph._deserialize(json.loads(sampleGraphContent))