Statistics
| Branch: | Revision:

iof-tools / networkxMiCe / networkx-master / networkx / classes / tests / test_graph.py @ 5cef0f13

History | View | Annotate | Download (27 KB)

1
from nose.tools import assert_equal
2
from nose.tools import assert_is
3
from nose.tools import assert_not_equal
4
from nose.tools import assert_raises
5
from nose.tools import raises
6
import pickle
7
import gc
8
import collections
9

    
10
import networkx as nx
11
from networkx.testing.utils import *
12

    
13

    
14
def test_deprecated():
15
    # for backwards compatibility with 1.x, will be removed for 3.x
16
    G = nx.complete_graph(3)
17
    assert_equal(G.node, {0: {}, 1: {}, 2: {}})
18

    
19
    G = nx.DiGraph()
20
    G.add_path([3, 4])
21
    assert_equal(G.adj, {3: {4: {}}, 4: {}})
22

    
23
    G = nx.DiGraph()
24
    G.add_cycle([3, 4, 5])
25
    assert_equal(G.adj, {3: {4: {}}, 4: {5: {}}, 5: {3: {}}})
26

    
27
    G = nx.DiGraph()
28
    G.add_star([3, 4, 5])
29
    assert_equal(G.adj, {3: {4: {}, 5: {}}, 4: {}, 5: {}})
30

    
31
    G = nx.DiGraph([(0, 0), (0, 1), (1, 2)])
32
    assert_equal(G.number_of_selfloops(), 1)
33
    assert_equal(list(G.nodes_with_selfloops()), [0])
34
    assert_equal(list(G.selfloop_edges()), [(0, 0)])
35

    
36

    
37
class BaseGraphTester(object):
38
    """ Tests for data-structure independent graph class features."""
39

    
40
    def test_contains(self):
41
        G = self.K3
42
        assert(1 in G)
43
        assert(4 not in G)
44
        assert('b' not in G)
45
        assert([] not in G)   # no exception for nonhashable
46
        assert({1: 1} not in G)  # no exception for nonhashable
47

    
48
    def test_order(self):
49
        G = self.K3
50
        assert_equal(len(G), 3)
51
        assert_equal(G.order(), 3)
52
        assert_equal(G.number_of_nodes(), 3)
53

    
54
    def test_nodes(self):
55
        G = self.K3
56
        assert_equal(sorted(G.nodes()), self.k3nodes)
57
        assert_equal(sorted(G.nodes(data=True)), [(0, {}), (1, {}), (2, {})])
58

    
59
    def test_has_node(self):
60
        G = self.K3
61
        assert(G.has_node(1))
62
        assert(not G.has_node(4))
63
        assert(not G.has_node([]))   # no exception for nonhashable
64
        assert(not G.has_node({1: 1}))  # no exception for nonhashable
65

    
66
    def test_has_edge(self):
67
        G = self.K3
68
        assert_equal(G.has_edge(0, 1), True)
69
        assert_equal(G.has_edge(0, -1), False)
70

    
71
    def test_neighbors(self):
72
        G = self.K3
73
        assert_equal(sorted(G.neighbors(0)), [1, 2])
74
        assert_raises((KeyError, nx.NetworkXError), G.neighbors, -1)
75

    
76
    def test_memory_leak(self):
77
        G = self.Graph()
78

    
79
        def count_objects_of_type(_type):
80
            return sum(1 for obj in gc.get_objects() if isinstance(obj, _type))
81

    
82
        gc.collect()
83
        before = count_objects_of_type(self.Graph)
84
        G.copy()
85
        after = count_objects_of_type(self.Graph)
86
        assert_equal(before, after)
87

    
88
        # test a subgraph of the base class
89
        class MyGraph(self.Graph):
90
            pass
91

    
92
        gc.collect()
93
        G = MyGraph()
94
        before = count_objects_of_type(MyGraph)
95
        G.copy()
96
        after = count_objects_of_type(MyGraph)
97
        assert_equal(before, after)
98

    
99
    def test_edges(self):
100
        G = self.K3
101
        assert_edges_equal(G.edges(), [(0, 1), (0, 2), (1, 2)])
102
        assert_edges_equal(G.edges(0), [(0, 1), (0, 2)])
103
        assert_edges_equal(G.edges([0, 1]), [(0, 1), (0, 2), (1, 2)])
104
        assert_raises((KeyError, nx.NetworkXError), G.edges, -1)
105

    
106
    def test_weighted_degree(self):
107
        G = self.Graph()
108
        G.add_edge(1, 2, weight=2)
109
        G.add_edge(2, 3, weight=3)
