Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/networkx/readwrite/tests/test_graphml.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 import pytest | |
2 import networkx as nx | |
3 from networkx.testing.utils import assert_edges_equal, assert_nodes_equal | |
4 import io | |
5 import tempfile | |
6 import os | |
7 from networkx.testing import almost_equal | |
8 | |
9 | |
10 class BaseGraphML: | |
11 @classmethod | |
12 def setup_class(cls): | |
13 cls.simple_directed_data = """<?xml version="1.0" encoding="UTF-8"?> | |
14 <!-- This file was written by the JAVA GraphML Library.--> | |
15 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
16 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
17 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
18 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
19 <graph id="G" edgedefault="directed"> | |
20 <node id="n0"/> | |
21 <node id="n1"/> | |
22 <node id="n2"/> | |
23 <node id="n3"/> | |
24 <node id="n4"/> | |
25 <node id="n5"/> | |
26 <node id="n6"/> | |
27 <node id="n7"/> | |
28 <node id="n8"/> | |
29 <node id="n9"/> | |
30 <node id="n10"/> | |
31 <edge id="foo" source="n0" target="n2"/> | |
32 <edge source="n1" target="n2"/> | |
33 <edge source="n2" target="n3"/> | |
34 <edge source="n3" target="n5"/> | |
35 <edge source="n3" target="n4"/> | |
36 <edge source="n4" target="n6"/> | |
37 <edge source="n6" target="n5"/> | |
38 <edge source="n5" target="n7"/> | |
39 <edge source="n6" target="n8"/> | |
40 <edge source="n8" target="n7"/> | |
41 <edge source="n8" target="n9"/> | |
42 </graph> | |
43 </graphml>""" | |
44 cls.simple_directed_graph = nx.DiGraph() | |
45 cls.simple_directed_graph.add_node("n10") | |
46 cls.simple_directed_graph.add_edge("n0", "n2", id="foo") | |
47 cls.simple_directed_graph.add_edge("n0", "n2") | |
48 cls.simple_directed_graph.add_edges_from( | |
49 [ | |
50 ("n1", "n2"), | |
51 ("n2", "n3"), | |
52 ("n3", "n5"), | |
53 ("n3", "n4"), | |
54 ("n4", "n6"), | |
55 ("n6", "n5"), | |
56 ("n5", "n7"), | |
57 ("n6", "n8"), | |
58 ("n8", "n7"), | |
59 ("n8", "n9"), | |
60 ] | |
61 ) | |
62 cls.simple_directed_fh = io.BytesIO(cls.simple_directed_data.encode("UTF-8")) | |
63 | |
64 cls.attribute_data = """<?xml version="1.0" encoding="UTF-8"?> | |
65 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
66 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
67 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
68 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
69 <key id="d0" for="node" attr.name="color" attr.type="string"> | |
70 <default>yellow</default> | |
71 </key> | |
72 <key id="d1" for="edge" attr.name="weight" attr.type="double"/> | |
73 <graph id="G" edgedefault="directed"> | |
74 <node id="n0"> | |
75 <data key="d0">green</data> | |
76 </node> | |
77 <node id="n1"/> | |
78 <node id="n2"> | |
79 <data key="d0">blue</data> | |
80 </node> | |
81 <node id="n3"> | |
82 <data key="d0">red</data> | |
83 </node> | |
84 <node id="n4"/> | |
85 <node id="n5"> | |
86 <data key="d0">turquoise</data> | |
87 </node> | |
88 <edge id="e0" source="n0" target="n2"> | |
89 <data key="d1">1.0</data> | |
90 </edge> | |
91 <edge id="e1" source="n0" target="n1"> | |
92 <data key="d1">1.0</data> | |
93 </edge> | |
94 <edge id="e2" source="n1" target="n3"> | |
95 <data key="d1">2.0</data> | |
96 </edge> | |
97 <edge id="e3" source="n3" target="n2"/> | |
98 <edge id="e4" source="n2" target="n4"/> | |
99 <edge id="e5" source="n3" target="n5"/> | |
100 <edge id="e6" source="n5" target="n4"> | |
101 <data key="d1">1.1</data> | |
102 </edge> | |
103 </graph> | |
104 </graphml> | |
105 """ | |
106 cls.attribute_graph = nx.DiGraph(id="G") | |
107 cls.attribute_graph.graph["node_default"] = {"color": "yellow"} | |
108 cls.attribute_graph.add_node("n0", color="green") | |
109 cls.attribute_graph.add_node("n2", color="blue") | |
110 cls.attribute_graph.add_node("n3", color="red") | |
111 cls.attribute_graph.add_node("n4") | |
112 cls.attribute_graph.add_node("n5", color="turquoise") | |
113 cls.attribute_graph.add_edge("n0", "n2", id="e0", weight=1.0) | |
114 cls.attribute_graph.add_edge("n0", "n1", id="e1", weight=1.0) | |
115 cls.attribute_graph.add_edge("n1", "n3", id="e2", weight=2.0) | |
116 cls.attribute_graph.add_edge("n3", "n2", id="e3") | |
117 cls.attribute_graph.add_edge("n2", "n4", id="e4") | |
118 cls.attribute_graph.add_edge("n3", "n5", id="e5") | |
119 cls.attribute_graph.add_edge("n5", "n4", id="e6", weight=1.1) | |
120 cls.attribute_fh = io.BytesIO(cls.attribute_data.encode("UTF-8")) | |
121 | |
122 cls.attribute_named_key_ids_data = """<?xml version='1.0' encoding='utf-8'?> | |
123 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
124 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
125 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
126 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
127 <key id="edge_prop" for="edge" attr.name="edge_prop" attr.type="string"/> | |
128 <key id="prop2" for="node" attr.name="prop2" attr.type="string"/> | |
129 <key id="prop1" for="node" attr.name="prop1" attr.type="string"/> | |
130 <graph edgedefault="directed"> | |
131 <node id="0"> | |
132 <data key="prop1">val1</data> | |
133 <data key="prop2">val2</data> | |
134 </node> | |
135 <node id="1"> | |
136 <data key="prop1">val_one</data> | |
137 <data key="prop2">val2</data> | |
138 </node> | |
139 <edge source="0" target="1"> | |
140 <data key="edge_prop">edge_value</data> | |
141 </edge> | |
142 </graph> | |
143 </graphml> | |
144 """ | |
145 cls.attribute_named_key_ids_graph = nx.DiGraph() | |
146 cls.attribute_named_key_ids_graph.add_node("0", prop1="val1", prop2="val2") | |
147 cls.attribute_named_key_ids_graph.add_node("1", prop1="val_one", prop2="val2") | |
148 cls.attribute_named_key_ids_graph.add_edge("0", "1", edge_prop="edge_value") | |
149 fh = io.BytesIO(cls.attribute_named_key_ids_data.encode("UTF-8")) | |
150 cls.attribute_named_key_ids_fh = fh | |
151 | |
152 cls.attribute_numeric_type_data = """<?xml version='1.0' encoding='utf-8'?> | |
153 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
154 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
155 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
156 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
157 <key attr.name="weight" attr.type="double" for="node" id="d1" /> | |
158 <key attr.name="weight" attr.type="double" for="edge" id="d0" /> | |
159 <graph edgedefault="directed"> | |
160 <node id="n0"> | |
161 <data key="d1">1</data> | |
162 </node> | |
163 <node id="n1"> | |
164 <data key="d1">2.0</data> | |
165 </node> | |
166 <edge source="n0" target="n1"> | |
167 <data key="d0">1</data> | |
168 </edge> | |
169 <edge source="n1" target="n0"> | |
170 <data key="d0">k</data> | |
171 </edge> | |
172 <edge source="n1" target="n1"> | |
173 <data key="d0">1.0</data> | |
174 </edge> | |
175 </graph> | |
176 </graphml> | |
177 """ | |
178 cls.attribute_numeric_type_graph = nx.DiGraph() | |
179 cls.attribute_numeric_type_graph.add_node("n0", weight=1) | |
180 cls.attribute_numeric_type_graph.add_node("n1", weight=2.0) | |
181 cls.attribute_numeric_type_graph.add_edge("n0", "n1", weight=1) | |
182 cls.attribute_numeric_type_graph.add_edge("n1", "n1", weight=1.0) | |
183 fh = io.BytesIO(cls.attribute_numeric_type_data.encode("UTF-8")) | |
184 cls.attribute_numeric_type_fh = fh | |
185 | |
186 cls.simple_undirected_data = """<?xml version="1.0" encoding="UTF-8"?> | |
187 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
188 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
189 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
190 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
191 <graph id="G"> | |
192 <node id="n0"/> | |
193 <node id="n1"/> | |
194 <node id="n2"/> | |
195 <node id="n10"/> | |
196 <edge id="foo" source="n0" target="n2"/> | |
197 <edge source="n1" target="n2"/> | |
198 <edge source="n2" target="n3"/> | |
199 </graph> | |
200 </graphml>""" | |
201 # <edge source="n8" target="n10" directed="false"/> | |
202 cls.simple_undirected_graph = nx.Graph() | |
203 cls.simple_undirected_graph.add_node("n10") | |
204 cls.simple_undirected_graph.add_edge("n0", "n2", id="foo") | |
205 cls.simple_undirected_graph.add_edges_from([("n1", "n2"), ("n2", "n3")]) | |
206 fh = io.BytesIO(cls.simple_undirected_data.encode("UTF-8")) | |
207 cls.simple_undirected_fh = fh | |
208 | |
209 cls.undirected_multigraph_data = """<?xml version="1.0" encoding="UTF-8"?> | |
210 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
211 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
212 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
213 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
214 <graph id="G"> | |
215 <node id="n0"/> | |
216 <node id="n1"/> | |
217 <node id="n2"/> | |
218 <node id="n10"/> | |
219 <edge id="e0" source="n0" target="n2"/> | |
220 <edge id="e1" source="n1" target="n2"/> | |
221 <edge id="e2" source="n2" target="n1"/> | |
222 </graph> | |
223 </graphml>""" | |
224 cls.undirected_multigraph = nx.MultiGraph() | |
225 cls.undirected_multigraph.add_node("n10") | |
226 cls.undirected_multigraph.add_edge("n0", "n2", id="e0") | |
227 cls.undirected_multigraph.add_edge("n1", "n2", id="e1") | |
228 cls.undirected_multigraph.add_edge("n2", "n1", id="e2") | |
229 fh = io.BytesIO(cls.undirected_multigraph_data.encode("UTF-8")) | |
230 cls.undirected_multigraph_fh = fh | |
231 | |
232 cls.undirected_multigraph_no_multiedge_data = """<?xml version="1.0" encoding="UTF-8"?> | |
233 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
234 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
235 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
236 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
237 <graph id="G"> | |
238 <node id="n0"/> | |
239 <node id="n1"/> | |
240 <node id="n2"/> | |
241 <node id="n10"/> | |
242 <edge id="e0" source="n0" target="n2"/> | |
243 <edge id="e1" source="n1" target="n2"/> | |
244 <edge id="e2" source="n2" target="n3"/> | |
245 </graph> | |
246 </graphml>""" | |
247 cls.undirected_multigraph_no_multiedge = nx.MultiGraph() | |
248 cls.undirected_multigraph_no_multiedge.add_node("n10") | |
249 cls.undirected_multigraph_no_multiedge.add_edge("n0", "n2", id="e0") | |
250 cls.undirected_multigraph_no_multiedge.add_edge("n1", "n2", id="e1") | |
251 cls.undirected_multigraph_no_multiedge.add_edge("n2", "n3", id="e2") | |
252 fh = io.BytesIO(cls.undirected_multigraph_no_multiedge_data.encode("UTF-8")) | |
253 cls.undirected_multigraph_no_multiedge_fh = fh | |
254 | |
255 cls.multigraph_only_ids_for_multiedges_data = """<?xml version="1.0" encoding="UTF-8"?> | |
256 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
257 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
258 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
259 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
260 <graph id="G"> | |
261 <node id="n0"/> | |
262 <node id="n1"/> | |
263 <node id="n2"/> | |
264 <node id="n10"/> | |
265 <edge source="n0" target="n2"/> | |
266 <edge id="e1" source="n1" target="n2"/> | |
267 <edge id="e2" source="n2" target="n1"/> | |
268 </graph> | |
269 </graphml>""" | |
270 cls.multigraph_only_ids_for_multiedges = nx.MultiGraph() | |
271 cls.multigraph_only_ids_for_multiedges.add_node("n10") | |
272 cls.multigraph_only_ids_for_multiedges.add_edge("n0", "n2") | |
273 cls.multigraph_only_ids_for_multiedges.add_edge("n1", "n2", id="e1") | |
274 cls.multigraph_only_ids_for_multiedges.add_edge("n2", "n1", id="e2") | |
275 fh = io.BytesIO(cls.multigraph_only_ids_for_multiedges_data.encode("UTF-8")) | |
276 cls.multigraph_only_ids_for_multiedges_fh = fh | |
277 | |
278 | |
279 class TestReadGraphML(BaseGraphML): | |
280 def test_read_simple_directed_graphml(self): | |
281 G = self.simple_directed_graph | |
282 H = nx.read_graphml(self.simple_directed_fh) | |
283 assert sorted(G.nodes()) == sorted(H.nodes()) | |
284 assert sorted(G.edges()) == sorted(H.edges()) | |
285 assert sorted(G.edges(data=True)) == sorted(H.edges(data=True)) | |
286 self.simple_directed_fh.seek(0) | |
287 | |
288 PG = nx.parse_graphml(self.simple_directed_data) | |
289 assert sorted(G.nodes()) == sorted(PG.nodes()) | |
290 assert sorted(G.edges()) == sorted(PG.edges()) | |
291 assert sorted(G.edges(data=True)) == sorted(PG.edges(data=True)) | |
292 | |
293 def test_read_simple_undirected_graphml(self): | |
294 G = self.simple_undirected_graph | |
295 H = nx.read_graphml(self.simple_undirected_fh) | |
296 assert_nodes_equal(G.nodes(), H.nodes()) | |
297 assert_edges_equal(G.edges(), H.edges()) | |
298 self.simple_undirected_fh.seek(0) | |
299 | |
300 PG = nx.parse_graphml(self.simple_undirected_data) | |
301 assert_nodes_equal(G.nodes(), PG.nodes()) | |
302 assert_edges_equal(G.edges(), PG.edges()) | |
303 | |
304 def test_read_undirected_multigraph_graphml(self): | |
305 G = self.undirected_multigraph | |
306 H = nx.read_graphml(self.undirected_multigraph_fh) | |
307 assert_nodes_equal(G.nodes(), H.nodes()) | |
308 assert_edges_equal(G.edges(), H.edges()) | |
309 self.undirected_multigraph_fh.seek(0) | |
310 | |
311 PG = nx.parse_graphml(self.undirected_multigraph_data) | |
312 assert_nodes_equal(G.nodes(), PG.nodes()) | |
313 assert_edges_equal(G.edges(), PG.edges()) | |
314 | |
315 def test_read_undirected_multigraph_no_multiedge_graphml(self): | |
316 G = self.undirected_multigraph_no_multiedge | |
317 H = nx.read_graphml(self.undirected_multigraph_no_multiedge_fh) | |
318 assert_nodes_equal(G.nodes(), H.nodes()) | |
319 assert_edges_equal(G.edges(), H.edges()) | |
320 self.undirected_multigraph_no_multiedge_fh.seek(0) | |
321 | |
322 PG = nx.parse_graphml(self.undirected_multigraph_no_multiedge_data) | |
323 assert_nodes_equal(G.nodes(), PG.nodes()) | |
324 assert_edges_equal(G.edges(), PG.edges()) | |
325 | |
326 def test_read_undirected_multigraph_only_ids_for_multiedges_graphml(self): | |
327 G = self.multigraph_only_ids_for_multiedges | |
328 H = nx.read_graphml(self.multigraph_only_ids_for_multiedges_fh) | |
329 assert_nodes_equal(G.nodes(), H.nodes()) | |
330 assert_edges_equal(G.edges(), H.edges()) | |
331 self.multigraph_only_ids_for_multiedges_fh.seek(0) | |
332 | |
333 PG = nx.parse_graphml(self.multigraph_only_ids_for_multiedges_data) | |
334 assert_nodes_equal(G.nodes(), PG.nodes()) | |
335 assert_edges_equal(G.edges(), PG.edges()) | |
336 | |
337 def test_read_attribute_graphml(self): | |
338 G = self.attribute_graph | |
339 H = nx.read_graphml(self.attribute_fh) | |
340 assert_nodes_equal(G.nodes(True), sorted(H.nodes(data=True))) | |
341 ge = sorted(G.edges(data=True)) | |
342 he = sorted(H.edges(data=True)) | |
343 for a, b in zip(ge, he): | |
344 assert a == b | |
345 self.attribute_fh.seek(0) | |
346 | |
347 PG = nx.parse_graphml(self.attribute_data) | |
348 assert sorted(G.nodes(True)) == sorted(PG.nodes(data=True)) | |
349 ge = sorted(G.edges(data=True)) | |
350 he = sorted(PG.edges(data=True)) | |
351 for a, b in zip(ge, he): | |
352 assert a == b | |
353 | |
354 def test_directed_edge_in_undirected(self): | |
355 s = """<?xml version="1.0" encoding="UTF-8"?> | |
356 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
357 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
358 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
359 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
360 <graph id="G"> | |
361 <node id="n0"/> | |
362 <node id="n1"/> | |
363 <node id="n2"/> | |
364 <edge source="n0" target="n1"/> | |
365 <edge source="n1" target="n2" directed='true'/> | |
366 </graph> | |
367 </graphml>""" | |
368 fh = io.BytesIO(s.encode("UTF-8")) | |
369 pytest.raises(nx.NetworkXError, nx.read_graphml, fh) | |
370 pytest.raises(nx.NetworkXError, nx.parse_graphml, s) | |
371 | |
372 def test_undirected_edge_in_directed(self): | |
373 s = """<?xml version="1.0" encoding="UTF-8"?> | |
374 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
375 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
376 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
377 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
378 <graph id="G" edgedefault='directed'> | |
379 <node id="n0"/> | |
380 <node id="n1"/> | |
381 <node id="n2"/> | |
382 <edge source="n0" target="n1"/> | |
383 <edge source="n1" target="n2" directed='false'/> | |
384 </graph> | |
385 </graphml>""" | |
386 fh = io.BytesIO(s.encode("UTF-8")) | |
387 pytest.raises(nx.NetworkXError, nx.read_graphml, fh) | |
388 pytest.raises(nx.NetworkXError, nx.parse_graphml, s) | |
389 | |
390 def test_key_raise(self): | |
391 s = """<?xml version="1.0" encoding="UTF-8"?> | |
392 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
393 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
394 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
395 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
396 <key id="d0" for="node" attr.name="color" attr.type="string"> | |
397 <default>yellow</default> | |
398 </key> | |
399 <key id="d1" for="edge" attr.name="weight" attr.type="double"/> | |
400 <graph id="G" edgedefault="directed"> | |
401 <node id="n0"> | |
402 <data key="d0">green</data> | |
403 </node> | |
404 <node id="n1"/> | |
405 <node id="n2"> | |
406 <data key="d0">blue</data> | |
407 </node> | |
408 <edge id="e0" source="n0" target="n2"> | |
409 <data key="d2">1.0</data> | |
410 </edge> | |
411 </graph> | |
412 </graphml> | |
413 """ | |
414 fh = io.BytesIO(s.encode("UTF-8")) | |
415 pytest.raises(nx.NetworkXError, nx.read_graphml, fh) | |
416 pytest.raises(nx.NetworkXError, nx.parse_graphml, s) | |
417 | |
418 def test_hyperedge_raise(self): | |
419 s = """<?xml version="1.0" encoding="UTF-8"?> | |
420 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
421 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
422 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
423 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
424 <key id="d0" for="node" attr.name="color" attr.type="string"> | |
425 <default>yellow</default> | |
426 </key> | |
427 <key id="d1" for="edge" attr.name="weight" attr.type="double"/> | |
428 <graph id="G" edgedefault="directed"> | |
429 <node id="n0"> | |
430 <data key="d0">green</data> | |
431 </node> | |
432 <node id="n1"/> | |
433 <node id="n2"> | |
434 <data key="d0">blue</data> | |
435 </node> | |
436 <hyperedge id="e0" source="n0" target="n2"> | |
437 <endpoint node="n0"/> | |
438 <endpoint node="n1"/> | |
439 <endpoint node="n2"/> | |
440 </hyperedge> | |
441 </graph> | |
442 </graphml> | |
443 """ | |
444 fh = io.BytesIO(s.encode("UTF-8")) | |
445 pytest.raises(nx.NetworkXError, nx.read_graphml, fh) | |
446 pytest.raises(nx.NetworkXError, nx.parse_graphml, s) | |
447 | |
448 def test_multigraph_keys(self): | |
449 # Test that reading multigraphs uses edge id attributes as keys | |
450 s = """<?xml version="1.0" encoding="UTF-8"?> | |
451 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
452 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
453 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
454 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
455 <graph id="G" edgedefault="directed"> | |
456 <node id="n0"/> | |
457 <node id="n1"/> | |
458 <edge id="e0" source="n0" target="n1"/> | |
459 <edge id="e1" source="n0" target="n1"/> | |
460 </graph> | |
461 </graphml> | |
462 """ | |
463 fh = io.BytesIO(s.encode("UTF-8")) | |
464 G = nx.read_graphml(fh) | |
465 expected = [("n0", "n1", "e0"), ("n0", "n1", "e1")] | |
466 assert sorted(G.edges(keys=True)) == expected | |
467 fh.seek(0) | |
468 H = nx.parse_graphml(s) | |
469 assert sorted(H.edges(keys=True)) == expected | |
470 | |
471 def test_preserve_multi_edge_data(self): | |
472 """ | |
473 Test that data and keys of edges are preserved on consequent | |
474 write and reads | |
475 """ | |
476 G = nx.MultiGraph() | |
477 G.add_node(1) | |
478 G.add_node(2) | |
479 G.add_edges_from( | |
480 [ | |
481 # edges with no data, no keys: | |
482 (1, 2), | |
483 # edges with only data: | |
484 (1, 2, dict(key="data_key1")), | |
485 (1, 2, dict(id="data_id2")), | |
486 (1, 2, dict(key="data_key3", id="data_id3")), | |
487 # edges with both data and keys: | |
488 (1, 2, 103, dict(key="data_key4")), | |
489 (1, 2, 104, dict(id="data_id5")), | |
490 (1, 2, 105, dict(key="data_key6", id="data_id7")), | |
491 ] | |
492 ) | |
493 fh = io.BytesIO() | |
494 nx.write_graphml(G, fh) | |
495 fh.seek(0) | |
496 H = nx.read_graphml(fh, node_type=int) | |
497 assert_edges_equal(G.edges(data=True, keys=True), H.edges(data=True, keys=True)) | |
498 assert G._adj == H._adj | |
499 | |
500 Gadj = { | |
501 str(node): { | |
502 str(nbr): {str(ekey): dd for ekey, dd in key_dict.items()} | |
503 for nbr, key_dict in nbr_dict.items() | |
504 } | |
505 for node, nbr_dict in G._adj.items() | |
506 } | |
507 fh.seek(0) | |
508 HH = nx.read_graphml(fh, node_type=str, edge_key_type=str) | |
509 assert Gadj == HH._adj | |
510 | |
511 fh.seek(0) | |
512 string_fh = fh.read() | |
513 HH = nx.parse_graphml(string_fh, node_type=str, edge_key_type=str) | |
514 assert Gadj == HH._adj | |
515 | |
516 def test_yfiles_extension(self): | |
517 data = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
518 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
519 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
520 xmlns:y="http://www.yworks.com/xml/graphml" | |
521 xmlns:yed="http://www.yworks.com/xml/yed/3" | |
522 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
523 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
524 <!--Created by yFiles for Java 2.7--> | |
525 <key for="graphml" id="d0" yfiles.type="resources"/> | |
526 <key attr.name="url" attr.type="string" for="node" id="d1"/> | |
527 <key attr.name="description" attr.type="string" for="node" id="d2"/> | |
528 <key for="node" id="d3" yfiles.type="nodegraphics"/> | |
529 <key attr.name="Description" attr.type="string" for="graph" id="d4"> | |
530 <default/> | |
531 </key> | |
532 <key attr.name="url" attr.type="string" for="edge" id="d5"/> | |
533 <key attr.name="description" attr.type="string" for="edge" id="d6"/> | |
534 <key for="edge" id="d7" yfiles.type="edgegraphics"/> | |
535 <graph edgedefault="directed" id="G"> | |
536 <node id="n0"> | |
537 <data key="d3"> | |
538 <y:ShapeNode> | |
539 <y:Geometry height="30.0" width="30.0" x="125.0" y="100.0"/> | |
540 <y:Fill color="#FFCC00" transparent="false"/> | |
541 <y:BorderStyle color="#000000" type="line" width="1.0"/> | |
542 <y:NodeLabel alignment="center" autoSizePolicy="content" | |
543 borderDistance="0.0" fontFamily="Dialog" fontSize="13" | |
544 fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" | |
545 height="19.1328125" modelName="internal" modelPosition="c" | |
546 textColor="#000000" visible="true" width="12.27099609375" | |
547 x="8.864501953125" y="5.43359375">1</y:NodeLabel> | |
548 <y:Shape type="rectangle"/> | |
549 </y:ShapeNode> | |
550 </data> | |
551 </node> | |
552 <node id="n1"> | |
553 <data key="d3"> | |
554 <y:ShapeNode> | |
555 <y:Geometry height="30.0" width="30.0" x="183.0" y="205.0"/> | |
556 <y:Fill color="#FFCC00" transparent="false"/> | |
557 <y:BorderStyle color="#000000" type="line" width="1.0"/> | |
558 <y:NodeLabel alignment="center" autoSizePolicy="content" | |
559 borderDistance="0.0" fontFamily="Dialog" fontSize="13" | |
560 fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" | |
561 height="19.1328125" modelName="internal" modelPosition="c" | |
562 textColor="#000000" visible="true" width="12.27099609375" | |
563 x="8.864501953125" y="5.43359375">2</y:NodeLabel> | |
564 <y:Shape type="rectangle"/> | |
565 </y:ShapeNode> | |
566 </data> | |
567 </node> | |
568 <edge id="e0" source="n0" target="n1"> | |
569 <data key="d7"> | |
570 <y:PolyLineEdge> | |
571 <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> | |
572 <y:LineStyle color="#000000" type="line" width="1.0"/> | |
573 <y:Arrows source="none" target="standard"/> | |
574 <y:BendStyle smoothed="false"/> | |
575 </y:PolyLineEdge> | |
576 </data> | |
577 </edge> | |
578 </graph> | |
579 <data key="d0"> | |
580 <y:Resources/> | |
581 </data> | |
582 </graphml> | |
583 """ | |
584 fh = io.BytesIO(data.encode("UTF-8")) | |
585 G = nx.read_graphml(fh, force_multigraph=True) | |
586 assert list(G.edges()) == [("n0", "n1")] | |
587 assert G.has_edge("n0", "n1", key="e0") | |
588 assert G.nodes["n0"]["label"] == "1" | |
589 assert G.nodes["n1"]["label"] == "2" | |
590 fh.seek(0) | |
591 G = nx.read_graphml(fh) | |
592 assert list(G.edges()) == [("n0", "n1")] | |
593 assert G["n0"]["n1"]["id"] == "e0" | |
594 assert G.nodes["n0"]["label"] == "1" | |
595 assert G.nodes["n1"]["label"] == "2" | |
596 | |
597 H = nx.parse_graphml(data, force_multigraph=True) | |
598 assert list(H.edges()) == [("n0", "n1")] | |
599 assert H.has_edge("n0", "n1", key="e0") | |
600 assert H.nodes["n0"]["label"] == "1" | |
601 assert H.nodes["n1"]["label"] == "2" | |
602 | |
603 H = nx.parse_graphml(data) | |
604 assert list(H.edges()) == [("n0", "n1")] | |
605 assert H["n0"]["n1"]["id"] == "e0" | |
606 assert H.nodes["n0"]["label"] == "1" | |
607 assert H.nodes["n1"]["label"] == "2" | |
608 | |
609 def test_bool(self): | |
610 s = """<?xml version="1.0" encoding="UTF-8"?> | |
611 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
612 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
613 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
614 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
615 <key id="d0" for="node" attr.name="test" attr.type="boolean"> | |
616 <default>false</default> | |
617 </key> | |
618 <graph id="G" edgedefault="directed"> | |
619 <node id="n0"> | |
620 <data key="d0">true</data> | |
621 </node> | |
622 <node id="n1"/> | |
623 <node id="n2"> | |
624 <data key="d0">false</data> | |
625 </node> | |
626 <node id="n3"> | |
627 <data key="d0">FaLsE</data> | |
628 </node> | |
629 <node id="n4"> | |
630 <data key="d0">True</data> | |
631 </node> | |
632 <node id="n5"> | |
633 <data key="d0">0</data> | |
634 </node> | |
635 <node id="n6"> | |
636 <data key="d0">1</data> | |
637 </node> | |
638 </graph> | |
639 </graphml> | |
640 """ | |
641 fh = io.BytesIO(s.encode("UTF-8")) | |
642 G = nx.read_graphml(fh) | |
643 H = nx.parse_graphml(s) | |
644 for graph in [G, H]: | |
645 assert graph.nodes["n0"]["test"] | |
646 assert not graph.nodes["n2"]["test"] | |
647 assert not graph.nodes["n3"]["test"] | |
648 assert graph.nodes["n4"]["test"] | |
649 assert not graph.nodes["n5"]["test"] | |
650 assert graph.nodes["n6"]["test"] | |
651 | |
652 def test_graphml_header_line(self): | |
653 good = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
654 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" | |
655 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
656 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns | |
657 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> | |
658 <key id="d0" for="node" attr.name="test" attr.type="boolean"> | |
659 <default>false</default> | |
660 </key> | |
661 <graph id="G"> | |
662 <node id="n0"> | |
663 <data key="d0">true</data> | |
664 </node> | |
665 </graph> | |
666 </graphml> | |
667 """ | |
668 bad = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
669 <graphml> | |
670 <key id="d0" for="node" attr.name="test" attr.type="boolean"> | |
671 <default>false</default> | |
672 </key> | |
673 <graph id="G"> | |
674 <node id="n0"> | |
675 <data key="d0">true</data> | |
676 </node> | |
677 </graph> | |
678 </graphml> | |
679 """ | |
680 ugly = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
681 <graphml xmlns="https://ghghgh"> | |
682 <key id="d0" for="node" attr.name="test" attr.type="boolean"> | |
683 <default>false</default> | |
684 </key> | |
685 <graph id="G"> | |
686 <node id="n0"> | |
687 <data key="d0">true</data> | |
688 </node> | |
689 </graph> | |
690 </graphml> | |
691 """ | |
692 for s in (good, bad): | |
693 fh = io.BytesIO(s.encode("UTF-8")) | |
694 G = nx.read_graphml(fh) | |
695 H = nx.parse_graphml(s) | |
696 for graph in [G, H]: | |
697 assert graph.nodes["n0"]["test"] | |
698 | |
699 fh = io.BytesIO(ugly.encode("UTF-8")) | |
700 pytest.raises(nx.NetworkXError, nx.read_graphml, fh) | |
701 pytest.raises(nx.NetworkXError, nx.parse_graphml, ugly) | |
702 | |
703 def test_read_attributes_with_groups(self): | |
704 data = """\ | |
705 <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
706 <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> | |
707 <!--Created by yEd 3.17--> | |
708 <key attr.name="Description" attr.type="string" for="graph" id="d0"/> | |
709 <key for="port" id="d1" yfiles.type="portgraphics"/> | |
710 <key for="port" id="d2" yfiles.type="portgeometry"/> | |
711 <key for="port" id="d3" yfiles.type="portuserdata"/> | |
712 <key attr.name="CustomProperty" attr.type="string" for="node" id="d4"> | |
713 <default/> | |
714 </key> | |
715 <key attr.name="url" attr.type="string" for="node" id="d5"/> | |
716 <key attr.name="description" attr.type="string" for="node" id="d6"/> | |
717 <key for="node" id="d7" yfiles.type="nodegraphics"/> | |
718 <key for="graphml" id="d8" yfiles.type="resources"/> | |
719 <key attr.name="url" attr.type="string" for="edge" id="d9"/> | |
720 <key attr.name="description" attr.type="string" for="edge" id="d10"/> | |
721 <key for="edge" id="d11" yfiles.type="edgegraphics"/> | |
722 <graph edgedefault="directed" id="G"> | |
723 <data key="d0"/> | |
724 <node id="n0"> | |
725 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
726 <data key="d6"/> | |
727 <data key="d7"> | |
728 <y:ShapeNode> | |
729 <y:Geometry height="30.0" width="30.0" x="125.0" y="-255.4611111111111"/> | |
730 <y:Fill color="#FFCC00" transparent="false"/> | |
731 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
732 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">2<y:LabelModel> | |
733 <y:SmartNodeLabelModel distance="4.0"/> | |
734 </y:LabelModel> | |
735 <y:ModelParameter> | |
736 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
737 </y:ModelParameter> | |
738 </y:NodeLabel> | |
739 <y:Shape type="rectangle"/> | |
740 </y:ShapeNode> | |
741 </data> | |
742 </node> | |
743 <node id="n1" yfiles.foldertype="group"> | |
744 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
745 <data key="d5"/> | |
746 <data key="d6"/> | |
747 <data key="d7"> | |
748 <y:ProxyAutoBoundsNode> | |
749 <y:Realizers active="0"> | |
750 <y:GroupNode> | |
751 <y:Geometry height="250.38333333333333" width="140.0" x="-30.0" y="-330.3833333333333"/> | |
752 <y:Fill color="#F5F5F5" transparent="false"/> | |
753 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
754 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="140.0" x="0.0" y="0.0">Group 3</y:NodeLabel> | |
755 <y:Shape type="roundrectangle"/> | |
756 <y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
757 <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/> | |
758 <y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/> | |
759 </y:GroupNode> | |
760 <y:GroupNode> | |
761 <y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/> | |
762 <y:Fill color="#F5F5F5" transparent="false"/> | |
763 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
764 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 3</y:NodeLabel> | |
765 <y:Shape type="roundrectangle"/> | |
766 <y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
767 <y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/> | |
768 <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/> | |
769 </y:GroupNode> | |
770 </y:Realizers> | |
771 </y:ProxyAutoBoundsNode> | |
772 </data> | |
773 <graph edgedefault="directed" id="n1:"> | |
774 <node id="n1::n0" yfiles.foldertype="group"> | |
775 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
776 <data key="d5"/> | |
777 <data key="d6"/> | |
778 <data key="d7"> | |
779 <y:ProxyAutoBoundsNode> | |
780 <y:Realizers active="0"> | |
781 <y:GroupNode> | |
782 <y:Geometry height="83.46111111111111" width="110.0" x="-15.0" y="-292.9222222222222"/> | |
783 <y:Fill color="#F5F5F5" transparent="false"/> | |
784 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
785 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="110.0" x="0.0" y="0.0">Group 1</y:NodeLabel> | |
786 <y:Shape type="roundrectangle"/> | |
787 <y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
788 <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/> | |
789 <y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/> | |
790 </y:GroupNode> | |
791 <y:GroupNode> | |
792 <y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/> | |
793 <y:Fill color="#F5F5F5" transparent="false"/> | |
794 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
795 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 1</y:NodeLabel> | |
796 <y:Shape type="roundrectangle"/> | |
797 <y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
798 <y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/> | |
799 <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/> | |
800 </y:GroupNode> | |
801 </y:Realizers> | |
802 </y:ProxyAutoBoundsNode> | |
803 </data> | |
804 <graph edgedefault="directed" id="n1::n0:"> | |
805 <node id="n1::n0::n0"> | |
806 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
807 <data key="d6"/> | |
808 <data key="d7"> | |
809 <y:ShapeNode> | |
810 <y:Geometry height="30.0" width="30.0" x="50.0" y="-255.4611111111111"/> | |
811 <y:Fill color="#FFCC00" transparent="false"/> | |
812 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
813 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">1<y:LabelModel> | |
814 <y:SmartNodeLabelModel distance="4.0"/> | |
815 </y:LabelModel> | |
816 <y:ModelParameter> | |
817 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
818 </y:ModelParameter> | |
819 </y:NodeLabel> | |
820 <y:Shape type="rectangle"/> | |
821 </y:ShapeNode> | |
822 </data> | |
823 </node> | |
824 <node id="n1::n0::n1"> | |
825 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
826 <data key="d6"/> | |
827 <data key="d7"> | |
828 <y:ShapeNode> | |
829 <y:Geometry height="30.0" width="30.0" x="0.0" y="-255.4611111111111"/> | |
830 <y:Fill color="#FFCC00" transparent="false"/> | |
831 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
832 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">3<y:LabelModel> | |
833 <y:SmartNodeLabelModel distance="4.0"/> | |
834 </y:LabelModel> | |
835 <y:ModelParameter> | |
836 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
837 </y:ModelParameter> | |
838 </y:NodeLabel> | |
839 <y:Shape type="rectangle"/> | |
840 </y:ShapeNode> | |
841 </data> | |
842 </node> | |
843 </graph> | |
844 </node> | |
845 <node id="n1::n1" yfiles.foldertype="group"> | |
846 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
847 <data key="d5"/> | |
848 <data key="d6"/> | |
849 <data key="d7"> | |
850 <y:ProxyAutoBoundsNode> | |
851 <y:Realizers active="0"> | |
852 <y:GroupNode> | |
853 <y:Geometry height="83.46111111111111" width="110.0" x="-15.0" y="-179.4611111111111"/> | |
854 <y:Fill color="#F5F5F5" transparent="false"/> | |
855 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
856 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="110.0" x="0.0" y="0.0">Group 2</y:NodeLabel> | |
857 <y:Shape type="roundrectangle"/> | |
858 <y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
859 <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/> | |
860 <y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/> | |
861 </y:GroupNode> | |
862 <y:GroupNode> | |
863 <y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/> | |
864 <y:Fill color="#F5F5F5" transparent="false"/> | |
865 <y:BorderStyle color="#000000" type="dashed" width="1.0"/> | |
866 <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 2</y:NodeLabel> | |
867 <y:Shape type="roundrectangle"/> | |
868 <y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/> | |
869 <y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/> | |
870 <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/> | |
871 </y:GroupNode> | |
872 </y:Realizers> | |
873 </y:ProxyAutoBoundsNode> | |
874 </data> | |
875 <graph edgedefault="directed" id="n1::n1:"> | |
876 <node id="n1::n1::n0"> | |
877 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
878 <data key="d6"/> | |
879 <data key="d7"> | |
880 <y:ShapeNode> | |
881 <y:Geometry height="30.0" width="30.0" x="0.0" y="-142.0"/> | |
882 <y:Fill color="#FFCC00" transparent="false"/> | |
883 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
884 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">5<y:LabelModel> | |
885 <y:SmartNodeLabelModel distance="4.0"/> | |
886 </y:LabelModel> | |
887 <y:ModelParameter> | |
888 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
889 </y:ModelParameter> | |
890 </y:NodeLabel> | |
891 <y:Shape type="rectangle"/> | |
892 </y:ShapeNode> | |
893 </data> | |
894 </node> | |
895 <node id="n1::n1::n1"> | |
896 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
897 <data key="d6"/> | |
898 <data key="d7"> | |
899 <y:ShapeNode> | |
900 <y:Geometry height="30.0" width="30.0" x="50.0" y="-142.0"/> | |
901 <y:Fill color="#FFCC00" transparent="false"/> | |
902 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
903 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">6<y:LabelModel> | |
904 <y:SmartNodeLabelModel distance="4.0"/> | |
905 </y:LabelModel> | |
906 <y:ModelParameter> | |
907 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
908 </y:ModelParameter> | |
909 </y:NodeLabel> | |
910 <y:Shape type="rectangle"/> | |
911 </y:ShapeNode> | |
912 </data> | |
913 </node> | |
914 </graph> | |
915 </node> | |
916 </graph> | |
917 </node> | |
918 <node id="n2"> | |
919 <data key="d4"><![CDATA[CustomPropertyValue]]></data> | |
920 <data key="d6"/> | |
921 <data key="d7"> | |
922 <y:ShapeNode> | |
923 <y:Geometry height="30.0" width="30.0" x="125.0" y="-142.0"/> | |
924 <y:Fill color="#FFCC00" transparent="false"/> | |
925 <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/> | |
926 <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">9<y:LabelModel> | |
927 <y:SmartNodeLabelModel distance="4.0"/> | |
928 </y:LabelModel> | |
929 <y:ModelParameter> | |
930 <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> | |
931 </y:ModelParameter> | |
932 </y:NodeLabel> | |
933 <y:Shape type="rectangle"/> | |
934 </y:ShapeNode> | |
935 </data> | |
936 </node> | |
937 <edge id="n1::n1::e0" source="n1::n1::n0" target="n1::n1::n1"> | |
938 <data key="d10"/> | |
939 <data key="d11"> | |
940 <y:PolyLineEdge> | |
941 <y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/> | |
942 <y:LineStyle color="#000000" type="line" width="1.0"/> | |
943 <y:Arrows source="none" target="standard"/> | |
944 <y:BendStyle smoothed="false"/> | |
945 </y:PolyLineEdge> | |
946 </data> | |
947 </edge> | |
948 <edge id="n1::n0::e0" source="n1::n0::n1" target="n1::n0::n0"> | |
949 <data key="d10"/> | |
950 <data key="d11"> | |
951 <y:PolyLineEdge> | |
952 <y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/> | |
953 <y:LineStyle color="#000000" type="line" width="1.0"/> | |
954 <y:Arrows source="none" target="standard"/> | |
955 <y:BendStyle smoothed="false"/> | |
956 </y:PolyLineEdge> | |
957 </data> | |
958 </edge> | |
959 <edge id="e0" source="n1::n0::n0" target="n0"> | |
960 <data key="d10"/> | |
961 <data key="d11"> | |
962 <y:PolyLineEdge> | |
963 <y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/> | |
964 <y:LineStyle color="#000000" type="line" width="1.0"/> | |
965 <y:Arrows source="none" target="standard"/> | |
966 <y:BendStyle smoothed="false"/> | |
967 </y:PolyLineEdge> | |
968 </data> | |
969 </edge> | |
970 <edge id="e1" source="n1::n1::n1" target="n2"> | |
971 <data key="d10"/> | |
972 <data key="d11"> | |
973 <y:PolyLineEdge> | |
974 <y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/> | |
975 <y:LineStyle color="#000000" type="line" width="1.0"/> | |
976 <y:Arrows source="none" target="standard"/> | |
977 <y:BendStyle smoothed="false"/> | |
978 </y:PolyLineEdge> | |
979 </data> | |
980 </edge> | |
981 </graph> | |
982 <data key="d8"> | |
983 <y:Resources/> | |
984 </data> | |
985 </graphml> | |
986 """ | |
987 # verify that nodes / attributes are correctly read when part of a group | |
988 fh = io.BytesIO(data.encode("UTF-8")) | |
989 G = nx.read_graphml(fh) | |
990 data = [x for _, x in G.nodes(data=True)] | |
991 assert len(data) == 9 | |
992 for node_data in data: | |
993 assert node_data["CustomProperty"] != "" | |
994 | |
995 | |
996 class TestWriteGraphML(BaseGraphML): | |
997 writer = staticmethod(nx.write_graphml_lxml) | |
998 | |
999 @classmethod | |
1000 def setup_class(cls): | |
1001 BaseGraphML.setup_class() | |
1002 _ = pytest.importorskip("lxml.etree") | |
1003 | |
1004 def test_write_interface(self): | |
1005 try: | |
1006 import lxml.etree | |
1007 | |
1008 assert nx.write_graphml == nx.write_graphml_lxml | |
1009 except ImportError: | |
1010 assert nx.write_graphml == nx.write_graphml_xml | |
1011 | |
1012 def test_write_read_simple_directed_graphml(self): | |
1013 G = self.simple_directed_graph | |
1014 G.graph["hi"] = "there" | |
1015 fh = io.BytesIO() | |
1016 self.writer(G, fh) | |
1017 fh.seek(0) | |
1018 H = nx.read_graphml(fh) | |
1019 assert sorted(G.nodes()) == sorted(H.nodes()) | |
1020 assert sorted(G.edges()) == sorted(H.edges()) | |
1021 assert sorted(G.edges(data=True)) == sorted(H.edges(data=True)) | |
1022 self.simple_directed_fh.seek(0) | |
1023 | |
1024 def test_write_read_attribute_named_key_ids_graphml(self): | |
1025 from xml.etree.ElementTree import parse | |
1026 | |
1027 G = self.attribute_named_key_ids_graph | |
1028 fh = io.BytesIO() | |
1029 self.writer(G, fh, named_key_ids=True) | |
1030 fh.seek(0) | |
1031 H = nx.read_graphml(fh) | |
1032 fh.seek(0) | |
1033 | |
1034 assert_nodes_equal(G.nodes(), H.nodes()) | |
1035 assert_edges_equal(G.edges(), H.edges()) | |
1036 assert_edges_equal(G.edges(data=True), H.edges(data=True)) | |
1037 self.attribute_named_key_ids_fh.seek(0) | |
1038 | |
1039 xml = parse(fh) | |
1040 # Children are the key elements, and the graph element | |
1041 children = list(xml.getroot()) | |
1042 assert len(children) == 4 | |
1043 | |
1044 keys = [child.items() for child in children[:3]] | |
1045 | |
1046 assert len(keys) == 3 | |
1047 assert ("id", "edge_prop") in keys[0] | |
1048 assert ("attr.name", "edge_prop") in keys[0] | |
1049 assert ("id", "prop2") in keys[1] | |
1050 assert ("attr.name", "prop2") in keys[1] | |
1051 assert ("id", "prop1") in keys[2] | |
1052 assert ("attr.name", "prop1") in keys[2] | |
1053 | |
1054 # Confirm the read graph nodes/edge are identical when compared to | |
1055 # default writing behavior. | |
1056 default_behavior_fh = io.BytesIO() | |
1057 nx.write_graphml(G, default_behavior_fh) | |
1058 default_behavior_fh.seek(0) | |
1059 H = nx.read_graphml(default_behavior_fh) | |
1060 | |
1061 named_key_ids_behavior_fh = io.BytesIO() | |
1062 nx.write_graphml(G, named_key_ids_behavior_fh, named_key_ids=True) | |
1063 named_key_ids_behavior_fh.seek(0) | |
1064 J = nx.read_graphml(named_key_ids_behavior_fh) | |
1065 | |
1066 assert all(n1 == n2 for (n1, n2) in zip(H.nodes, J.nodes)) | |
1067 assert all(e1 == e2 for (e1, e2) in zip(H.edges, J.edges)) | |
1068 | |
1069 def test_write_read_attribute_numeric_type_graphml(self): | |
1070 from xml.etree.ElementTree import parse | |
1071 | |
1072 G = self.attribute_numeric_type_graph | |
1073 fh = io.BytesIO() | |
1074 self.writer(G, fh, infer_numeric_types=True) | |
1075 fh.seek(0) | |
1076 H = nx.read_graphml(fh) | |
1077 fh.seek(0) | |
1078 | |
1079 assert_nodes_equal(G.nodes(), H.nodes()) | |
1080 assert_edges_equal(G.edges(), H.edges()) | |
1081 assert_edges_equal(G.edges(data=True), H.edges(data=True)) | |
1082 self.attribute_numeric_type_fh.seek(0) | |
1083 | |
1084 xml = parse(fh) | |
1085 # Children are the key elements, and the graph element | |
1086 children = list(xml.getroot()) | |
1087 assert len(children) == 3 | |
1088 | |
1089 keys = [child.items() for child in children[:2]] | |
1090 | |
1091 assert len(keys) == 2 | |
1092 assert ("attr.type", "double") in keys[0] | |
1093 assert ("attr.type", "double") in keys[1] | |
1094 | |
1095 def test_more_multigraph_keys(self): | |
1096 """Writing keys as edge id attributes means keys become strings. | |
1097 The original keys are stored as data, so read them back in | |
1098 if `str(key) == edge_id` | |
1099 This allows the adjacency to remain the same. | |
1100 """ | |
1101 G = nx.MultiGraph() | |
1102 G.add_edges_from([("a", "b", 2), ("a", "b", 3)]) | |
1103 fd, fname = tempfile.mkstemp() | |
1104 self.writer(G, fname) | |
1105 H = nx.read_graphml(fname) | |
1106 assert H.is_multigraph() | |
1107 assert_edges_equal(G.edges(keys=True), H.edges(keys=True)) | |
1108 assert G._adj == H._adj | |
1109 os.close(fd) | |
1110 os.unlink(fname) | |
1111 | |
1112 def test_default_attribute(self): | |
1113 G = nx.Graph(name="Fred") | |
1114 G.add_node(1, label=1, color="green") | |
1115 nx.add_path(G, [0, 1, 2, 3]) | |
1116 G.add_edge(1, 2, weight=3) | |
1117 G.graph["node_default"] = {"color": "yellow"} | |
1118 G.graph["edge_default"] = {"weight": 7} | |
1119 fh = io.BytesIO() | |
1120 self.writer(G, fh) | |
1121 fh.seek(0) | |
1122 H = nx.read_graphml(fh, node_type=int) | |
1123 assert_nodes_equal(G.nodes(), H.nodes()) | |
1124 assert_edges_equal(G.edges(), H.edges()) | |
1125 assert G.graph == H.graph | |
1126 | |
1127 def test_mixed_type_attributes(self): | |
1128 G = nx.MultiGraph() | |
1129 G.add_node("n0", special=False) | |
1130 G.add_node("n1", special=0) | |
1131 G.add_edge("n0", "n1", special=False) | |
1132 G.add_edge("n0", "n1", special=0) | |
1133 fh = io.BytesIO() | |
1134 self.writer(G, fh) | |
1135 fh.seek(0) | |
1136 H = nx.read_graphml(fh) | |
1137 assert not H.nodes["n0"]["special"] | |
1138 assert H.nodes["n1"]["special"] == 0 | |
1139 assert not H.edges["n0", "n1", 0]["special"] | |
1140 assert H.edges["n0", "n1", 1]["special"] == 0 | |
1141 | |
1142 def test_numpy_float(self): | |
1143 np = pytest.importorskip("numpy") | |
1144 wt = np.float(3.4) | |
1145 G = nx.Graph([(1, 2, {"weight": wt})]) | |
1146 fd, fname = tempfile.mkstemp() | |
1147 self.writer(G, fname) | |
1148 H = nx.read_graphml(fname, node_type=int) | |
1149 assert G._adj == H._adj | |
1150 os.close(fd) | |
1151 os.unlink(fname) | |
1152 | |
1153 def test_multigraph_to_graph(self): | |
1154 # test converting multigraph to graph if no parallel edges found | |
1155 G = nx.MultiGraph() | |
1156 G.add_edges_from([("a", "b", 2), ("b", "c", 3)]) # no multiedges | |
1157 fd, fname = tempfile.mkstemp() | |
1158 self.writer(G, fname) | |
1159 H = nx.read_graphml(fname) | |
1160 assert not H.is_multigraph() | |
1161 H = nx.read_graphml(fname, force_multigraph=True) | |
1162 assert H.is_multigraph() | |
1163 os.close(fd) | |
1164 os.unlink(fname) | |
1165 | |
1166 # add a multiedge | |
1167 G.add_edge("a", "b", "e-id") | |
1168 fd, fname = tempfile.mkstemp() | |
1169 self.writer(G, fname) | |
1170 H = nx.read_graphml(fname) | |
1171 assert H.is_multigraph() | |
1172 H = nx.read_graphml(fname, force_multigraph=True) | |
1173 assert H.is_multigraph() | |
1174 os.close(fd) | |
1175 os.unlink(fname) | |
1176 | |
1177 def test_numpy_float64(self): | |
1178 np = pytest.importorskip("numpy") | |
1179 wt = np.float64(3.4) | |
1180 G = nx.Graph([(1, 2, {"weight": wt})]) | |
1181 fd, fname = tempfile.mkstemp() | |
1182 self.writer(G, fname) | |
1183 H = nx.read_graphml(fname, node_type=int) | |
1184 assert G.edges == H.edges | |
1185 wtG = G[1][2]["weight"] | |
1186 wtH = H[1][2]["weight"] | |
1187 assert almost_equal(wtG, wtH, places=6) | |
1188 assert type(wtG) == np.float64 | |
1189 assert type(wtH) == float | |
1190 os.close(fd) | |
1191 os.unlink(fname) | |
1192 | |
1193 def test_numpy_float32(self): | |
1194 np = pytest.importorskip("numpy") | |
1195 wt = np.float32(3.4) | |
1196 G = nx.Graph([(1, 2, {"weight": wt})]) | |
1197 fd, fname = tempfile.mkstemp() | |
1198 self.writer(G, fname) | |
1199 H = nx.read_graphml(fname, node_type=int) | |
1200 assert G.edges == H.edges | |
1201 wtG = G[1][2]["weight"] | |
1202 wtH = H[1][2]["weight"] | |
1203 assert almost_equal(wtG, wtH, places=6) | |
1204 assert type(wtG) == np.float32 | |
1205 assert type(wtH) == float | |
1206 os.close(fd) | |
1207 os.unlink(fname) | |
1208 | |
1209 def test_numpy_float64_inference(self): | |
1210 np = pytest.importorskip("numpy") | |
1211 G = self.attribute_numeric_type_graph | |
1212 G.edges[("n1", "n1")]["weight"] = np.float64(1.1) | |
1213 fd, fname = tempfile.mkstemp() | |
1214 self.writer(G, fname, infer_numeric_types=True) | |
1215 H = nx.read_graphml(fname) | |
1216 assert G._adj == H._adj | |
1217 os.close(fd) | |
1218 os.unlink(fname) | |
1219 | |
1220 def test_unicode_attributes(self): | |
1221 G = nx.Graph() | |
1222 name1 = chr(2344) + chr(123) + chr(6543) | |
1223 name2 = chr(5543) + chr(1543) + chr(324) | |
1224 node_type = str | |
1225 G.add_edge(name1, "Radiohead", foo=name2) | |
1226 fd, fname = tempfile.mkstemp() | |
1227 self.writer(G, fname) | |
1228 H = nx.read_graphml(fname, node_type=node_type) | |
1229 assert G._adj == H._adj | |
1230 os.close(fd) | |
1231 os.unlink(fname) | |
1232 | |
1233 def test_unicode_escape(self): | |
1234 # test for handling json escaped stings in python 2 Issue #1880 | |
1235 import json | |
1236 | |
1237 a = dict(a='{"a": "123"}') # an object with many chars to escape | |
1238 sa = json.dumps(a) | |
1239 G = nx.Graph() | |
1240 G.graph["test"] = sa | |
1241 fh = io.BytesIO() | |
1242 self.writer(G, fh) | |
1243 fh.seek(0) | |
1244 H = nx.read_graphml(fh) | |
1245 assert G.graph["test"] == H.graph["test"] | |
1246 | |
1247 | |
1248 class TestXMLGraphML(TestWriteGraphML): | |
1249 writer = staticmethod(nx.write_graphml_xml) | |
1250 | |
1251 @classmethod | |
1252 def setup_class(cls): | |
1253 TestWriteGraphML.setup_class() | |
1254 pytest.importorskip("xml.etree.ElementTree") |