Skip to content

Commit

Permalink
added error handling for JSON duplicate IDs (#538)
Browse files Browse the repository at this point in the history
* added error handling for JSON duplicate IDs

* Update test_json.py

* fixed failing tests

* Update test_json.py
  • Loading branch information
nwlandry committed May 10, 2024
1 parent 9140f10 commit 6495dcc
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
10 changes: 7 additions & 3 deletions docs/source/api/recipes/recipes.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -958,21 +958,25 @@
}
],
"source": [
"import xgi\n",
"import itertools\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib import gridspec\n",
"import numpy as np\n",
"import itertools\n",
"from matplotlib import gridspec\n",
"\n",
"import xgi\n",
"\n",
"link_color = \"#000000\"\n",
"triangle_color = \"#648FFF\"\n",
"square_color = \"#785EF0\"\n",
"pentagon_color = \"#DC267F\"\n",
"colors = [link_color, triangle_color, square_color, pentagon_color]\n",
"\n",
"\n",
"def color_edges(H):\n",
" return [colors[i - 2] for i in H.edges.filterby(\"order\", 1, \"gt\").size.aslist()]\n",
"\n",
"\n",
"links = [[1, 2], [1, 3], [5, 6], [1, 7]]\n",
"triangles = [[3, 5, 7], [2, 7, 1], [6, 10, 15]]\n",
"squares = [[7, 8, 9, 10]]\n",
Expand Down
12 changes: 12 additions & 0 deletions tests/readwrite/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,15 @@ def test_write_json(edgelist1):
assert H2.nodes[2] == {"name": "Ilya"}
assert H2.edges[1] == {"weight": 2}
assert H2["name"] == "test"

badH = xgi.Hypergraph()
# duplicate node IDs when casting to a string
badH.add_nodes_from(["2", 2])
with pytest.raises(XGIError):
xgi.write_json(badH, "test.json")

badH = xgi.Hypergraph()
# duplicate edge IDs when casting to a string
badH.add_edges_from({"2": [1, 2, 3], 2: [4, 5, 6]})
with pytest.raises(XGIError):
xgi.write_json(badH, "test.json")
27 changes: 27 additions & 0 deletions xgi/readwrite/json.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Read from and write to JSON."""
import json
from collections import Counter

from ..convert import dict_to_hypergraph
from ..exception import XGIError
Expand All @@ -18,6 +19,12 @@ def write_json(H, path):
path: string
The path of the file to read from
Raises
------
XGIError
If the node or edge IDs have conflicts after casting
to strings, e.g., node IDs "2" and 2.
"""
# initialize empty data
data = {}
Expand All @@ -29,11 +36,31 @@ def write_json(H, path):
# get node data
try:
data["node-data"] = {str(idx): H.nodes[idx] for idx in H.nodes}

if len(data["node-data"]) != H.num_nodes:
dups = [
item
for item, count in Counter([str(n) for n in H.nodes]).items()
if count > 1
]
raise XGIError(
f"When casting node IDs to strings, ID(s) {', '.join(dups)} have conflicting IDs!"
)
except KeyError:
raise XGIError("Node attributes not saved!")

try:
data["edge-data"] = {str(idx): H.edges[idx] for idx in H.edges}

if len(data["edge-data"]) != H.num_edges:
dups = [
item
for item, count in Counter([str(n) for n in H.edges]).items()
if count > 1
]
raise XGIError(
f"When casting edge IDs to strings, ID(s) {', '.join(dups)} have conflicting IDs!"
)
except KeyError:
raise XGIError("Edge attributes not saved!")

Expand Down

0 comments on commit 6495dcc

Please sign in to comment.