110
        assert_equal(sorted(d for n, d in G.degree(weight='weight')),
111
                     [2, 3, 5])
112
        assert_equal(dict(G.degree(weight='weight')), {1: 2, 2: 5, 3: 3})
113
        assert_equal(G.degree(1, weight='weight'), 2)
114
        assert_equal(G.degree([1], weight='weight'), [(1, 2)])
115

    
116
    def test_degree(self):
117
        G = self.K3
118
        assert_equal(sorted(G.degree()), [(0, 2), (1, 2), (2, 2)])
119
        assert_equal(dict(G.degree()), {0: 2, 1: 2, 2: 2})
120
        assert_equal(G.degree(0), 2)
121
        assert_raises(nx.NetworkXError, G.degree, -1)  # node not in graph
122

    
123
    def test_size(self):
124
        G = self.K3
125
        assert_equal(G.size(), 3)
126
        assert_equal(G.number_of_edges(), 3)
127

    
128
    def test_nbunch_iter(self):
129
        G = self.K3
130
        assert_nodes_equal(G.nbunch_iter(), self.k3nodes)  # all nodes
131
        assert_nodes_equal(G.nbunch_iter(0), [0])  # single node
132
        assert_nodes_equal(G.nbunch_iter([0, 1]), [0, 1])  # sequence
133
        # sequence with none in graph
134
        assert_nodes_equal(G.nbunch_iter([-1]), [])
135
        # string sequence with none in graph
136
        assert_nodes_equal(G.nbunch_iter("foo"), [])
137
        # node not in graph doesn't get caught upon creation of iterator
138
        bunch = G.nbunch_iter(-1)
139
        # but gets caught when iterator used
140
        assert_raises(nx.NetworkXError, list, bunch)
141
        # unhashable doesn't get caught upon creation of iterator
142
        bunch = G.nbunch_iter([0, 1, 2, {}])
143
        # but gets caught when iterator hits the unhashable
144
        assert_raises(nx.NetworkXError, list, bunch)
145

    
146
    @raises(nx.NetworkXError)
147
    def test_nbunch_iter_node_format_raise(self):
148
        # Tests that a node that would have failed string formatting
149
        # doesn't cause an error when attempting to raise a
150
        # :exc:`nx.NetworkXError`.
151

    
152
        # For more information, see pull request #1813.
153
        G = self.Graph()
154
        nbunch = [('x', set())]
155
        list(G.nbunch_iter(nbunch))
156

    
157
    def test_selfloop_degree(self):
158
        G = self.Graph()
159
        G.add_edge(1, 1)
160
        assert_equal(sorted(G.degree()), [(1, 2)])
161
        assert_equal(dict(G.degree()), {1: 2})
162
        assert_equal(G.degree(1), 2)
163
        assert_equal(sorted(G.degree([1])), [(1, 2)])
164
        assert_equal(G.degree(1, weight='weight'), 2)
165

    
166
    def test_selfloops(self):
167
        G = self.K3.copy()
168
        G.add_edge(0, 0)
169
        assert_nodes_equal(nx.nodes_with_selfloops(G), [0])
170
        assert_edges_equal(nx.selfloop_edges(G), [(0, 0)])
171
        assert_equal(nx.number_of_selfloops(G), 1)
172
        G.remove_edge(0, 0)
173
        G.add_edge(0, 0)
174
        G.remove_edges_from([(0, 0)])
175
        G.add_edge(1, 1)
176
        G.remove_node(1)
177
        G.add_edge(0, 0)
178
        G.add_edge(1, 1)
179
        G.remove_nodes_from([0, 1])
180

    
181

    
182
class BaseAttrGraphTester(BaseGraphTester):
183
    """ Tests of graph class attribute features."""
184

    
185
    def test_weighted_degree(self):
186
        G = self.Graph()
187
        G.add_edge(1, 2, weight=2, other=3)
188
        G.add_edge(2, 3, weight=3, other=4)
189
        assert_equal(sorted(d for n, d in G.degree(weight='weight')),
190
                     [2, 3, 5])
191
        assert_equal(dict(G.degree(weight='weight')), {1: 2, 2: 5, 3: 3})
192
        assert_equal(G.degree(1, weight='weight'), 2)
193
        assert_nodes_equal((G.degree([1], weight='weight')), [(1, 2)])
194

    
195
        assert_nodes_equal((d for n, d in G.degree(weight='other')), [3, 7, 4])
196
        assert_equal(dict(G.degree(weight='other')), {1: 3, 2: 7, 3: 4})
197
        assert_equal(G.degree(1, weight='other'), 3)
