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")