-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor Graph de/serialization #2612
Open
yann-lty
wants to merge
18
commits into
develop
Choose a base branch
from
dev/graphIO
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,414
−764
Open
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
9dfd9cf
[core] Move `nodeFactory` to its own module
yann-lty d7f4034
[tests] Add extra compatibility tests
yann-lty 5e8e900
[core] Refactor `nodeFactory` function
yann-lty e6160bf
[core] Graph: initial refactoring of graph loading API and logic
yann-lty 3fdb91d
[core] Graph: add importGraphContent API
yann-lty 035625f
[core] CompatibilityNode: do not use link expressions as default valu…
yann-lty 7465823
[core] Introducing new graphIO module
yann-lty f7ae76d
[graphIO] Introduce graph serializer classes
yann-lty 4aa6eac
[core][graphIO] Introduce PartialGraphSerializer
yann-lty 44dc09b
[core] Graph: improve uid conflicts check on deserialization
yann-lty 9576389
[ui] Refactor node pasting using graph partial serialization
yann-lty 85c0812
[core] Add `Graph.copy` method
yann-lty c97d40f
[core] Graph: cleanup unused methods
yann-lty 5c556f9
[core][graphIO] Add "template" as an explicit key
yann-lty 7ca0900
[core] Graph: add `replaceNode` method
yann-lty 42550b6
[core] Graph: improved uid conflicts evaluation on deserialization
yann-lty 357575d
[commands] UpgradeNode.undo: only set expected uid when "downgrading"…
yann-lty dbafe84
[test] Extra partial serialization tests
yann-lty File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -643,7 +643,7 @@ def _createUniqueNodeName(self, inputName: str, existingNames: Optional[set[str] | |
def node(self, nodeName): | ||
return self._nodes.get(nodeName) | ||
|
||
def upgradeNode(self, nodeName): | ||
def upgradeNode(self, nodeName) -> Node: | ||
""" | ||
Upgrade the CompatibilityNode identified as 'nodeName' | ||
Args: | ||
|
@@ -663,25 +663,49 @@ def upgradeNode(self, nodeName): | |
if not isinstance(node, CompatibilityNode): | ||
raise ValueError("Upgrade is only available on CompatibilityNode instances.") | ||
upgradedNode = node.upgrade() | ||
self.replaceNode(nodeName, upgradedNode) | ||
return upgradedNode | ||
|
||
@changeTopology | ||
def replaceNode(self, nodeName: str, newNode: BaseNode): | ||
"""Replace the node idenfitied by `nodeName` with `newNode`, while restoring compatible edges. | ||
|
||
Args: | ||
nodeName: The name of the Node to replace. | ||
newNode: The Node instance to replace it with. | ||
""" | ||
with GraphModification(self): | ||
inEdges, outEdges, outListAttributes = self.removeNode(nodeName) | ||
self.addNode(upgradedNode, nodeName) | ||
for dst, src in outEdges.items(): | ||
# Re-create the entries in ListAttributes that were completely removed during the call to "removeNode" | ||
# If they are not re-created first, adding their edges will lead to errors | ||
# 0 = attribute name, 1 = attribute index, 2 = attribute value | ||
if dst in outListAttributes.keys(): | ||
listAttr = self.attribute(outListAttributes[dst][0]) | ||
if isinstance(outListAttributes[dst][2], list): | ||
listAttr[outListAttributes[dst][1]:outListAttributes[dst][1]] = outListAttributes[dst][2] | ||
else: | ||
listAttr.insert(outListAttributes[dst][1], outListAttributes[dst][2]) | ||
try: | ||
self.addEdge(self.attribute(src), self.attribute(dst)) | ||
except (KeyError, ValueError) as e: | ||
logging.warning("Failed to restore edge {} -> {}: {}".format(src, dst, str(e))) | ||
|
||
return upgradedNode, inEdges, outEdges, outListAttributes | ||
_, outEdges, outListAttributes = self.removeNode(nodeName) | ||
self.addNode(newNode, nodeName) | ||
self._restoreOutEdges(outEdges, outListAttributes) | ||
|
||
def _restoreOutEdges(self, outEdges: dict[str, str], outListAttributes): | ||
"""Restore output edges that were removed during a call to "removeNode". | ||
|
||
Args: | ||
outEdges: a dictionary containing the outgoing edges removed by a call to "removeNode". | ||
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()} | ||
outListAttributes: a dictionary containing the values, indices and keys of attributes that were connected | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not introduced by this PR, but it may be good to create a structured type instead of this dictionnary. |
||
to a ListAttribute prior to the removal of all edges. | ||
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)} | ||
""" | ||
def _recreateTargetListAttributeChildren(listAttrName: str, index: int, value: Any): | ||
listAttr = self.attribute(listAttrName) | ||
if not isinstance(listAttr, ListAttribute): | ||
return | ||
if isinstance(value, list): | ||
listAttr[index:index] = value | ||
else: | ||
listAttr.insert(index, value) | ||
|
||
for dstName, srcName in outEdges.items(): | ||
# Re-create the entries in ListAttributes that were completely removed during the call to "removeNode" | ||
if dstName in outListAttributes: | ||
_recreateTargetListAttributeChildren(*outListAttributes[dstName]) | ||
try: | ||
self.addEdge(self.attribute(srcName), self.attribute(dstName)) | ||
except (KeyError, ValueError) as e: | ||
logging.warning(f"Failed to restore edge {srcName} -> {dstName}: {str(e)}") | ||
|
||
def upgradeAllNodes(self): | ||
""" Upgrade all upgradable CompatibilityNode instances in the graph. """ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's much better!