198
        assert_edges_equal((G.degree([1], weight='other')), [(1, 3)])
199

    
200
    def add_attributes(self, G):
201
        G.graph['foo'] = []
202
        G.nodes[0]['foo'] = []
203
        G.remove_edge(1, 2)
204
        ll = []
205
        G.add_edge(1, 2, foo=ll)
206
        G.add_edge(2, 1, foo=ll)
207

    
208
    def test_name(self):
209
        G = self.Graph(name='')
210
        assert_equal(G.name, "")
211
        G = self.Graph(name='test')
212
        assert_equal(G.__str__(), "test")
213
        assert_equal(G.name, "test")
214

    
215
    def test_graph_chain(self):
216
        G = self.Graph([(0, 1), (1, 2)])
217
        DG = G.to_directed(as_view=True)
218
        SDG = DG.subgraph([0, 1])
219
        RSDG = SDG.reverse(copy=False)
220
        assert_is(G, DG._graph)
221
        assert_is(DG, SDG._graph)
222
        assert_is(SDG, RSDG._graph)
223

    
224
    def test_copy(self):
225
        G = self.Graph()
226
        G.add_node(0)
227
        G.add_edge(1, 2)
228
        self.add_attributes(G)
229
        # copy edge datadict but any container attr are same
230
        H = G.copy()
231
        self.graphs_equal(H, G)
232
        self.different_attrdict(H, G)
233
        self.shallow_copy_attrdict(H, G)
234

    
235
    def test_class_copy(self):
236
        G = self.Graph()
237
        G.add_node(0)
238
        G.add_edge(1, 2)
239
        self.add_attributes(G)
240
        # copy edge datadict but any container attr are same
241
        H = G.__class__(G)
242
        self.graphs_equal(H, G)
243
        self.different_attrdict(H, G)
244
        self.shallow_copy_attrdict(H, G)
245

    
246
    def test_fresh_copy(self):
247
        G = self.Graph()
248
        G.add_node(0)
249
        G.add_edge(1, 2)
250
        self.add_attributes(G)
251
        # copy graph structure but use fresh datadict
252
        H = G.fresh_copy()
253
        H.add_nodes_from(G)
254
        H.add_edges_from(G.edges())
255
        assert_equal(len(G.nodes[0]), 1)
256
        ddict = G.adj[1][2][0] if G.is_multigraph() else G.adj[1][2]
257
        assert_equal(len(ddict), 1)
258
        assert_equal(len(H.nodes[0]), 0)
259
        ddict = H.adj[1][2][0] if H.is_multigraph() else H.adj[1][2]
260
        assert_equal(len(ddict), 0)
261

    
262
    def is_deepcopy(self, H, G):
263
        self.graphs_equal(H, G)
264
        self.different_attrdict(H, G)
265
        self.deep_copy_attrdict(H, G)
266

    
267
    def deep_copy_attrdict(self, H, G):
268
        self.deepcopy_graph_attr(H, G)
269
        self.deepcopy_node_attr(H, G)
270
        self.deepcopy_edge_attr(H, G)
271

    
272
    def deepcopy_graph_attr(self, H, G):
273
        assert_equal(G.graph['foo'], H.graph['foo'])
274
        G.graph['foo'].append(1)
275
        assert_not_equal(G.graph['foo'], H.graph['foo'])
276

    
277
    def deepcopy_node_attr(self, H, G):
278
        assert_equal(G.nodes[0]['foo'], H.nodes[0]['foo'])
279
        G.nodes[0]['foo'].append(1)
280
        assert_not_equal(G.nodes[0]['foo'], H.nodes[0]['foo'])
281

    
282
    def deepcopy_edge_attr(self, H, G):
283
        assert_equal(G[1][2]['foo'], H[1][2]['foo'])
284
        G[1][2]['foo'].append(1)
285
        assert_not_equal(G[1][2]['foo'], H[1][2]['foo'])
286

    
287
    def is_shallow_copy(self, H, G):
288
        self.graphs_equal(H, G)
289
        self.shallow_copy_attrdict(H, G)
290

    
291
    def shallow_copy_attrdict(self, H, G):
292
        self.shallow_copy_graph_attr(H, G)
293
        self.shallow_copy_node_attr(H, G)
294
        self.shallow_copy_edge_attr(H, G)
295

    
296
    def shallow_copy_graph_attr(self, H, G):
297
        assert_equal(G.graph['foo'], H.graph['foo'])
298
        G.graph['foo'].append(1)
299
        assert_equal(G.graph['foo'], H.graph['foo'])
300

    
301
    def shallow_copy_node_attr(self, H, G):
302
        assert_equal(G.nodes[0]['foo'], H.nodes[0]['foo'])
303
        G.nodes[0]['foo'].append(1)
304
        assert_equal(G.nodes[0]['foo'], H.nodes[0]['foo'])
305

    
306
    def shallow_copy_edge_attr(self, H, G):
307
        assert_equal(G[1][2]['foo'], H[1][2]['foo'])
308
        G[1][2]['foo'].append(1)
309
        assert_equal(G[1][2]['foo'], H[1][2]['foo'])
310

    
311
    def same_attrdict(self, H, G):
312
        old_foo = H[1][2]['foo']
313
        H.adj[1][2]['foo'] = 'baz'
314
        assert_equal(G.edges, H.edges)
315
        H.adj[1][2]['foo'] = old_foo
316
        assert_equal(G.edges, H.edges)
317

    
318
        old_foo = H.nodes[0]['foo']
319
        H.nodes[0]['foo'] = 'baz'
320
        assert_equal(G.nodes, H.nodes)
321
        H.nodes[0]['foo'] = old_foo
322
        assert_equal(G.nodes, H.nodes)
323

    
324
    def different_attrdict(self, H, G):
325
        old_foo = H[1][2]['foo']
326
        H.adj[1][2]['foo'] = 'baz'
327
        assert_not_equal(G._adj, H._adj)
328
        H.adj[1][2]['foo'] = old_foo
329
        assert_equal(G._adj, H._adj)
330

    
331
        old_foo = H.nodes[0]['foo']
332
        H.nodes[0]['foo'] = 'baz'
333
        assert_not_equal(G._node, H._node)
334
        H.nodes[0]['foo'] = old_foo
335
        assert_equal(G._node, H._node)
336

    
337
    def graphs_equal(self, H, G):
338
        assert_equal(G._adj, H._adj)
339
        assert_equal(G._node, H._node)
340
        assert_equal(G.graph, H.graph)
341
        assert_equal(G.name, H.name)
342
        if not G.is_directed() and not H.is_directed():
343
            assert_is(H._adj[1][2], H._adj[2][1])
344
            assert_is(G._adj[1][2], G._adj[2][1])
345
        else:  # at least one is directed
346
            if not G.is_directed():
347
                G._pred = G._adj
348
                G._succ = G._adj
349
            if not H.is_directed():
350
                H._pred = H._adj
351
                H._succ = H._adj
352
            assert_equal(G._pred, H._pred)
353
            assert_equal(G._succ, H._succ)
354
            assert_is(H._succ[1][2], H._pred[2][1])
355
            assert_is(G._succ[1][2], G._pred[2][1])
356

    
357
    def test_graph_attr(self):
358
        G = self.K3
359
        G.graph['foo'] = 'bar'
360
        assert_equal(G.graph['foo'], 'bar')
361
        del G.graph['foo']
362
        assert_equal(G.graph, {})
363
        H = self.Graph(foo='bar')
364
        assert_equal(H.graph['foo'], 'bar')
365

    
366
    def test_node_attr(self):
367
        G = self.K3
368
        G.add_node(1, foo='bar')
369
        assert_nodes_equal(G.nodes(), [0, 1, 2])
370
        assert_nodes_equal(G.nodes(data=True),
371
                           [(0, {}), (1, {'foo': 'bar'}), (2, {})])
372
        G.nodes[1]['foo'] = 'baz'
373
        assert_nodes_equal(G.nodes(data=True),
374
                           [(0, {}), (1, {'foo': 'baz'}), (2, {})])
375
        assert_nodes_equal(G.nodes(data='foo'),
376
                           [(0, None), (1, 'baz'), (2, None)])
377
        assert_nodes_equal(G.nodes(data='foo', default='bar'),
378
                           [(0, 'bar'), (1, 'baz'), (2, 'bar')])
379

    
380
    def test_node_attr2(self):
381
        G = self.K3
382
        a = {'foo': 'bar'}
383
        G.add_node(3, **a)
384
        assert_nodes_equal(G.nodes(), [0, 1, 2, 3])
385
        assert_nodes_equal(G.nodes(data=True),
386
                           [(0, {}), (1, {}), (2, {}), (3, {'foo': 'bar'})])
387

    
388
    def test_edge_lookup(self):
389
        G = self.Graph()
390
        G.add_edge(1, 2, foo='bar')
391
        assert_edges_equal(G.edges[1, 2], {'foo': 'bar'})
392

    
393
    def test_edge_attr(self):
394
        G = self.Graph()
