Statistics
| Branch: | Revision:

iof-tools / networkxMiCe / networkx-master / networkx / readwrite / tests / test_gml.py @ 5cef0f13

History | View | Annotate | Download (14 KB)

1
#!/usr/bin/env python
2
# encoding: utf-8
3

    
4
from ast import literal_eval
5
import codecs
6
import io
7
from nose.tools import *
8
from nose import SkipTest
9
import networkx as nx
10
from networkx.readwrite.gml import literal_stringizer, literal_destringizer
11
import os
12
import tempfile
13

    
14
try:
15
    unicode
16
except NameError:
17
    unicode = str
18
try:
19
    unichr
20
except NameError:
21
    unichr = chr
22

    
23

    
24
class TestGraph(object):
25

    
26
    def setUp(self):
27
        self.simple_data = """Creator "me"
28
Version "xx"
29
graph [
30
 comment "This is a sample graph"
31
 directed 1
32
 IsPlanar 1
33
 pos  [ x 0 y 1 ]
34
 node [
35
   id 1
36
   label "Node 1"
37
   pos [ x 1 y 1 ]
38
 ]
39
 node [
40
    id 2
41
    pos [ x 1 y 2 ]
42
    label "Node 2"
43
    ]
44
  node [
45
    id 3
46
    label "Node 3"
47
    pos [ x 1 y 3 ]
48
  ]
49
  edge [
50
    source 1
51
    target 2
52
    label "Edge from node 1 to node 2"
53
    color [line "blue" thickness 3]
54

55
  ]
56
  edge [
57
    source 2
58
    target 3
59
    label "Edge from node 2 to node 3"
60
  ]
61
  edge [
62
    source 3
63
    target 1
64
    label "Edge from node 3 to node 1"
65
  ]
66
]
67
"""
68

    
69
    def test_parse_gml_cytoscape_bug(self):
70
        # example from issue #321, originally #324 in trac
71
        cytoscape_example = """
72
Creator "Cytoscape"
73
Version 1.0
74
graph   [
75
    node    [
76
        root_index  -3
77
        id  -3
78
        graphics    [
79
            x   -96.0
80
            y   -67.0
81
            w   40.0
82
            h   40.0
83
            fill    "#ff9999"
84
            type    "ellipse"
85
            outline "#666666"
86
            outline_width   1.5
87
        ]
88
        label   "node2"
89
    ]
90
    node    [
91
        root_index  -2
92
        id  -2
93
        graphics    [
94
            x   63.0
95
            y   37.0
96
            w   40.0
97
            h   40.0
98
            fill    "#ff9999"
99
            type    "ellipse"
100
            outline "#666666"
101
            outline_width   1.5
102
        ]
103
        label   "node1"
104
    ]
105
    node    [
106
        root_index  -1
107
        id  -1
108
        graphics    [
109
            x   -31.0
110
            y   -17.0
111
            w   40.0
112
            h   40.0
113
            fill    "#ff9999"
114
            type    "ellipse"
115
            outline "#666666"
116
            outline_width   1.5
117
        ]
118
        label   "node0"
119
    ]
120
    edge    [
121
        root_index  -2
122
        target  -2
123
        source  -1
124
        graphics    [
125
            width   1.5
126
            fill    "#0000ff"
127
            type    "line"
128
            Line    [
129
            ]
130
            source_arrow    0
131
            target_arrow    3
132
        ]
133
        label   "DirectedEdge"
134
    ]
135
    edge    [
136
        root_index  -1
137
        target  -1
138
        source  -3
139
        graphics    [
140
            width   1.5
141
            fill    "#0000ff"
142
            type    "line"
143
            Line    [
144
            ]
145
            source_arrow    0
146
            target_arrow    3
147
        ]
148
        label   "DirectedEdge"
149
    ]
150
]
151
"""
152
        nx.parse_gml(cytoscape_example)
153

    
154
    def test_parse_gml(self):
155
        G = nx.parse_gml(self.simple_data, label='label')
156
        assert_equals(sorted(G.nodes()),
157
                      ['Node 1', 'Node 2', 'Node 3'])
158
        assert_equals([e for e in sorted(G.edges())],
159
                      [('Node 1', 'Node 2'),
160
                       ('Node 2', 'Node 3'),
161
                       ('Node 3', 'Node 1')])
