-
-
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.
Open
+1,414
−764
Conversation
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
yann-lty
force-pushed
the
dev/graphIO
branch
3 times, most recently
from
December 7, 2024 18:49
309cc2a
to
6b829e7
Compare
Add a new test suite for graph template loading.
Rewrite `nodeFactory` to reduce cognitive complexity, while preserving the current behavior.
* API Instead of having a single `load` function that exposes in its API some elements only applicable to initializing a graph from a templates, split it into 2 distinct functions: `load` and `initFromTemplate`. Apply those changes to users of the API (UI, CLI), and simplify Graph wrapper classes to better align with those concepts. * Deserialization Reduce the cognitive complexity of the deserizalization process by splitting it into more atomic functions, while maintaining the current behavior.
Extract the logic of importing the content of a graph within a graph instance from the graph loading logic. Add `Graph.importGraphContent` and `Graph.importGraphContentFromFile` methods. Use the deserialization API to load the content in another temporary graph instance, to handle the renaming of nodes using the Graph API, rather than manipulating entries in a raw dictionnary.
…es for unknown File attributes When creating a compatibility description for an unknown attribute, do not consider a link expression as the default value for a File attribute. This is breaking how the link expression solving system works, as it's resetting the attribute to its default value after applying the link. If that expression is kept as the default value, it can be re-evaluated several times incorrectly. Added a test case that was failing before that change to illustrate the issue.
Move Graph.IO internal class to its own module, and rename it to `GraphIO`. This avoid nested classes within the core Graph class, and starts decoupling the management of graph's IO from the logic of the graph itself.
Move the serialization logic to dedicated serializer classes. Implement both `GraphSerializer` and `TemplateGraphSerializer` to cover for the existing serialization use-cases.
Add a new serializer class to manage partial graph serialization logic, ensuring to remove link expressions on attributes refering to nodes that are not in the subset of nodes to serialize.
Only perform uid check when we have both a serialized and a computed UID. If the node has not been serialized with a UID, it means that it does not expect to match a specific value on deserialization.
Re-implement node pasting by relying on the graph partial serializer, to serialize only the subset of selected nodes. On pasting, use standard graph deserialization and import the content of the serialized graph in the active graph instance. Simplify the positioning of pasted nodes to only consider mouse position or center of the graph, which works well for the major variety of use-cases. Compute the offset to apply to imported nodes by using the de-serialized graph content's bounding box.
Add a new method to create a copy of a graph instance, relying on chaining serialization and deserialization operations. Add test suite to validate its behavior, and the underlying serialization processes.
yann-lty
force-pushed
the
dev/graphIO
branch
from
December 10, 2024 11:53
a5a016e
to
b3117de
Compare
Factorize the logic of replacing a node with another one and re-creating output edges into `Graph.replaceNode` and `Graph._restoreOutEdges`.
At the end of the deserialization process, solve node uid conflicts iteratively by node depths, and only replace the conflicting nodes with a CompatibilityNode. Add new test suite for testing uid conflict handling.
… UidConflict Only set the expectedUid when undoing the upgrade of a uid conflicting node. Otherwise, let the other type of conflicts take precedence.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Refactoring graph de/serialization for code-base simplification, fixing issues and better testability.
This PR introduces a major refactoring of the graph serialization/deserialization logic (aka graph IO).
With those changes, we address some of the known issues in this area, most notably when copy/pasting nodes.
Overall, the main concept is that any operation that needs to operate on serialized Graph data uses deserialization first, to work with Graph API, instead of manipulating a raw dictionary of serialized data.
It also creates a clear distinction in the API between the loading of a Meshroom file, the initialization of a Graph from a template and importing the content of another Graph.
Features
Implementation details
The goal of this PR is to move away from a monolothic Graph class that mixes a lot of responsibilities, to make the code more manageable and testable.
NodeFactory
The nodeFactory function has been refactored to rely on an underlying class that manages the compatibility checks. While preserving the existing behavior, this class helps understanding the different steps that occurs during that that process.
Graph
Deserialization
The current implementation exposes a unique entry point, as a single
load
function with several booleans to manage the different cases, to deal with:This makes it complex to manage the possible combinations of options, as all of them are not necessarily meaningful.
In the new approach, those are decoupled into as many entry points as required to handle the distinct logic those operations have:
UID conflict check
The current implementation creates all nodes twice to deal with UID compatibility issues, which increases load times and may keep false-positives depending on the order in which nodes are handled.
In the new approach, we only consider nodes that actually have a UID conflict, and solve them by depth ordering.
Indeed, UID conflicts are contagious: an upstream node can impact the downstream ones, as UID flow through connections.
By replacing upstream nodes first with CompatibilityNodes, we restore their serialized UID, which may solve the "false-positive" conflicts downstream, that were only due to the contagion by this node.
Importing another graph content
This area benefits the most from the refactoring, which solves errors we may currently encounter in the copy-pasting of nodes.
Instead of manipulating raw dictionaries to solve conflicting node names w.r.t the current content of the Graph, it now relies on:
Serialization
Introducing new GraphSerializer classes, following a Template Method pattern.
This makes it easier to define several node serialization logic, while inheriting from the standard serialization structure.