395
        G.add_edge(1, 2, foo='bar')
396
        assert_edges_equal(G.edges(data=True), [(1, 2, {'foo': 'bar'})])
397
        assert_edges_equal(G.edges(data='foo'), [(1, 2, 'bar')])
398

    
399
    def test_edge_attr2(self):
400
        G = self.Graph()
401
        G.add_edges_from([(1, 2), (3, 4)], foo='foo')
402
        assert_edges_equal(G.edges(data=True),
403
                           [(1, 2, {'foo': 'foo'}), (3, 4, {'foo': 'foo'})])
404
        assert_edges_equal(G.edges(data='foo'),
405
                           [(1, 2, 'foo'), (3, 4, 'foo')])
406

    
407
    def test_edge_attr3(self):
408
        G = self.Graph()
409
        G.add_edges_from([(1, 2, {'weight': 32}),
410
                          (3, 4, {'weight': 64})], foo='foo')
411
        assert_edges_equal(G.edges(data=True),
412
                           [(1, 2, {'foo': 'foo', 'weight': 32}),
413
                            (3, 4, {'foo': 'foo', 'weight': 64})])
414

    
415
        G.remove_edges_from([(1, 2), (3, 4)])
416
        G.add_edge(1, 2, data=7, spam='bar', bar='foo')
417
        assert_edges_equal(G.edges(data=True),
418
                           [(1, 2, {'data': 7, 'spam': 'bar', 'bar': 'foo'})])
419

    
420
    def test_edge_attr4(self):
421
        G = self.Graph()
422
        G.add_edge(1, 2, data=7, spam='bar', bar='foo')
423
        assert_edges_equal(G.edges(data=True),
424
                           [(1, 2, {'data': 7, 'spam': 'bar', 'bar': 'foo'})])
425
        G[1][2]['data'] = 10  # OK to set data like this
426
        assert_edges_equal(G.edges(data=True),
427
                           [(1, 2, {'data': 10, 'spam': 'bar', 'bar': 'foo'})])
428

    
429
        G.adj[1][2]['data'] = 20
430
        assert_edges_equal(G.edges(data=True),
431
                           [(1, 2, {'data': 20, 'spam': 'bar', 'bar': 'foo'})])
432
        G.edges[1, 2]['data'] = 21  # another spelling, "edge"
433
        assert_edges_equal(G.edges(data=True),
434
                           [(1, 2, {'data': 21, 'spam': 'bar', 'bar': 'foo'})])
435
        G.adj[1][2]['listdata'] = [20, 200]
436
        G.adj[1][2]['weight'] = 20
437
        dd = {'data': 21, 'spam': 'bar', 'bar': 'foo',
438
              'listdata': [20, 200], 'weight': 20}
439
        assert_edges_equal(G.edges(data=True), [(1, 2, dd)])
440

    
441
    def test_to_undirected(self):
442
        G = self.K3
443
        self.add_attributes(G)
444
        H = nx.Graph(G)
445
        self.is_shallow_copy(H, G)
446
        self.different_attrdict(H, G)
447
        H = G.to_undirected()
448
        self.is_deepcopy(H, G)
449

    
450
    def test_to_directed(self):
451
        G = self.K3
452
        self.add_attributes(G)
453
        H = nx.DiGraph(G)
454
        self.is_shallow_copy(H, G)
455
        self.different_attrdict(H, G)
456
        H = G.to_directed()
457
        self.is_deepcopy(H, G)
458

    
459
    def test_subgraph(self):
460
        G = self.K3
461
        self.add_attributes(G)
462
        H = G.subgraph([0, 1, 2, 5])
463
        self.graphs_equal(H, G)
464
        self.same_attrdict(H, G)
465
        self.shallow_copy_attrdict(H, G)
466

    
467
        H = G.subgraph(0)
468
        assert_equal(H.adj, {0: {}})
469
        H = G.subgraph([])
470
        assert_equal(H.adj, {})
471
        assert_not_equal(G.adj, {})
472

    
473
    def test_selfloops_attr(self):
474
        G = self.K3.copy()
475
        G.add_edge(0, 0)
476
        G.add_edge(1, 1, weight=2)
477
        assert_edges_equal(nx.selfloop_edges(G, data=True),
478
                           [(0, 0, {}), (1, 1, {'weight': 2})])
479
        assert_edges_equal(nx.selfloop_edges(G, data='weight'),
480
                           [(0, 0, None), (1, 1, 2)])
481

    
482

    
483
class TestGraph(BaseAttrGraphTester):
484
    """Tests specific to dict-of-dict-of-dict graph data structure"""
