Repository navigation
feat: a graph can be pickled, and copy() works for graphs of any size - #44
Merged
Merged
Conversation
Pickle and deepcopy followed the web of vertex and edge references recursively, so copy() overflowed the stack for a path of about a hundred vertices, and a graph with a built-in metric could not be pickled at all because the metric was a local function. The graph now describes itself flatly: vertices, then edges that refer to their end vertices by index, replayed in order of addition so that every vertex's edge lists are rebuilt in their original order. Built-in metrics are module level and saved by name. A vertex or edge on its own refuses to be pickled or copied, since it has no meaning apart from its graph. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 57 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #44 +/- ##
==========================================
+ Coverage 94.61% 94.79% +0.17%
==========================================
Files 3 3
Lines 1208 1249 +41
==========================================
+ Hits 1143 1184 +41
Misses 65 65 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The built-in metrics return float(...) so that mypy, against the CI's numpy, sees a float rather than floating[Any]. The tests pickle their own graphs, so the pickle calls go through one marked helper pair. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or 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
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.
Summary
A graph can be pickled, and
copy()/copy.deepcopywork for graphs of any size.What was wrong
pickle.dumps(g)failed for every graph with a built-in metric:L1/L2/SE2were local functions inside_metricfunc, which pickle cannot find by name.g.copy()(which iscopy.deepcopy) raisedRecursionErrorfor a graph with a path of about 100 vertices, and pickle did the same at about 2000. A graph is a web of mutual references (vertex, edge, vertex, ...) that pickle and deepcopy follow recursively, so the recursion depth grows with the longest chain, not the size of the graph.Change
_attachhook in order of addition, so every vertex's edge lists (and aDGraph's in-lists) come back in their original order, including parallel edges and self-loops.__init__, so user subclasses with their own constructor signature (e.g. MVTBViewPoint(x, fixed, color)) restore correctly, with their extra attributes.export()is the portable one).Behaviour to review
TypeError: ... pickle or copy its graph instead): it has no meaning apart from its graph. Consequences:copy.copy(e)/copy.deepcopy(e)on an edge now raise (an existing test that asserted otherwise was updated), and vertex/edgedatathat refers to another vertex or edge cannot be pickled or copied.copy.copy(g)goes through the same hook, so it is a structural copy (new vertices and edges sharing coordinate arrays and data).Tests
tests/test_pickle.py(37 tests, both graph kinds): round trip of every observable including order, every pickle protocol,copy()independence, settings and metrics, 5,000-vertex chains for pickle /copy()/deepcopy, subclasses with their own constructors, the refusals. Run against the parent they fail (36 of 43), which is the point.Closes
Supersedes the copy half of #36 together with #43 (already merged).
🤖 Generated with Claude Code