Skip to content

Conversation

@d-miketa
Copy link
Contributor

Addresses #1516: JSON roundtrip is broken whenever the graph contains deleted (or contracted) nodes.

This leaves just the GraphML format as incapable of a clean round-trip.

@coveralls
Copy link

Pull Request Test Coverage Report for Build 18563991601

Details

  • 57 of 71 (80.28%) changed or added relevant lines in 4 files are covered.
  • 2 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.05%) to 94.108%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/json/mod.rs 28 32 87.5%
src/json/node_link_data.rs 27 37 72.97%
Files with Coverage Reduction New Missed Lines %
src/digraph.rs 1 98.11%
src/graph.rs 1 97.05%
Totals Coverage Status
Change from base Build 18083333380: -0.05%
Covered Lines: 18177
Relevant Lines: 19315

💛 - Coveralls

@IvanIsCoding
Copy link
Collaborator

I will take a look at this during the weekend. Thanks for sending the fix for an issue you found!

Copy link
Collaborator

@IvanIsCoding IvanIsCoding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent test cases! I have no doubt this works, I just left some comments on what should be improved in Rust.

},
None => py.None(),
};
let node_id = node.id.unwrap_or(0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let node_id = node.id.unwrap_or(0);
let node_id = node.id?;

I don't think we should default to 0 if it is not defined.

Comment on lines +97 to +101
let mut tmp_nodes: Vec<NodeIndex> = Vec::new();
for _ in 0..=max_id {
let idx = out_graph.add_node(py.None());
tmp_nodes.push(idx);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a more idiomatic way of writing this:

let tmp_nodes: Vec<NodeIndex> = (0..=max_id)
    .map(|_| out_graph.add_node(py.None()))
    .collect();

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion also works with HashSet by the way


id_mapping.insert(node_id, idx);
// Mark this index as used (remove from tmp_nodes)
tmp_nodes.retain(|&n| n != idx);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can lead to quadratic behaviour, we are looping through all tmp_nodes to delete the index.

Please use https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html instead

}

has_gaps
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit picking: can you swap the if/else order? i.e. use if ! preserve_ids.

This is a style choice but I prefer to have the most common case first in if statements.

self.assertEqual(g.node_indices(), gprime.node_indices())
self.assertEqual(g.edge_list(), gprime.edge_list())
self.assertEqual(g.nodes(), gprime.nodes())
self.assertEqual(dict(g.edge_index_map()), dict(gprime.edge_index_map()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course you copied examples that don't use it but: https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertDictEqual

This just has a nicer error message, in case someone ever introduces a bug

@IvanIsCoding
Copy link
Collaborator

Also, you'll need to solve some minor conflicts with #1510

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants