Fixed database typo and removed unnecessary class identifier.

This commit is contained in:
Batuhan Berk Başoğlu 2020-10-14 10:10:37 -04:00
parent 00ad49a143
commit 45fb349a7d
5098 changed files with 952558 additions and 85 deletions

View file

@ -0,0 +1,474 @@
"""Original NetworkX graph tests"""
import pytest
import networkx as nx
from networkx import convert_node_labels_to_integers as cnlti
from networkx.testing import assert_edges_equal, assert_nodes_equal
class HistoricalTests:
@classmethod
def setup_class(cls):
cls.null = nx.null_graph()
cls.P1 = cnlti(nx.path_graph(1), first_label=1)
cls.P3 = cnlti(nx.path_graph(3), first_label=1)
cls.P10 = cnlti(nx.path_graph(10), first_label=1)
cls.K1 = cnlti(nx.complete_graph(1), first_label=1)
cls.K3 = cnlti(nx.complete_graph(3), first_label=1)
cls.K4 = cnlti(nx.complete_graph(4), first_label=1)
cls.K5 = cnlti(nx.complete_graph(5), first_label=1)
cls.K10 = cnlti(nx.complete_graph(10), first_label=1)
cls.G = nx.Graph
def test_name(self):
G = self.G(name="test")
assert str(G) == "test"
assert G.name == "test"
H = self.G()
assert H.name == ""
# Nodes
def test_add_remove_node(self):
G = self.G()
G.add_node("A")
assert G.has_node("A")
G.remove_node("A")
assert not G.has_node("A")
def test_nonhashable_node(self):
# Test if a non-hashable object is in the Graph. A python dict will
# raise a TypeError, but for a Graph class a simple False should be
# returned (see Graph __contains__). If it cannot be a node then it is
# not a node.
G = self.G()
assert not G.has_node(["A"])
assert not G.has_node({"A": 1})
def test_add_nodes_from(self):
G = self.G()
G.add_nodes_from(list("ABCDEFGHIJKL"))
assert G.has_node("L")
G.remove_nodes_from(["H", "I", "J", "K", "L"])
G.add_nodes_from([1, 2, 3, 4])
assert sorted(G.nodes(), key=str) == [
1,
2,
3,
4,
"A",
"B",
"C",
"D",
"E",
"F",
"G",
]
# test __iter__
assert sorted(G, key=str) == [1, 2, 3, 4, "A", "B", "C", "D", "E", "F", "G"]
def test_contains(self):
G = self.G()
G.add_node("A")
assert "A" in G
assert not [] in G # never raise a Key or TypeError in this test
assert not {1: 1} in G
def test_add_remove(self):
# Test add_node and remove_node acting for various nbunch
G = self.G()
G.add_node("m")
assert G.has_node("m")
G.add_node("m") # no complaints
pytest.raises(nx.NetworkXError, G.remove_node, "j")
G.remove_node("m")
assert list(G) == []
def test_nbunch_is_list(self):
G = self.G()
G.add_nodes_from(list("ABCD"))
G.add_nodes_from(self.P3) # add nbunch of nodes (nbunch=Graph)
assert sorted(G.nodes(), key=str) == [1, 2, 3, "A", "B", "C", "D"]
G.remove_nodes_from(self.P3) # remove nbunch of nodes (nbunch=Graph)
assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D"]
def test_nbunch_is_set(self):
G = self.G()
nbunch = set("ABCDEFGHIJKL")
G.add_nodes_from(nbunch)
assert G.has_node("L")
def test_nbunch_dict(self):
# nbunch is a dict with nodes as keys
G = self.G()
nbunch = set("ABCDEFGHIJKL")
G.add_nodes_from(nbunch)
nbunch = {"I": "foo", "J": 2, "K": True, "L": "spam"}
G.remove_nodes_from(nbunch)
assert sorted(G.nodes(), key=str), ["A", "B", "C", "D", "E", "F", "G", "H"]
def test_nbunch_iterator(self):
G = self.G()
G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
n_iter = self.P3.nodes()
G.add_nodes_from(n_iter)
assert sorted(G.nodes(), key=str) == [
1,
2,
3,
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
]
n_iter = self.P3.nodes() # rebuild same iterator
G.remove_nodes_from(n_iter) # remove nbunch of nodes (nbunch=iterator)
assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D", "E", "F", "G", "H"]
def test_nbunch_graph(self):
G = self.G()
G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
nbunch = self.K3
G.add_nodes_from(nbunch)
assert sorted(G.nodes(), key=str), [
1,
2,
3,
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
]
# Edges
def test_add_edge(self):
G = self.G()
pytest.raises(TypeError, G.add_edge, "A")
G.add_edge("A", "B") # testing add_edge()
G.add_edge("A", "B") # should fail silently
assert G.has_edge("A", "B")
assert not G.has_edge("A", "C")
assert G.has_edge(*("A", "B"))
if G.is_directed():
assert not G.has_edge("B", "A")
else:
# G is undirected, so B->A is an edge
assert G.has_edge("B", "A")
G.add_edge("A", "C") # test directedness
G.add_edge("C", "A")
G.remove_edge("C", "A")
if G.is_directed():
assert G.has_edge("A", "C")
else:
assert not G.has_edge("A", "C")
assert not G.has_edge("C", "A")
def test_self_loop(self):
G = self.G()
G.add_edge("A", "A") # test self loops
assert G.has_edge("A", "A")
G.remove_edge("A", "A")
G.add_edge("X", "X")
assert G.has_node("X")
G.remove_node("X")
G.add_edge("A", "Z") # should add the node silently
assert G.has_node("Z")
def test_add_edges_from(self):
G = self.G()
G.add_edges_from([("B", "C")]) # test add_edges_from()
assert G.has_edge("B", "C")
if G.is_directed():
assert not G.has_edge("C", "B")
else:
assert G.has_edge("C", "B") # undirected
G.add_edges_from([("D", "F"), ("B", "D")])
assert G.has_edge("D", "F")
assert G.has_edge("B", "D")
if G.is_directed():
assert not G.has_edge("D", "B")
else:
assert G.has_edge("D", "B") # undirected
def test_add_edges_from2(self):
G = self.G()
# after failing silently, should add 2nd edge
G.add_edges_from([tuple("IJ"), list("KK"), tuple("JK")])
assert G.has_edge(*("I", "J"))
assert G.has_edge(*("K", "K"))
assert G.has_edge(*("J", "K"))
if G.is_directed():
assert not G.has_edge(*("K", "J"))
else:
assert G.has_edge(*("K", "J"))
def test_add_edges_from3(self):
G = self.G()
G.add_edges_from(zip(list("ACD"), list("CDE")))
assert G.has_edge("D", "E")
assert not G.has_edge("E", "C")
def test_remove_edge(self):
G = self.G()
G.add_nodes_from([1, 2, 3, "A", "B", "C", "D", "E", "F", "G", "H"])
G.add_edges_from(zip(list("MNOP"), list("NOPM")))
assert G.has_edge("O", "P")
assert G.has_edge("P", "M")
G.remove_node("P") # tests remove_node()'s handling of edges.
assert not G.has_edge("P", "M")
pytest.raises(TypeError, G.remove_edge, "M")
G.add_edge("N", "M")
assert G.has_edge("M", "N")
G.remove_edge("M", "N")
assert not G.has_edge("M", "N")
# self loop fails silently
G.remove_edges_from([list("HI"), list("DF"), tuple("KK"), tuple("JK")])
assert not G.has_edge("H", "I")
assert not G.has_edge("J", "K")
G.remove_edges_from([list("IJ"), list("KK"), list("JK")])
assert not G.has_edge("I", "J")
G.remove_nodes_from(set("ZEFHIMNO"))
G.add_edge("J", "K")
def test_edges_nbunch(self):
# Test G.edges(nbunch) with various forms of nbunch
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
# node not in nbunch should be quietly ignored
pytest.raises(nx.NetworkXError, G.edges, 6)
assert list(G.edges("Z")) == [] # iterable non-node
# nbunch can be an empty list
assert list(G.edges([])) == []
if G.is_directed():
elist = [("A", "B"), ("A", "C"), ("B", "D")]
else:
elist = [("A", "B"), ("A", "C"), ("B", "C"), ("B", "D")]
# nbunch can be a list
assert_edges_equal(list(G.edges(["A", "B"])), elist)
# nbunch can be a set
assert_edges_equal(G.edges({"A", "B"}), elist)
# nbunch can be a graph
G1 = self.G()
G1.add_nodes_from("AB")
assert_edges_equal(G.edges(G1), elist)
# nbunch can be a dict with nodes as keys
ndict = {"A": "thing1", "B": "thing2"}
assert_edges_equal(G.edges(ndict), elist)
# nbunch can be a single node
assert_edges_equal(list(G.edges("A")), [("A", "B"), ("A", "C")])
assert_nodes_equal(sorted(G), ["A", "B", "C", "D"])
# nbunch can be nothing (whole graph)
assert_edges_equal(
list(G.edges()),
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")],
)
def test_degree(self):
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
assert G.degree("A") == 2
# degree of single node in iterable container must return dict
assert list(G.degree(["A"])) == [("A", 2)]
assert sorted(d for n, d in G.degree(["A", "B"])) == [2, 3]
assert sorted(d for n, d in G.degree()) == [2, 2, 3, 3]
def test_degree2(self):
H = self.G()
H.add_edges_from([(1, 24), (1, 2)])
assert sorted(d for n, d in H.degree([1, 24])) == [1, 2]
def test_degree_graph(self):
P3 = nx.path_graph(3)
P5 = nx.path_graph(5)
# silently ignore nodes not in P3
assert dict(d for n, d in P3.degree(["A", "B"])) == {}
# nbunch can be a graph
assert sorted(d for n, d in P5.degree(P3)) == [1, 2, 2]
# nbunch can be a graph that's way too big
assert sorted(d for n, d in P3.degree(P5)) == [1, 1, 2]
assert list(P5.degree([])) == []
assert dict(P5.degree([])) == {}
def test_null(self):
null = nx.null_graph()
assert list(null.degree()) == []
assert dict(null.degree()) == {}
def test_order_size(self):
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
assert G.order() == 4
assert G.size() == 5
assert G.number_of_edges() == 5
assert G.number_of_edges("A", "B") == 1
assert G.number_of_edges("A", "D") == 0
def test_copy(self):
G = self.G()
H = G.copy() # copy
assert H.adj == G.adj
assert H.name == G.name
assert H != G
def test_subgraph(self):
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
SG = G.subgraph(["A", "B", "D"])
assert_nodes_equal(list(SG), ["A", "B", "D"])
assert_edges_equal(list(SG.edges()), [("A", "B"), ("B", "D")])
def test_to_directed(self):
G = self.G()
if not G.is_directed():
G.add_edges_from(
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
)
DG = G.to_directed()
assert DG != G # directed copy or copy
assert DG.is_directed()
assert DG.name == G.name
assert DG.adj == G.adj
assert sorted(DG.out_edges(list("AB"))) == [
("A", "B"),
("A", "C"),
("B", "A"),
("B", "C"),
("B", "D"),
]
DG.remove_edge("A", "B")
assert DG.has_edge("B", "A") # this removes B-A but not A-B
assert not DG.has_edge("A", "B")
def test_to_undirected(self):
G = self.G()
if G.is_directed():
G.add_edges_from(
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
)
UG = G.to_undirected() # to_undirected
assert UG != G
assert not UG.is_directed()
assert G.is_directed()
assert UG.name == G.name
assert UG.adj != G.adj
assert sorted(UG.edges(list("AB"))) == [
("A", "B"),
("A", "C"),
("B", "C"),
("B", "D"),
]
assert sorted(UG.edges(["A", "B"])) == [
("A", "B"),
("A", "C"),
("B", "C"),
("B", "D"),
]
UG.remove_edge("A", "B")
assert not UG.has_edge("B", "A")
assert not UG.has_edge("A", "B")
def test_neighbors(self):
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
G.add_nodes_from("GJK")
assert sorted(G["A"]) == ["B", "C"]
assert sorted(G.neighbors("A")) == ["B", "C"]
assert sorted(G.neighbors("A")) == ["B", "C"]
assert sorted(G.neighbors("G")) == []
pytest.raises(nx.NetworkXError, G.neighbors, "j")
def test_iterators(self):
G = self.G()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
G.add_nodes_from("GJK")
assert sorted(G.nodes()) == ["A", "B", "C", "D", "G", "J", "K"]
assert_edges_equal(
G.edges(), [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
)
assert sorted([v for k, v in G.degree()]) == [0, 0, 0, 2, 2, 3, 3]
assert sorted(G.degree(), key=str) == [
("A", 2),
("B", 3),
("C", 3),
("D", 2),
("G", 0),
("J", 0),
("K", 0),
]
assert sorted(G.neighbors("A")) == ["B", "C"]
pytest.raises(nx.NetworkXError, G.neighbors, "X")
G.clear()
assert nx.number_of_nodes(G) == 0
assert nx.number_of_edges(G) == 0
def test_null_subgraph(self):
# Subgraph of a null graph is a null graph
nullgraph = nx.null_graph()
G = nx.null_graph()
H = G.subgraph([])
assert nx.is_isomorphic(H, nullgraph)
def test_empty_subgraph(self):
# Subgraph of an empty graph is an empty graph. test 1
nullgraph = nx.null_graph()
E5 = nx.empty_graph(5)
E10 = nx.empty_graph(10)
H = E10.subgraph([])
assert nx.is_isomorphic(H, nullgraph)
H = E10.subgraph([1, 2, 3, 4, 5])
assert nx.is_isomorphic(H, E5)
def test_complete_subgraph(self):
# Subgraph of a complete graph is a complete graph
K1 = nx.complete_graph(1)
K3 = nx.complete_graph(3)
K5 = nx.complete_graph(5)
H = K5.subgraph([1, 2, 3])
assert nx.is_isomorphic(H, K3)
def test_subgraph_nbunch(self):
nullgraph = nx.null_graph()
K1 = nx.complete_graph(1)
K3 = nx.complete_graph(3)
K5 = nx.complete_graph(5)
# Test G.subgraph(nbunch), where nbunch is a single node
H = K5.subgraph(1)
assert nx.is_isomorphic(H, K1)
# Test G.subgraph(nbunch), where nbunch is a set
H = K5.subgraph({1})
assert nx.is_isomorphic(H, K1)
# Test G.subgraph(nbunch), where nbunch is an iterator
H = K5.subgraph(iter(K3))
assert nx.is_isomorphic(H, K3)
# Test G.subgraph(nbunch), where nbunch is another graph
H = K5.subgraph(K3)
assert nx.is_isomorphic(H, K3)
H = K5.subgraph([9])
assert nx.is_isomorphic(H, nullgraph)
def test_node_tuple_issue(self):
H = self.G()
# Test error handling of tuple as a node
pytest.raises(nx.NetworkXError, H.remove_node, (1, 2))
H.remove_nodes_from([(1, 2)]) # no error
pytest.raises(nx.NetworkXError, H.neighbors, (1, 2))

View file

@ -0,0 +1,356 @@
import pytest
import pickle
import networkx as nx
class TestAtlasView:
# node->data
def setup(self):
self.d = {0: {"color": "blue", "weight": 1.2}, 1: {}, 2: {"color": 1}}
self.av = nx.classes.coreviews.AtlasView(self.d)
def test_pickle(self):
view = self.av
pview = pickle.loads(pickle.dumps(view, -1))
assert view == pview
assert view.__slots__ == pview.__slots__
pview = pickle.loads(pickle.dumps(view))
assert view == pview
assert view.__slots__ == pview.__slots__
def test_len(self):
assert len(self.av) == len(self.d)
def test_iter(self):
assert list(self.av) == list(self.d)
def test_getitem(self):
assert self.av[1] is self.d[1]
assert self.av[2]["color"] == 1
pytest.raises(KeyError, self.av.__getitem__, 3)
def test_copy(self):
avcopy = self.av.copy()
assert avcopy[0] == self.av[0]
assert avcopy == self.av
assert avcopy[0] is not self.av[0]
assert avcopy is not self.av
avcopy[5] = {}
assert avcopy != self.av
avcopy[0]["ht"] = 4
assert avcopy[0] != self.av[0]
self.av[0]["ht"] = 4
assert avcopy[0] == self.av[0]
del self.av[0]["ht"]
assert not hasattr(self.av, "__setitem__")
def test_items(self):
assert sorted(self.av.items()) == sorted(self.d.items())
def test_str(self):
out = str(self.d)
assert str(self.av) == out
def test_repr(self):
out = "AtlasView(" + str(self.d) + ")"
assert repr(self.av) == out
class TestAdjacencyView:
# node->nbr->data
def setup(self):
dd = {"color": "blue", "weight": 1.2}
self.nd = {0: dd, 1: {}, 2: {"color": 1}}
self.adj = {3: self.nd, 0: {3: dd}, 1: {}, 2: {3: {"color": 1}}}
self.adjview = nx.classes.coreviews.AdjacencyView(self.adj)
def test_pickle(self):
view = self.adjview
pview = pickle.loads(pickle.dumps(view, -1))
assert view == pview
assert view.__slots__ == pview.__slots__
def test_len(self):
assert len(self.adjview) == len(self.adj)
def test_iter(self):
assert list(self.adjview) == list(self.adj)
def test_getitem(self):
assert self.adjview[1] is not self.adj[1]
assert self.adjview[3][0] is self.adjview[0][3]
assert self.adjview[2][3]["color"] == 1
pytest.raises(KeyError, self.adjview.__getitem__, 4)
def test_copy(self):
avcopy = self.adjview.copy()
assert avcopy[0] == self.adjview[0]
assert avcopy[0] is not self.adjview[0]
avcopy[2][3]["ht"] = 4
assert avcopy[2] != self.adjview[2]
self.adjview[2][3]["ht"] = 4
assert avcopy[2] == self.adjview[2]
del self.adjview[2][3]["ht"]
assert not hasattr(self.adjview, "__setitem__")
def test_items(self):
view_items = sorted((n, dict(d)) for n, d in self.adjview.items())
assert view_items == sorted(self.adj.items())
def test_str(self):
out = str(dict(self.adj))
assert str(self.adjview) == out
def test_repr(self):
out = self.adjview.__class__.__name__ + "(" + str(self.adj) + ")"
assert repr(self.adjview) == out
class TestMultiAdjacencyView(TestAdjacencyView):
# node->nbr->key->data
def setup(self):
dd = {"color": "blue", "weight": 1.2}
self.kd = {0: dd, 1: {}, 2: {"color": 1}}
self.nd = {3: self.kd, 0: {3: dd}, 1: {0: {}}, 2: {3: {"color": 1}}}
self.adj = {3: self.nd, 0: {3: {3: dd}}, 1: {}, 2: {3: {8: {}}}}
self.adjview = nx.classes.coreviews.MultiAdjacencyView(self.adj)
def test_getitem(self):
assert self.adjview[1] is not self.adj[1]
assert self.adjview[3][0][3] is self.adjview[0][3][3]
assert self.adjview[3][2][3]["color"] == 1
pytest.raises(KeyError, self.adjview.__getitem__, 4)
def test_copy(self):
avcopy = self.adjview.copy()
assert avcopy[0] == self.adjview[0]
assert avcopy[0] is not self.adjview[0]
avcopy[2][3][8]["ht"] = 4
assert avcopy[2] != self.adjview[2]
self.adjview[2][3][8]["ht"] = 4
assert avcopy[2] == self.adjview[2]
del self.adjview[2][3][8]["ht"]
assert not hasattr(self.adjview, "__setitem__")
class TestUnionAtlas:
# node->data
def setup(self):
self.s = {0: {"color": "blue", "weight": 1.2}, 1: {}, 2: {"color": 1}}
self.p = {3: {"color": "blue", "weight": 1.2}, 4: {}, 2: {"watch": 2}}
self.av = nx.classes.coreviews.UnionAtlas(self.s, self.p)
def test_pickle(self):
view = self.av
pview = pickle.loads(pickle.dumps(view, -1))
assert view == pview
assert view.__slots__ == pview.__slots__
def test_len(self):
assert len(self.av) == len(self.s) + len(self.p)
def test_iter(self):
assert set(self.av) == set(self.s) | set(self.p)
def test_getitem(self):
assert self.av[0] is self.s[0]
assert self.av[4] is self.p[4]
assert self.av[2]["color"] == 1
pytest.raises(KeyError, self.av[2].__getitem__, "watch")
pytest.raises(KeyError, self.av.__getitem__, 8)
def test_copy(self):
avcopy = self.av.copy()
assert avcopy[0] == self.av[0]
assert avcopy[0] is not self.av[0]
assert avcopy is not self.av
avcopy[5] = {}
assert avcopy != self.av
avcopy[0]["ht"] = 4
assert avcopy[0] != self.av[0]
self.av[0]["ht"] = 4
assert avcopy[0] == self.av[0]
del self.av[0]["ht"]
assert not hasattr(self.av, "__setitem__")
def test_items(self):
expected = dict(self.p.items())
expected.update(self.s)
assert sorted(self.av.items()) == sorted(expected.items())
def test_str(self):
out = str(dict(self.av))
assert str(self.av) == out
def test_repr(self):
out = f"{self.av.__class__.__name__}({self.s}, {self.p})"
assert repr(self.av) == out
class TestUnionAdjacency:
# node->nbr->data
def setup(self):
dd = {"color": "blue", "weight": 1.2}
self.nd = {0: dd, 1: {}, 2: {"color": 1}}
self.s = {3: self.nd, 0: {}, 1: {}, 2: {3: {"color": 1}}}
self.p = {3: {}, 0: {3: dd}, 1: {0: {}}, 2: {1: {"color": 1}}}
self.adjview = nx.classes.coreviews.UnionAdjacency(self.s, self.p)
def test_pickle(self):
view = self.adjview
pview = pickle.loads(pickle.dumps(view, -1))
assert view == pview
assert view.__slots__ == pview.__slots__
def test_len(self):
assert len(self.adjview) == len(self.s)
def test_iter(self):
assert sorted(self.adjview) == sorted(self.s)
def test_getitem(self):
assert self.adjview[1] is not self.s[1]
assert self.adjview[3][0] is self.adjview[0][3]
assert self.adjview[2][3]["color"] == 1
pytest.raises(KeyError, self.adjview.__getitem__, 4)
def test_copy(self):
avcopy = self.adjview.copy()
assert avcopy[0] == self.adjview[0]
assert avcopy[0] is not self.adjview[0]
avcopy[2][3]["ht"] = 4
assert avcopy[2] != self.adjview[2]
self.adjview[2][3]["ht"] = 4
assert avcopy[2] == self.adjview[2]
del self.adjview[2][3]["ht"]
assert not hasattr(self.adjview, "__setitem__")
def test_str(self):
out = str(dict(self.adjview))
assert str(self.adjview) == out
def test_repr(self):
clsname = self.adjview.__class__.__name__
out = f"{clsname}({self.s}, {self.p})"
assert repr(self.adjview) == out
class TestUnionMultiInner(TestUnionAdjacency):
# nbr->key->data
def setup(self):
dd = {"color": "blue", "weight": 1.2}
self.kd = {7: {}, "ekey": {}, 9: {"color": 1}}
self.s = {3: self.kd, 0: {7: dd}, 1: {}, 2: {"key": {"color": 1}}}
self.p = {3: {}, 0: {3: dd}, 1: {}, 2: {1: {"span": 2}}}
self.adjview = nx.classes.coreviews.UnionMultiInner(self.s, self.p)
def test_len(self):
assert len(self.adjview) == len(self.s) + len(self.p)
def test_getitem(self):
assert self.adjview[1] is not self.s[1]
assert self.adjview[0][7] is self.adjview[0][3]
assert self.adjview[2]["key"]["color"] == 1
assert self.adjview[2][1]["span"] == 2
pytest.raises(KeyError, self.adjview.__getitem__, 4)
pytest.raises(KeyError, self.adjview[1].__getitem__, "key")
def test_copy(self):
avcopy = self.adjview.copy()
assert avcopy[0] == self.adjview[0]
assert avcopy[0] is not self.adjview[0]
avcopy[2][1]["width"] = 8
assert avcopy[2] != self.adjview[2]
self.adjview[2][1]["width"] = 8
assert avcopy[2] == self.adjview[2]
del self.adjview[2][1]["width"]
assert not hasattr(self.adjview, "__setitem__")
assert hasattr(avcopy, "__setitem__")
class TestUnionMultiAdjacency(TestUnionAdjacency):
# node->nbr->key->data
def setup(self):
dd = {"color": "blue", "weight": 1.2}
self.kd = {7: {}, 8: {}, 9: {"color": 1}}
self.nd = {3: self.kd, 0: {9: dd}, 1: {8: {}}, 2: {9: {"color": 1}}}
self.s = {3: self.nd, 0: {3: {7: dd}}, 1: {}, 2: {3: {8: {}}}}
self.p = {3: {}, 0: {3: {9: dd}}, 1: {}, 2: {1: {8: {}}}}
self.adjview = nx.classes.coreviews.UnionMultiAdjacency(self.s, self.p)
def test_getitem(self):
assert self.adjview[1] is not self.s[1]
assert self.adjview[3][0][9] is self.adjview[0][3][9]
assert self.adjview[3][2][9]["color"] == 1
pytest.raises(KeyError, self.adjview.__getitem__, 4)
def test_copy(self):
avcopy = self.adjview.copy()
assert avcopy[0] == self.adjview[0]
assert avcopy[0] is not self.adjview[0]
avcopy[2][3][8]["ht"] = 4
assert avcopy[2] != self.adjview[2]
self.adjview[2][3][8]["ht"] = 4
assert avcopy[2] == self.adjview[2]
del self.adjview[2][3][8]["ht"]
assert not hasattr(self.adjview, "__setitem__")
assert hasattr(avcopy, "__setitem__")
class TestFilteredGraphs:
def setup(self):
self.Graphs = [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
self.SubGraphs = [nx.graphviews.subgraph_view] * 4
def test_hide_show_nodes(self):
for Graph, SubGraph in zip(self.Graphs, self.SubGraphs):
G = nx.path_graph(4, Graph)
SG = G.subgraph([2, 3])
RG = SubGraph(G, nx.filters.hide_nodes([0, 1]))
assert SG.nodes == RG.nodes
assert SG.edges == RG.edges
SGC = SG.copy()
RGC = RG.copy()
assert SGC.nodes == RGC.nodes
assert SGC.edges == RGC.edges
def test_str_repr(self):
for Graph, SubGraph in zip(self.Graphs, self.SubGraphs):
G = nx.path_graph(4, Graph)
SG = G.subgraph([2, 3])
RG = SubGraph(G, nx.filters.hide_nodes([0, 1]))
str(SG.adj)
str(RG.adj)
repr(SG.adj)
repr(RG.adj)
str(SG.adj[2])
str(RG.adj[2])
repr(SG.adj[2])
repr(RG.adj[2])
def test_copy(self):
for Graph, SubGraph in zip(self.Graphs, self.SubGraphs):
G = nx.path_graph(4, Graph)
SG = G.subgraph([2, 3])
RG = SubGraph(G, nx.filters.hide_nodes([0, 1]))
assert G.adj.copy() == G.adj
assert G.adj[2].copy() == G.adj[2]
assert SG.adj.copy() == SG.adj
assert SG.adj[2].copy() == SG.adj[2]
assert RG.adj.copy() == RG.adj
assert RG.adj[2].copy() == RG.adj[2]

View file

@ -0,0 +1,301 @@
import pytest
import networkx as nx
from networkx.testing import assert_nodes_equal
from .test_graph import BaseGraphTester, BaseAttrGraphTester
from .test_graph import TestGraph as _TestGraph
from .test_graph import TestEdgeSubgraph as _TestGraphEdgeSubgraph
class BaseDiGraphTester(BaseGraphTester):
def test_has_successor(self):
G = self.K3
assert G.has_successor(0, 1)
assert not G.has_successor(0, -1)
def test_successors(self):
G = self.K3
assert sorted(G.successors(0)) == [1, 2]
with pytest.raises(nx.NetworkXError):
G.successors(-1)
def test_has_predecessor(self):
G = self.K3
assert G.has_predecessor(0, 1)
assert not G.has_predecessor(0, -1)
def test_predecessors(self):
G = self.K3
assert sorted(G.predecessors(0)) == [1, 2]
with pytest.raises(nx.NetworkXError):
G.predecessors(-1)
def test_edges(self):
G = self.K3
assert sorted(G.edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.edges(0)) == [(0, 1), (0, 2)]
assert sorted(G.edges([0, 1])) == [(0, 1), (0, 2), (1, 0), (1, 2)]
with pytest.raises(nx.NetworkXError):
G.edges(-1)
def test_out_edges(self):
G = self.K3
assert sorted(G.out_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.out_edges(0)) == [(0, 1), (0, 2)]
with pytest.raises(nx.NetworkXError):
G.out_edges(-1)
def test_out_edges_dir(self):
G = self.P3
assert sorted(G.out_edges()) == [(0, 1), (1, 2)]
assert sorted(G.out_edges(0)) == [(0, 1)]
assert sorted(G.out_edges(2)) == []
def test_out_edges_data(self):
G = nx.DiGraph([(0, 1, {"data": 0}), (1, 0, {})])
assert sorted(G.out_edges(data=True)) == [(0, 1, {"data": 0}), (1, 0, {})]
assert sorted(G.out_edges(0, data=True)) == [(0, 1, {"data": 0})]
assert sorted(G.out_edges(data="data")) == [(0, 1, 0), (1, 0, None)]
assert sorted(G.out_edges(0, data="data")) == [(0, 1, 0)]
def test_in_edges_dir(self):
G = self.P3
assert sorted(G.in_edges()) == [(0, 1), (1, 2)]
assert sorted(G.in_edges(0)) == []
assert sorted(G.in_edges(2)) == [(1, 2)]
def test_in_edges_data(self):
G = nx.DiGraph([(0, 1, {"data": 0}), (1, 0, {})])
assert sorted(G.in_edges(data=True)) == [(0, 1, {"data": 0}), (1, 0, {})]
assert sorted(G.in_edges(1, data=True)) == [(0, 1, {"data": 0})]
assert sorted(G.in_edges(data="data")) == [(0, 1, 0), (1, 0, None)]
assert sorted(G.in_edges(1, data="data")) == [(0, 1, 0)]
def test_degree(self):
G = self.K3
assert sorted(G.degree()) == [(0, 4), (1, 4), (2, 4)]
assert dict(G.degree()) == {0: 4, 1: 4, 2: 4}
assert G.degree(0) == 4
assert list(G.degree(iter([0]))) == [(0, 4)] # run through iterator
def test_in_degree(self):
G = self.K3
assert sorted(G.in_degree()) == [(0, 2), (1, 2), (2, 2)]
assert dict(G.in_degree()) == {0: 2, 1: 2, 2: 2}
assert G.in_degree(0) == 2
assert list(G.in_degree(iter([0]))) == [(0, 2)] # run through iterator
def test_out_degree(self):
G = self.K3
assert sorted(G.out_degree()) == [(0, 2), (1, 2), (2, 2)]
assert dict(G.out_degree()) == {0: 2, 1: 2, 2: 2}
assert G.out_degree(0) == 2
assert list(G.out_degree(iter([0]))) == [(0, 2)]
def test_size(self):
G = self.K3
assert G.size() == 6
assert G.number_of_edges() == 6
def test_to_undirected_reciprocal(self):
G = self.Graph()
G.add_edge(1, 2)
assert G.to_undirected().has_edge(1, 2)
assert not G.to_undirected(reciprocal=True).has_edge(1, 2)
G.add_edge(2, 1)
assert G.to_undirected(reciprocal=True).has_edge(1, 2)
def test_reverse_copy(self):
G = nx.DiGraph([(0, 1), (1, 2)])
R = G.reverse()
assert sorted(R.edges()) == [(1, 0), (2, 1)]
R.remove_edge(1, 0)
assert sorted(R.edges()) == [(2, 1)]
assert sorted(G.edges()) == [(0, 1), (1, 2)]
def test_reverse_nocopy(self):
G = nx.DiGraph([(0, 1), (1, 2)])
R = G.reverse(copy=False)
assert sorted(R.edges()) == [(1, 0), (2, 1)]
with pytest.raises(nx.NetworkXError):
R.remove_edge(1, 0)
def test_reverse_hashable(self):
class Foo:
pass
x = Foo()
y = Foo()
G = nx.DiGraph()
G.add_edge(x, y)
assert_nodes_equal(G.nodes(), G.reverse().nodes())
assert [(y, x)] == list(G.reverse().edges())
class BaseAttrDiGraphTester(BaseDiGraphTester, BaseAttrGraphTester):
def test_edges_data(self):
G = self.K3
all_edges = [
(0, 1, {}),
(0, 2, {}),
(1, 0, {}),
(1, 2, {}),
(2, 0, {}),
(2, 1, {}),
]
assert sorted(G.edges(data=True)) == all_edges
assert sorted(G.edges(0, data=True)) == all_edges[:2]
assert sorted(G.edges([0, 1], data=True)) == all_edges[:4]
with pytest.raises(nx.NetworkXError):
G.edges(-1, True)
def test_in_degree_weighted(self):
G = self.K3.copy()
G.add_edge(0, 1, weight=0.3, other=1.2)
assert sorted(G.in_degree(weight="weight")) == [(0, 2), (1, 1.3), (2, 2)]
assert dict(G.in_degree(weight="weight")) == {0: 2, 1: 1.3, 2: 2}
assert G.in_degree(1, weight="weight") == 1.3
assert sorted(G.in_degree(weight="other")) == [(0, 2), (1, 2.2), (2, 2)]
assert dict(G.in_degree(weight="other")) == {0: 2, 1: 2.2, 2: 2}
assert G.in_degree(1, weight="other") == 2.2
assert list(G.in_degree(iter([1]), weight="other")) == [(1, 2.2)]
def test_out_degree_weighted(self):
G = self.K3.copy()
G.add_edge(0, 1, weight=0.3, other=1.2)
assert sorted(G.out_degree(weight="weight")) == [(0, 1.3), (1, 2), (2, 2)]
assert dict(G.out_degree(weight="weight")) == {0: 1.3, 1: 2, 2: 2}
assert G.out_degree(0, weight="weight") == 1.3
assert sorted(G.out_degree(weight="other")) == [(0, 2.2), (1, 2), (2, 2)]
assert dict(G.out_degree(weight="other")) == {0: 2.2, 1: 2, 2: 2}
assert G.out_degree(0, weight="other") == 2.2
assert list(G.out_degree(iter([0]), weight="other")) == [(0, 2.2)]
class TestDiGraph(BaseAttrDiGraphTester, _TestGraph):
"""Tests specific to dict-of-dict-of-dict digraph data structure"""
def setup_method(self):
self.Graph = nx.DiGraph
# build dict-of-dict-of-dict K3
ed1, ed2, ed3, ed4, ed5, ed6 = ({}, {}, {}, {}, {}, {})
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed3, 2: ed4}, 2: {0: ed5, 1: ed6}}
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = self.K3._succ = self.k3adj
self.K3._pred = {0: {1: ed3, 2: ed5}, 1: {0: ed1, 2: ed6}, 2: {0: ed2, 1: ed4}}
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
ed1, ed2 = ({}, {})
self.P3 = self.Graph()
self.P3._adj = {0: {1: ed1}, 1: {2: ed2}, 2: {}}
self.P3._succ = self.P3._adj
self.P3._pred = {0: {}, 1: {0: ed1}, 2: {1: ed2}}
self.P3._node = {}
self.P3._node[0] = {}
self.P3._node[1] = {}
self.P3._node[2] = {}
def test_data_input(self):
G = self.Graph({1: [2], 2: [1]}, name="test")
assert G.name == "test"
assert sorted(G.adj.items()) == [(1, {2: {}}), (2, {1: {}})]
assert sorted(G.succ.items()) == [(1, {2: {}}), (2, {1: {}})]
assert sorted(G.pred.items()) == [(1, {2: {}}), (2, {1: {}})]
def test_add_edge(self):
G = self.Graph()
G.add_edge(0, 1)
assert G.adj == {0: {1: {}}, 1: {}}
assert G.succ == {0: {1: {}}, 1: {}}
assert G.pred == {0: {}, 1: {0: {}}}
G = self.Graph()
G.add_edge(*(0, 1))
assert G.adj == {0: {1: {}}, 1: {}}
assert G.succ == {0: {1: {}}, 1: {}}
assert G.pred == {0: {}, 1: {0: {}}}
def test_add_edges_from(self):
G = self.Graph()
G.add_edges_from([(0, 1), (0, 2, {"data": 3})], data=2)
assert G.adj == {0: {1: {"data": 2}, 2: {"data": 3}}, 1: {}, 2: {}}
assert G.succ == {0: {1: {"data": 2}, 2: {"data": 3}}, 1: {}, 2: {}}
assert G.pred == {0: {}, 1: {0: {"data": 2}}, 2: {0: {"data": 3}}}
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0,)]) # too few in tuple
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0, 1, 2, 3)]) # too many in tuple
with pytest.raises(TypeError):
G.add_edges_from([0]) # not a tuple
def test_remove_edge(self):
G = self.K3.copy()
G.remove_edge(0, 1)
assert G.succ == {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}}
assert G.pred == {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
with pytest.raises(nx.NetworkXError):
G.remove_edge(-1, 0)
def test_remove_edges_from(self):
G = self.K3.copy()
G.remove_edges_from([(0, 1)])
assert G.succ == {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}}
assert G.pred == {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
G.remove_edges_from([(0, 0)]) # silent fail
def test_clear(self):
G = self.K3
G.graph["name"] = "K3"
G.clear()
assert list(G.nodes) == []
assert G.succ == {}
assert G.pred == {}
assert G.graph == {}
def test_clear_edges(self):
G = self.K3
G.graph["name"] = "K3"
nodes = list(G.nodes)
G.clear_edges()
assert list(G.nodes) == nodes
expected = {0: {}, 1: {}, 2: {}}
assert G.succ == expected
assert G.pred == expected
assert list(G.edges) == []
assert G.graph["name"] == "K3"
class TestEdgeSubgraph(_TestGraphEdgeSubgraph):
"""Unit tests for the :meth:`DiGraph.edge_subgraph` method."""
def setup_method(self):
# Create a doubly-linked path graph on five nodes.
G = nx.DiGraph(nx.path_graph(5))
# Add some node, edge, and graph attributes.
for i in range(5):
G.nodes[i]["name"] = f"node{i}"
G.edges[0, 1]["name"] = "edge01"
G.edges[3, 4]["name"] = "edge34"
G.graph["name"] = "graph"
# Get the subgraph induced by the first and last edges.
self.G = G
self.H = G.edge_subgraph([(0, 1), (3, 4)])
def test_pred_succ(self):
"""Test that nodes are added to predecessors and successors.
For more information, see GitHub issue #2370.
"""
G = nx.DiGraph()
G.add_edge(0, 1)
H = G.edge_subgraph([(0, 1)])
assert list(H.predecessors(0)) == []
assert list(H.successors(0)) == [1]
assert list(H.predecessors(1)) == [0]
assert list(H.successors(1)) == []

View file

@ -0,0 +1,109 @@
"""Original NetworkX graph tests"""
import pytest
import networkx
import networkx as nx
from .historical_tests import HistoricalTests
class TestDiGraphHistorical(HistoricalTests):
@classmethod
def setup_class(cls):
HistoricalTests.setup_class()
cls.G = nx.DiGraph
def test_in_degree(self):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
assert sorted(d for n, d in G.in_degree()) == [0, 0, 0, 0, 1, 2, 2]
assert dict(G.in_degree()) == {
"A": 0,
"C": 2,
"B": 1,
"D": 2,
"G": 0,
"K": 0,
"J": 0,
}
def test_out_degree(self):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
assert sorted([v for k, v in G.in_degree()]) == [0, 0, 0, 0, 1, 2, 2]
assert dict(G.out_degree()) == {
"A": 2,
"C": 1,
"B": 2,
"D": 0,
"G": 0,
"K": 0,
"J": 0,
}
def test_degree_digraph(self):
H = nx.DiGraph()
H.add_edges_from([(1, 24), (1, 2)])
assert sorted(d for n, d in H.in_degree([1, 24])) == [0, 1]
assert sorted(d for n, d in H.out_degree([1, 24])) == [0, 2]
assert sorted(d for n, d in H.degree([1, 24])) == [1, 2]
def test_neighbors(self):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
assert sorted(G.neighbors("C")) == ["D"]
assert sorted(G["C"]) == ["D"]
assert sorted(G.neighbors("A")) == ["B", "C"]
pytest.raises(nx.NetworkXError, G.neighbors, "j")
pytest.raises(nx.NetworkXError, G.neighbors, "j")
def test_successors(self):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
assert sorted(G.successors("A")) == ["B", "C"]
assert sorted(G.successors("A")) == ["B", "C"]
assert sorted(G.successors("G")) == []
assert sorted(G.successors("D")) == []
assert sorted(G.successors("G")) == []
pytest.raises(nx.NetworkXError, G.successors, "j")
pytest.raises(nx.NetworkXError, G.successors, "j")
def test_predecessors(self):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
assert sorted(G.predecessors("C")) == ["A", "B"]
assert sorted(G.predecessors("C")) == ["A", "B"]
assert sorted(G.predecessors("G")) == []
assert sorted(G.predecessors("A")) == []
assert sorted(G.predecessors("G")) == []
assert sorted(G.predecessors("A")) == []
assert sorted(G.successors("D")) == []
pytest.raises(nx.NetworkXError, G.predecessors, "j")
pytest.raises(nx.NetworkXError, G.predecessors, "j")
def test_reverse(self):
G = nx.complete_graph(10)
H = G.to_directed()
HR = H.reverse()
assert nx.is_isomorphic(H, HR)
assert sorted(H.edges()) == sorted(HR.edges())
def test_reverse2(self):
H = nx.DiGraph()
foo = [H.add_edge(u, u + 1) for u in range(0, 5)]
HR = H.reverse()
for u in range(0, 5):
assert HR.has_edge(u + 1, u)
def test_reverse3(self):
H = nx.DiGraph()
H.add_nodes_from([1, 2, 3, 4])
HR = H.reverse()
assert sorted(HR.nodes()) == [1, 2, 3, 4]

View file

@ -0,0 +1,176 @@
import pytest
import networkx as nx
class TestFilterFactory:
def test_no_filter(self):
nf = nx.filters.no_filter
assert nf()
assert nf(1)
assert nf(2, 1)
def test_hide_nodes(self):
f = nx.classes.filters.hide_nodes([1, 2, 3])
assert not f(1)
assert not f(2)
assert not f(3)
assert f(4)
assert f(0)
assert f("a")
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f)
def test_show_nodes(self):
f = nx.classes.filters.show_nodes([1, 2, 3])
assert f(1)
assert f(2)
assert f(3)
assert not f(4)
assert not f(0)
assert not f("a")
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f)
def test_hide_edges(self):
factory = nx.classes.filters.hide_edges
f = factory([(1, 2), (3, 4)])
assert not f(1, 2)
assert not f(3, 4)
assert not f(4, 3)
assert f(2, 3)
assert f(0, -1)
assert f("a", "b")
pytest.raises(TypeError, f, 1, 2, 3)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2, 3)])
def test_show_edges(self):
factory = nx.classes.filters.show_edges
f = factory([(1, 2), (3, 4)])
assert f(1, 2)
assert f(3, 4)
assert f(4, 3)
assert not f(2, 3)
assert not f(0, -1)
assert not f("a", "b")
pytest.raises(TypeError, f, 1, 2, 3)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2, 3)])
def test_hide_diedges(self):
factory = nx.classes.filters.hide_diedges
f = factory([(1, 2), (3, 4)])
assert not f(1, 2)
assert not f(3, 4)
assert f(4, 3)
assert f(2, 3)
assert f(0, -1)
assert f("a", "b")
pytest.raises(TypeError, f, 1, 2, 3)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2, 3)])
def test_show_diedges(self):
factory = nx.classes.filters.show_diedges
f = factory([(1, 2), (3, 4)])
assert f(1, 2)
assert f(3, 4)
assert not f(4, 3)
assert not f(2, 3)
assert not f(0, -1)
assert not f("a", "b")
pytest.raises(TypeError, f, 1, 2, 3)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2, 3)])
def test_hide_multiedges(self):
factory = nx.classes.filters.hide_multiedges
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
assert not f(1, 2, 0)
assert not f(1, 2, 1)
assert f(1, 2, 2)
assert f(3, 4, 0)
assert not f(3, 4, 1)
assert not f(4, 3, 1)
assert f(4, 3, 0)
assert f(2, 3, 0)
assert f(0, -1, 0)
assert f("a", "b", 0)
pytest.raises(TypeError, f, 1, 2, 3, 4)
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2)])
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
def test_show_multiedges(self):
factory = nx.classes.filters.show_multiedges
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
assert f(1, 2, 0)
assert f(1, 2, 1)
assert not f(1, 2, 2)
assert not f(3, 4, 0)
assert f(3, 4, 1)
assert f(4, 3, 1)
assert not f(4, 3, 0)
assert not f(2, 3, 0)
assert not f(0, -1, 0)
assert not f("a", "b", 0)
pytest.raises(TypeError, f, 1, 2, 3, 4)
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2)])
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
def test_hide_multidiedges(self):
factory = nx.classes.filters.hide_multidiedges
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
assert not f(1, 2, 0)
assert not f(1, 2, 1)
assert f(1, 2, 2)
assert f(3, 4, 0)
assert not f(3, 4, 1)
assert f(4, 3, 1)
assert f(4, 3, 0)
assert f(2, 3, 0)
assert f(0, -1, 0)
assert f("a", "b", 0)
pytest.raises(TypeError, f, 1, 2, 3, 4)
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2)])
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
def test_show_multidiedges(self):
factory = nx.classes.filters.show_multidiedges
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
assert f(1, 2, 0)
assert f(1, 2, 1)
assert not f(1, 2, 2)
assert not f(3, 4, 0)
assert f(3, 4, 1)
assert not f(4, 3, 1)
assert not f(4, 3, 0)
assert not f(2, 3, 0)
assert not f(0, -1, 0)
assert not f("a", "b", 0)
pytest.raises(TypeError, f, 1, 2, 3, 4)
pytest.raises(TypeError, f, 1, 2)
pytest.raises(TypeError, f, 1)
pytest.raises(TypeError, f)
pytest.raises(TypeError, factory, [1, 2, 3])
pytest.raises(ValueError, factory, [(1, 2)])
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])