485

    
486
    def setUp(self):
487
        self.Graph = nx.Graph
488
        # build dict-of-dict-of-dict K3
489
        ed1, ed2, ed3 = ({}, {}, {})
490
        self.k3adj = {0: {1: ed1, 2: ed2},
491
                      1: {0: ed1, 2: ed3},
492
                      2: {0: ed2, 1: ed3}}
493
        self.k3edges = [(0, 1), (0, 2), (1, 2)]
494
        self.k3nodes = [0, 1, 2]
495
        self.K3 = self.Graph()
496
        self.K3._adj = self.k3adj
497
        self.K3._node = {}
498
        self.K3._node[0] = {}
499
        self.K3._node[1] = {}
500
        self.K3._node[2] = {}
501

    
502
    def test_pickle(self):
503
        G = self.K3
504
        pg = pickle.loads(pickle.dumps(G, -1))
505
        self.graphs_equal(pg, G)
506
        pg = pickle.loads(pickle.dumps(G))
507
        self.graphs_equal(pg, G)
508

    
509
    def test_data_input(self):
510
        G = self.Graph({1: [2], 2: [1]}, name="test")
511
        assert_equal(G.name, "test")
512
        assert_equal(sorted(G.adj.items()), [(1, {2: {}}), (2, {1: {}})])
513
        G = self.Graph({1: [2], 2: [1]}, name="test")
514
        assert_equal(G.name, "test")
515
        assert_equal(sorted(G.adj.items()), [(1, {2: {}}), (2, {1: {}})])
516

    
517
    def test_adjacency(self):
518
        G = self.K3
519
        assert_equal(dict(G.adjacency()),
520
                     {0: {1: {}, 2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}})
521

    
522
    def test_getitem(self):
523
        G = self.K3
524
        assert_equal(G[0], {1: {}, 2: {}})
525
        assert_raises(KeyError, G.__getitem__, 'j')
526
        assert_raises((TypeError, nx.NetworkXError), G.__getitem__, ['A'])
527

    
528
    def test_add_node(self):
529
        G = self.Graph()
530
        G.add_node(0)
531
        assert_equal(G.adj, {0: {}})
532
        # test add attributes
533
        G.add_node(1, c='red')
534
        G.add_node(2, c='blue')
535
        G.add_node(3, c='red')
536
        assert_equal(G.nodes[1]['c'], 'red')
537
        assert_equal(G.nodes[2]['c'], 'blue')
538
        assert_equal(G.nodes[3]['c'], 'red')
539
        # test updating attributes
540
        G.add_node(1, c='blue')
541
        G.add_node(2, c='red')
542
        G.add_node(3, c='blue')
543
        assert_equal(G.nodes[1]['c'], 'blue')
544
        assert_equal(G.nodes[2]['c'], 'red')
545
        assert_equal(G.nodes[3]['c'], 'blue')
546

    
547
    def test_add_nodes_from(self):
548
        G = self.Graph()
549
        G.add_nodes_from([0, 1, 2])
550
        assert_equal(G.adj, {0: {}, 1: {}, 2: {}})
551
        # test add attributes
552
        G.add_nodes_from([0, 1, 2], c='red')
553
        assert_equal(G.nodes[0]['c'], 'red')
554
        assert_equal(G.nodes[2]['c'], 'red')
555
        # test that attribute dicts are not the same
556
        assert(G.nodes[0] is not G.nodes[1])
557
        # test updating attributes
558
        G.add_nodes_from([0, 1, 2], c='blue')
559
        assert_equal(G.nodes[0]['c'], 'blue')
560
        assert_equal(G.nodes[2]['c'], 'blue')
561
        assert(G.nodes[0] is not G.nodes[1])
562
        # test tuple input
563
        H = self.Graph()
564
        H.add_nodes_from(G.nodes(data=True))
565
        assert_equal(H.nodes[0]['c'], 'blue')
566
        assert_equal(H.nodes[2]['c'], 'blue')
567
        assert(H.nodes[0] is not H.nodes[1])
568
        # specific overrides general
569
        H.add_nodes_from([0, (1, {'c': 'green'}), (3, {'c': 'cyan'})], c='red')
570
        assert_equal(H.nodes[0]['c'], 'red')
571
        assert_equal(H.nodes[1]['c'], 'green')
572
        assert_equal(H.nodes[2]['c'], 'blue')
573
        assert_equal(H.nodes[3]['c'], 'cyan')
574

    
575
    def test_remove_node(self):
576
        G = self.K3
577
        G.remove_node(0)
578
        assert_equal(G.adj, {1: {2: {}}, 2: {1: {}}})