162

    
163
        assert_equals([e for e in sorted(G.edges(data=True))],
164
                      [('Node 1', 'Node 2',
165
                        {'color': {'line': 'blue', 'thickness': 3},
166
                         'label': 'Edge from node 1 to node 2'}),
167
                       ('Node 2', 'Node 3',
168
                        {'label': 'Edge from node 2 to node 3'}),
169
                       ('Node 3', 'Node 1',
170
                        {'label': 'Edge from node 3 to node 1'})])
171

    
172
    def test_read_gml(self):
173
        (fd, fname) = tempfile.mkstemp()
174
        fh = open(fname, 'w')
175
        fh.write(self.simple_data)
176
        fh.close()
177
        Gin = nx.read_gml(fname, label='label')
178
        G = nx.parse_gml(self.simple_data, label='label')
179
        assert_equals(sorted(G.nodes(data=True)), sorted(Gin.nodes(data=True)))
180
        assert_equals(sorted(G.edges(data=True)), sorted(Gin.edges(data=True)))
181
        os.close(fd)
182
        os.unlink(fname)
183

    
184
    def test_labels_are_strings(self):
185
        # GML requires labels to be strings (i.e., in quotes)
186
        answer = """graph [
187
  node [
188
    id 0
189
    label "1203"
190
  ]
191
]"""
192
        G = nx.Graph()
193
        G.add_node(1203)
194
        data = '\n'.join(nx.generate_gml(G, stringizer=literal_stringizer))
195
        assert_equal(data, answer)
196

    
197
    def test_relabel_duplicate(self):
198
        data = """
199
graph
200
[
201
        label   ""
202
        directed        1
203
        node
204
        [
205
                id      0
206
                label   "same"
207
        ]
208
        node
209
        [
210
                id      1
211
                label   "same"
212
        ]
213
]
214
"""
215
        fh = io.BytesIO(data.encode('UTF-8'))
216
        fh.seek(0)
217
        assert_raises(
218
            nx.NetworkXError, nx.read_gml, fh, label='label')
219

    
220
    def test_tuplelabels(self):
221
        # https://github.com/networkx/networkx/pull/1048
222
        # Writing tuple labels to GML failed.
223
        G = nx.OrderedGraph()
224
        G.add_edge((0, 1), (1, 0))
225
        data = '\n'.join(nx.generate_gml(G, stringizer=literal_stringizer))
226
        answer = """graph [
227
  node [
228
    id 0
229
    label "(0,1)"
230
  ]
231
  node [
232
    id 1
233
    label "(1,0)"
234
  ]
235
  edge [
236
    source 0
237
    target 1
238
  ]
239
]"""
240
        assert_equal(data, answer)
241

    
242
    def test_quotes(self):
243
        # https://github.com/networkx/networkx/issues/1061
244
        # Encoding quotes as HTML entities.
245
        G = nx.path_graph(1)
246
        G.name = "path_graph(1)"
247
        attr = 'This is "quoted" and this is a copyright: ' + unichr(169)
248
        G.nodes[0]['demo'] = attr
249
        fobj = tempfile.NamedTemporaryFile()
250
        nx.write_gml(G, fobj)
251
        fobj.seek(0)
252
        # Should be bytes in 2.x and 3.x
253
        data = fobj.read().strip().decode('ascii')
254
        answer = """graph [
255
  name "path_graph(1)"
256
  node [
257
    id 0
258
    label "0"
259
    demo "This is "quoted" and this is a copyright: ©"
260
  ]
261
]"""
262
        assert_equal(data, answer)
263

    
264
    def test_unicode_node(self):
265
        node = 'node' + unichr(169)
266
        G = nx.Graph()
267
        G.add_node(node)
268
        fobj = tempfile.NamedTemporaryFile()
269
        nx.write_gml(G, fobj)
270
        fobj.seek(0)
271
        # Should be bytes in 2.x and 3.x
272
        data = fobj.read().strip().decode('ascii')
273
        answer = """graph [
274
  node [
275
    id 0
276
    label "node©"
277
  ]
278
]"""
279
        assert_equal(data, answer)
280

    
281
    def test_float_label(self):
282
        node = 1.0
283
        G = nx.Graph()
284
        G.add_node(node)
285
        fobj = tempfile.NamedTemporaryFile()
286
        nx.write_gml(G, fobj)
287
        fobj.seek(0)
288
        # Should be bytes in 2.x and 3.x
289
        data = fobj.read().strip().decode('ascii')
