Spaces:
Paused
Paused
| import pytest | |
| import networkx as nx | |
| from networkx.utils import edges_equal, nodes_equal | |
| # Note: SubGraph views are not tested here. They have their own testing file | |
| class TestReverseView: | |
| def setup_method(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): | |
| G = nx.Graph() | |
| pytest.raises(nx.NetworkXNotImplemented, nx.reverse_view, G) | |
| 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_method(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): | |
| MG = nx.MultiGraph(self.G) | |
| pytest.raises(nx.NetworkXNotImplemented, nx.reverse_view, MG) | |
| def test_generic_multitype(): | |
| nxg = nx.graphviews | |
| G = nx.DiGraph([(1, 2)]) | |
| with pytest.raises(nx.NetworkXError): | |
| nxg.generic_graph_view(G, create_using=nx.MultiGraph) | |
| G = nx.MultiDiGraph([(1, 2)]) | |
| with pytest.raises(nx.NetworkXError): | |
| nxg.generic_graph_view(G, create_using=nx.DiGraph) | |
| class TestToDirected: | |
| def setup_method(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_method(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: | |
| 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.Graph(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.MultiGraph(self.MGv) | |
| assert G.__class__.__name__ == "MultiGraph" | |
| G = G.copy(as_view=True) | |
| assert G.__class__.__name__ == "MultiGraph" | |
| 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 3 not in H or 3 in SG | |