579
        assert_raises((KeyError, nx.NetworkXError), G.remove_node, -1)
580

    
581
        # generator here to implement list,set,string...
582
    def test_remove_nodes_from(self):
583
        G = self.K3
584
        G.remove_nodes_from([0, 1])
585
        assert_equal(G.adj, {2: {}})
586
        G.remove_nodes_from([-1])  # silent fail
587

    
588
    def test_add_edge(self):
589
        G = self.Graph()
590
        G.add_edge(0, 1)
591
        assert_equal(G.adj, {0: {1: {}}, 1: {0: {}}})
592
        G = self.Graph()
593
        G.add_edge(*(0, 1))
594
        assert_equal(G.adj, {0: {1: {}}, 1: {0: {}}})
595

    
596
    def test_add_edges_from(self):
597
        G = self.Graph()
598
        G.add_edges_from([(0, 1), (0, 2, {'weight': 3})])
599
        assert_equal(G.adj, {0: {1: {}, 2: {'weight': 3}}, 1: {0: {}},
600
                             2: {0: {'weight': 3}}})
601
        G = self.Graph()
602
        G.add_edges_from([(0, 1), (0, 2, {'weight': 3}),
603
                          (1, 2, {'data': 4})], data=2)
604
        assert_equal(G.adj, {
605
            0: {1: {'data': 2}, 2: {'weight': 3, 'data': 2}},
606
            1: {0: {'data': 2}, 2: {'data': 4}},
607
            2: {0: {'weight': 3, 'data': 2}, 1: {'data': 4}}
608
        })
609

    
610
        assert_raises(nx.NetworkXError,
611
                      G.add_edges_from, [(0,)])  # too few in tuple
612
        assert_raises(nx.NetworkXError,
613
                      G.add_edges_from, [(0, 1, 2, 3)])  # too many in tuple
614
        assert_raises(TypeError, G.add_edges_from, [0])  # not a tuple
615

    
616
    def test_remove_edge(self):
617
        G = self.K3
618
        G.remove_edge(0, 1)
619
        assert_equal(G.adj, {0: {2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}})
620
        assert_raises((KeyError, nx.NetworkXError), G.remove_edge, -1, 0)
621

    
622
    def test_remove_edges_from(self):
623
        G = self.K3
624
        G.remove_edges_from([(0, 1)])
625
        assert_equal(G.adj, {0: {2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}})
626
        G.remove_edges_from([(0, 0)])  # silent fail
627

    
628
    def test_clear(self):
629
        G = self.K3
630
        G.clear()
631
        assert_equal(G.adj, {})
632

    
633
    def test_edges_data(self):
634
        G = self.K3
635
        all_edges = [(0, 1, {}), (0, 2, {}), (1, 2, {})]
636
        assert_edges_equal(G.edges(data=True), all_edges)
637
        assert_edges_equal(G.edges(0, data=True), [(0, 1, {}), (0, 2, {})])
638
        assert_edges_equal(G.edges([0, 1], data=True), all_edges)
639
        assert_raises((KeyError, nx.NetworkXError), G.edges, -1, True)
640

    
641
    def test_get_edge_data(self):
642
        G = self.K3
643
        assert_equal(G.get_edge_data(0, 1), {})
644
        assert_equal(G[0][1], {})
645
        assert_equal(G.get_edge_data(10, 20), None)
646
        assert_equal(G.get_edge_data(-1, 0), None)
647
        assert_equal(G.get_edge_data(-1, 0, default=1), 1)
648

    
649
    def test_update(self):
650
        # specify both edgees and nodes
651
        G = self.K3.copy()
652
        G.update(nodes=[3, (4, {'size': 2})],
653
                 edges=[(4, 5), (6, 7, {'weight': 2})])
654
        nlist = [(0, {}), (1, {}), (2, {}), (3, {}),
655
                 (4, {'size': 2}), (5, {}), (6, {}), (7, {})]
656
        assert_equal(sorted(G.nodes.data()), nlist)
657
        if G.is_directed():
658
            elist = [(0, 1, {}), (0, 2, {}), (1, 0, {}), (1, 2, {}),
659
                     (2, 0, {}), (2, 1, {}),
660
                     (4, 5, {}), (6, 7, {'weight': 2})]
661
        else:
662
            elist = [(0, 1, {}), (0, 2, {}), (1, 2, {}),
663
                     (4, 5, {}), (6, 7, {'weight': 2})]
664
        assert_equal(sorted(G.edges.data()), elist)
665
        assert_equal(G.graph, {})
