[core] Graph: Detect UID conflicts when loading a graph

When loading the graph, once all the nodes have been created and the
links resolved, the computed nodes' UID can be compared with those
stored in the graph.

If a mismatch is detected, the node that presents the UID conflict is
removed from the graph and replaced with a CompatibilityNode, set with
`UidConflict`.

Nodes that come from templates are ignored as no UID is stored in
templates. Similarly, nodes that are already Compatibility nodes are left
out as they do not have a UID.
This commit is contained in:
Candice Bentéjac 2023-06-15 19:12:38 +02:00
parent 7cb13905a1
commit cdf5c6746f

View file

@ -243,7 +243,7 @@ class Graph(BaseObject):
@Slot(str)
def load(self, filepath, setupProjectFile=True, importProject=False, publishOutputs=False):
"""
Load a meshroom graph ".mg" file.
Load a Meshroom graph ".mg" file.
Args:
filepath: project filepath to load
@ -308,8 +308,39 @@ class Graph(BaseObject):
# Note: needs to be done at the end as it will trigger an updateInternals.
self._setFilepath(filepath)
# By this point, the graph has been fully loaded and an updateInternals has been triggered, so all the nodes'
# links have been resolved and their UID computations are all complete.
# It is now possible to check whether the UIDs stored in the graph file for each node correspond to the ones
# that were computed.
if not isTemplate: # UIDs are not stored in templates
self._evaluateUidConflicts(graphData)
self._applyExpr()
return True
def _evaluateUidConflicts(self, data):
"""
Compare the UIDs of all the nodes in the graph with the UID that is expected in the graph file. If there
are mismatches, the nodes with the unexpected UID are replaced with "UidConflict" compatibility nodes.
Args:
data (dict): the dictionary containing all the nodes to import and their data
"""
for nodeName, nodeData in sorted(data.items(), key=lambda x: self.getNodeIndexFromName(x[0])):
node = self.node(nodeName)
# If the node is a CompatibilityNode, its UID is not available and there is no need to check it
if isinstance(node, CompatibilityNode):
continue
savedUid = nodeData.get("uids", "").get("0", "") # Node's UID from the graph file
graphUid = node._uids.get(0) # Node's UID from the graph itself
if savedUid != graphUid and graphUid is not None:
# Different UIDs, remove the existing node from the graph and replace it with a CompatibilityNode
logging.debug("UID conflict detected for {}".format(nodeName))
self.removeNode(nodeName)
n = nodeFactory(nodeData, nodeName, template=False, uidConflict=True)
self._addNode(n, nodeName)
def updateImportedProject(self, data):
"""
Update the names and links of the project to import so that it can fit