290
        answer = """graph [
291
  node [
292
    id 0
293
    label "1.0"
294
  ]
295
]"""
296
        assert_equal(data, answer)
297

    
298
    def test_name(self):
299
        G = nx.parse_gml('graph [ name "x" node [ id 0 label "x" ] ]')
300
        assert_equal('x', G.graph['name'])
301
        G = nx.parse_gml('graph [ node [ id 0 label "x" ] ]')
302
        assert_equal('', G.name)
303
        assert_not_in('name', G.graph)
304

    
305
    def test_graph_types(self):
306
        for directed in [None, False, True]:
307
            for multigraph in [None, False, True]:
308
                gml = 'graph ['
309
                if directed is not None:
310
                    gml += ' directed ' + str(int(directed))
311
                if multigraph is not None:
312
                    gml += ' multigraph ' + str(int(multigraph))
313
                gml += ' node [ id 0 label "0" ]'
314
                gml += ' edge [ source 0 target 0 ]'
315
                gml += ' ]'
316
                G = nx.parse_gml(gml)
317
                assert_equal(bool(directed), G.is_directed())
318
                assert_equal(bool(multigraph), G.is_multigraph())
319
                gml = 'graph [\n'
320
                if directed is True:
321
                    gml += '  directed 1\n'
322
                if multigraph is True:
323
                    gml += '  multigraph 1\n'
324
                gml += """  node [
325
    id 0
326
    label "0"
327
  ]
328
  edge [
329
    source 0
330
    target 0
331
"""
332
                if multigraph:
333
                    gml += '    key 0\n'
334
                gml += '  ]\n]'
335
                assert_equal(gml, '\n'.join(nx.generate_gml(G)))
336

    
337
    def test_data_types(self):
338
        data = [True, False, 10 ** 20, -2e33, "'", '"&&&""',
339
                [{(b'\xfd',): '\x7f', unichr(0x4444): (1, 2)}, (2, "3")]]
340
        try:
341
            data.append(unichr(0x14444))  # fails under IronPython
342
        except ValueError:
343
            data.append(unichr(0x1444))
344
        try:
345
            data.append(literal_eval('{2.3j, 1 - 2.3j, ()}'))  # fails under Python 2.7
346
        except ValueError:
347
            data.append([2.3j, 1 - 2.3j, ()])
348
        G = nx.Graph()
349
        G.name = data
350
        G.graph['data'] = data
351
        G.add_node(0, int=-1, data=dict(data=data))
352
        G.add_edge(0, 0, float=-2.5, data=data)
353
        gml = '\n'.join(nx.generate_gml(G, stringizer=literal_stringizer))
354
        G = nx.parse_gml(gml, destringizer=literal_destringizer)
355
        assert_equal(data, G.name)
356
        assert_equal({'name': data, unicode('data'): data}, G.graph)
357
        assert_equal(list(G.nodes(data=True)),
358
                     [(0, dict(int=-1, data=dict(data=data)))])
359
        assert_equal(list(G.edges(data=True)), [(0, 0, dict(float=-2.5, data=data))])
360
        G = nx.Graph()
361
        G.graph['data'] = 'frozenset([1, 2, 3])'
362
        G = nx.parse_gml(nx.generate_gml(G), destringizer=literal_eval)
363
        assert_equal(G.graph['data'], 'frozenset([1, 2, 3])')
364

    
365
    def test_escape_unescape(self):
366
        gml = """graph [
367
  name "&"䑄��&unknown;"
368
]"""
369
        G = nx.parse_gml(gml)
370
        assert_equal(
371
            '&"\x0f' + unichr(0x4444) + '��&unknown;',
372
            G.name)
373
        gml = '\n'.join(nx.generate_gml(G))
374
        assert_equal("""graph [
375
  name "&"䑄��&unknown;"
376
]""", gml)
377

    
378
    def test_exceptions(self):
379
        assert_raises(ValueError, literal_destringizer, '(')
380
        assert_raises(ValueError, literal_destringizer, 'frozenset([1, 2, 3])')
381
        assert_raises(ValueError, literal_destringizer, literal_destringizer)
382
        assert_raises(ValueError, literal_stringizer, frozenset([1, 2, 3]))
383
        assert_raises(ValueError, literal_stringizer, literal_stringizer)
384
        with tempfile.TemporaryFile() as f:
385
            f.write(codecs.BOM_UTF8 + 'graph[]'.encode('ascii'))