View file

@ -0,0 +1,718 @@
import random
import pytest
import networkx as nx
from networkx.testing.utils import assert_edges_equal, assert_nodes_equal
class TestFunction:
def setup_method(self):
self.G = nx.Graph({0: [1, 2, 3], 1: [1, 2, 0], 4: []}, name="Test")
self.Gdegree = {0: 3, 1: 2, 2: 2, 3: 1, 4: 0}
self.Gnodes = list(range(5))
self.Gedges = [(0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2)]
self.DG = nx.DiGraph({0: [1, 2, 3], 1: [1, 2, 0], 4: []})
self.DGin_degree = {0: 1, 1: 2, 2: 2, 3: 1, 4: 0}
self.DGout_degree = {0: 3, 1: 3, 2: 0, 3: 0, 4: 0}
self.DGnodes = list(range(5))
self.DGedges = [(0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2)]
def test_nodes(self):
assert_nodes_equal(self.G.nodes(), list(nx.nodes(self.G)))
assert_nodes_equal(self.DG.nodes(), list(nx.nodes(self.DG)))
def test_edges(self):
assert_edges_equal(self.G.edges(), list(nx.edges(self.G)))
assert sorted(self.DG.edges()) == sorted(nx.edges(self.DG))
assert_edges_equal(
self.G.edges(nbunch=[0, 1, 3]), list(nx.edges(self.G, nbunch=[0, 1, 3]))
)
assert sorted(self.DG.edges(nbunch=[0, 1, 3])) == sorted(
nx.edges(self.DG, nbunch=[0, 1, 3])
)
def test_degree(self):
assert_edges_equal(self.G.degree(), list(nx.degree(self.G)))
assert sorted(self.DG.degree()) == sorted(nx.degree(self.DG))
assert_edges_equal(
self.G.degree(nbunch=[0, 1]), list(nx.degree(self.G, nbunch=[0, 1]))
)
assert sorted(self.DG.degree(nbunch=[0, 1])) == sorted(
nx.degree(self.DG, nbunch=[0, 1])
)
assert_edges_equal(
self.G.degree(weight="weight"), list(nx.degree(self.G, weight="weight"))
)
assert sorted(self.DG.degree(weight="weight")) == sorted(
nx.degree(self.DG, weight="weight")
)
def test_neighbors(self):
assert list(self.G.neighbors(1)) == list(nx.neighbors(self.G, 1))
assert list(self.DG.neighbors(1)) == list(nx.neighbors(self.DG, 1))
def test_number_of_nodes(self):
assert self.G.number_of_nodes() == nx.number_of_nodes(self.G)
assert self.DG.number_of_nodes() == nx.number_of_nodes(self.DG)
def test_number_of_edges(self):
assert self.G.number_of_edges() == nx.number_of_edges(self.G)
assert self.DG.number_of_edges() == nx.number_of_edges(self.DG)
def test_is_directed(self):
assert self.G.is_directed() == nx.is_directed(self.G)
assert self.DG.is_directed() == nx.is_directed(self.DG)
def test_add_star(self):
G = self.G.copy()
nlist = [12, 13, 14, 15]
nx.add_star(G, nlist)
assert_edges_equal(G.edges(nlist), [(12, 13), (12, 14), (12, 15)])
G = self.G.copy()
nx.add_star(G, nlist, weight=2.0)
assert_edges_equal(
G.edges(nlist, data=True),
[
(12, 13, {"weight": 2.0}),
(12, 14, {"weight": 2.0}),
(12, 15, {"weight": 2.0}),
],
)
G = self.G.copy()
nlist = [12]
nx.add_star(G, nlist)
assert_nodes_equal(G, list(self.G) + nlist)
G = self.G.copy()
nlist = []
nx.add_star(G, nlist)
assert_nodes_equal(G.nodes, self.Gnodes)
assert_edges_equal(G.edges, self.G.edges)
def test_add_path(self):
G = self.G.copy()
nlist = [12, 13, 14, 15]
nx.add_path(G, nlist)
assert_edges_equal(G.edges(nlist), [(12, 13), (13, 14), (14, 15)])
G = self.G.copy()
nx.add_path(G, nlist, weight=2.0)
assert_edges_equal(
G.edges(nlist, data=True),
[
(12, 13, {"weight": 2.0}),
(13, 14, {"weight": 2.0}),
(14, 15, {"weight": 2.0}),
],
)
G = self.G.copy()
nlist = [None]
nx.add_path(G, nlist)
assert_edges_equal(G.edges(nlist), [])
assert_nodes_equal(G, list(self.G) + [None])
G = self.G.copy()
nlist = iter([None])
nx.add_path(G, nlist)
assert_edges_equal(G.edges([None]), [])
assert_nodes_equal(G, list(self.G) + [None])
G = self.G.copy()
nlist = [12]
nx.add_path(G, nlist)
assert_edges_equal(G.edges(nlist), [])
assert_nodes_equal(G, list(self.G) + [12])
G = self.G.copy()
nlist = iter([12])
nx.add_path(G, nlist)
assert_edges_equal(G.edges([12]), [])
assert_nodes_equal(G, list(self.G) + [12])
G = self.G.copy()
nlist = []
nx.add_path(G, nlist)
assert_edges_equal(G.edges, self.G.edges)
assert_nodes_equal(G, list(self.G))
G = self.G.copy()
nlist = iter([])
nx.add_path(G, nlist)
assert_edges_equal(G.edges, self.G.edges)
assert_nodes_equal(G, list(self.G))
def test_add_cycle(self):
G = self.G.copy()
nlist = [12, 13, 14, 15]
oklists = [
[(12, 13), (12, 15), (13, 14), (14, 15)],
[(12, 13), (13, 14), (14, 15), (15, 12)],
]
nx.add_cycle(G, nlist)
assert sorted(G.edges(nlist)) in oklists
G = self.G.copy()
oklists = [
[
(12, 13, {"weight": 1.0}),
(12, 15, {"weight": 1.0}),
(13, 14, {"weight": 1.0}),
(14, 15, {"weight": 1.0}),
],
[
(12, 13, {"weight": 1.0}),
(13, 14, {"weight": 1.0}),
(14, 15, {"weight": 1.0}),
(15, 12, {"weight": 1.0}),
],
]
nx.add_cycle(G, nlist, weight=1.0)
assert sorted(G.edges(nlist, data=True)) in oklists
G = self.G.copy()
nlist = [12]
nx.add_cycle(G, nlist)
assert_nodes_equal(G, list(self.G) + nlist)
G = self.G.copy()
nlist = []
nx.add_cycle(G, nlist)
assert_nodes_equal(G.nodes, self.Gnodes)
assert_edges_equal(G.edges, self.G.edges)
def test_subgraph(self):
assert (
self.G.subgraph([0, 1, 2, 4]).adj == nx.subgraph(self.G, [0, 1, 2, 4]).adj
)
assert (
self.DG.subgraph([0, 1, 2, 4]).adj == nx.subgraph(self.DG, [0, 1, 2, 4]).adj
)
assert (
self.G.subgraph([0, 1, 2, 4]).adj
== nx.induced_subgraph(self.G, [0, 1, 2, 4]).adj
)
assert (
self.DG.subgraph([0, 1, 2, 4]).adj
== nx.induced_subgraph(self.DG, [0, 1, 2, 4]).adj
)
# subgraph-subgraph chain is allowed in function interface
H = nx.induced_subgraph(self.G.subgraph([0, 1, 2, 4]), [0, 1, 4])
assert H._graph is not self.G
assert H.adj == self.G.subgraph([0, 1, 4]).adj
def test_edge_subgraph(self):
assert (
self.G.edge_subgraph([(1, 2), (0, 3)]).adj
== nx.edge_subgraph(self.G, [(1, 2), (0, 3)]).adj
)
assert (
self.DG.edge_subgraph([(1, 2), (0, 3)]).adj
== nx.edge_subgraph(self.DG, [(1, 2), (0, 3)]).adj
)
def test_restricted_view(self):
H = nx.restricted_view(self.G, [0, 2, 5], [(1, 2), (3, 4)])
assert set(H.nodes) == {1, 3, 4}
assert set(H.edges) == {(1, 1)}
def test_create_empty_copy(self):
G = nx.create_empty_copy(self.G, with_data=False)
assert_nodes_equal(G, list(self.G))
assert G.graph == {}
assert G._node == {}.fromkeys(self.G.nodes(), {})
assert G._adj == {}.fromkeys(self.G.nodes(), {})
G = nx.create_empty_copy(self.G)
assert_nodes_equal(G, list(self.G))
assert G.graph == self.G.graph
assert G._node == self.G._node
assert G._adj == {}.fromkeys(self.G.nodes(), {})
def test_degree_histogram(self):
assert nx.degree_histogram(self.G) == [1, 1, 1, 1, 1]
def test_density(self):
assert nx.density(self.G) == 0.5
assert nx.density(self.DG) == 0.3
G = nx.Graph()
G.add_node(1)
assert nx.density(G) == 0.0
def test_density_selfloop(self):
G = nx.Graph()
G.add_edge(1, 1)
assert nx.density(G) == 0.0
G.add_edge(1, 2)
assert nx.density(G) == 2.0
def test_freeze(self):
G = nx.freeze(self.G)
assert G.frozen
pytest.raises(nx.NetworkXError, G.add_node, 1)
pytest.raises(nx.NetworkXError, G.add_nodes_from, [1])
pytest.raises(nx.NetworkXError, G.remove_node, 1)
pytest.raises(nx.NetworkXError, G.remove_nodes_from, [1])
pytest.raises(nx.NetworkXError, G.add_edge, 1, 2)
pytest.raises(nx.NetworkXError, G.add_edges_from, [(1, 2)])
pytest.raises(nx.NetworkXError, G.remove_edge, 1, 2)
pytest.raises(nx.NetworkXError, G.remove_edges_from, [(1, 2)])
pytest.raises(nx.NetworkXError, G.clear)
def test_is_frozen(self):
assert not nx.is_frozen(self.G)
G = nx.freeze(self.G)
assert G.frozen == nx.is_frozen(self.G)
assert G.frozen
def test_info(self):
G = nx.path_graph(5)
G.name = "path_graph(5)"
info = nx.info(G)
expected_graph_info = "\n".join(
[
"Name: path_graph(5)",
"Type: Graph",
"Number of nodes: 5",
"Number of edges: 4",
"Average degree: 1.6000",
]
)
assert info == expected_graph_info
info = nx.info(G, n=1)
assert type(info) == str
expected_node_info = "\n".join(
["Node 1 has the following properties:", "Degree: 2", "Neighbors: 0 2"]
)
assert info == expected_node_info
# must raise an error for a non-existent node
pytest.raises(nx.NetworkXError, nx.info, G, 1248)
def test_info_digraph(self):
G = nx.DiGraph(name="path_graph(5)")
nx.add_path(G, [0, 1, 2, 3, 4])
info = nx.info(G)
expected_graph_info = "\n".join(
[
"Name: path_graph(5)",
"Type: DiGraph",
"Number of nodes: 5",
"Number of edges: 4",
"Average in degree: 0.8000",
"Average out degree: 0.8000",
]
)
assert info == expected_graph_info
info = nx.info(G, n=1)
expected_node_info = "\n".join(
["Node 1 has the following properties:", "Degree: 2", "Neighbors: 2"]
)
assert info == expected_node_info
pytest.raises(nx.NetworkXError, nx.info, G, n=-1)
def test_neighbors_complete_graph(self):
graph = nx.complete_graph(100)
pop = random.sample(list(graph), 1)
nbors = list(nx.neighbors(graph, pop[0]))
# should be all the other vertices in the graph
assert len(nbors) == len(graph) - 1
graph = nx.path_graph(100)
node = random.sample(list(graph), 1)[0]
nbors = list(nx.neighbors(graph, node))
# should be all the other vertices in the graph
if node != 0 and node != 99:
assert len(nbors) == 2
else:
assert len(nbors) == 1
# create a star graph with 99 outer nodes
graph = nx.star_graph(99)
nbors = list(nx.neighbors(graph, 0))
assert len(nbors) == 99
def test_non_neighbors(self):
graph = nx.complete_graph(100)
pop = random.sample(list(graph), 1)
nbors = list(nx.non_neighbors(graph, pop[0]))
# should be all the other vertices in the graph
assert len(nbors) == 0
graph = nx.path_graph(100)
node = random.sample(list(graph), 1)[0]
nbors = list(nx.non_neighbors(graph, node))
# should be all the other vertices in the graph
if node != 0 and node != 99:
assert len(nbors) == 97
else:
assert len(nbors) == 98
# create a star graph with 99 outer nodes
graph = nx.star_graph(99)
nbors = list(nx.non_neighbors(graph, 0))
assert len(nbors) == 0
# disconnected graph
graph = nx.Graph()
graph.add_nodes_from(range(10))
nbors = list(nx.non_neighbors(graph, 0))
assert len(nbors) == 9
def test_non_edges(self):
# All possible edges exist
graph = nx.complete_graph(5)
nedges = list(nx.non_edges(graph))
assert len(nedges) == 0
graph = nx.path_graph(4)
expected = [(0, 2), (0, 3), (1, 3)]
nedges = list(nx.non_edges(graph))
for (u, v) in expected:
assert (u, v) in nedges or (v, u) in nedges
graph = nx.star_graph(4)
expected = [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
nedges = list(nx.non_edges(graph))
for (u, v) in expected:
assert (u, v) in nedges or (v, u) in nedges
# Directed graphs
graph = nx.DiGraph()
graph.add_edges_from([(0, 2), (2, 0), (2, 1)])
expected = [(0, 1), (1, 0), (1, 2)]
nedges = list(nx.non_edges(graph))
for e in expected:
assert e in nedges
def test_is_weighted(self):
G = nx.Graph()
assert not nx.is_weighted(G)
G = nx.path_graph(4)
assert not nx.is_weighted(G)
assert not nx.is_weighted(G, (2, 3))
G.add_node(4)
G.add_edge(3, 4, weight=4)
assert not nx.is_weighted(G)
assert nx.is_weighted(G, (3, 4))
G = nx.DiGraph()
G.add_weighted_edges_from(
[
("0", "3", 3),
("0", "1", -5),
("1", "0", -5),
("0", "2", 2),
("1", "2", 4),
("2", "3", 1),
]
)
assert nx.is_weighted(G)
assert nx.is_weighted(G, ("1", "0"))
G = G.to_undirected()
assert nx.is_weighted(G)
assert nx.is_weighted(G, ("1", "0"))
pytest.raises(nx.NetworkXError, nx.is_weighted, G, (1, 2))
def test_is_negatively_weighted(self):
G = nx.Graph()
assert not nx.is_negatively_weighted(G)
G.add_node(1)
G.add_nodes_from([2, 3, 4, 5])
assert not nx.is_negatively_weighted(G)
G.add_edge(1, 2, weight=4)
assert not nx.is_negatively_weighted(G, (1, 2))
G.add_edges_from([(1, 3), (2, 4), (2, 6)])
G[1][3]["color"] = "blue"
assert not nx.is_negatively_weighted(G)
assert not nx.is_negatively_weighted(G, (1, 3))
G[2][4]["weight"] = -2
assert nx.is_negatively_weighted(G, (2, 4))
assert nx.is_negatively_weighted(G)
G = nx.DiGraph()
G.add_weighted_edges_from(
[
("0", "3", 3),
("0", "1", -5),
("1", "0", -2),
("0", "2", 2),
("1", "2", -3),
("2", "3", 1),
]
)
assert nx.is_negatively_weighted(G)
assert not nx.is_negatively_weighted(G, ("0", "3"))
assert nx.is_negatively_weighted(G, ("1", "0"))
pytest.raises(nx.NetworkXError, nx.is_negatively_weighted, G, (1, 4))
class TestCommonNeighbors:
@classmethod
def setup_class(cls):
cls.func = staticmethod(nx.common_neighbors)
def test_func(G, u, v, expected):
result = sorted(cls.func(G, u, v))
assert result == expected
cls.test = staticmethod(test_func)
def test_K5(self):
G = nx.complete_graph(5)
self.test(G, 0, 1, [2, 3, 4])
def test_P3(self):
G = nx.path_graph(3)
self.test(G, 0, 2, [1])
def test_S4(self):
G = nx.star_graph(4)
self.test(G, 1, 2, [0])
def test_digraph(self):
with pytest.raises(nx.NetworkXNotImplemented):
G = nx.DiGraph()
G.add_edges_from([(0, 1), (1, 2)])
self.func(G, 0, 2)
def test_nonexistent_nodes(self):
G = nx.complete_graph(5)
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 5, 4)
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 4, 5)
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 5, 6)
def test_custom1(self):
"""Case of no common neighbors."""
G = nx.Graph()
G.add_nodes_from([0, 1])
self.test(G, 0, 1, [])
def test_custom2(self):
"""Case of equal nodes."""
G = nx.complete_graph(4)
self.test(G, 0, 0, [1, 2, 3])
def test_set_node_attributes():
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
for G in graphs:
# Test single value
G = nx.path_graph(3, create_using=G)
vals = 100
attr = "hello"
nx.set_node_attributes(G, vals, attr)
assert G.nodes[0][attr] == vals
assert G.nodes[1][attr] == vals
assert G.nodes[2][attr] == vals
# Test dictionary
G = nx.path_graph(3, create_using=G)
vals = dict(zip(sorted(G.nodes()), range(len(G))))
attr = "hi"
nx.set_node_attributes(G, vals, attr)
assert G.nodes[0][attr] == 0
assert G.nodes[1][attr] == 1
assert G.nodes[2][attr] == 2
# Test dictionary of dictionaries
G = nx.path_graph(3, create_using=G)
d = {"hi": 0, "hello": 200}
vals = dict.fromkeys(G.nodes(), d)
vals.pop(0)
nx.set_node_attributes(G, vals)
assert G.nodes[0] == {}
assert G.nodes[1]["hi"] == 0
assert G.nodes[2]["hello"] == 200
def test_set_edge_attributes():
graphs = [nx.Graph(), nx.DiGraph()]
for G in graphs:
# Test single value
G = nx.path_graph(3, create_using=G)
attr = "hello"
vals = 3
nx.set_edge_attributes(G, vals, attr)
assert G[0][1][attr] == vals
assert G[1][2][attr] == vals
# Test multiple values
G = nx.path_graph(3, create_using=G)
attr = "hi"
edges = [(0, 1), (1, 2)]
vals = dict(zip(edges, range(len(edges))))
nx.set_edge_attributes(G, vals, attr)
assert G[0][1][attr] == 0
assert G[1][2][attr] == 1
# Test dictionary of dictionaries
G = nx.path_graph(3, create_using=G)
d = {"hi": 0, "hello": 200}
edges = [(0, 1)]
vals = dict.fromkeys(edges, d)
nx.set_edge_attributes(G, vals)
assert G[0][1]["hi"] == 0
assert G[0][1]["hello"] == 200
assert G[1][2] == {}
def test_set_edge_attributes_multi():
graphs = [nx.MultiGraph(), nx.MultiDiGraph()]
for G in graphs:
# Test single value
G = nx.path_graph(3, create_using=G)
attr = "hello"
vals = 3
nx.set_edge_attributes(G, vals, attr)
assert G[0][1][0][attr] == vals
assert G[1][2][0][attr] == vals
# Test multiple values
G = nx.path_graph(3, create_using=G)
attr = "hi"
edges = [(0, 1, 0), (1, 2, 0)]
vals = dict(zip(edges, range(len(edges))))
nx.set_edge_attributes(G, vals, attr)
assert G[0][1][0][attr] == 0
assert G[1][2][0][attr] == 1
# Test dictionary of dictionaries
G = nx.path_graph(3, create_using=G)
d = {"hi": 0, "hello": 200}
edges = [(0, 1, 0)]
vals = dict.fromkeys(edges, d)
nx.set_edge_attributes(G, vals)
assert G[0][1][0]["hi"] == 0
assert G[0][1][0]["hello"] == 200
assert G[1][2][0] == {}
def test_get_node_attributes():
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
for G in graphs:
G = nx.path_graph(3, create_using=G)
attr = "hello"
vals = 100
nx.set_node_attributes(G, vals, attr)
attrs = nx.get_node_attributes(G, attr)
assert attrs[0] == vals
assert attrs[1] == vals
assert attrs[2] == vals
def test_get_edge_attributes():
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
for G in graphs:
G = nx.path_graph(3, create_using=G)
attr = "hello"
vals = 100
nx.set_edge_attributes(G, vals, attr)
attrs = nx.get_edge_attributes(G, attr)
assert len(attrs) == 2
if G.is_multigraph():
keys = [(0, 1, 0), (1, 2, 0)]
for u, v, k in keys:
try:
assert attrs[(u, v, k)] == 100
except KeyError:
assert attrs[(v, u, k)] == 100
else:
keys = [(0, 1), (1, 2)]
for u, v in keys:
try:
assert attrs[(u, v)] == 100
except KeyError:
assert attrs[(v, u)] == 100
def test_is_empty():
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
for G in graphs:
assert nx.is_empty(G)
G.add_nodes_from(range(5))
assert nx.is_empty(G)
G.add_edges_from([(1, 2), (3, 4)])
assert not nx.is_empty(G)
def test_selfloops():
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
for graph in graphs:
G = nx.complete_graph(3, create_using=graph)
G.add_edge(0, 0)
assert_nodes_equal(nx.nodes_with_selfloops(G), [0])
assert_edges_equal(nx.selfloop_edges(G), [(0, 0)])
assert_edges_equal(nx.selfloop_edges(G, data=True), [(0, 0, {})])
assert nx.number_of_selfloops(G) == 1
# test selfloop attr
G.add_edge(1, 1, weight=2)
assert_edges_equal(
nx.selfloop_edges(G, data=True), [(0, 0, {}), (1, 1, {"weight": 2})]
)
assert_edges_equal(
nx.selfloop_edges(G, data="weight"), [(0, 0, None), (1, 1, 2)]
)
# test removing selfloops behavior vis-a-vis altering a dict while iterating
G.add_edge(0, 0)
G.remove_edges_from(nx.selfloop_edges(G))
if G.is_multigraph():
G.add_edge(0, 0)
pytest.raises(
RuntimeError, G.remove_edges_from, nx.selfloop_edges(G, keys=True)
)
G.add_edge(0, 0)
pytest.raises(
TypeError, G.remove_edges_from, nx.selfloop_edges(G, data=True)
)
G.add_edge(0, 0)
pytest.raises(
RuntimeError,
G.remove_edges_from,
nx.selfloop_edges(G, data=True, keys=True),
)
else:
G.add_edge(0, 0)
G.remove_edges_from(nx.selfloop_edges(G, keys=True))
G.add_edge(0, 0)
G.remove_edges_from(nx.selfloop_edges(G, data=True))
G.add_edge(0, 0)
G.remove_edges_from(nx.selfloop_edges(G, keys=True, data=True))
def test_pathweight():
valid_path = [1, 2, 3]
invalid_path = [1, 3, 2]
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
edges = [
(1, 2, dict(cost=5, dist=6)),
(2, 3, dict(cost=3, dist=4)),
(1, 2, dict(cost=1, dist=2)),
]
for graph in graphs:
graph.add_edges_from(edges)
assert nx.path_weight(graph, valid_path, "cost") == 4
assert nx.path_weight(graph, valid_path, "dist") == 6
pytest.raises(nx.NetworkXNoPath, nx.path_weight, graph, invalid_path, "cost")
def test_ispath():
valid_path = [1, 2, 3, 4]
invalid_path = [1, 2, 4, 3]
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
edges = [(1, 2), (2, 3), (1, 2), (3, 4)]
for graph in graphs:
graph.add_edges_from(edges)
assert nx.is_path(graph, valid_path)
assert not nx.is_path(graph, invalid_path)