666

    
667
        # no keywords -- order is edges, nodes
668
        G = self.K3.copy()
669
        G.update([(4, 5), (6, 7, {'weight': 2})], [3, (4, {'size': 2})])
670
        assert_equal(sorted(G.nodes.data()), nlist)
671
        assert_equal(sorted(G.edges.data()), elist)
672
        assert_equal(G.graph, {})
673

    
674
        # update using only a graph
675
        G = self.Graph()
676
        G.graph['foo'] = 'bar'
677
        G.add_node(2, data=4)
678
        G.add_edge(0, 1, weight=0.5)
679
        GG = G.copy()
680
        H = self.Graph()
681
        GG.update(H)
682
        assert_graphs_equal(G, GG)
683
        H.update(G)
684
        assert_graphs_equal(H, G)
685

    
686
        # update nodes only
687
        H = self.Graph()
688
        H.update(nodes=[3, 4])
689
        assert_equal(H.nodes ^ {3, 4}, set([]))
690
        assert_equal(H.size(), 0)
691

    
692
        # update edges only
693
        H = self.Graph()
694
        H.update(edges=[(3, 4)])
695
        assert_equal(sorted(H.edges.data()), [(3, 4, {})])
696
        assert_equal(H.size(), 1)
697

    
698
        # No inputs -> exception
699
        assert_raises(nx.NetworkXError, nx.Graph().update)
700

    
701

    
702
class TestEdgeSubgraph(object):
703
    """Unit tests for the :meth:`Graph.edge_subgraph` method."""
704

    
705
    def setup(self):
706
        # Create a path graph on five nodes.
707
        G = nx.path_graph(5)
708
        # Add some node, edge, and graph attributes.
709
        for i in range(5):
710
            G.nodes[i]['name'] = 'node{}'.format(i)
711
        G.edges[0, 1]['name'] = 'edge01'
712
        G.edges[3, 4]['name'] = 'edge34'
713
        G.graph['name'] = 'graph'
714
        # Get the subgraph induced by the first and last edges.
715
        self.G = G
716
        self.H = G.edge_subgraph([(0, 1), (3, 4)])
717

    
718
    def test_correct_nodes(self):
719
        """Tests that the subgraph has the correct nodes."""
720
        assert_equal([0, 1, 3, 4], sorted(self.H.nodes()))
721

    
722
    def test_correct_edges(self):
723
        """Tests that the subgraph has the correct edges."""
724
        assert_equal([(0, 1, 'edge01'), (3, 4, 'edge34')],
725
                     sorted(self.H.edges(data='name')))
726

    
727
    def test_add_node(self):
728
        """Tests that adding a node to the original graph does not
729
        affect the nodes of the subgraph.
730

731
        """
732
        self.G.add_node(5)
733
        assert_equal([0, 1, 3, 4], sorted(self.H.nodes()))
734

    
735
    def test_remove_node(self):
736
        """Tests that removing a node in the original graph does
737
        affect the nodes of the subgraph.
738

739
        """
740
        self.G.remove_node(0)
741
        assert_equal([1, 3, 4], sorted(self.H.nodes()))
742

    
743
    def test_node_attr_dict(self):
744
        """Tests that the node attribute dictionary of the two graphs is
745
        the same object.
746

747
        """
748
        for v in self.H:
749
            assert_equal(self.G.nodes[v], self.H.nodes[v])
750
        # Making a change to G should make a change in H and vice versa.
751
        self.G.nodes[0]['name'] = 'foo'
752
        assert_equal(self.G.nodes[0], self.H.nodes[0])
753
        self.H.nodes[1]['name'] = 'bar'
754
        assert_equal(self.G.nodes[1], self.H.nodes[1])
755

    
756
    def test_edge_attr_dict(self):
757
        """Tests that the edge attribute dictionary of the two graphs is
758
        the same object.
759

760
        """
761
        for u, v in self.H.edges():
762
            assert_equal(self.G.edges[u, v], self.H.edges[u, v])
763
        # Making a change to G should make a change in H and vice versa.
764
        self.G.edges[0, 1]['name'] = 'foo'
765
        assert_equal(self.G.edges[0, 1]['name'],
766
                     self.H.edges[0, 1]['name'])
767
        self.H.edges[3, 4]['name'] = 'bar'
768
        assert_equal(self.G.edges[3, 4]['name'],
769
                     self.H.edges[3, 4]['name'])
770

    
771
    def test_graph_attr_dict(self):
772
        """Tests that the graph attribute dictionary of the two graphs
773
        is the same object.
774

775
        """
776
        assert_is(self.G.graph, self.H.graph)