386
            f.seek(0)
387
            assert_raises(nx.NetworkXError, nx.read_gml, f)
388

    
389
        def assert_parse_error(gml):
390
            assert_raises(nx.NetworkXError, nx.parse_gml, gml)
391

    
392
        assert_parse_error(['graph [\n\n', unicode(']')])
393
        assert_parse_error('')
394
        assert_parse_error('Creator ""')
395
        assert_parse_error('0')
396
        assert_parse_error('graph ]')
397
        assert_parse_error('graph [ 1 ]')
398
        assert_parse_error('graph [ 1.E+2 ]')
399
        assert_parse_error('graph [ "A" ]')
400
        assert_parse_error('graph [ ] graph ]')
401
        assert_parse_error('graph [ ] graph [ ]')
402
        assert_parse_error('graph [ data [1, 2, 3] ]')
403
        assert_parse_error('graph [ node [ ] ]')
404
        assert_parse_error('graph [ node [ id 0 ] ]')
405
        nx.parse_gml('graph [ node [ id "a" ] ]', label='id')
406
        assert_parse_error(
407
            'graph [ node [ id 0 label 0 ] node [ id 0 label 1 ] ]')
408
        assert_parse_error(
409
            'graph [ node [ id 0 label 0 ] node [ id 1 label 0 ] ]')
410
        assert_parse_error('graph [ node [ id 0 label 0 ] edge [ ] ]')
411
        assert_parse_error('graph [ node [ id 0 label 0 ] edge [ source 0 ] ]')
412
        nx.parse_gml(
413
            'graph [edge [ source 0 target 0 ] node [ id 0 label 0 ] ]')
414
        assert_parse_error(
415
            'graph [ node [ id 0 label 0 ] edge [ source 1 target 0 ] ]')
416
        assert_parse_error(
417
            'graph [ node [ id 0 label 0 ] edge [ source 0 target 1 ] ]')
418
        assert_parse_error(
419
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
420
            'edge [ source 0 target 1 ] edge [ source 1 target 0 ] ]')
421
        nx.parse_gml(
422
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
423
            'edge [ source 0 target 1 ] edge [ source 1 target 0 ] '
424
            'directed 1 ]')
425
        nx.parse_gml(
426
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
427
            'edge [ source 0 target 1 ] edge [ source 0 target 1 ]'
428
            'multigraph 1 ]')
429
        nx.parse_gml(
430
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
431
            'edge [ source 0 target 1 key 0 ] edge [ source 0 target 1 ]'
432
            'multigraph 1 ]')
433
        assert_parse_error(
434
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
435
            'edge [ source 0 target 1 key 0 ] edge [ source 0 target 1 key 0 ]'
436
            'multigraph 1 ]')
437
        nx.parse_gml(
438
            'graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] '
439
            'edge [ source 0 target 1 key 0 ] edge [ source 1 target 0 key 0 ]'
440
            'directed 1 multigraph 1 ]')
441

    
442
        def assert_generate_error(*args, **kwargs):
443
            assert_raises(nx.NetworkXError,
444
                          lambda: list(nx.generate_gml(*args, **kwargs)))
445

    
446
        G = nx.Graph()
447
        G.graph[3] = 3
448
        assert_generate_error(G)
449
        G = nx.Graph()
450
        G.graph['3'] = 3
451
        assert_generate_error(G)
452
        G = nx.Graph()
453
        G.graph['data'] = frozenset([1, 2, 3])
454
        assert_generate_error(G, stringizer=literal_stringizer)
455
        G = nx.Graph()
456
        G.graph['data'] = []
457
        assert_generate_error(G)
458
        assert_generate_error(G, stringizer=len)
459

    
460
    def test_label_kwarg(self):
461
        G = nx.parse_gml(self.simple_data, label='id')
462
        assert_equals(sorted(G.nodes), [1, 2, 3])
463
        labels = [G.nodes[n]['label'] for n in sorted(G.nodes)]
464
        assert_equals(labels, ['Node 1', 'Node 2', 'Node 3'])
465

    
466
        G = nx.parse_gml(self.simple_data, label=None)
467
        assert_equals(sorted(G.nodes), [1, 2, 3])
468
        labels = [G.nodes[n]['label'] for n in sorted(G.nodes)]
469
        assert_equals(labels, ['Node 1', 'Node 2', 'Node 3'])