View file

@ -0,0 +1,803 @@
import pickle
import gc
import networkx as nx
from networkx.testing.utils import (
assert_graphs_equal,
assert_edges_equal,
assert_nodes_equal,
)
import pytest
class BaseGraphTester:
""" Tests for data-structure independent graph class features."""
def test_contains(self):
G = self.K3
assert 1 in G
assert 4 not in G
assert "b" not in G
assert [] not in G # no exception for nonhashable
assert {1: 1} not in G # no exception for nonhashable
def test_order(self):
G = self.K3
assert len(G) == 3
assert G.order() == 3
assert G.number_of_nodes() == 3
def test_nodes(self):
G = self.K3
assert sorted(G.nodes()) == self.k3nodes
assert sorted(G.nodes(data=True)) == [(0, {}), (1, {}), (2, {})]
def test_has_node(self):
G = self.K3
assert G.has_node(1)
assert not G.has_node(4)
assert not G.has_node([]) # no exception for nonhashable
assert not G.has_node({1: 1}) # no exception for nonhashable
def test_has_edge(self):
G = self.K3
assert G.has_edge(0, 1)
assert not G.has_edge(0, -1)
def test_neighbors(self):
G = self.K3
assert sorted(G.neighbors(0)) == [1, 2]
with pytest.raises(nx.NetworkXError):
G.neighbors(-1)
def test_memory_leak(self):
G = self.Graph()
def count_objects_of_type(_type):
return sum(1 for obj in gc.get_objects() if isinstance(obj, _type))
gc.collect()
before = count_objects_of_type(self.Graph)
G.copy()
gc.collect()
after = count_objects_of_type(self.Graph)
assert before == after
# test a subgraph of the base class
class MyGraph(self.Graph):
pass
gc.collect()
G = MyGraph()
before = count_objects_of_type(MyGraph)
G.copy()
gc.collect()
after = count_objects_of_type(MyGraph)
assert before == after
def test_edges(self):
G = self.K3
assert_edges_equal(G.edges(), [(0, 1), (0, 2), (1, 2)])
assert_edges_equal(G.edges(0), [(0, 1), (0, 2)])
assert_edges_equal(G.edges([0, 1]), [(0, 1), (0, 2), (1, 2)])
with pytest.raises(nx.NetworkXError):
G.edges(-1)
def test_degree(self):
G = self.K3
assert sorted(G.degree()) == [(0, 2), (1, 2), (2, 2)]
assert dict(G.degree()) == {0: 2, 1: 2, 2: 2}
assert G.degree(0) == 2
with pytest.raises(nx.NetworkXError):
G.degree(-1) # node not in graph
def test_size(self):
G = self.K3
assert G.size() == 3
assert G.number_of_edges() == 3
def test_nbunch_iter(self):
G = self.K3
assert_nodes_equal(G.nbunch_iter(), self.k3nodes) # all nodes
assert_nodes_equal(G.nbunch_iter(0), [0]) # single node
assert_nodes_equal(G.nbunch_iter([0, 1]), [0, 1]) # sequence
# sequence with none in graph
assert_nodes_equal(G.nbunch_iter([-1]), [])
# string sequence with none in graph
assert_nodes_equal(G.nbunch_iter("foo"), [])
# node not in graph doesn't get caught upon creation of iterator
bunch = G.nbunch_iter(-1)
# but gets caught when iterator used
with pytest.raises(nx.NetworkXError):
list(bunch)
# unhashable doesn't get caught upon creation of iterator
bunch = G.nbunch_iter([0, 1, 2, {}])
# but gets caught when iterator hits the unhashable
with pytest.raises(nx.NetworkXError):
list(bunch)
def test_nbunch_iter_node_format_raise(self):
# Tests that a node that would have failed string formatting
# doesn't cause an error when attempting to raise a
# :exc:`nx.NetworkXError`.
# For more information, see pull request #1813.
G = self.Graph()
nbunch = [("x", set())]
with pytest.raises(nx.NetworkXError):
list(G.nbunch_iter(nbunch))
def test_selfloop_degree(self):
G = self.Graph()
G.add_edge(1, 1)
assert sorted(G.degree()) == [(1, 2)]
assert dict(G.degree()) == {1: 2}
assert G.degree(1) == 2
assert sorted(G.degree([1])) == [(1, 2)]
assert G.degree(1, weight="weight") == 2
def test_selfloops(self):
G = self.K3.copy()
G.add_edge(0, 0)
assert_nodes_equal(nx.nodes_with_selfloops(G), [0])
assert_edges_equal(nx.selfloop_edges(G), [(0, 0)])
assert nx.number_of_selfloops(G) == 1
G.remove_edge(0, 0)
G.add_edge(0, 0)
G.remove_edges_from([(0, 0)])
G.add_edge(1, 1)
G.remove_node(1)
G.add_edge(0, 0)
G.add_edge(1, 1)
G.remove_nodes_from([0, 1])
class BaseAttrGraphTester(BaseGraphTester):
""" Tests of graph class attribute features."""
def test_weighted_degree(self):
G = self.Graph()
G.add_edge(1, 2, weight=2, other=3)
G.add_edge(2, 3, weight=3, other=4)
assert sorted(d for n, d in G.degree(weight="weight")) == [2, 3, 5]
assert dict(G.degree(weight="weight")) == {1: 2, 2: 5, 3: 3}
assert G.degree(1, weight="weight") == 2
assert_nodes_equal((G.degree([1], weight="weight")), [(1, 2)])
assert_nodes_equal((d for n, d in G.degree(weight="other")), [3, 7, 4])
assert dict(G.degree(weight="other")) == {1: 3, 2: 7, 3: 4}
assert G.degree(1, weight="other") == 3
assert_edges_equal((G.degree([1], weight="other")), [(1, 3)])
def add_attributes(self, G):
G.graph["foo"] = []
G.nodes[0]["foo"] = []
G.remove_edge(1, 2)
ll = []
G.add_edge(1, 2, foo=ll)
G.add_edge(2, 1, foo=ll)
def test_name(self):
G = self.Graph(name="")
assert G.name == ""
G = self.Graph(name="test")
assert G.__str__() == "test"
assert G.name == "test"
def test_graph_chain(self):
G = self.Graph([(0, 1), (1, 2)])
DG = G.to_directed(as_view=True)
SDG = DG.subgraph([0, 1])
RSDG = SDG.reverse(copy=False)
assert G is DG._graph
assert DG is SDG._graph
assert SDG is RSDG._graph
def test_copy(self):
G = self.Graph()
G.add_node(0)
G.add_edge(1, 2)
self.add_attributes(G)
# copy edge datadict but any container attr are same
H = G.copy()
self.graphs_equal(H, G)
self.different_attrdict(H, G)
self.shallow_copy_attrdict(H, G)
def test_class_copy(self):
G = self.Graph()
G.add_node(0)
G.add_edge(1, 2)
self.add_attributes(G)
# copy edge datadict but any container attr are same
H = G.__class__(G)
self.graphs_equal(H, G)
self.different_attrdict(H, G)
self.shallow_copy_attrdict(H, G)
def test_fresh_copy(self):
G = self.Graph()
G.add_node(0)
G.add_edge(1, 2)
self.add_attributes(G)
# copy graph structure but use fresh datadict
H = G.__class__()
H.add_nodes_from(G)
H.add_edges_from(G.edges())
assert len(G.nodes[0]) == 1
ddict = G.adj[1][2][0] if G.is_multigraph() else G.adj[1][2]
assert len(ddict) == 1
assert len(H.nodes[0]) == 0
ddict = H.adj[1][2][0] if H.is_multigraph() else H.adj[1][2]
assert len(ddict) == 0
def is_deepcopy(self, H, G):
self.graphs_equal(H, G)
self.different_attrdict(H, G)
self.deep_copy_attrdict(H, G)
def deep_copy_attrdict(self, H, G):
self.deepcopy_graph_attr(H, G)
self.deepcopy_node_attr(H, G)
self.deepcopy_edge_attr(H, G)
def deepcopy_graph_attr(self, H, G):
assert G.graph["foo"] == H.graph["foo"]
G.graph["foo"].append(1)
assert G.graph["foo"] != H.graph["foo"]
def deepcopy_node_attr(self, H, G):
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
G.nodes[0]["foo"].append(1)
assert G.nodes[0]["foo"] != H.nodes[0]["foo"]
def deepcopy_edge_attr(self, H, G):
assert G[1][2]["foo"] == H[1][2]["foo"]
G[1][2]["foo"].append(1)
assert G[1][2]["foo"] != H[1][2]["foo"]
def is_shallow_copy(self, H, G):
self.graphs_equal(H, G)
self.shallow_copy_attrdict(H, G)
def shallow_copy_attrdict(self, H, G):
self.shallow_copy_graph_attr(H, G)
self.shallow_copy_node_attr(H, G)
self.shallow_copy_edge_attr(H, G)
def shallow_copy_graph_attr(self, H, G):
assert G.graph["foo"] == H.graph["foo"]
G.graph["foo"].append(1)
assert G.graph["foo"] == H.graph["foo"]
def shallow_copy_node_attr(self, H, G):
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
G.nodes[0]["foo"].append(1)
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
def shallow_copy_edge_attr(self, H, G):
assert G[1][2]["foo"] == H[1][2]["foo"]
G[1][2]["foo"].append(1)
assert G[1][2]["foo"] == H[1][2]["foo"]
def same_attrdict(self, H, G):
old_foo = H[1][2]["foo"]
H.adj[1][2]["foo"] = "baz"
assert G.edges == H.edges
H.adj[1][2]["foo"] = old_foo
assert G.edges == H.edges
old_foo = H.nodes[0]["foo"]
H.nodes[0]["foo"] = "baz"
assert G.nodes == H.nodes
H.nodes[0]["foo"] = old_foo
assert G.nodes == H.nodes
def different_attrdict(self, H, G):
old_foo = H[1][2]["foo"]
H.adj[1][2]["foo"] = "baz"
assert G._adj != H._adj
H.adj[1][2]["foo"] = old_foo
assert G._adj == H._adj
old_foo = H.nodes[0]["foo"]
H.nodes[0]["foo"] = "baz"
assert G._node != H._node
H.nodes[0]["foo"] = old_foo
assert G._node == H._node
def graphs_equal(self, H, G):
assert G._adj == H._adj
assert G._node == H._node
assert G.graph == H.graph
assert G.name == H.name
if not G.is_directed() and not H.is_directed():
assert H._adj[1][2] is H._adj[2][1]
assert G._adj[1][2] is G._adj[2][1]
else: # at least one is directed
if not G.is_directed():
G._pred = G._adj
G._succ = G._adj
if not H.is_directed():
H._pred = H._adj
H._succ = H._adj
assert G._pred == H._pred
assert G._succ == H._succ
assert H._succ[1][2] is H._pred[2][1]
assert G._succ[1][2] is G._pred[2][1]
def test_graph_attr(self):
G = self.K3.copy()
G.graph["foo"] = "bar"
assert G.graph["foo"] == "bar"
del G.graph["foo"]
assert G.graph == {}
H = self.Graph(foo="bar")
assert H.graph["foo"] == "bar"
def test_node_attr(self):
G = self.K3.copy()
G.add_node(1, foo="bar")
assert_nodes_equal(G.nodes(), [0, 1, 2])
assert_nodes_equal(G.nodes(data=True), [(0, {}), (1, {"foo": "bar"}), (2, {})])
G.nodes[1]["foo"] = "baz"
assert_nodes_equal(G.nodes(data=True), [(0, {}), (1, {"foo": "baz"}), (2, {})])
assert_nodes_equal(G.nodes(data="foo"), [(0, None), (1, "baz"), (2, None)])
assert_nodes_equal(
G.nodes(data="foo", default="bar"), [(0, "bar"), (1, "baz"), (2, "bar")]
)
def test_node_attr2(self):
G = self.K3.copy()
a = {"foo": "bar"}
G.add_node(3, **a)
assert_nodes_equal(G.nodes(), [0, 1, 2, 3])
assert_nodes_equal(
G.nodes(data=True), [(0, {}), (1, {}), (2, {}), (3, {"foo": "bar"})]
)
def test_edge_lookup(self):
G = self.Graph()
G.add_edge(1, 2, foo="bar")
assert_edges_equal(G.edges[1, 2], {"foo": "bar"})
def test_edge_attr(self):
G = self.Graph()
G.add_edge(1, 2, foo="bar")
assert_edges_equal(G.edges(data=True), [(1, 2, {"foo": "bar"})])
assert_edges_equal(G.edges(data="foo"), [(1, 2, "bar")])
def test_edge_attr2(self):
G = self.Graph()
G.add_edges_from([(1, 2), (3, 4)], foo="foo")
assert_edges_equal(
G.edges(data=True), [(1, 2, {"foo": "foo"}), (3, 4, {"foo": "foo"})]
)
assert_edges_equal(G.edges(data="foo"), [(1, 2, "foo"), (3, 4, "foo")])
def test_edge_attr3(self):
G = self.Graph()
G.add_edges_from([(1, 2, {"weight": 32}), (3, 4, {"weight": 64})], foo="foo")
assert_edges_equal(
G.edges(data=True),
[
(1, 2, {"foo": "foo", "weight": 32}),
(3, 4, {"foo": "foo", "weight": 64}),
],
)
G.remove_edges_from([(1, 2), (3, 4)])
G.add_edge(1, 2, data=7, spam="bar", bar="foo")
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
)
def test_edge_attr4(self):
G = self.Graph()
G.add_edge(1, 2, data=7, spam="bar", bar="foo")
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
)
G[1][2]["data"] = 10 # OK to set data like this
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 10, "spam": "bar", "bar": "foo"})]
)
G.adj[1][2]["data"] = 20
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 20, "spam": "bar", "bar": "foo"})]
)
G.edges[1, 2]["data"] = 21 # another spelling, "edge"
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 21, "spam": "bar", "bar": "foo"})]
)
G.adj[1][2]["listdata"] = [20, 200]
G.adj[1][2]["weight"] = 20
dd = {
"data": 21,
"spam": "bar",
"bar": "foo",
"listdata": [20, 200],
"weight": 20,
}
assert_edges_equal(G.edges(data=True), [(1, 2, dd)])
def test_to_undirected(self):
G = self.K3
self.add_attributes(G)
H = nx.Graph(G)
self.is_shallow_copy(H, G)
self.different_attrdict(H, G)
H = G.to_undirected()
self.is_deepcopy(H, G)
def test_to_directed(self):
G = self.K3
self.add_attributes(G)
H = nx.DiGraph(G)
self.is_shallow_copy(H, G)
self.different_attrdict(H, G)
H = G.to_directed()
self.is_deepcopy(H, G)
def test_subgraph(self):
G = self.K3
self.add_attributes(G)
H = G.subgraph([0, 1, 2, 5])
self.graphs_equal(H, G)
self.same_attrdict(H, G)
self.shallow_copy_attrdict(H, G)
H = G.subgraph(0)
assert H.adj == {0: {}}
H = G.subgraph([])
assert H.adj == {}
assert G.adj != {}
def test_selfloops_attr(self):
G = self.K3.copy()
G.add_edge(0, 0)
G.add_edge(1, 1, weight=2)
assert_edges_equal(
nx.selfloop_edges(G, data=True), [(0, 0, {}), (1, 1, {"weight": 2})]
)
assert_edges_equal(
nx.selfloop_edges(G, data="weight"), [(0, 0, None), (1, 1, 2)]
)
class TestGraph(BaseAttrGraphTester):
"""Tests specific to dict-of-dict-of-dict graph data structure"""
def setup_method(self):
self.Graph = nx.Graph
# build dict-of-dict-of-dict K3
ed1, ed2, ed3 = ({}, {}, {})
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = self.k3adj
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
def test_pickle(self):
G = self.K3
pg = pickle.loads(pickle.dumps(G, -1))
self.graphs_equal(pg, G)
pg = pickle.loads(pickle.dumps(G))
self.graphs_equal(pg, G)
def test_data_input(self):
G = self.Graph({1: [2], 2: [1]}, name="test")
assert G.name == "test"
assert sorted(G.adj.items()) == [(1, {2: {}}), (2, {1: {}})]
G = self.Graph({1: [2], 2: [1]}, name="test")
assert G.name == "test"
assert sorted(G.adj.items()) == [(1, {2: {}}), (2, {1: {}})]
def test_adjacency(self):
G = self.K3
assert dict(G.adjacency()) == {
0: {1: {}, 2: {}},
1: {0: {}, 2: {}},
2: {0: {}, 1: {}},
}
def test_getitem(self):
G = self.K3
assert G[0] == {1: {}, 2: {}}
with pytest.raises(KeyError):
G.__getitem__("j")
with pytest.raises(TypeError):
G.__getitem__(["A"])
def test_add_node(self):
G = self.Graph()
G.add_node(0)
assert G.adj == {0: {}}
# test add attributes
G.add_node(1, c="red")
G.add_node(2, c="blue")
G.add_node(3, c="red")
assert G.nodes[1]["c"] == "red"
assert G.nodes[2]["c"] == "blue"
assert G.nodes[3]["c"] == "red"
# test updating attributes
G.add_node(1, c="blue")
G.add_node(2, c="red")
G.add_node(3, c="blue")
assert G.nodes[1]["c"] == "blue"
assert G.nodes[2]["c"] == "red"
assert G.nodes[3]["c"] == "blue"
def test_add_nodes_from(self):
G = self.Graph()
G.add_nodes_from([0, 1, 2])
assert G.adj == {0: {}, 1: {}, 2: {}}
# test add attributes
G.add_nodes_from([0, 1, 2], c="red")
assert G.nodes[0]["c"] == "red"
assert G.nodes[2]["c"] == "red"
# test that attribute dicts are not the same
assert G.nodes[0] is not G.nodes[1]
# test updating attributes
G.add_nodes_from([0, 1, 2], c="blue")
assert G.nodes[0]["c"] == "blue"
assert G.nodes[2]["c"] == "blue"
assert G.nodes[0] is not G.nodes[1]
# test tuple input
H = self.Graph()
H.add_nodes_from(G.nodes(data=True))
assert H.nodes[0]["c"] == "blue"
assert H.nodes[2]["c"] == "blue"
assert H.nodes[0] is not H.nodes[1]
# specific overrides general
H.add_nodes_from([0, (1, {"c": "green"}), (3, {"c": "cyan"})], c="red")
assert H.nodes[0]["c"] == "red"
assert H.nodes[1]["c"] == "green"
assert H.nodes[2]["c"] == "blue"
assert H.nodes[3]["c"] == "cyan"
def test_remove_node(self):
G = self.K3.copy()
G.remove_node(0)
assert G.adj == {1: {2: {}}, 2: {1: {}}}
with pytest.raises(nx.NetworkXError):
G.remove_node(-1)
# generator here to implement list,set,string...
def test_remove_nodes_from(self):
G = self.K3.copy()
G.remove_nodes_from([0, 1])
assert G.adj == {2: {}}
G.remove_nodes_from([-1]) # silent fail
def test_add_edge(self):
G = self.Graph()
G.add_edge(0, 1)
assert G.adj == {0: {1: {}}, 1: {0: {}}}
G = self.Graph()
G.add_edge(*(0, 1))
assert G.adj == {0: {1: {}}, 1: {0: {}}}
def test_add_edges_from(self):
G = self.Graph()
G.add_edges_from([(0, 1), (0, 2, {"weight": 3})])
assert G.adj == {
0: {1: {}, 2: {"weight": 3}},
1: {0: {}},
2: {0: {"weight": 3}},
}
G = self.Graph()
G.add_edges_from([(0, 1), (0, 2, {"weight": 3}), (1, 2, {"data": 4})], data=2)
assert G.adj == {
0: {1: {"data": 2}, 2: {"weight": 3, "data": 2}},
1: {0: {"data": 2}, 2: {"data": 4}},
2: {0: {"weight": 3, "data": 2}, 1: {"data": 4}},
}
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0,)]) # too few in tuple
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0, 1, 2, 3)]) # too many in tuple
with pytest.raises(TypeError):
G.add_edges_from([0]) # not a tuple
def test_remove_edge(self):
G = self.K3.copy()
G.remove_edge(0, 1)
assert G.adj == {0: {2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
with pytest.raises(nx.NetworkXError):
G.remove_edge(-1, 0)
def test_remove_edges_from(self):
G = self.K3.copy()
G.remove_edges_from([(0, 1)])
assert G.adj == {0: {2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
G.remove_edges_from([(0, 0)]) # silent fail
def test_clear(self):
G = self.K3.copy()
G.graph["name"] = "K3"
G.clear()
assert list(G.nodes) == []
assert G.adj == {}
assert G.graph == {}
def test_clear_edges(self):
G = self.K3.copy()
G.graph["name"] = "K3"
nodes = list(G.nodes)
G.clear_edges()
assert list(G.nodes) == nodes
assert G.adj == {0: {}, 1: {}, 2: {}}
assert list(G.edges) == []
assert G.graph["name"] == "K3"
def test_edges_data(self):
G = self.K3
all_edges = [(0, 1, {}), (0, 2, {}), (1, 2, {})]
assert_edges_equal(G.edges(data=True), all_edges)
assert_edges_equal(G.edges(0, data=True), [(0, 1, {}), (0, 2, {})])
assert_edges_equal(G.edges([0, 1], data=True), all_edges)
with pytest.raises(nx.NetworkXError):
G.edges(-1, True)
def test_get_edge_data(self):
G = self.K3.copy()
assert G.get_edge_data(0, 1) == {}
assert G[0][1] == {}
assert G.get_edge_data(10, 20) is None
assert G.get_edge_data(-1, 0) is None
assert G.get_edge_data(-1, 0, default=1) == 1
def test_update(self):
# specify both edgees and nodes
G = self.K3.copy()
G.update(nodes=[3, (4, {"size": 2})], edges=[(4, 5), (6, 7, {"weight": 2})])
nlist = [
(0, {}),
(1, {}),
(2, {}),
(3, {}),
(4, {"size": 2}),
(5, {}),
(6, {}),
(7, {}),
]
assert sorted(G.nodes.data()) == nlist
if G.is_directed():
elist = [
(0, 1, {}),
(0, 2, {}),
(1, 0, {}),
(1, 2, {}),
(2, 0, {}),
(2, 1, {}),
(4, 5, {}),
(6, 7, {"weight": 2}),
]
else:
elist = [
(0, 1, {}),
(0, 2, {}),
(1, 2, {}),
(4, 5, {}),
(6, 7, {"weight": 2}),
]
assert sorted(G.edges.data()) == elist
assert G.graph == {}
# no keywords -- order is edges, nodes
G = self.K3.copy()
G.update([(4, 5), (6, 7, {"weight": 2})], [3, (4, {"size": 2})])
assert sorted(G.nodes.data()) == nlist
assert sorted(G.edges.data()) == elist
assert G.graph == {}
# update using only a graph
G = self.Graph()
G.graph["foo"] = "bar"
G.add_node(2, data=4)
G.add_edge(0, 1, weight=0.5)
GG = G.copy()
H = self.Graph()
GG.update(H)
assert_graphs_equal(G, GG)
H.update(G)
assert_graphs_equal(H, G)
# update nodes only
H = self.Graph()
H.update(nodes=[3, 4])
assert H.nodes ^ {3, 4} == set()
assert H.size() == 0
# update edges only
H = self.Graph()
H.update(edges=[(3, 4)])
assert sorted(H.edges.data()) == [(3, 4, {})]
assert H.size() == 1
# No inputs -> exception
with pytest.raises(nx.NetworkXError):
nx.Graph().update()
class TestEdgeSubgraph:
"""Unit tests for the :meth:`Graph.edge_subgraph` method."""
def setup_method(self):
# Create a path graph on five nodes.
G = nx.path_graph(5)
# Add some node, edge, and graph attributes.
for i in range(5):
G.nodes[i]["name"] = f"node{i}"
G.edges[0, 1]["name"] = "edge01"
G.edges[3, 4]["name"] = "edge34"
G.graph["name"] = "graph"
# Get the subgraph induced by the first and last edges.
self.G = G
self.H = G.edge_subgraph([(0, 1), (3, 4)])
def test_correct_nodes(self):
"""Tests that the subgraph has the correct nodes."""
assert [0, 1, 3, 4] == sorted(self.H.nodes())
def test_correct_edges(self):
"""Tests that the subgraph has the correct edges."""
assert [(0, 1, "edge01"), (3, 4, "edge34")] == sorted(self.H.edges(data="name"))
def test_add_node(self):
"""Tests that adding a node to the original graph does not
affect the nodes of the subgraph.
"""
self.G.add_node(5)
assert [0, 1, 3, 4] == sorted(self.H.nodes())
def test_remove_node(self):
"""Tests that removing a node in the original graph does
affect the nodes of the subgraph.
"""
self.G.remove_node(0)
assert [1, 3, 4] == sorted(self.H.nodes())
def test_node_attr_dict(self):
"""Tests that the node attribute dictionary of the two graphs is
the same object.
"""
for v in self.H:
assert self.G.nodes[v] == self.H.nodes[v]
# Making a change to G should make a change in H and vice versa.
self.G.nodes[0]["name"] = "foo"
assert self.G.nodes[0] == self.H.nodes[0]
self.H.nodes[1]["name"] = "bar"
assert self.G.nodes[1] == self.H.nodes[1]
def test_edge_attr_dict(self):
"""Tests that the edge attribute dictionary of the two graphs is
the same object.
"""
for u, v in self.H.edges():
assert self.G.edges[u, v] == self.H.edges[u, v]
# Making a change to G should make a change in H and vice versa.
self.G.edges[0, 1]["name"] = "foo"
assert self.G.edges[0, 1]["name"] == self.H.edges[0, 1]["name"]
self.H.edges[3, 4]["name"] = "bar"
assert self.G.edges[3, 4]["name"] == self.H.edges[3, 4]["name"]
def test_graph_attr_dict(self):
"""Tests that the graph attribute dictionary of the two graphs
is the same object.
"""
assert self.G.graph is self.H.graph

View file

@ -0,0 +1,12 @@
"""Original NetworkX graph tests"""
import networkx
import networkx as nx
from .historical_tests import HistoricalTests
class TestGraphHistorical(HistoricalTests):
@classmethod
def setup_class(cls):
HistoricalTests.setup_class()
cls.G = nx.Graph

View file

@ -0,0 +1,341 @@
import pytest
import networkx as nx
from networkx.testing import assert_edges_equal, assert_nodes_equal
# Note: SubGraph views are not tested here. They have their own testing file
class TestReverseView:
def setup(self):
self.G = nx.path_graph(9, create_using=nx.DiGraph())
self.rv = nx.reverse_view(self.G)
def test_pickle(self):
import pickle
rv = self.rv
prv = pickle.loads(pickle.dumps(rv, -1))
assert rv._node == prv._node
assert rv._adj == prv._adj
assert rv.graph == prv.graph
def test_contains(self):
assert (2, 3) in self.G.edges
assert (3, 2) not in self.G.edges
assert (2, 3) not in self.rv.edges
assert (3, 2) in self.rv.edges
def test_iter(self):
expected = sorted(tuple(reversed(e)) for e in self.G.edges)
assert sorted(self.rv.edges) == expected
def test_exceptions(self):
nxg = nx.graphviews
pytest.raises(nx.NetworkXNotImplemented, nxg.reverse_view, nx.Graph())
def test_subclass(self):
class MyGraph(nx.DiGraph):
def my_method(self):
return "me"
def to_directed_class(self):
return MyGraph()
M = MyGraph()
M.add_edge(1, 2)
RM = nx.reverse_view(M)
print("RM class", RM.__class__)
RMC = RM.copy()
print("RMC class", RMC.__class__)
print(RMC.edges)
assert RMC.has_edge(2, 1)
assert RMC.my_method() == "me"
class TestMultiReverseView:
def setup(self):
self.G = nx.path_graph(9, create_using=nx.MultiDiGraph())
self.G.add_edge(4, 5)
self.rv = nx.reverse_view(self.G)
def test_pickle(self):
import pickle
rv = self.rv
prv = pickle.loads(pickle.dumps(rv, -1))
assert rv._node == prv._node
assert rv._adj == prv._adj
assert rv.graph == prv.graph
def test_contains(self):
assert (2, 3, 0) in self.G.edges
assert (3, 2, 0) not in self.G.edges
assert (2, 3, 0) not in self.rv.edges
assert (3, 2, 0) in self.rv.edges
assert (5, 4, 1) in self.rv.edges
assert (4, 5, 1) not in self.rv.edges
def test_iter(self):
expected = sorted((v, u, k) for u, v, k in self.G.edges)
assert sorted(self.rv.edges) == expected
def test_exceptions(self):
nxg = nx.graphviews
MG = nx.MultiGraph(self.G)
pytest.raises(nx.NetworkXNotImplemented, nxg.reverse_view, MG)
class TestToDirected:
def setup(self):
self.G = nx.path_graph(9)
self.dv = nx.to_directed(self.G)
self.MG = nx.path_graph(9, create_using=nx.MultiGraph())
self.Mdv = nx.to_directed(self.MG)
def test_directed(self):
assert not self.G.is_directed()
assert self.dv.is_directed()
def test_already_directed(self):
dd = nx.to_directed(self.dv)
Mdd = nx.to_directed(self.Mdv)
assert_edges_equal(dd.edges, self.dv.edges)
assert_edges_equal(Mdd.edges, self.Mdv.edges)
def test_pickle(self):
import pickle
dv = self.dv
pdv = pickle.loads(pickle.dumps(dv, -1))
assert dv._node == pdv._node
assert dv._succ == pdv._succ
assert dv._pred == pdv._pred
assert dv.graph == pdv.graph
def test_contains(self):
assert (2, 3) in self.G.edges
assert (3, 2) in self.G.edges
assert (2, 3) in self.dv.edges
assert (3, 2) in self.dv.edges
def test_iter(self):
revd = [tuple(reversed(e)) for e in self.G.edges]
expected = sorted(list(self.G.edges) + revd)
assert sorted(self.dv.edges) == expected
class TestToUndirected:
def setup(self):
self.DG = nx.path_graph(9, create_using=nx.DiGraph())
self.uv = nx.to_undirected(self.DG)
self.MDG = nx.path_graph(9, create_using=nx.MultiDiGraph())
self.Muv = nx.to_undirected(self.MDG)
def test_directed(self):
assert self.DG.is_directed()
assert not self.uv.is_directed()
def test_already_directed(self):
uu = nx.to_undirected(self.uv)
Muu = nx.to_undirected(self.Muv)
assert_edges_equal(uu.edges, self.uv.edges)
assert_edges_equal(Muu.edges, self.Muv.edges)
def test_pickle(self):
import pickle
uv = self.uv
puv = pickle.loads(pickle.dumps(uv, -1))
assert uv._node == puv._node
assert uv._adj == puv._adj
assert uv.graph == puv.graph
assert hasattr(uv, "_graph")
def test_contains(self):
assert (2, 3) in self.DG.edges
assert (3, 2) not in self.DG.edges
assert (2, 3) in self.uv.edges
assert (3, 2) in self.uv.edges
def test_iter(self):
expected = sorted(self.DG.edges)
assert sorted(self.uv.edges) == expected
class TestChainsOfViews:
@classmethod
def setup_class(cls):
cls.G = nx.path_graph(9)
cls.DG = nx.path_graph(9, create_using=nx.DiGraph())
cls.MG = nx.path_graph(9, create_using=nx.MultiGraph())
cls.MDG = nx.path_graph(9, create_using=nx.MultiDiGraph())
cls.Gv = nx.to_undirected(cls.DG)
cls.DGv = nx.to_directed(cls.G)
cls.MGv = nx.to_undirected(cls.MDG)
cls.MDGv = nx.to_directed(cls.MG)
cls.Rv = cls.DG.reverse()
cls.MRv = cls.MDG.reverse()
cls.graphs = [
cls.G,
cls.DG,
cls.MG,
cls.MDG,
cls.Gv,
cls.DGv,
cls.MGv,
cls.MDGv,
cls.Rv,
cls.MRv,
]
for G in cls.graphs:
G.edges, G.nodes, G.degree
def test_pickle(self):
import pickle
for G in self.graphs:
H = pickle.loads(pickle.dumps(G, -1))
assert_edges_equal(H.edges, G.edges)
assert_nodes_equal(H.nodes, G.nodes)
def test_subgraph_of_subgraph(self):
SGv = nx.subgraph(self.G, range(3, 7))
SDGv = nx.subgraph(self.DG, range(3, 7))
SMGv = nx.subgraph(self.MG, range(3, 7))
SMDGv = nx.subgraph(self.MDG, range(3, 7))
for G in self.graphs + [SGv, SDGv, SMGv, SMDGv]:
SG = nx.induced_subgraph(G, [4, 5, 6])
assert list(SG) == [4, 5, 6]
SSG = SG.subgraph([6, 7])
assert list(SSG) == [6]
# subgraph-subgraph chain is short-cut in base class method
assert SSG._graph is G
def test_restricted_induced_subgraph_chains(self):
""" Test subgraph chains that both restrict and show nodes/edges.
A restricted_view subgraph should allow induced subgraphs using
G.subgraph that automagically without a chain (meaning the result
is a subgraph view of the original graph not a subgraph-of-subgraph.
"""
hide_nodes = [3, 4, 5]
hide_edges = [(6, 7)]
RG = nx.restricted_view(self.G, hide_nodes, hide_edges)
nodes = [4, 5, 6, 7, 8]
SG = nx.induced_subgraph(RG, nodes)
SSG = RG.subgraph(nodes)
assert RG._graph is self.G
assert SSG._graph is self.G
assert SG._graph is RG
assert_edges_equal(SG.edges, SSG.edges)
# should be same as morphing the graph
CG = self.G.copy()
CG.remove_nodes_from(hide_nodes)
CG.remove_edges_from(hide_edges)
assert_edges_equal(CG.edges(nodes), SSG.edges)
CG.remove_nodes_from([0, 1, 2, 3])
assert_edges_equal(CG.edges, SSG.edges)
# switch order: subgraph first, then restricted view
SSSG = self.G.subgraph(nodes)
RSG = nx.restricted_view(SSSG, hide_nodes, hide_edges)
assert RSG._graph is not self.G
assert_edges_equal(RSG.edges, CG.edges)
def test_subgraph_copy(self):
for origG in self.graphs:
G = nx.OrderedGraph(origG)
SG = G.subgraph([4, 5, 6])
H = SG.copy()
assert type(G) == type(H)
def test_subgraph_todirected(self):
SG = nx.induced_subgraph(self.G, [4, 5, 6])
SSG = SG.to_directed()
assert sorted(SSG) == [4, 5, 6]
assert sorted(SSG.edges) == [(4, 5), (5, 4), (5, 6), (6, 5)]
def test_subgraph_toundirected(self):
SG = nx.induced_subgraph(self.G, [4, 5, 6])
SSG = SG.to_undirected()
assert list(SSG) == [4, 5, 6]
assert sorted(SSG.edges) == [(4, 5), (5, 6)]
def test_reverse_subgraph_toundirected(self):
G = self.DG.reverse(copy=False)
SG = G.subgraph([4, 5, 6])
SSG = SG.to_undirected()
assert list(SSG) == [4, 5, 6]
assert sorted(SSG.edges) == [(4, 5), (5, 6)]
def test_reverse_reverse_copy(self):
G = self.DG.reverse(copy=False)
H = G.reverse(copy=True)
assert H.nodes == self.DG.nodes
assert H.edges == self.DG.edges
G = self.MDG.reverse(copy=False)
H = G.reverse(copy=True)
assert H.nodes == self.MDG.nodes
assert H.edges == self.MDG.edges
def test_subgraph_edgesubgraph_toundirected(self):
G = self.G.copy()
SG = G.subgraph([4, 5, 6])
SSG = SG.edge_subgraph([(4, 5), (5, 4)])
USSG = SSG.to_undirected()
assert list(USSG) == [4, 5]
assert sorted(USSG.edges) == [(4, 5)]
def test_copy_subgraph(self):
G = self.G.copy()
SG = G.subgraph([4, 5, 6])
CSG = SG.copy(as_view=True)
DCSG = SG.copy(as_view=False)
assert hasattr(CSG, "_graph") # is a view
assert not hasattr(DCSG, "_graph") # not a view
def test_copy_disubgraph(self):
G = self.DG.copy()
SG = G.subgraph([4, 5, 6])
CSG = SG.copy(as_view=True)
DCSG = SG.copy(as_view=False)
assert hasattr(CSG, "_graph") # is a view
assert not hasattr(DCSG, "_graph") # not a view
def test_copy_multidisubgraph(self):
G = self.MDG.copy()
SG = G.subgraph([4, 5, 6])
CSG = SG.copy(as_view=True)
DCSG = SG.copy(as_view=False)
assert hasattr(CSG, "_graph") # is a view
assert not hasattr(DCSG, "_graph") # not a view
def test_copy_multisubgraph(self):
G = self.MG.copy()
SG = G.subgraph([4, 5, 6])
CSG = SG.copy(as_view=True)
DCSG = SG.copy(as_view=False)
assert hasattr(CSG, "_graph") # is a view
assert not hasattr(DCSG, "_graph") # not a view
def test_copy_of_view(self):
G = nx.OrderedMultiGraph(self.MGv)
assert G.__class__.__name__ == "OrderedMultiGraph"
G = G.copy(as_view=True)
assert G.__class__.__name__ == "OrderedMultiGraph"
def test_subclass(self):
class MyGraph(nx.DiGraph):
def my_method(self):
return "me"
def to_directed_class(self):
return MyGraph()
for origG in self.graphs:
G = MyGraph(origG)
SG = G.subgraph([4, 5, 6])
H = SG.copy()
assert SG.my_method() == "me"
assert H.my_method() == "me"
assert not 3 in H or 3 in SG

View file

@ -0,0 +1,399 @@
import pytest
from networkx.testing import assert_edges_equal
import networkx as nx
from .test_multigraph import BaseMultiGraphTester
from .test_multigraph import TestMultiGraph as _TestMultiGraph
from .test_multigraph import TestEdgeSubgraph as _TestMultiGraphEdgeSubgraph
class BaseMultiDiGraphTester(BaseMultiGraphTester):
def test_edges(self):
G = self.K3
edges = [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.edges()) == edges
assert sorted(G.edges(0)) == [(0, 1), (0, 2)]
pytest.raises((KeyError, nx.NetworkXError), G.edges, -1)
def test_edges_data(self):
G = self.K3
edges = [(0, 1, {}), (0, 2, {}), (1, 0, {}), (1, 2, {}), (2, 0, {}), (2, 1, {})]
assert sorted(G.edges(data=True)) == edges
assert sorted(G.edges(0, data=True)) == [(0, 1, {}), (0, 2, {})]
pytest.raises((KeyError, nx.NetworkXError), G.neighbors, -1)
def test_edges_multi(self):
G = self.K3
assert sorted(G.edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.edges(0)) == [(0, 1), (0, 2)]
G.add_edge(0, 1)
assert sorted(G.edges()) == [
(0, 1),
(0, 1),
(0, 2),
(1, 0),
(1, 2),
(2, 0),
(2, 1),
]
def test_out_edges(self):
G = self.K3
assert sorted(G.out_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.out_edges(0)) == [(0, 1), (0, 2)]
pytest.raises((KeyError, nx.NetworkXError), G.out_edges, -1)
assert sorted(G.out_edges(0, keys=True)) == [(0, 1, 0), (0, 2, 0)]
def test_out_edges_multi(self):
G = self.K3
assert sorted(G.out_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.out_edges(0)) == [(0, 1), (0, 2)]
G.add_edge(0, 1, 2)
assert sorted(G.out_edges()) == [
(0, 1),
(0, 1),
(0, 2),
(1, 0),
(1, 2),
(2, 0),
(2, 1),
]
def test_out_edges_data(self):
G = self.K3
assert sorted(G.edges(0, data=True)) == [(0, 1, {}), (0, 2, {})]
G.remove_edge(0, 1)
G.add_edge(0, 1, data=1)
assert sorted(G.edges(0, data=True)) == [(0, 1, {"data": 1}), (0, 2, {})]
assert sorted(G.edges(0, data="data")) == [(0, 1, 1), (0, 2, None)]
assert sorted(G.edges(0, data="data", default=-1)) == [(0, 1, 1), (0, 2, -1)]
def test_in_edges(self):
G = self.K3
assert sorted(G.in_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.in_edges(0)) == [(1, 0), (2, 0)]
pytest.raises((KeyError, nx.NetworkXError), G.in_edges, -1)
G.add_edge(0, 1, 2)
assert sorted(G.in_edges()) == [
(0, 1),
(0, 1),
(0, 2),
(1, 0),
(1, 2),
(2, 0),
(2, 1),
]
assert sorted(G.in_edges(0, keys=True)) == [(1, 0, 0), (2, 0, 0)]
def test_in_edges_no_keys(self):
G = self.K3
assert sorted(G.in_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
assert sorted(G.in_edges(0)) == [(1, 0), (2, 0)]
G.add_edge(0, 1, 2)
assert sorted(G.in_edges()) == [
(0, 1),
(0, 1),
(0, 2),
(1, 0),
(1, 2),
(2, 0),
(2, 1),
]
assert sorted(G.in_edges(data=True, keys=False)) == [
(0, 1, {}),
(0, 1, {}),
(0, 2, {}),
(1, 0, {}),
(1, 2, {}),
(2, 0, {}),
(2, 1, {}),
]
def test_in_edges_data(self):
G = self.K3
assert sorted(G.in_edges(0, data=True)) == [(1, 0, {}), (2, 0, {})]
G.remove_edge(1, 0)
G.add_edge(1, 0, data=1)
assert sorted(G.in_edges(0, data=True)) == [(1, 0, {"data": 1}), (2, 0, {})]
assert sorted(G.in_edges(0, data="data")) == [(1, 0, 1), (2, 0, None)]
assert sorted(G.in_edges(0, data="data", default=-1)) == [(1, 0, 1), (2, 0, -1)]
def is_shallow(self, H, G):
# graph
assert G.graph["foo"] == H.graph["foo"]
G.graph["foo"].append(1)
assert G.graph["foo"] == H.graph["foo"]
# node
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
G.nodes[0]["foo"].append(1)
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
# edge
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
G[1][2][0]["foo"].append(1)
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
def is_deep(self, H, G):
# graph
assert G.graph["foo"] == H.graph["foo"]
G.graph["foo"].append(1)
assert G.graph["foo"] != H.graph["foo"]
# node
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
G.nodes[0]["foo"].append(1)
assert G.nodes[0]["foo"] != H.nodes[0]["foo"]
# edge
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
G[1][2][0]["foo"].append(1)
assert G[1][2][0]["foo"] != H[1][2][0]["foo"]
def test_to_undirected(self):
# MultiDiGraph -> MultiGraph changes number of edges so it is
# not a copy operation... use is_shallow, not is_shallow_copy
G = self.K3
self.add_attributes(G)
H = nx.MultiGraph(G)
# self.is_shallow(H,G)
# the result is traversal order dependent so we
# can't use the is_shallow() test here.
try:
assert_edges_equal(H.edges(), [(0, 1), (1, 2), (2, 0)])
except AssertionError:
assert_edges_equal(H.edges(), [(0, 1), (1, 2), (1, 2), (2, 0)])
H = G.to_undirected()
self.is_deep(H, G)
def test_has_successor(self):
G = self.K3
assert G.has_successor(0, 1)
assert not G.has_successor(0, -1)
def test_successors(self):
G = self.K3
assert sorted(G.successors(0)) == [1, 2]
pytest.raises((KeyError, nx.NetworkXError), G.successors, -1)
def test_has_predecessor(self):
G = self.K3
assert G.has_predecessor(0, 1)
assert not G.has_predecessor(0, -1)
def test_predecessors(self):
G = self.K3
assert sorted(G.predecessors(0)) == [1, 2]
pytest.raises((KeyError, nx.NetworkXError), G.predecessors, -1)
def test_degree(self):
G = self.K3
assert sorted(G.degree()) == [(0, 4), (1, 4), (2, 4)]
assert dict(G.degree()) == {0: 4, 1: 4, 2: 4}
assert G.degree(0) == 4
assert list(G.degree(iter([0]))) == [(0, 4)]
G.add_edge(0, 1, weight=0.3, other=1.2)
assert sorted(G.degree(weight="weight")) == [(0, 4.3), (1, 4.3), (2, 4)]
assert sorted(G.degree(weight="other")) == [(0, 5.2), (1, 5.2), (2, 4)]
def test_in_degree(self):
G = self.K3
assert sorted(G.in_degree()) == [(0, 2), (1, 2), (2, 2)]
assert dict(G.in_degree()) == {0: 2, 1: 2, 2: 2}
assert G.in_degree(0) == 2
assert list(G.in_degree(iter([0]))) == [(0, 2)]
assert G.in_degree(0, weight="weight") == 2
def test_out_degree(self):
G = self.K3
assert sorted(G.out_degree()) == [(0, 2), (1, 2), (2, 2)]
assert dict(G.out_degree()) == {0: 2, 1: 2, 2: 2}
assert G.out_degree(0) == 2
assert list(G.out_degree(iter([0]))) == [(0, 2)]
assert G.out_degree(0, weight="weight") == 2
def test_size(self):
G = self.K3
assert G.size() == 6
assert G.number_of_edges() == 6
G.add_edge(0, 1, weight=0.3, other=1.2)
assert round(G.size(weight="weight"), 2) == 6.3
assert round(G.size(weight="other"), 2) == 7.2
def test_to_undirected_reciprocal(self):
G = self.Graph()
G.add_edge(1, 2)
assert G.to_undirected().has_edge(1, 2)
assert not G.to_undirected(reciprocal=True).has_edge(1, 2)
G.add_edge(2, 1)
assert G.to_undirected(reciprocal=True).has_edge(1, 2)
def test_reverse_copy(self):
G = nx.MultiDiGraph([(0, 1), (0, 1)])
R = G.reverse()
assert sorted(R.edges()) == [(1, 0), (1, 0)]
R.remove_edge(1, 0)
assert sorted(R.edges()) == [(1, 0)]
assert sorted(G.edges()) == [(0, 1), (0, 1)]
def test_reverse_nocopy(self):
G = nx.MultiDiGraph([(0, 1), (0, 1)])
R = G.reverse(copy=False)
assert sorted(R.edges()) == [(1, 0), (1, 0)]
pytest.raises(nx.NetworkXError, R.remove_edge, 1, 0)
class TestMultiDiGraph(BaseMultiDiGraphTester, _TestMultiGraph):
def setup_method(self):
self.Graph = nx.MultiDiGraph
# build K3
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = {0: {}, 1: {}, 2: {}}
self.K3._succ = self.K3._adj
self.K3._pred = {0: {}, 1: {}, 2: {}}
for u in self.k3nodes:
for v in self.k3nodes:
if u == v:
continue
d = {0: {}}
self.K3._succ[u][v] = d
self.K3._pred[v][u] = d
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
def test_add_edge(self):
G = self.Graph()
G.add_edge(0, 1)
assert G._adj == {0: {1: {0: {}}}, 1: {}}
assert G._succ == {0: {1: {0: {}}}, 1: {}}
assert G._pred == {0: {}, 1: {0: {0: {}}}}
G = self.Graph()
G.add_edge(*(0, 1))
assert G._adj == {0: {1: {0: {}}}, 1: {}}
assert G._succ == {0: {1: {0: {}}}, 1: {}}
assert G._pred == {0: {}, 1: {0: {0: {}}}}
def test_add_edges_from(self):
G = self.Graph()
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})])
assert G._adj == {0: {1: {0: {}, 1: {"weight": 3}}}, 1: {}}
assert G._succ == {0: {1: {0: {}, 1: {"weight": 3}}}, 1: {}}
assert G._pred == {0: {}, 1: {0: {0: {}, 1: {"weight": 3}}}}
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})], weight=2)
assert G._succ == {
0: {1: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
1: {},
}
assert G._pred == {
0: {},
1: {0: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
}
G = self.Graph()
edges = [
(0, 1, {"weight": 3}),
(0, 1, (("weight", 2),)),
(0, 1, 5),
(0, 1, "s"),
]
G.add_edges_from(edges)
keydict = {0: {"weight": 3}, 1: {"weight": 2}, 5: {}, "s": {}}
assert G._succ == {0: {1: keydict}, 1: {}}
assert G._pred == {1: {0: keydict}, 0: {}}
# too few in tuple
pytest.raises(nx.NetworkXError, G.add_edges_from, [(0,)])
# too many in tuple
pytest.raises(nx.NetworkXError, G.add_edges_from, [(0, 1, 2, 3, 4)])
# not a tuple
pytest.raises(TypeError, G.add_edges_from, [0])
def test_remove_edge(self):
G = self.K3
G.remove_edge(0, 1)
assert G._succ == {
0: {2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
assert G._pred == {
0: {1: {0: {}}, 2: {0: {}}},
1: {2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, -1, 0)
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, 0, 2, key=1)
def test_remove_multiedge(self):
G = self.K3
G.add_edge(0, 1, key="parallel edge")
G.remove_edge(0, 1, key="parallel edge")
assert G._adj == {
0: {1: {0: {}}, 2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
assert G._succ == {
0: {1: {0: {}}, 2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
assert G._pred == {
0: {1: {0: {}}, 2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
G.remove_edge(0, 1)
assert G._succ == {
0: {2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
assert G._pred == {
0: {1: {0: {}}, 2: {0: {}}},
1: {2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, -1, 0)
def test_remove_edges_from(self):
G = self.K3
G.remove_edges_from([(0, 1)])
assert G._succ == {
0: {2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
assert G._pred == {
0: {1: {0: {}}, 2: {0: {}}},
1: {2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
G.remove_edges_from([(0, 0)]) # silent fail
class TestEdgeSubgraph(_TestMultiGraphEdgeSubgraph):
"""Unit tests for the :meth:`MultiDiGraph.edge_subgraph` method."""
def setup_method(self):
# Create a quadruply-linked path graph on five nodes.
G = nx.MultiDiGraph()
nx.add_path(G, range(5))
nx.add_path(G, range(5))
nx.add_path(G, reversed(range(5)))
nx.add_path(G, reversed(range(5)))
# Add some node, edge, and graph attributes.
for i in range(5):
G.nodes[i]["name"] = f"node{i}"
G.adj[0][1][0]["name"] = "edge010"
G.adj[0][1][1]["name"] = "edge011"
G.adj[3][4][0]["name"] = "edge340"
G.adj[3][4][1]["name"] = "edge341"
G.graph["name"] = "graph"
# Get the subgraph induced by one of the first edges and one of
# the last edges.
self.G = G
self.H = G.edge_subgraph([(0, 1, 0), (3, 4, 1)])

View file

@ -0,0 +1,375 @@
import pytest
import networkx as nx
from networkx.testing.utils import assert_edges_equal
from .test_graph import BaseAttrGraphTester
from .test_graph import TestGraph as _TestGraph
class BaseMultiGraphTester(BaseAttrGraphTester):
def test_has_edge(self):
G = self.K3
assert G.has_edge(0, 1)
assert not G.has_edge(0, -1)
assert G.has_edge(0, 1, 0)
assert not G.has_edge(0, 1, 1)
def test_get_edge_data(self):
G = self.K3
assert G.get_edge_data(0, 1) == {0: {}}
assert G[0][1] == {0: {}}
assert G[0][1][0] == {}
assert G.get_edge_data(10, 20) is None
assert G.get_edge_data(0, 1, 0) == {}
def test_adjacency(self):
G = self.K3
assert dict(G.adjacency()) == {
0: {1: {0: {}}, 2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
def deepcopy_edge_attr(self, H, G):
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
G[1][2][0]["foo"].append(1)
assert G[1][2][0]["foo"] != H[1][2][0]["foo"]
def shallow_copy_edge_attr(self, H, G):
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
G[1][2][0]["foo"].append(1)
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
def graphs_equal(self, H, G):
assert G._adj == H._adj
assert G._node == H._node
assert G.graph == H.graph
assert G.name == H.name
if not G.is_directed() and not H.is_directed():
assert H._adj[1][2][0] is H._adj[2][1][0]
assert G._adj[1][2][0] is G._adj[2][1][0]
else: # at least one is directed
if not G.is_directed():
G._pred = G._adj
G._succ = G._adj
if not H.is_directed():
H._pred = H._adj
H._succ = H._adj
assert G._pred == H._pred
assert G._succ == H._succ
assert H._succ[1][2][0] is H._pred[2][1][0]
assert G._succ[1][2][0] is G._pred[2][1][0]
def same_attrdict(self, H, G):
# same attrdict in the edgedata
old_foo = H[1][2][0]["foo"]
H.adj[1][2][0]["foo"] = "baz"
assert G._adj == H._adj
H.adj[1][2][0]["foo"] = old_foo
assert G._adj == H._adj
old_foo = H.nodes[0]["foo"]
H.nodes[0]["foo"] = "baz"
assert G._node == H._node
H.nodes[0]["foo"] = old_foo
assert G._node == H._node
def different_attrdict(self, H, G):
# used by graph_equal_but_different
old_foo = H[1][2][0]["foo"]
H.adj[1][2][0]["foo"] = "baz"
assert G._adj != H._adj
H.adj[1][2][0]["foo"] = old_foo
assert G._adj == H._adj
old_foo = H.nodes[0]["foo"]
H.nodes[0]["foo"] = "baz"
assert G._node != H._node
H.nodes[0]["foo"] = old_foo
assert G._node == H._node
def test_to_undirected(self):
G = self.K3
self.add_attributes(G)
H = nx.MultiGraph(G)
self.is_shallow_copy(H, G)
H = G.to_undirected()
self.is_deepcopy(H, G)
def test_to_directed(self):
G = self.K3
self.add_attributes(G)
H = nx.MultiDiGraph(G)
self.is_shallow_copy(H, G)
H = G.to_directed()
self.is_deepcopy(H, G)
def test_number_of_edges_selfloops(self):
G = self.K3
G.add_edge(0, 0)
G.add_edge(0, 0)
G.add_edge(0, 0, key="parallel edge")
G.remove_edge(0, 0, key="parallel edge")
assert G.number_of_edges(0, 0) == 2
G.remove_edge(0, 0)
assert G.number_of_edges(0, 0) == 1
def test_edge_lookup(self):
G = self.Graph()
G.add_edge(1, 2, foo="bar")
G.add_edge(1, 2, "key", foo="biz")
assert_edges_equal(G.edges[1, 2, 0], {"foo": "bar"})
assert_edges_equal(G.edges[1, 2, "key"], {"foo": "biz"})
def test_edge_attr4(self):
G = self.Graph()
G.add_edge(1, 2, key=0, data=7, spam="bar", bar="foo")
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
)
G[1][2][0]["data"] = 10 # OK to set data like this
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 10, "spam": "bar", "bar": "foo"})]
)
G.adj[1][2][0]["data"] = 20
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 20, "spam": "bar", "bar": "foo"})]
)
G.edges[1, 2, 0]["data"] = 21 # another spelling, "edge"
assert_edges_equal(
G.edges(data=True), [(1, 2, {"data": 21, "spam": "bar", "bar": "foo"})]
)
G.adj[1][2][0]["listdata"] = [20, 200]
G.adj[1][2][0]["weight"] = 20
assert_edges_equal(
G.edges(data=True),
[
(
1,
2,
{
"data": 21,
"spam": "bar",
"bar": "foo",
"listdata": [20, 200],
"weight": 20,
},
)
],
)
class TestMultiGraph(BaseMultiGraphTester, _TestGraph):
def setup_method(self):
self.Graph = nx.MultiGraph
# build K3
ed1, ed2, ed3 = ({0: {}}, {0: {}}, {0: {}})
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = self.k3adj
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
def test_data_input(self):
G = self.Graph({1: [2], 2: [1]}, name="test")
assert G.name == "test"
expected = [(1, {2: {0: {}}}), (2, {1: {0: {}}})]
assert sorted(G.adj.items()) == expected
def test_getitem(self):
G = self.K3
assert G[0] == {1: {0: {}}, 2: {0: {}}}
with pytest.raises(KeyError):
G.__getitem__("j")
with pytest.raises(TypeError):
G.__getitem__(["A"])
def test_remove_node(self):
G = self.K3
G.remove_node(0)
assert G.adj == {1: {2: {0: {}}}, 2: {1: {0: {}}}}
with pytest.raises(nx.NetworkXError):
G.remove_node(-1)
def test_add_edge(self):
G = self.Graph()
G.add_edge(0, 1)
assert G.adj == {0: {1: {0: {}}}, 1: {0: {0: {}}}}
G = self.Graph()
G.add_edge(*(0, 1))
assert G.adj == {0: {1: {0: {}}}, 1: {0: {0: {}}}}
def test_add_edge_conflicting_key(self):
G = self.Graph()
G.add_edge(0, 1, key=1)
G.add_edge(0, 1)
assert G.number_of_edges() == 2
G = self.Graph()
G.add_edges_from([(0, 1, 1, {})])
G.add_edges_from([(0, 1)])
assert G.number_of_edges() == 2
def test_add_edges_from(self):
G = self.Graph()
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})])
assert G.adj == {
0: {1: {0: {}, 1: {"weight": 3}}},
1: {0: {0: {}, 1: {"weight": 3}}},
}
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})], weight=2)
assert G.adj == {
0: {1: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
1: {0: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
}
G = self.Graph()
edges = [
(0, 1, {"weight": 3}),
(0, 1, (("weight", 2),)),
(0, 1, 5),
(0, 1, "s"),
]
G.add_edges_from(edges)
keydict = {0: {"weight": 3}, 1: {"weight": 2}, 5: {}, "s": {}}
assert G._adj == {0: {1: keydict}, 1: {0: keydict}}
# too few in tuple
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0,)])
# too many in tuple
with pytest.raises(nx.NetworkXError):
G.add_edges_from([(0, 1, 2, 3, 4)])
# not a tuple
with pytest.raises(TypeError):
G.add_edges_from([0])
def test_remove_edge(self):
G = self.K3
G.remove_edge(0, 1)
assert G.adj == {0: {2: {0: {}}}, 1: {2: {0: {}}}, 2: {0: {0: {}}, 1: {0: {}}}}
with pytest.raises(nx.NetworkXError):
G.remove_edge(-1, 0)
with pytest.raises(nx.NetworkXError):
G.remove_edge(0, 2, key=1)
def test_remove_edges_from(self):
G = self.K3.copy()
G.remove_edges_from([(0, 1)])
kd = {0: {}}
assert G.adj == {0: {2: kd}, 1: {2: kd}, 2: {0: kd, 1: kd}}
G.remove_edges_from([(0, 0)]) # silent fail
self.K3.add_edge(0, 1)
G = self.K3.copy()
G.remove_edges_from(list(G.edges(data=True, keys=True)))
assert G.adj == {0: {}, 1: {}, 2: {}}
G = self.K3.copy()
G.remove_edges_from(list(G.edges(data=False, keys=True)))
assert G.adj == {0: {}, 1: {}, 2: {}}
G = self.K3.copy()
G.remove_edges_from(list(G.edges(data=False, keys=False)))
assert G.adj == {0: {}, 1: {}, 2: {}}
G = self.K3.copy()
G.remove_edges_from([(0, 1, 0), (0, 2, 0, {}), (1, 2)])
assert G.adj == {0: {1: {1: {}}}, 1: {0: {1: {}}}, 2: {}}
def test_remove_multiedge(self):
G = self.K3
G.add_edge(0, 1, key="parallel edge")
G.remove_edge(0, 1, key="parallel edge")
assert G.adj == {
0: {1: {0: {}}, 2: {0: {}}},
1: {0: {0: {}}, 2: {0: {}}},
2: {0: {0: {}}, 1: {0: {}}},
}
G.remove_edge(0, 1)
kd = {0: {}}
assert G.adj == {0: {2: kd}, 1: {2: kd}, 2: {0: kd, 1: kd}}
with pytest.raises(nx.NetworkXError):
G.remove_edge(-1, 0)
class TestEdgeSubgraph:
"""Unit tests for the :meth:`MultiGraph.edge_subgraph` method."""
def setup_method(self):
# Create a doubly-linked path graph on five nodes.
G = nx.MultiGraph()
nx.add_path(G, range(5))
nx.add_path(G, range(5))
# Add some node, edge, and graph attributes.
for i in range(5):
G.nodes[i]["name"] = f"node{i}"
G.adj[0][1][0]["name"] = "edge010"
G.adj[0][1][1]["name"] = "edge011"
G.adj[3][4][0]["name"] = "edge340"
G.adj[3][4][1]["name"] = "edge341"
G.graph["name"] = "graph"
# Get the subgraph induced by one of the first edges and one of
# the last edges.
self.G = G
self.H = G.edge_subgraph([(0, 1, 0), (3, 4, 1)])
def test_correct_nodes(self):
"""Tests that the subgraph has the correct nodes."""
assert [0, 1, 3, 4] == sorted(self.H.nodes())
def test_correct_edges(self):
"""Tests that the subgraph has the correct edges."""
assert [(0, 1, 0, "edge010"), (3, 4, 1, "edge341")] == sorted(
self.H.edges(keys=True, data="name")
)
def test_add_node(self):
"""Tests that adding a node to the original graph does not
affect the nodes of the subgraph.
"""
self.G.add_node(5)
assert [0, 1, 3, 4] == sorted(self.H.nodes())
def test_remove_node(self):
"""Tests that removing a node in the original graph does
affect the nodes of the subgraph.
"""
self.G.remove_node(0)
assert [1, 3, 4] == sorted(self.H.nodes())
def test_node_attr_dict(self):
"""Tests that the node attribute dictionary of the two graphs is
the same object.
"""
for v in self.H:
assert self.G.nodes[v] == self.H.nodes[v]
# Making a change to G should make a change in H and vice versa.
self.G.nodes[0]["name"] = "foo"
assert self.G.nodes[0] == self.H.nodes[0]
self.H.nodes[1]["name"] = "bar"
assert self.G.nodes[1] == self.H.nodes[1]
def test_edge_attr_dict(self):
"""Tests that the edge attribute dictionary of the two graphs is
the same object.
"""
for u, v, k in self.H.edges(keys=True):
assert self.G._adj[u][v][k] == self.H._adj[u][v][k]
# Making a change to G should make a change in H and vice versa.
self.G._adj[0][1][0]["name"] = "foo"
assert self.G._adj[0][1][0]["name"] == self.H._adj[0][1][0]["name"]
self.H._adj[3][4][1]["name"] = "bar"
assert self.G._adj[3][4][1]["name"] == self.H._adj[3][4][1]["name"]
def test_graph_attr_dict(self):
"""Tests that the graph attribute dictionary of the two graphs
is the same object.
"""
assert self.G.graph is self.H.graph

View file

@ -0,0 +1,40 @@
import networkx as nx
class TestOrdered:
# Just test instantiation.
def test_graph(self):
G = nx.OrderedGraph()
def test_digraph(self):
G = nx.OrderedDiGraph()
def test_multigraph(self):
G = nx.OrderedMultiGraph()
def test_multidigraph(self):
G = nx.OrderedMultiDiGraph()
class TestOrderedFeatures:
@classmethod
def setup_class(cls):
cls.G = nx.OrderedDiGraph()
cls.G.add_nodes_from([1, 2, 3])
cls.G.add_edges_from([(2, 3), (1, 3)])
def test_subgraph_order(self):
G = self.G
G_sub = G.subgraph([1, 2, 3])
assert list(G.nodes) == list(G_sub.nodes)
assert list(G.edges) == list(G_sub.edges)
assert list(G.pred[3]) == list(G_sub.pred[3])
assert [2, 1] == list(G_sub.pred[3])
assert [] == list(G_sub.succ[3])
G_sub = nx.induced_subgraph(G, [1, 2, 3])
assert list(G.nodes) == list(G_sub.nodes)
assert list(G.edges) == list(G_sub.edges)
assert list(G.pred[3]) == list(G_sub.pred[3])
assert [2, 1] == list(G_sub.pred[3])
assert [] == list(G_sub.succ[3])

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,184 @@
from collections import OrderedDict
import networkx as nx
from .test_graph import TestGraph as _TestGraph
from .test_graph import BaseGraphTester
from .test_digraph import TestDiGraph as _TestDiGraph
from .test_digraph import BaseDiGraphTester
from .test_multigraph import TestMultiGraph as _TestMultiGraph
from .test_multidigraph import TestMultiDiGraph as _TestMultiDiGraph
def test_factories():
class mydict1(dict):
pass
class mydict2(dict):
pass
class mydict3(dict):
pass
class mydict4(dict):
pass
class mydict5(dict):
pass
for Graph in (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph):
# print("testing class: ", Graph.__name__)
class MyGraph(Graph):
node_dict_factory = mydict1
adjlist_outer_dict_factory = mydict2
adjlist_inner_dict_factory = mydict3
edge_key_dict_factory = mydict4
edge_attr_dict_factory = mydict5
G = MyGraph()
assert isinstance(G._node, mydict1)
assert isinstance(G._adj, mydict2)
G.add_node(1)
assert isinstance(G._adj[1], mydict3)
if G.is_directed():
assert isinstance(G._pred, mydict2)
assert isinstance(G._succ, mydict2)
assert isinstance(G._pred[1], mydict3)
G.add_edge(1, 2)
if G.is_multigraph():
assert isinstance(G._adj[1][2], mydict4)
assert isinstance(G._adj[1][2][0], mydict5)
else:
assert isinstance(G._adj[1][2], mydict5)
class TestSpecialGraph(_TestGraph):
def setup_method(self):
_TestGraph.setup_method(self)
self.Graph = nx.Graph
class TestOrderedGraph(_TestGraph):
def setup_method(self):
_TestGraph.setup_method(self)
class MyGraph(nx.Graph):
node_dict_factory = OrderedDict
adjlist_outer_dict_factory = OrderedDict
adjlist_inner_dict_factory = OrderedDict
edge_attr_dict_factory = OrderedDict
self.Graph = MyGraph
class TestThinGraph(BaseGraphTester):
def setup_method(self):
all_edge_dict = {"weight": 1}
class MyGraph(nx.Graph):
def edge_attr_dict_factory(self):
return all_edge_dict
self.Graph = MyGraph
# build dict-of-dict-of-dict K3
ed1, ed2, ed3 = (all_edge_dict, all_edge_dict, all_edge_dict)
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = self.k3adj
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
class TestSpecialDiGraph(_TestDiGraph):
def setup_method(self):
_TestDiGraph.setup_method(self)
self.Graph = nx.DiGraph
class TestOrderedDiGraph(_TestDiGraph):
def setup_method(self):
_TestDiGraph.setup_method(self)
class MyGraph(nx.DiGraph):
node_dict_factory = OrderedDict
adjlist_outer_dict_factory = OrderedDict
adjlist_inner_dict_factory = OrderedDict
edge_attr_dict_factory = OrderedDict
self.Graph = MyGraph
class TestThinDiGraph(BaseDiGraphTester):
def setup_method(self):
all_edge_dict = {"weight": 1}
class MyGraph(nx.DiGraph):
def edge_attr_dict_factory(self):
return all_edge_dict
self.Graph = MyGraph
# build dict-of-dict-of-dict K3
ed1, ed2, ed3 = (all_edge_dict, all_edge_dict, all_edge_dict)
ed4, ed5, ed6 = (all_edge_dict, all_edge_dict, all_edge_dict)
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed3, 2: ed4}, 2: {0: ed5, 1: ed6}}
self.k3edges = [(0, 1), (0, 2), (1, 2)]
self.k3nodes = [0, 1, 2]
self.K3 = self.Graph()
self.K3._adj = self.K3._succ = self.k3adj
self.K3._pred = {0: {1: ed3, 2: ed5}, 1: {0: ed1, 2: ed6}, 2: {0: ed2, 1: ed4}}
self.K3._node = {}
self.K3._node[0] = {}
self.K3._node[1] = {}
self.K3._node[2] = {}
ed1, ed2 = (all_edge_dict, all_edge_dict)
self.P3 = self.Graph()
self.P3._adj = {0: {1: ed1}, 1: {2: ed2}, 2: {}}
self.P3._succ = self.P3._adj
self.P3._pred = {0: {}, 1: {0: ed1}, 2: {1: ed2}}
self.P3._node = {}
self.P3._node[0] = {}
self.P3._node[1] = {}
self.P3._node[2] = {}
class TestSpecialMultiGraph(_TestMultiGraph):
def setup_method(self):
_TestMultiGraph.setup_method(self)
self.Graph = nx.MultiGraph
class TestOrderedMultiGraph(_TestMultiGraph):
def setup_method(self):
_TestMultiGraph.setup_method(self)
class MyGraph(nx.MultiGraph):
node_dict_factory = OrderedDict
adjlist_outer_dict_factory = OrderedDict
adjlist_inner_dict_factory = OrderedDict
edge_key_dict_factory = OrderedDict
edge_attr_dict_factory = OrderedDict
self.Graph = MyGraph
class TestSpecialMultiDiGraph(_TestMultiDiGraph):
def setup_method(self):
_TestMultiDiGraph.setup_method(self)
self.Graph = nx.MultiDiGraph
class TestOrderedMultiDiGraph(_TestMultiDiGraph):
def setup_method(self):
_TestMultiDiGraph.setup_method(self)
class MyGraph(nx.MultiDiGraph):
node_dict_factory = OrderedDict
adjlist_outer_dict_factory = OrderedDict
adjlist_inner_dict_factory = OrderedDict
edge_key_dict_factory = OrderedDict
edge_attr_dict_factory = OrderedDict
self.Graph = MyGraph

View file

@ -0,0 +1,351 @@
import pytest
import networkx as nx
class TestSubGraphView:
gview = staticmethod(nx.graphviews.subgraph_view)
graph = nx.Graph
hide_edges_filter = staticmethod(nx.filters.hide_edges)
show_edges_filter = staticmethod(nx.filters.show_edges)
@classmethod
def setup_class(cls):
cls.G = nx.path_graph(9, create_using=cls.graph())
cls.hide_edges_w_hide_nodes = {(3, 4), (4, 5), (5, 6)}
def test_hidden_nodes(self):
hide_nodes = [4, 5, 111]
nodes_gone = nx.filters.hide_nodes(hide_nodes)
gview = self.gview
print(gview)
G = gview(self.G, filter_node=nodes_gone)
assert self.G.nodes - G.nodes == {4, 5}
assert self.G.edges - G.edges == self.hide_edges_w_hide_nodes
if G.is_directed():
assert list(G[3]) == []
assert list(G[2]) == [3]
else:
assert list(G[3]) == [2]
assert set(G[2]) == {1, 3}
pytest.raises(KeyError, G.__getitem__, 4)
pytest.raises(KeyError, G.__getitem__, 112)
pytest.raises(KeyError, G.__getitem__, 111)
assert G.degree(3) == (3 if G.is_multigraph() else 1)
assert G.size() == (7 if G.is_multigraph() else 5)
def test_hidden_edges(self):
hide_edges = [(2, 3), (8, 7), (222, 223)]
edges_gone = self.hide_edges_filter(hide_edges)
gview = self.gview
G = gview(self.G, filter_edge=edges_gone)
assert self.G.nodes == G.nodes
if G.is_directed():
assert self.G.edges - G.edges == {(2, 3)}
assert list(G[2]) == []
assert list(G.pred[3]) == []
assert list(G.pred[2]) == [1]
assert G.size() == 7
else:
assert self.G.edges - G.edges == {(2, 3), (7, 8)}
assert list(G[2]) == [1]
assert G.size() == 6
assert list(G[3]) == [4]
pytest.raises(KeyError, G.__getitem__, 221)
pytest.raises(KeyError, G.__getitem__, 222)
assert G.degree(3) == 1
def test_shown_node(self):
induced_subgraph = nx.filters.show_nodes([2, 3, 111])
gview = self.gview
G = gview(self.G, filter_node=induced_subgraph)
assert set(G.nodes) == {2, 3}
if G.is_directed():
assert list(G[3]) == []
else:
assert list(G[3]) == [2]
assert list(G[2]) == [3]
pytest.raises(KeyError, G.__getitem__, 4)
pytest.raises(KeyError, G.__getitem__, 112)
pytest.raises(KeyError, G.__getitem__, 111)
assert G.degree(3) == (3 if G.is_multigraph() else 1)
assert G.size() == (3 if G.is_multigraph() else 1)
def test_shown_edges(self):
show_edges = [(2, 3), (8, 7), (222, 223)]
edge_subgraph = self.show_edges_filter(show_edges)
G = self.gview(self.G, filter_edge=edge_subgraph)
assert self.G.nodes == G.nodes
if G.is_directed():
assert G.edges == {(2, 3)}
assert list(G[3]) == []
assert list(G[2]) == [3]
assert list(G.pred[3]) == [2]
assert list(G.pred[2]) == []
assert G.size() == 1
else:
assert G.edges == {(2, 3), (7, 8)}
assert list(G[3]) == [2]
assert list(G[2]) == [3]
assert G.size() == 2
pytest.raises(KeyError, G.__getitem__, 221)
pytest.raises(KeyError, G.__getitem__, 222)
assert G.degree(3) == 1
class TestSubDiGraphView(TestSubGraphView):
gview = staticmethod(nx.graphviews.subgraph_view)
graph = nx.DiGraph
hide_edges_filter = staticmethod(nx.filters.hide_diedges)
show_edges_filter = staticmethod(nx.filters.show_diedges)
hide_edges = [(2, 3), (8, 7), (222, 223)]
excluded = {(2, 3), (3, 4), (4, 5), (5, 6)}
def test_inoutedges(self):
edges_gone = self.hide_edges_filter(self.hide_edges)
hide_nodes = [4, 5, 111]
nodes_gone = nx.filters.hide_nodes(hide_nodes)
G = self.gview(self.G, nodes_gone, edges_gone)
assert self.G.in_edges - G.in_edges == self.excluded
assert self.G.out_edges - G.out_edges == self.excluded
def test_pred(self):
edges_gone = self.hide_edges_filter(self.hide_edges)
hide_nodes = [4, 5, 111]
nodes_gone = nx.filters.hide_nodes(hide_nodes)
G = self.gview(self.G, nodes_gone, edges_gone)
assert list(G.pred[2]) == [1]
assert list(G.pred[6]) == []
def test_inout_degree(self):
edges_gone = self.hide_edges_filter(self.hide_edges)
hide_nodes = [4, 5, 111]
nodes_gone = nx.filters.hide_nodes(hide_nodes)
G = self.gview(self.G, nodes_gone, edges_gone)
assert G.degree(2) == 1
assert G.out_degree(2) == 0
assert G.in_degree(2) == 1
assert G.size() == 4
# multigraph
class TestMultiGraphView(TestSubGraphView):
gview = staticmethod(nx.graphviews.subgraph_view)
graph = nx.MultiGraph
hide_edges_filter = staticmethod(nx.filters.hide_multiedges)
show_edges_filter = staticmethod(nx.filters.show_multiedges)
@classmethod
def setup_class(cls):
cls.G = nx.path_graph(9, create_using=cls.graph())
multiedges = {(2, 3, 4), (2, 3, 5)}
cls.G.add_edges_from(multiedges)
cls.hide_edges_w_hide_nodes = {(3, 4, 0), (4, 5, 0), (5, 6, 0)}
def test_hidden_edges(self):
hide_edges = [(2, 3, 4), (2, 3, 3), (8, 7, 0), (222, 223, 0)]
edges_gone = self.hide_edges_filter(hide_edges)
G = self.gview(self.G, filter_edge=edges_gone)
assert self.G.nodes == G.nodes
if G.is_directed():
assert self.G.edges - G.edges == {(2, 3, 4)}
assert list(G[3]) == [4]
assert list(G[2]) == [3]
assert list(G.pred[3]) == [2] # only one 2 but two edges
assert list(G.pred[2]) == [1]
assert G.size() == 9
else:
assert self.G.edges - G.edges == {(2, 3, 4), (7, 8, 0)}
assert list(G[3]) == [2, 4]
assert list(G[2]) == [1, 3]
assert G.size() == 8
assert G.degree(3) == 3
pytest.raises(KeyError, G.__getitem__, 221)
pytest.raises(KeyError, G.__getitem__, 222)
def test_shown_edges(self):
show_edges = [(2, 3, 4), (2, 3, 3), (8, 7, 0), (222, 223, 0)]
edge_subgraph = self.show_edges_filter(show_edges)
G = self.gview(self.G, filter_edge=edge_subgraph)
assert self.G.nodes == G.nodes
if G.is_directed():
assert G.edges == {(2, 3, 4)}
assert list(G[3]) == []
assert list(G.pred[3]) == [2]
assert list(G.pred[2]) == []
assert G.size() == 1
else:
assert G.edges == {(2, 3, 4), (7, 8, 0)}
assert G.size() == 2
assert list(G[3]) == [2]
assert G.degree(3) == 1
assert list(G[2]) == [3]
pytest.raises(KeyError, G.__getitem__, 221)
pytest.raises(KeyError, G.__getitem__, 222)
# multidigraph
class TestMultiDiGraphView(TestMultiGraphView, TestSubDiGraphView):
gview = staticmethod(nx.graphviews.subgraph_view)
graph = nx.MultiDiGraph
hide_edges_filter = staticmethod(nx.filters.hide_multidiedges)
show_edges_filter = staticmethod(nx.filters.show_multidiedges)
hide_edges = [(2, 3, 0), (8, 7, 0), (222, 223, 0)]
excluded = {(2, 3, 0), (3, 4, 0), (4, 5, 0), (5, 6, 0)}
def test_inout_degree(self):
edges_gone = self.hide_edges_filter(self.hide_edges)
hide_nodes = [4, 5, 111]
nodes_gone = nx.filters.hide_nodes(hide_nodes)
G = self.gview(self.G, nodes_gone, edges_gone)
assert G.degree(2) == 3
assert G.out_degree(2) == 2
assert G.in_degree(2) == 1
assert G.size() == 6
# induced_subgraph
class TestInducedSubGraph:
@classmethod
def setup_class(cls):
cls.K3 = G = nx.complete_graph(3)
G.graph["foo"] = []
G.nodes[0]["foo"] = []
G.remove_edge(1, 2)
ll = []
G.add_edge(1, 2, foo=ll)
G.add_edge(2, 1, foo=ll)
def test_full_graph(self):
G = self.K3
H = nx.induced_subgraph(G, [0, 1, 2, 5])
assert H.name == G.name
self.graphs_equal(H, G)
self.same_attrdict(H, G)
def test_partial_subgraph(self):
G = self.K3
H = nx.induced_subgraph(G, 0)
assert dict(H.adj) == {0: {}}
assert dict(G.adj) != {0: {}}
H = nx.induced_subgraph(G, [0, 1])
assert dict(H.adj) == {0: {1: {}}, 1: {0: {}}}
def same_attrdict(self, H, G):
old_foo = H[1][2]["foo"]
H.edges[1, 2]["foo"] = "baz"
assert G.edges == H.edges
H.edges[1, 2]["foo"] = old_foo
assert G.edges == H.edges
old_foo = H.nodes[0]["foo"]
H.nodes[0]["foo"] = "baz"
assert G.nodes == H.nodes
H.nodes[0]["foo"] = old_foo
assert G.nodes == H.nodes
def graphs_equal(self, H, G):
assert G._adj == H._adj
assert G._node == H._node
assert G.graph == H.graph
assert G.name == H.name
if not G.is_directed() and not H.is_directed():
assert H._adj[1][2] is H._adj[2][1]
assert G._adj[1][2] is G._adj[2][1]
else: # at least one is directed
if not G.is_directed():
G._pred = G._adj
G._succ = G._adj
if not H.is_directed():
H._pred = H._adj
H._succ = H._adj
assert G._pred == H._pred
assert G._succ == H._succ
assert H._succ[1][2] is H._pred[2][1]
assert G._succ[1][2] is G._pred[2][1]
# edge_subgraph
class TestEdgeSubGraph:
@classmethod
def setup_class(cls):
# Create a path graph on five nodes.
cls.G = G = nx.path_graph(5)
# Add some node, edge, and graph attributes.
for i in range(5):
G.nodes[i]["name"] = f"node{i}"
G.edges[0, 1]["name"] = "edge01"
G.edges[3, 4]["name"] = "edge34"
G.graph["name"] = "graph"
# Get the subgraph induced by the first and last edges.
cls.H = nx.edge_subgraph(G, [(0, 1), (3, 4)])
def test_correct_nodes(self):
"""Tests that the subgraph has the correct nodes."""
assert [0, 1, 3, 4] == sorted(self.H.nodes)
def test_correct_edges(self):
"""Tests that the subgraph has the correct edges."""
assert [(0, 1, "edge01"), (3, 4, "edge34")] == sorted(self.H.edges(data="name"))
def test_add_node(self):
"""Tests that adding a node to the original graph does not
affect the nodes of the subgraph.
"""
self.G.add_node(5)
assert [0, 1, 3, 4] == sorted(self.H.nodes)
self.G.remove_node(5)
def test_remove_node(self):
"""Tests that removing a node in the original graph
removes the nodes of the subgraph.
"""
self.G.remove_node(0)
assert [1, 3, 4] == sorted(self.H.nodes)
self.G.add_edge(0, 1)
def test_node_attr_dict(self):
"""Tests that the node attribute dictionary of the two graphs is
the same object.
"""
for v in self.H:
assert self.G.nodes[v] == self.H.nodes[v]
# Making a change to G should make a change in H and vice versa.
self.G.nodes[0]["name"] = "foo"
assert self.G.nodes[0] == self.H.nodes[0]
self.H.nodes[1]["name"] = "bar"
assert self.G.nodes[1] == self.H.nodes[1]
def test_edge_attr_dict(self):
"""Tests that the edge attribute dictionary of the two graphs is
the same object.
"""
for u, v in self.H.edges():
assert self.G.edges[u, v] == self.H.edges[u, v]
# Making a change to G should make a change in H and vice versa.
self.G.edges[0, 1]["name"] = "foo"
assert self.G.edges[0, 1]["name"] == self.H.edges[0, 1]["name"]
self.H.edges[3, 4]["name"] = "bar"
assert self.G.edges[3, 4]["name"] == self.H.edges[3, 4]["name"]
def test_graph_attr_dict(self):
"""Tests that the graph attribute dictionary of the two graphs
is the same object.
"""
assert self.G.graph is self.H.graph
def test_readonly(self):
"""Tests that the subgraph cannot change the graph structure"""
pytest.raises(nx.NetworkXError, self.H.add_node, 5)
pytest.raises(nx.NetworkXError, self.H.remove_node, 0)
pytest.raises(nx.NetworkXError, self.H.add_edge, 5, 6)
pytest.raises(nx.NetworkXError, self.H.remove_edge, 0, 1)