add padding function to imgScalePadding()
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,268 +0,0 @@
|
||||
"""
|
||||
Unit tests for adjlist.
|
||||
"""
|
||||
import io
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, graphs_equal, nodes_equal
|
||||
|
||||
|
||||
class TestAdjlist:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.Graph(name="test")
|
||||
e = [("a", "b"), ("b", "c"), ("c", "d"), ("d", "e"), ("e", "f"), ("a", "f")]
|
||||
cls.G.add_edges_from(e)
|
||||
cls.G.add_node("g")
|
||||
cls.DG = nx.DiGraph(cls.G)
|
||||
cls.XG = nx.MultiGraph()
|
||||
cls.XG.add_weighted_edges_from([(1, 2, 5), (1, 2, 5), (1, 2, 1), (3, 3, 42)])
|
||||
cls.XDG = nx.MultiDiGraph(cls.XG)
|
||||
|
||||
def test_read_multiline_adjlist_1(self):
|
||||
# Unit test for https://networkx.lanl.gov/trac/ticket/252
|
||||
s = b"""# comment line
|
||||
1 2
|
||||
# comment line
|
||||
2
|
||||
3
|
||||
"""
|
||||
bytesIO = io.BytesIO(s)
|
||||
G = nx.read_multiline_adjlist(bytesIO)
|
||||
adj = {"1": {"3": {}, "2": {}}, "3": {"1": {}}, "2": {"1": {}}}
|
||||
assert graphs_equal(G, nx.Graph(adj))
|
||||
|
||||
def test_unicode(self):
|
||||
G = nx.Graph()
|
||||
name1 = chr(2344) + chr(123) + chr(6543)
|
||||
name2 = chr(5543) + chr(1543) + chr(324)
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(fname)
|
||||
assert graphs_equal(G, H)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_latin1_err(self):
|
||||
G = nx.Graph()
|
||||
name1 = chr(2344) + chr(123) + chr(6543)
|
||||
name2 = chr(5543) + chr(1543) + chr(324)
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
pytest.raises(
|
||||
UnicodeEncodeError, nx.write_multiline_adjlist, G, fname, encoding="latin-1"
|
||||
)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_latin1(self):
|
||||
G = nx.Graph()
|
||||
name1 = "Bj" + chr(246) + "rk"
|
||||
name2 = chr(220) + "ber"
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname, encoding="latin-1")
|
||||
H = nx.read_multiline_adjlist(fname, encoding="latin-1")
|
||||
assert graphs_equal(G, H)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_parse_adjlist(self):
|
||||
lines = ["1 2 5", "2 3 4", "3 5", "4", "5"]
|
||||
nx.parse_adjlist(lines, nodetype=int) # smoke test
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_adjlist(lines, nodetype="int")
|
||||
lines = ["1 2 5", "2 b", "c"]
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_adjlist(lines, nodetype=int)
|
||||
|
||||
def test_adjlist_graph(self):
|
||||
G = self.G
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_adjlist(G, fname)
|
||||
H = nx.read_adjlist(fname)
|
||||
H2 = nx.read_adjlist(fname)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_adjlist_digraph(self):
|
||||
G = self.DG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_adjlist(G, fname)
|
||||
H = nx.read_adjlist(fname, create_using=nx.DiGraph())
|
||||
H2 = nx.read_adjlist(fname, create_using=nx.DiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_adjlist_integers(self):
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
G = nx.convert_node_labels_to_integers(self.G)
|
||||
nx.write_adjlist(G, fname)
|
||||
H = nx.read_adjlist(fname, nodetype=int)
|
||||
H2 = nx.read_adjlist(fname, nodetype=int)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_adjlist_multigraph(self):
|
||||
G = self.XG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_adjlist(G, fname)
|
||||
H = nx.read_adjlist(fname, nodetype=int, create_using=nx.MultiGraph())
|
||||
H2 = nx.read_adjlist(fname, nodetype=int, create_using=nx.MultiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_adjlist_multidigraph(self):
|
||||
G = self.XDG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_adjlist(G, fname)
|
||||
H = nx.read_adjlist(fname, nodetype=int, create_using=nx.MultiDiGraph())
|
||||
H2 = nx.read_adjlist(fname, nodetype=int, create_using=nx.MultiDiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_adjlist_delimiter(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.path_graph(3)
|
||||
nx.write_adjlist(G, fh, delimiter=":")
|
||||
fh.seek(0)
|
||||
H = nx.read_adjlist(fh, nodetype=int, delimiter=":")
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
|
||||
|
||||
class TestMultilineAdjlist:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.Graph(name="test")
|
||||
e = [("a", "b"), ("b", "c"), ("c", "d"), ("d", "e"), ("e", "f"), ("a", "f")]
|
||||
cls.G.add_edges_from(e)
|
||||
cls.G.add_node("g")
|
||||
cls.DG = nx.DiGraph(cls.G)
|
||||
cls.DG.remove_edge("b", "a")
|
||||
cls.DG.remove_edge("b", "c")
|
||||
cls.XG = nx.MultiGraph()
|
||||
cls.XG.add_weighted_edges_from([(1, 2, 5), (1, 2, 5), (1, 2, 1), (3, 3, 42)])
|
||||
cls.XDG = nx.MultiDiGraph(cls.XG)
|
||||
|
||||
def test_parse_multiline_adjlist(self):
|
||||
lines = [
|
||||
"1 2",
|
||||
"b {'weight':3, 'name': 'Frodo'}",
|
||||
"c {}",
|
||||
"d 1",
|
||||
"e {'weight':6, 'name': 'Saruman'}",
|
||||
]
|
||||
nx.parse_multiline_adjlist(iter(lines)) # smoke test
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines), nodetype=int)
|
||||
nx.parse_multiline_adjlist(iter(lines), edgetype=str) # smoke test
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines), nodetype=int)
|
||||
lines = ["1 a"]
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines))
|
||||
lines = ["a 2"]
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines), nodetype=int)
|
||||
lines = ["1 2"]
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines))
|
||||
lines = ["1 2", "2 {}"]
|
||||
with pytest.raises(TypeError):
|
||||
nx.parse_multiline_adjlist(iter(lines))
|
||||
|
||||
def test_multiline_adjlist_graph(self):
|
||||
G = self.G
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(fname)
|
||||
H2 = nx.read_multiline_adjlist(fname)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_multiline_adjlist_digraph(self):
|
||||
G = self.DG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(fname, create_using=nx.DiGraph())
|
||||
H2 = nx.read_multiline_adjlist(fname, create_using=nx.DiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_multiline_adjlist_integers(self):
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
G = nx.convert_node_labels_to_integers(self.G)
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(fname, nodetype=int)
|
||||
H2 = nx.read_multiline_adjlist(fname, nodetype=int)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_multiline_adjlist_multigraph(self):
|
||||
G = self.XG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(fname, nodetype=int, create_using=nx.MultiGraph())
|
||||
H2 = nx.read_multiline_adjlist(
|
||||
fname, nodetype=int, create_using=nx.MultiGraph()
|
||||
)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_multiline_adjlist_multidigraph(self):
|
||||
G = self.XDG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_multiline_adjlist(G, fname)
|
||||
H = nx.read_multiline_adjlist(
|
||||
fname, nodetype=int, create_using=nx.MultiDiGraph()
|
||||
)
|
||||
H2 = nx.read_multiline_adjlist(
|
||||
fname, nodetype=int, create_using=nx.MultiDiGraph()
|
||||
)
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_multiline_adjlist_delimiter(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.path_graph(3)
|
||||
nx.write_multiline_adjlist(G, fh, delimiter=":")
|
||||
fh.seek(0)
|
||||
H = nx.read_multiline_adjlist(fh, nodetype=int, delimiter=":")
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
@@ -1,314 +0,0 @@
|
||||
"""
|
||||
Unit tests for edgelists.
|
||||
"""
|
||||
import io
|
||||
import os
|
||||
import tempfile
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, graphs_equal, nodes_equal
|
||||
|
||||
edges_no_data = textwrap.dedent(
|
||||
"""
|
||||
# comment line
|
||||
1 2
|
||||
# comment line
|
||||
2 3
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
edges_with_values = textwrap.dedent(
|
||||
"""
|
||||
# comment line
|
||||
1 2 2.0
|
||||
# comment line
|
||||
2 3 3.0
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
edges_with_weight = textwrap.dedent(
|
||||
"""
|
||||
# comment line
|
||||
1 2 {'weight':2.0}
|
||||
# comment line
|
||||
2 3 {'weight':3.0}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
edges_with_multiple_attrs = textwrap.dedent(
|
||||
"""
|
||||
# comment line
|
||||
1 2 {'weight':2.0, 'color':'green'}
|
||||
# comment line
|
||||
2 3 {'weight':3.0, 'color':'red'}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
edges_with_multiple_attrs_csv = textwrap.dedent(
|
||||
"""
|
||||
# comment line
|
||||
1, 2, {'weight':2.0, 'color':'green'}
|
||||
# comment line
|
||||
2, 3, {'weight':3.0, 'color':'red'}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
_expected_edges_weights = [(1, 2, {"weight": 2.0}), (2, 3, {"weight": 3.0})]
|
||||
_expected_edges_multiattr = [
|
||||
(1, 2, {"weight": 2.0, "color": "green"}),
|
||||
(2, 3, {"weight": 3.0, "color": "red"}),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("data", "extra_kwargs"),
|
||||
(
|
||||
(edges_no_data, {}),
|
||||
(edges_with_values, {}),
|
||||
(edges_with_weight, {}),
|
||||
(edges_with_multiple_attrs, {}),
|
||||
(edges_with_multiple_attrs_csv, {"delimiter": ","}),
|
||||
),
|
||||
)
|
||||
def test_read_edgelist_no_data(data, extra_kwargs):
|
||||
bytesIO = io.BytesIO(data.encode("utf-8"))
|
||||
G = nx.read_edgelist(bytesIO, nodetype=int, data=False, **extra_kwargs)
|
||||
assert edges_equal(G.edges(), [(1, 2), (2, 3)])
|
||||
|
||||
|
||||
def test_read_weighted_edgelist():
|
||||
bytesIO = io.BytesIO(edges_with_values.encode("utf-8"))
|
||||
G = nx.read_weighted_edgelist(bytesIO, nodetype=int)
|
||||
assert edges_equal(G.edges(data=True), _expected_edges_weights)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("data", "extra_kwargs", "expected"),
|
||||
(
|
||||
(edges_with_weight, {}, _expected_edges_weights),
|
||||
(edges_with_multiple_attrs, {}, _expected_edges_multiattr),
|
||||
(edges_with_multiple_attrs_csv, {"delimiter": ","}, _expected_edges_multiattr),
|
||||
),
|
||||
)
|
||||
def test_read_edgelist_with_data(data, extra_kwargs, expected):
|
||||
bytesIO = io.BytesIO(data.encode("utf-8"))
|
||||
G = nx.read_edgelist(bytesIO, nodetype=int, **extra_kwargs)
|
||||
assert edges_equal(G.edges(data=True), expected)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def example_graph():
|
||||
G = nx.Graph()
|
||||
G.add_weighted_edges_from([(1, 2, 3.0), (2, 3, 27.0), (3, 4, 3.0)])
|
||||
return G
|
||||
|
||||
|
||||
def test_parse_edgelist_no_data(example_graph):
|
||||
G = example_graph
|
||||
H = nx.parse_edgelist(["1 2", "2 3", "3 4"], nodetype=int)
|
||||
assert nodes_equal(G.nodes, H.nodes)
|
||||
assert edges_equal(G.edges, H.edges)
|
||||
|
||||
|
||||
def test_parse_edgelist_with_data_dict(example_graph):
|
||||
G = example_graph
|
||||
H = nx.parse_edgelist(
|
||||
["1 2 {'weight': 3}", "2 3 {'weight': 27}", "3 4 {'weight': 3.0}"], nodetype=int
|
||||
)
|
||||
assert nodes_equal(G.nodes, H.nodes)
|
||||
assert edges_equal(G.edges(data=True), H.edges(data=True))
|
||||
|
||||
|
||||
def test_parse_edgelist_with_data_list(example_graph):
|
||||
G = example_graph
|
||||
H = nx.parse_edgelist(
|
||||
["1 2 3", "2 3 27", "3 4 3.0"], nodetype=int, data=(("weight", float),)
|
||||
)
|
||||
assert nodes_equal(G.nodes, H.nodes)
|
||||
assert edges_equal(G.edges(data=True), H.edges(data=True))
|
||||
|
||||
|
||||
def test_parse_edgelist():
|
||||
# ignore lines with less than 2 nodes
|
||||
lines = ["1;2", "2 3", "3 4"]
|
||||
G = nx.parse_edgelist(lines, nodetype=int)
|
||||
assert list(G.edges()) == [(2, 3), (3, 4)]
|
||||
# unknown nodetype
|
||||
with pytest.raises(TypeError, match="Failed to convert nodes"):
|
||||
lines = ["1 2", "2 3", "3 4"]
|
||||
nx.parse_edgelist(lines, nodetype="nope")
|
||||
# lines have invalid edge format
|
||||
with pytest.raises(TypeError, match="Failed to convert edge data"):
|
||||
lines = ["1 2 3", "2 3", "3 4"]
|
||||
nx.parse_edgelist(lines, nodetype=int)
|
||||
# edge data and data_keys not the same length
|
||||
with pytest.raises(IndexError, match="not the same length"):
|
||||
lines = ["1 2 3", "2 3 27", "3 4 3.0"]
|
||||
nx.parse_edgelist(
|
||||
lines, nodetype=int, data=(("weight", float), ("capacity", int))
|
||||
)
|
||||
# edge data can't be converted to edge type
|
||||
with pytest.raises(TypeError, match="Failed to convert"):
|
||||
lines = ["1 2 't1'", "2 3 't3'", "3 4 't3'"]
|
||||
nx.parse_edgelist(lines, nodetype=int, data=(("weight", float),))
|
||||
|
||||
|
||||
def test_comments_None():
|
||||
edgelist = ["node#1 node#2", "node#2 node#3"]
|
||||
# comments=None supported to ignore all comment characters
|
||||
G = nx.parse_edgelist(edgelist, comments=None)
|
||||
H = nx.Graph([e.split(" ") for e in edgelist])
|
||||
assert edges_equal(G.edges, H.edges)
|
||||
|
||||
|
||||
class TestEdgelist:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.Graph(name="test")
|
||||
e = [("a", "b"), ("b", "c"), ("c", "d"), ("d", "e"), ("e", "f"), ("a", "f")]
|
||||
cls.G.add_edges_from(e)
|
||||
cls.G.add_node("g")
|
||||
cls.DG = nx.DiGraph(cls.G)
|
||||
cls.XG = nx.MultiGraph()
|
||||
cls.XG.add_weighted_edges_from([(1, 2, 5), (1, 2, 5), (1, 2, 1), (3, 3, 42)])
|
||||
cls.XDG = nx.MultiDiGraph(cls.XG)
|
||||
|
||||
def test_write_edgelist_1(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.Graph()
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
nx.write_edgelist(G, fh, data=False)
|
||||
fh.seek(0)
|
||||
assert fh.read() == b"1 2\n2 3\n"
|
||||
|
||||
def test_write_edgelist_2(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.Graph()
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
nx.write_edgelist(G, fh, data=True)
|
||||
fh.seek(0)
|
||||
assert fh.read() == b"1 2 {}\n2 3 {}\n"
|
||||
|
||||
def test_write_edgelist_3(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.Graph()
|
||||
G.add_edge(1, 2, weight=2.0)
|
||||
G.add_edge(2, 3, weight=3.0)
|
||||
nx.write_edgelist(G, fh, data=True)
|
||||
fh.seek(0)
|
||||
assert fh.read() == b"1 2 {'weight': 2.0}\n2 3 {'weight': 3.0}\n"
|
||||
|
||||
def test_write_edgelist_4(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.Graph()
|
||||
G.add_edge(1, 2, weight=2.0)
|
||||
G.add_edge(2, 3, weight=3.0)
|
||||
nx.write_edgelist(G, fh, data=[("weight")])
|
||||
fh.seek(0)
|
||||
assert fh.read() == b"1 2 2.0\n2 3 3.0\n"
|
||||
|
||||
def test_unicode(self):
|
||||
G = nx.Graph()
|
||||
name1 = chr(2344) + chr(123) + chr(6543)
|
||||
name2 = chr(5543) + chr(1543) + chr(324)
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname)
|
||||
assert graphs_equal(G, H)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_latin1_issue(self):
|
||||
G = nx.Graph()
|
||||
name1 = chr(2344) + chr(123) + chr(6543)
|
||||
name2 = chr(5543) + chr(1543) + chr(324)
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
pytest.raises(
|
||||
UnicodeEncodeError, nx.write_edgelist, G, fname, encoding="latin-1"
|
||||
)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_latin1(self):
|
||||
G = nx.Graph()
|
||||
name1 = "Bj" + chr(246) + "rk"
|
||||
name2 = chr(220) + "ber"
|
||||
G.add_edge(name1, "Radiohead", **{name2: 3})
|
||||
fd, fname = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname, encoding="latin-1")
|
||||
H = nx.read_edgelist(fname, encoding="latin-1")
|
||||
assert graphs_equal(G, H)
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_edgelist_graph(self):
|
||||
G = self.G
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname)
|
||||
H2 = nx.read_edgelist(fname)
|
||||
assert H is not H2 # they should be different graphs
|
||||
G.remove_node("g") # isolated nodes are not written in edgelist
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_edgelist_digraph(self):
|
||||
G = self.DG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname, create_using=nx.DiGraph())
|
||||
H2 = nx.read_edgelist(fname, create_using=nx.DiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
G.remove_node("g") # isolated nodes are not written in edgelist
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_edgelist_integers(self):
|
||||
G = nx.convert_node_labels_to_integers(self.G)
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname, nodetype=int)
|
||||
# isolated nodes are not written in edgelist
|
||||
G.remove_nodes_from(list(nx.isolates(G)))
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_edgelist_multigraph(self):
|
||||
G = self.XG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname, nodetype=int, create_using=nx.MultiGraph())
|
||||
H2 = nx.read_edgelist(fname, nodetype=int, create_using=nx.MultiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_edgelist_multidigraph(self):
|
||||
G = self.XDG
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
nx.write_edgelist(G, fname)
|
||||
H = nx.read_edgelist(fname, nodetype=int, create_using=nx.MultiDiGraph())
|
||||
H2 = nx.read_edgelist(fname, nodetype=int, create_using=nx.MultiDiGraph())
|
||||
assert H is not H2 # they should be different graphs
|
||||
assert nodes_equal(list(H), list(G))
|
||||
assert edges_equal(list(H.edges()), list(G.edges()))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
@@ -1,557 +0,0 @@
|
||||
import io
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestGEXF:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.simple_directed_data = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
|
||||
<graph mode="static" defaultedgetype="directed">
|
||||
<nodes>
|
||||
<node id="0" label="Hello" />
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" />
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
cls.simple_directed_graph = nx.DiGraph()
|
||||
cls.simple_directed_graph.add_node("0", label="Hello")
|
||||
cls.simple_directed_graph.add_node("1", label="World")
|
||||
cls.simple_directed_graph.add_edge("0", "1", id="0")
|
||||
|
||||
cls.simple_directed_fh = io.BytesIO(cls.simple_directed_data.encode("UTF-8"))
|
||||
|
||||
cls.attribute_data = """<?xml version="1.0" encoding="UTF-8"?>\
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi="http://www.w3.\
|
||||
org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gexf.net/\
|
||||
1.2draft http://www.gexf.net/1.2draft/gexf.xsd" version="1.2">
|
||||
<meta lastmodifieddate="2009-03-20">
|
||||
<creator>Gephi.org</creator>
|
||||
<description>A Web network</description>
|
||||
</meta>
|
||||
<graph defaultedgetype="directed">
|
||||
<attributes class="node">
|
||||
<attribute id="0" title="url" type="string"/>
|
||||
<attribute id="1" title="indegree" type="integer"/>
|
||||
<attribute id="2" title="frog" type="boolean">
|
||||
<default>true</default>
|
||||
</attribute>
|
||||
</attributes>
|
||||
<nodes>
|
||||
<node id="0" label="Gephi">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="https://gephi.org"/>
|
||||
<attvalue for="1" value="1"/>
|
||||
<attvalue for="2" value="false"/>
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="1" label="Webatlas">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="http://webatlas.fr"/>
|
||||
<attvalue for="1" value="2"/>
|
||||
<attvalue for="2" value="false"/>
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="2" label="RTGI">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="http://rtgi.fr"/>
|
||||
<attvalue for="1" value="1"/>
|
||||
<attvalue for="2" value="true"/>
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="3" label="BarabasiLab">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="http://barabasilab.com"/>
|
||||
<attvalue for="1" value="1"/>
|
||||
<attvalue for="2" value="true"/>
|
||||
</attvalues>
|
||||
</node>
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" label="foo"/>
|
||||
<edge id="1" source="0" target="2"/>
|
||||
<edge id="2" source="1" target="0"/>
|
||||
<edge id="3" source="2" target="1"/>
|
||||
<edge id="4" source="0" target="3"/>
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
cls.attribute_graph = nx.DiGraph()
|
||||
cls.attribute_graph.graph["node_default"] = {"frog": True}
|
||||
cls.attribute_graph.add_node(
|
||||
"0", label="Gephi", url="https://gephi.org", indegree=1, frog=False
|
||||
)
|
||||
cls.attribute_graph.add_node(
|
||||
"1", label="Webatlas", url="http://webatlas.fr", indegree=2, frog=False
|
||||
)
|
||||
cls.attribute_graph.add_node(
|
||||
"2", label="RTGI", url="http://rtgi.fr", indegree=1, frog=True
|
||||
)
|
||||
cls.attribute_graph.add_node(
|
||||
"3",
|
||||
label="BarabasiLab",
|
||||
url="http://barabasilab.com",
|
||||
indegree=1,
|
||||
frog=True,
|
||||
)
|
||||
cls.attribute_graph.add_edge("0", "1", id="0", label="foo")
|
||||
cls.attribute_graph.add_edge("0", "2", id="1")
|
||||
cls.attribute_graph.add_edge("1", "0", id="2")
|
||||
cls.attribute_graph.add_edge("2", "1", id="3")
|
||||
cls.attribute_graph.add_edge("0", "3", id="4")
|
||||
cls.attribute_fh = io.BytesIO(cls.attribute_data.encode("UTF-8"))
|
||||
|
||||
cls.simple_undirected_data = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
|
||||
<graph mode="static" defaultedgetype="undirected">
|
||||
<nodes>
|
||||
<node id="0" label="Hello" />
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" />
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
cls.simple_undirected_graph = nx.Graph()
|
||||
cls.simple_undirected_graph.add_node("0", label="Hello")
|
||||
cls.simple_undirected_graph.add_node("1", label="World")
|
||||
cls.simple_undirected_graph.add_edge("0", "1", id="0")
|
||||
|
||||
cls.simple_undirected_fh = io.BytesIO(
|
||||
cls.simple_undirected_data.encode("UTF-8")
|
||||
)
|
||||
|
||||
def test_read_simple_directed_graphml(self):
|
||||
G = self.simple_directed_graph
|
||||
H = nx.read_gexf(self.simple_directed_fh)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(G.edges()) == sorted(H.edges())
|
||||
assert sorted(G.edges(data=True)) == sorted(H.edges(data=True))
|
||||
self.simple_directed_fh.seek(0)
|
||||
|
||||
def test_write_read_simple_directed_graphml(self):
|
||||
G = self.simple_directed_graph
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(G.edges()) == sorted(H.edges())
|
||||
assert sorted(G.edges(data=True)) == sorted(H.edges(data=True))
|
||||
self.simple_directed_fh.seek(0)
|
||||
|
||||
def test_read_simple_undirected_graphml(self):
|
||||
G = self.simple_undirected_graph
|
||||
H = nx.read_gexf(self.simple_undirected_fh)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
self.simple_undirected_fh.seek(0)
|
||||
|
||||
def test_read_attribute_graphml(self):
|
||||
G = self.attribute_graph
|
||||
H = nx.read_gexf(self.attribute_fh)
|
||||
assert sorted(G.nodes(True)) == sorted(H.nodes(data=True))
|
||||
ge = sorted(G.edges(data=True))
|
||||
he = sorted(H.edges(data=True))
|
||||
for a, b in zip(ge, he):
|
||||
assert a == b
|
||||
self.attribute_fh.seek(0)
|
||||
|
||||
def test_directed_edge_in_undirected(self):
|
||||
s = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version='1.2'>
|
||||
<graph mode="static" defaultedgetype="undirected" name="">
|
||||
<nodes>
|
||||
<node id="0" label="Hello" />
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" type="directed"/>
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
fh = io.BytesIO(s.encode("UTF-8"))
|
||||
pytest.raises(nx.NetworkXError, nx.read_gexf, fh)
|
||||
|
||||
def test_undirected_edge_in_directed(self):
|
||||
s = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version='1.2'>
|
||||
<graph mode="static" defaultedgetype="directed" name="">
|
||||
<nodes>
|
||||
<node id="0" label="Hello" />
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" type="undirected"/>
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
fh = io.BytesIO(s.encode("UTF-8"))
|
||||
pytest.raises(nx.NetworkXError, nx.read_gexf, fh)
|
||||
|
||||
def test_key_raises(self):
|
||||
s = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version='1.2'>
|
||||
<graph mode="static" defaultedgetype="directed" name="">
|
||||
<nodes>
|
||||
<node id="0" label="Hello">
|
||||
<attvalues>
|
||||
<attvalue for='0' value='1'/>
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1" type="undirected"/>
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
fh = io.BytesIO(s.encode("UTF-8"))
|
||||
pytest.raises(nx.NetworkXError, nx.read_gexf, fh)
|
||||
|
||||
def test_relabel(self):
|
||||
s = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gexf xmlns="http://www.gexf.net/1.2draft" version='1.2'>
|
||||
<graph mode="static" defaultedgetype="directed" name="">
|
||||
<nodes>
|
||||
<node id="0" label="Hello" />
|
||||
<node id="1" label="Word" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge id="0" source="0" target="1"/>
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>
|
||||
"""
|
||||
fh = io.BytesIO(s.encode("UTF-8"))
|
||||
G = nx.read_gexf(fh, relabel=True)
|
||||
assert sorted(G.nodes()) == ["Hello", "Word"]
|
||||
|
||||
def test_default_attribute(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(1, label="1", color="green")
|
||||
nx.add_path(G, [0, 1, 2, 3])
|
||||
G.add_edge(1, 2, foo=3)
|
||||
G.graph["node_default"] = {"color": "yellow"}
|
||||
G.graph["edge_default"] = {"foo": 7}
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
# Reading a gexf graph always sets mode attribute to either
|
||||
# 'static' or 'dynamic'. Remove the mode attribute from the
|
||||
# read graph for the sake of comparing remaining attributes.
|
||||
del H.graph["mode"]
|
||||
assert G.graph == H.graph
|
||||
|
||||
def test_serialize_ints_to_strings(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(1, id=7, label=77)
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert list(H) == [7]
|
||||
assert H.nodes[7]["label"] == "77"
|
||||
|
||||
def test_write_with_node_attributes(self):
|
||||
# Addresses #673.
|
||||
G = nx.Graph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (2, 3)])
|
||||
for i in range(4):
|
||||
G.nodes[i]["id"] = i
|
||||
G.nodes[i]["label"] = i
|
||||
G.nodes[i]["pid"] = i
|
||||
G.nodes[i]["start"] = i
|
||||
G.nodes[i]["end"] = i + 1
|
||||
|
||||
expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
|
||||
="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=\
|
||||
"http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/\
|
||||
gexf.xsd" version="1.2">
|
||||
<meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
|
||||
<creator>NetworkX {nx.__version__}</creator>
|
||||
</meta>
|
||||
<graph defaultedgetype="undirected" mode="dynamic" name="" timeformat="long">
|
||||
<nodes>
|
||||
<node id="0" label="0" pid="0" start="0" end="1" />
|
||||
<node id="1" label="1" pid="1" start="1" end="2" />
|
||||
<node id="2" label="2" pid="2" start="2" end="3" />
|
||||
<node id="3" label="3" pid="3" start="3" end="4" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge source="0" target="1" id="0" />
|
||||
<edge source="1" target="2" id="1" />
|
||||
<edge source="2" target="3" id="2" />
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>"""
|
||||
obtained = "\n".join(nx.generate_gexf(G))
|
||||
assert expected == obtained
|
||||
|
||||
def test_edge_id_construct(self):
|
||||
G = nx.Graph()
|
||||
G.add_edges_from([(0, 1, {"id": 0}), (1, 2, {"id": 2}), (2, 3)])
|
||||
|
||||
expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
|
||||
="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.\
|
||||
gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd" version="1.2">
|
||||
<meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
|
||||
<creator>NetworkX {nx.__version__}</creator>
|
||||
</meta>
|
||||
<graph defaultedgetype="undirected" mode="static" name="">
|
||||
<nodes>
|
||||
<node id="0" label="0" />
|
||||
<node id="1" label="1" />
|
||||
<node id="2" label="2" />
|
||||
<node id="3" label="3" />
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge source="0" target="1" id="0" />
|
||||
<edge source="1" target="2" id="2" />
|
||||
<edge source="2" target="3" id="1" />
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>"""
|
||||
|
||||
obtained = "\n".join(nx.generate_gexf(G))
|
||||
assert expected == obtained
|
||||
|
||||
def test_numpy_type(self):
|
||||
np = pytest.importorskip("numpy")
|
||||
G = nx.path_graph(4)
|
||||
nx.set_node_attributes(G, {n: n for n in np.arange(4)}, "number")
|
||||
G[0][1]["edge-number"] = np.float64(1.1)
|
||||
|
||||
expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft"\
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation\
|
||||
="http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd"\
|
||||
version="1.2">
|
||||
<meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
|
||||
<creator>NetworkX {nx.__version__}</creator>
|
||||
</meta>
|
||||
<graph defaultedgetype="undirected" mode="static" name="">
|
||||
<attributes mode="static" class="edge">
|
||||
<attribute id="1" title="edge-number" type="float" />
|
||||
</attributes>
|
||||
<attributes mode="static" class="node">
|
||||
<attribute id="0" title="number" type="int" />
|
||||
</attributes>
|
||||
<nodes>
|
||||
<node id="0" label="0">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="0" />
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="1" label="1">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="1" />
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="2" label="2">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="2" />
|
||||
</attvalues>
|
||||
</node>
|
||||
<node id="3" label="3">
|
||||
<attvalues>
|
||||
<attvalue for="0" value="3" />
|
||||
</attvalues>
|
||||
</node>
|
||||
</nodes>
|
||||
<edges>
|
||||
<edge source="0" target="1" id="0">
|
||||
<attvalues>
|
||||
<attvalue for="1" value="1.1" />
|
||||
</attvalues>
|
||||
</edge>
|
||||
<edge source="1" target="2" id="1" />
|
||||
<edge source="2" target="3" id="2" />
|
||||
</edges>
|
||||
</graph>
|
||||
</gexf>"""
|
||||
obtained = "\n".join(nx.generate_gexf(G))
|
||||
assert expected == obtained
|
||||
|
||||
def test_bool(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(1, testattr=True)
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert H.nodes[1]["testattr"]
|
||||
|
||||
# Test for NaN, INF and -INF
|
||||
def test_specials(self):
|
||||
from math import isnan
|
||||
|
||||
inf, nan = float("inf"), float("nan")
|
||||
G = nx.Graph()
|
||||
G.add_node(1, testattr=inf, strdata="inf", key="a")
|
||||
G.add_node(2, testattr=nan, strdata="nan", key="b")
|
||||
G.add_node(3, testattr=-inf, strdata="-inf", key="c")
|
||||
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
filetext = fh.read()
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
|
||||
assert b"INF" in filetext
|
||||
assert b"NaN" in filetext
|
||||
assert b"-INF" in filetext
|
||||
|
||||
assert H.nodes[1]["testattr"] == inf
|
||||
assert isnan(H.nodes[2]["testattr"])
|
||||
assert H.nodes[3]["testattr"] == -inf
|
||||
|
||||
assert H.nodes[1]["strdata"] == "inf"
|
||||
assert H.nodes[2]["strdata"] == "nan"
|
||||
assert H.nodes[3]["strdata"] == "-inf"
|
||||
|
||||
assert H.nodes[1]["networkx_key"] == "a"
|
||||
assert H.nodes[2]["networkx_key"] == "b"
|
||||
assert H.nodes[3]["networkx_key"] == "c"
|
||||
|
||||
def test_simple_list(self):
|
||||
G = nx.Graph()
|
||||
list_value = [(1, 2, 3), (9, 1, 2)]
|
||||
G.add_node(1, key=list_value)
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert H.nodes[1]["networkx_key"] == list_value
|
||||
|
||||
def test_dynamic_mode(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(1, label="1", color="green")
|
||||
G.graph["mode"] = "dynamic"
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
def test_multigraph_with_missing_attributes(self):
|
||||
G = nx.MultiGraph()
|
||||
G.add_node(0, label="1", color="green")
|
||||
G.add_node(1, label="2", color="green")
|
||||
G.add_edge(0, 1, id="0", weight=3, type="undirected", start=0, end=1)
|
||||
G.add_edge(0, 1, id="1", label="foo", start=0, end=1)
|
||||
G.add_edge(0, 1)
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
def test_missing_viz_attributes(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(0, label="1", color="green")
|
||||
G.nodes[0]["viz"] = {"size": 54}
|
||||
G.nodes[0]["viz"]["position"] = {"x": 0, "y": 1, "z": 0}
|
||||
G.nodes[0]["viz"]["color"] = {"r": 0, "g": 0, "b": 256}
|
||||
G.nodes[0]["viz"]["shape"] = "http://random.url"
|
||||
G.nodes[0]["viz"]["thickness"] = 2
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh, version="1.1draft")
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
# Test missing alpha value for version >draft1.1 - set default alpha value
|
||||
# to 1.0 instead of `None` when writing for better general compatibility
|
||||
fh = io.BytesIO()
|
||||
# G.nodes[0]["viz"]["color"] does not have an alpha value explicitly defined
|
||||
# so the default is used instead
|
||||
nx.write_gexf(G, fh, version="1.2draft")
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert H.nodes[0]["viz"]["color"]["a"] == 1.0
|
||||
|
||||
# Second graph for the other branch
|
||||
G = nx.Graph()
|
||||
G.add_node(0, label="1", color="green")
|
||||
G.nodes[0]["viz"] = {"size": 54}
|
||||
G.nodes[0]["viz"]["position"] = {"x": 0, "y": 1, "z": 0}
|
||||
G.nodes[0]["viz"]["color"] = {"r": 0, "g": 0, "b": 256, "a": 0.5}
|
||||
G.nodes[0]["viz"]["shape"] = "ftp://random.url"
|
||||
G.nodes[0]["viz"]["thickness"] = 2
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
def test_slice_and_spell(self):
|
||||
# Test spell first, so version = 1.2
|
||||
G = nx.Graph()
|
||||
G.add_node(0, label="1", color="green")
|
||||
G.nodes[0]["spells"] = [(1, 2)]
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
G = nx.Graph()
|
||||
G.add_node(0, label="1", color="green")
|
||||
G.nodes[0]["slices"] = [(1, 2)]
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh, version="1.1draft")
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
|
||||
def test_add_parent(self):
|
||||
G = nx.Graph()
|
||||
G.add_node(0, label="1", color="green", parents=[1, 2])
|
||||
fh = io.BytesIO()
|
||||
nx.write_gexf(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_gexf(fh, node_type=int)
|
||||
assert sorted(G.nodes()) == sorted(H.nodes())
|
||||
assert sorted(sorted(e) for e in G.edges()) == sorted(
|
||||
sorted(e) for e in H.edges()
|
||||
)
|
||||
@@ -1,730 +0,0 @@
|
||||
import codecs
|
||||
import io
|
||||
import math
|
||||
import os
|
||||
import tempfile
|
||||
from ast import literal_eval
|
||||
from contextlib import contextmanager
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.readwrite.gml import literal_destringizer, literal_stringizer
|
||||
|
||||
|
||||
class TestGraph:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.simple_data = """Creator "me"
|
||||
Version "xx"
|
||||
graph [
|
||||
comment "This is a sample graph"
|
||||
directed 1
|
||||
IsPlanar 1
|
||||
pos [ x 0 y 1 ]
|
||||
node [
|
||||
id 1
|
||||
label "Node 1"
|
||||
pos [ x 1 y 1 ]
|
||||
]
|
||||
node [
|
||||
id 2
|
||||
pos [ x 1 y 2 ]
|
||||
label "Node 2"
|
||||
]
|
||||
node [
|
||||
id 3
|
||||
label "Node 3"
|
||||
pos [ x 1 y 3 ]
|
||||
]
|
||||
edge [
|
||||
source 1
|
||||
target 2
|
||||
label "Edge from node 1 to node 2"
|
||||
color [line "blue" thickness 3]
|
||||
|
||||
]
|
||||
edge [
|
||||
source 2
|
||||
target 3
|
||||
label "Edge from node 2 to node 3"
|
||||
]
|
||||
edge [
|
||||
source 3
|
||||
target 1
|
||||
label "Edge from node 3 to node 1"
|
||||
]
|
||||
]
|
||||
"""
|
||||
|
||||
def test_parse_gml_cytoscape_bug(self):
|
||||
# example from issue #321, originally #324 in trac
|
||||
cytoscape_example = """
|
||||
Creator "Cytoscape"
|
||||
Version 1.0
|
||||
graph [
|
||||
node [
|
||||
root_index -3
|
||||
id -3
|
||||
graphics [
|
||||
x -96.0
|
||||
y -67.0
|
||||
w 40.0
|
||||
h 40.0
|
||||
fill "#ff9999"
|
||||
type "ellipse"
|
||||
outline "#666666"
|
||||
outline_width 1.5
|
||||
]
|
||||
label "node2"
|
||||
]
|
||||
node [
|
||||
root_index -2
|
||||
id -2
|
||||
graphics [
|
||||
x 63.0
|
||||
y 37.0
|
||||
w 40.0
|
||||
h 40.0
|
||||
fill "#ff9999"
|
||||
type "ellipse"
|
||||
outline "#666666"
|
||||
outline_width 1.5
|
||||
]
|
||||
label "node1"
|
||||
]
|
||||
node [
|
||||
root_index -1
|
||||
id -1
|
||||
graphics [
|
||||
x -31.0
|
||||
y -17.0
|
||||
w 40.0
|
||||
h 40.0
|
||||
fill "#ff9999"
|
||||
type "ellipse"
|
||||
outline "#666666"
|
||||
outline_width 1.5
|
||||
]
|
||||
label "node0"
|
||||
]
|
||||
edge [
|
||||
root_index -2
|
||||
target -2
|
||||
source -1
|
||||
graphics [
|
||||
width 1.5
|
||||
fill "#0000ff"
|
||||
type "line"
|
||||
Line [
|
||||
]
|
||||
source_arrow 0
|
||||
target_arrow 3
|
||||
]
|
||||
label "DirectedEdge"
|
||||
]
|
||||
edge [
|
||||
root_index -1
|
||||
target -1
|
||||
source -3
|
||||
graphics [
|
||||
width 1.5
|
||||
fill "#0000ff"
|
||||
type "line"
|
||||
Line [
|
||||
]
|
||||
source_arrow 0
|
||||
target_arrow 3
|
||||
]
|
||||
label "DirectedEdge"
|
||||
]
|
||||
]
|
||||
"""
|
||||
nx.parse_gml(cytoscape_example)
|
||||
|
||||
def test_parse_gml(self):
|
||||
G = nx.parse_gml(self.simple_data, label="label")
|
||||
assert sorted(G.nodes()) == ["Node 1", "Node 2", "Node 3"]
|
||||
assert sorted(G.edges()) == [
|
||||
("Node 1", "Node 2"),
|
||||
("Node 2", "Node 3"),
|
||||
("Node 3", "Node 1"),
|
||||
]
|
||||
|
||||
assert sorted(G.edges(data=True)) == [
|
||||
(
|
||||
"Node 1",
|
||||
"Node 2",
|
||||
{
|
||||
"color": {"line": "blue", "thickness": 3},
|
||||
"label": "Edge from node 1 to node 2",
|
||||
},
|
||||
),
|
||||
("Node 2", "Node 3", {"label": "Edge from node 2 to node 3"}),
|
||||
("Node 3", "Node 1", {"label": "Edge from node 3 to node 1"}),
|
||||
]
|
||||
|
||||
def test_read_gml(self):
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
fh = open(fname, "w")
|
||||
fh.write(self.simple_data)
|
||||
fh.close()
|
||||
Gin = nx.read_gml(fname, label="label")
|
||||
G = nx.parse_gml(self.simple_data, label="label")
|
||||
assert sorted(G.nodes(data=True)) == sorted(Gin.nodes(data=True))
|
||||
assert sorted(G.edges(data=True)) == sorted(Gin.edges(data=True))
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
def test_labels_are_strings(self):
|
||||
# GML requires labels to be strings (i.e., in quotes)
|
||||
answer = """graph [
|
||||
node [
|
||||
id 0
|
||||
label "1203"
|
||||
]
|
||||
]"""
|
||||
G = nx.Graph()
|
||||
G.add_node(1203)
|
||||
data = "\n".join(nx.generate_gml(G, stringizer=literal_stringizer))
|
||||
assert data == answer
|
||||
|
||||
def test_relabel_duplicate(self):
|
||||
data = """
|
||||
graph
|
||||
[
|
||||
label ""
|
||||
directed 1
|
||||
node
|
||||
[
|
||||
id 0
|
||||
label "same"
|
||||
]
|
||||
node
|
||||
[
|
||||
id 1
|
||||
label "same"
|
||||
]
|
||||
]
|
||||
"""
|
||||
fh = io.BytesIO(data.encode("UTF-8"))
|
||||
fh.seek(0)
|
||||
pytest.raises(nx.NetworkXError, nx.read_gml, fh, label="label")
|
||||
|
||||
def test_tuplelabels(self):
|
||||
# https://github.com/networkx/networkx/pull/1048
|
||||
# Writing tuple labels to GML failed.
|
||||
G = nx.Graph()
|
||||
G.add_edge((0, 1), (1, 0))
|
||||
data = "\n".join(nx.generate_gml(G, stringizer=literal_stringizer))
|
||||
answer = """graph [
|
||||
node [
|
||||
id 0
|
||||
label "(0,1)"
|
||||
]
|
||||
node [
|
||||
id 1
|
||||
label "(1,0)"
|
||||
]
|
||||
edge [
|
||||
source 0
|
||||
target 1
|
||||
]
|
||||
]"""
|
||||
assert data == answer
|
||||
|
||||
def test_quotes(self):
|
||||
# https://github.com/networkx/networkx/issues/1061
|
||||
# Encoding quotes as HTML entities.
|
||||
G = nx.path_graph(1)
|
||||
G.name = "path_graph(1)"
|
||||
attr = 'This is "quoted" and this is a copyright: ' + chr(169)
|
||||
G.nodes[0]["demo"] = attr
|
||||
fobj = tempfile.NamedTemporaryFile()
|
||||
nx.write_gml(G, fobj)
|
||||
fobj.seek(0)
|
||||
# Should be bytes in 2.x and 3.x
|
||||
data = fobj.read().strip().decode("ascii")
|
||||
answer = """graph [
|
||||
name "path_graph(1)"
|
||||
node [
|
||||
id 0
|
||||
label "0"
|
||||
demo "This is "quoted" and this is a copyright: ©"
|
||||
]
|
||||
]"""
|
||||
assert data == answer
|
||||
|
||||
def test_unicode_node(self):
|
||||
node = "node" + chr(169)
|
||||
G = nx.Graph()
|
||||
G.add_node(node)
|
||||
fobj = tempfile.NamedTemporaryFile()
|
||||
nx.write_gml(G, fobj)
|
||||
fobj.seek(0)
|
||||
# Should be bytes in 2.x and 3.x
|
||||
data = fobj.read().strip().decode("ascii")
|
||||
answer = """graph [
|
||||
node [
|
||||
id 0
|
||||
label "node©"
|
||||
]
|
||||
]"""
|
||||
assert data == answer
|
||||
|
||||
def test_float_label(self):
|
||||
node = 1.0
|
||||
G = nx.Graph()
|
||||
G.add_node(node)
|
||||
fobj = tempfile.NamedTemporaryFile()
|
||||
nx.write_gml(G, fobj)
|
||||
fobj.seek(0)
|
||||
# Should be bytes in 2.x and 3.x
|
||||
data = fobj.read().strip().decode("ascii")
|
||||
answer = """graph [
|
||||
node [
|
||||
id 0
|
||||
label "1.0"
|
||||
]
|
||||
]"""
|
||||
assert data == answer
|
||||
|
||||
def test_special_float_label(self):
|
||||
special_floats = [float("nan"), float("+inf"), float("-inf")]
|
||||
try:
|
||||
import numpy as np
|
||||
|
||||
special_floats += [np.nan, np.inf, np.inf * -1]
|
||||
except ImportError:
|
||||
special_floats += special_floats
|
||||
|
||||
G = nx.cycle_graph(len(special_floats))
|
||||
attrs = dict(enumerate(special_floats))
|
||||
nx.set_node_attributes(G, attrs, "nodefloat")
|
||||
edges = list(G.edges)
|
||||
attrs = {edges[i]: value for i, value in enumerate(special_floats)}
|
||||
nx.set_edge_attributes(G, attrs, "edgefloat")
|
||||
|
||||
fobj = tempfile.NamedTemporaryFile()
|
||||
nx.write_gml(G, fobj)
|
||||
fobj.seek(0)
|
||||
# Should be bytes in 2.x and 3.x
|
||||
data = fobj.read().strip().decode("ascii")
|
||||
answer = """graph [
|
||||
node [
|
||||
id 0
|
||||
label "0"
|
||||
nodefloat NAN
|
||||
]
|
||||
node [
|
||||
id 1
|
||||
label "1"
|
||||
nodefloat +INF
|
||||
]
|
||||
node [
|
||||
id 2
|
||||
label "2"
|
||||
nodefloat -INF
|
||||
]
|
||||
node [
|
||||
id 3
|
||||
label "3"
|
||||
nodefloat NAN
|
||||
]
|
||||
node [
|
||||
id 4
|
||||
label "4"
|
||||
nodefloat +INF
|
||||
]
|
||||
node [
|
||||
id 5
|
||||
label "5"
|
||||
nodefloat -INF
|
||||
]
|
||||
edge [
|
||||
source 0
|
||||
target 1
|
||||
edgefloat NAN
|
||||
]
|
||||
edge [
|
||||
source 0
|
||||
target 5
|
||||
edgefloat +INF
|
||||
]
|
||||
edge [
|
||||
source 1
|
||||
target 2
|
||||
edgefloat -INF
|
||||
]
|
||||
edge [
|
||||
source 2
|
||||
target 3
|
||||
edgefloat NAN
|
||||
]
|
||||
edge [
|
||||
source 3
|
||||
target 4
|
||||
edgefloat +INF
|
||||
]
|
||||
edge [
|
||||
source 4
|
||||
target 5
|
||||
edgefloat -INF
|
||||
]
|
||||
]"""
|
||||
assert data == answer
|
||||
|
||||
fobj.seek(0)
|
||||
graph = nx.read_gml(fobj)
|
||||
for indx, value in enumerate(special_floats):
|
||||
node_value = graph.nodes[str(indx)]["nodefloat"]
|
||||
if math.isnan(value):
|
||||
assert math.isnan(node_value)
|
||||
else:
|
||||
assert node_value == value
|
||||
|
||||
edge = edges[indx]
|
||||
string_edge = (str(edge[0]), str(edge[1]))
|
||||
edge_value = graph.edges[string_edge]["edgefloat"]
|
||||
if math.isnan(value):
|
||||
assert math.isnan(edge_value)
|
||||
else:
|
||||
assert edge_value == value
|
||||
|
||||
def test_name(self):
|
||||
G = nx.parse_gml('graph [ name "x" node [ id 0 label "x" ] ]')
|
||||
assert "x" == G.graph["name"]
|
||||
G = nx.parse_gml('graph [ node [ id 0 label "x" ] ]')
|
||||
assert "" == G.name
|
||||
assert "name" not in G.graph
|
||||
|
||||
def test_graph_types(self):
|
||||
for directed in [None, False, True]:
|
||||
for multigraph in [None, False, True]:
|
||||
gml = "graph ["
|
||||
if directed is not None:
|
||||
gml += " directed " + str(int(directed))
|
||||
if multigraph is not None:
|
||||
gml += " multigraph " + str(int(multigraph))
|
||||
gml += ' node [ id 0 label "0" ]'
|
||||
gml += " edge [ source 0 target 0 ]"
|
||||
gml += " ]"
|
||||
G = nx.parse_gml(gml)
|
||||
assert bool(directed) == G.is_directed()
|
||||
assert bool(multigraph) == G.is_multigraph()
|
||||
gml = "graph [\n"
|
||||
if directed is True:
|
||||
gml += " directed 1\n"
|
||||
if multigraph is True:
|
||||
gml += " multigraph 1\n"
|
||||
gml += """ node [
|
||||
id 0
|
||||
label "0"
|
||||
]
|
||||
edge [
|
||||
source 0
|
||||
target 0
|
||||
"""
|
||||
if multigraph:
|
||||
gml += " key 0\n"
|
||||
gml += " ]\n]"
|
||||
assert gml == "\n".join(nx.generate_gml(G))
|
||||
|
||||
def test_data_types(self):
|
||||
data = [
|
||||
True,
|
||||
False,
|
||||
10**20,
|
||||
-2e33,
|
||||
"'",
|
||||
'"&&&""',
|
||||
[{(b"\xfd",): "\x7f", chr(0x4444): (1, 2)}, (2, "3")],
|
||||
]
|
||||
data.append(chr(0x14444))
|
||||
data.append(literal_eval("{2.3j, 1 - 2.3j, ()}"))
|
||||
G = nx.Graph()
|
||||
G.name = data
|
||||
G.graph["data"] = data
|
||||
G.add_node(0, int=-1, data={"data": data})
|
||||
G.add_edge(0, 0, float=-2.5, data=data)
|
||||
gml = "\n".join(nx.generate_gml(G, stringizer=literal_stringizer))
|
||||
G = nx.parse_gml(gml, destringizer=literal_destringizer)
|
||||
assert data == G.name
|
||||
assert {"name": data, "data": data} == G.graph
|
||||
assert list(G.nodes(data=True)) == [(0, {"int": -1, "data": {"data": data}})]
|
||||
assert list(G.edges(data=True)) == [(0, 0, {"float": -2.5, "data": data})]
|
||||
G = nx.Graph()
|
||||
G.graph["data"] = "frozenset([1, 2, 3])"
|
||||
G = nx.parse_gml(nx.generate_gml(G), destringizer=literal_eval)
|
||||
assert G.graph["data"] == "frozenset([1, 2, 3])"
|
||||
|
||||
def test_escape_unescape(self):
|
||||
gml = """graph [
|
||||
name "&"䑄��&unknown;"
|
||||
]"""
|
||||
G = nx.parse_gml(gml)
|
||||
assert (
|
||||
'&"\x0f' + chr(0x4444) + "��&unknown;"
|
||||
== G.name
|
||||
)
|
||||
gml = "\n".join(nx.generate_gml(G))
|
||||
alnu = "#1234567890;&#x1234567890abcdef"
|
||||
answer = (
|
||||
"""graph [
|
||||
name "&"䑄&"""
|
||||
+ alnu
|
||||
+ """;&unknown;"
|
||||
]"""
|
||||
)
|
||||
assert answer == gml
|
||||
|
||||
def test_exceptions(self):
|
||||
pytest.raises(ValueError, literal_destringizer, "(")
|
||||
pytest.raises(ValueError, literal_destringizer, "frozenset([1, 2, 3])")
|
||||
pytest.raises(ValueError, literal_destringizer, literal_destringizer)
|
||||
pytest.raises(ValueError, literal_stringizer, frozenset([1, 2, 3]))
|
||||
pytest.raises(ValueError, literal_stringizer, literal_stringizer)
|
||||
with tempfile.TemporaryFile() as f:
|
||||
f.write(codecs.BOM_UTF8 + b"graph[]")
|
||||
f.seek(0)
|
||||
pytest.raises(nx.NetworkXError, nx.read_gml, f)
|
||||
|
||||
def assert_parse_error(gml):
|
||||
pytest.raises(nx.NetworkXError, nx.parse_gml, gml)
|
||||
|
||||
assert_parse_error(["graph [\n\n", "]"])
|
||||
assert_parse_error("")
|
||||
assert_parse_error('Creator ""')
|
||||
assert_parse_error("0")
|
||||
assert_parse_error("graph ]")
|
||||
assert_parse_error("graph [ 1 ]")
|
||||
assert_parse_error("graph [ 1.E+2 ]")
|
||||
assert_parse_error('graph [ "A" ]')
|
||||
assert_parse_error("graph [ ] graph ]")
|
||||
assert_parse_error("graph [ ] graph [ ]")
|
||||
assert_parse_error("graph [ data [1, 2, 3] ]")
|
||||
assert_parse_error("graph [ node [ ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 ] ]")
|
||||
nx.parse_gml('graph [ node [ id "a" ] ]', label="id")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] node [ id 0 label 1 ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] node [ id 1 label 0 ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] edge [ ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] edge [ source 0 ] ]")
|
||||
nx.parse_gml("graph [edge [ source 0 target 0 ] node [ id 0 label 0 ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] edge [ source 1 target 0 ] ]")
|
||||
assert_parse_error("graph [ node [ id 0 label 0 ] edge [ source 0 target 1 ] ]")
|
||||
assert_parse_error(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 ] edge [ source 1 target 0 ] ]"
|
||||
)
|
||||
nx.parse_gml(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 ] edge [ source 1 target 0 ] "
|
||||
"directed 1 ]"
|
||||
)
|
||||
nx.parse_gml(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 ] edge [ source 0 target 1 ]"
|
||||
"multigraph 1 ]"
|
||||
)
|
||||
nx.parse_gml(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 key 0 ] edge [ source 0 target 1 ]"
|
||||
"multigraph 1 ]"
|
||||
)
|
||||
assert_parse_error(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 key 0 ] edge [ source 0 target 1 key 0 ]"
|
||||
"multigraph 1 ]"
|
||||
)
|
||||
nx.parse_gml(
|
||||
"graph [ node [ id 0 label 0 ] node [ id 1 label 1 ] "
|
||||
"edge [ source 0 target 1 key 0 ] edge [ source 1 target 0 key 0 ]"
|
||||
"directed 1 multigraph 1 ]"
|
||||
)
|
||||
|
||||
# Tests for string convertible alphanumeric id and label values
|
||||
nx.parse_gml("graph [edge [ source a target a ] node [ id a label b ] ]")
|
||||
nx.parse_gml(
|
||||
"graph [ node [ id n42 label 0 ] node [ id x43 label 1 ]"
|
||||
"edge [ source n42 target x43 key 0 ]"
|
||||
"edge [ source x43 target n42 key 0 ]"
|
||||
"directed 1 multigraph 1 ]"
|
||||
)
|
||||
assert_parse_error(
|
||||
"graph [edge [ source u'u\4200' target u'u\4200' ] "
|
||||
+ "node [ id u'u\4200' label b ] ]"
|
||||
)
|
||||
|
||||
def assert_generate_error(*args, **kwargs):
|
||||
pytest.raises(
|
||||
nx.NetworkXError, lambda: list(nx.generate_gml(*args, **kwargs))
|
||||
)
|
||||
|
||||
G = nx.Graph()
|
||||
G.graph[3] = 3
|
||||
assert_generate_error(G)
|
||||
G = nx.Graph()
|
||||
G.graph["3"] = 3
|
||||
assert_generate_error(G)
|
||||
G = nx.Graph()
|
||||
G.graph["data"] = frozenset([1, 2, 3])
|
||||
assert_generate_error(G, stringizer=literal_stringizer)
|
||||
|
||||
def test_label_kwarg(self):
|
||||
G = nx.parse_gml(self.simple_data, label="id")
|
||||
assert sorted(G.nodes) == [1, 2, 3]
|
||||
labels = [G.nodes[n]["label"] for n in sorted(G.nodes)]
|
||||
assert labels == ["Node 1", "Node 2", "Node 3"]
|
||||
|
||||
G = nx.parse_gml(self.simple_data, label=None)
|
||||
assert sorted(G.nodes) == [1, 2, 3]
|
||||
labels = [G.nodes[n]["label"] for n in sorted(G.nodes)]
|
||||
assert labels == ["Node 1", "Node 2", "Node 3"]
|
||||
|
||||
def test_outofrange_integers(self):
|
||||
# GML restricts integers to 32 signed bits.
|
||||
# Check that we honor this restriction on export
|
||||
G = nx.Graph()
|
||||
# Test export for numbers that barely fit or don't fit into 32 bits,
|
||||
# and 3 numbers in the middle
|
||||
numbers = {
|
||||
"toosmall": (-(2**31)) - 1,
|
||||
"small": -(2**31),
|
||||
"med1": -4,
|
||||
"med2": 0,
|
||||
"med3": 17,
|
||||
"big": (2**31) - 1,
|
||||
"toobig": 2**31,
|
||||
}
|
||||
G.add_node("Node", **numbers)
|
||||
|
||||
fd, fname = tempfile.mkstemp()
|
||||
try:
|
||||
nx.write_gml(G, fname)
|
||||
# Check that the export wrote the nonfitting numbers as strings
|
||||
G2 = nx.read_gml(fname)
|
||||
for attr, value in G2.nodes["Node"].items():
|
||||
if attr == "toosmall" or attr == "toobig":
|
||||
assert type(value) == str
|
||||
else:
|
||||
assert type(value) == int
|
||||
finally:
|
||||
os.close(fd)
|
||||
os.unlink(fname)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def byte_file():
|
||||
_file_handle = io.BytesIO()
|
||||
yield _file_handle
|
||||
_file_handle.seek(0)
|
||||
|
||||
|
||||
class TestPropertyLists:
|
||||
def test_writing_graph_with_multi_element_property_list(self):
|
||||
g = nx.Graph()
|
||||
g.add_node("n1", properties=["element", 0, 1, 2.5, True, False])
|
||||
with byte_file() as f:
|
||||
nx.write_gml(g, f)
|
||||
result = f.read().decode()
|
||||
|
||||
assert result == dedent(
|
||||
"""\
|
||||
graph [
|
||||
node [
|
||||
id 0
|
||||
label "n1"
|
||||
properties "element"
|
||||
properties 0
|
||||
properties 1
|
||||
properties 2.5
|
||||
properties 1
|
||||
properties 0
|
||||
]
|
||||
]
|
||||
"""
|
||||
)
|
||||
|
||||
def test_writing_graph_with_one_element_property_list(self):
|
||||
g = nx.Graph()
|
||||
g.add_node("n1", properties=["element"])
|
||||
with byte_file() as f:
|
||||
nx.write_gml(g, f)
|
||||
result = f.read().decode()
|
||||
|
||||
assert result == dedent(
|
||||
"""\
|
||||
graph [
|
||||
node [
|
||||
id 0
|
||||
label "n1"
|
||||
properties "_networkx_list_start"
|
||||
properties "element"
|
||||
]
|
||||
]
|
||||
"""
|
||||
)
|
||||
|
||||
def test_reading_graph_with_list_property(self):
|
||||
with byte_file() as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""
|
||||
graph [
|
||||
node [
|
||||
id 0
|
||||
label "n1"
|
||||
properties "element"
|
||||
properties 0
|
||||
properties 1
|
||||
properties 2.5
|
||||
]
|
||||
]
|
||||
"""
|
||||
).encode("ascii")
|
||||
)
|
||||
f.seek(0)
|
||||
graph = nx.read_gml(f)
|
||||
assert graph.nodes(data=True)["n1"] == {"properties": ["element", 0, 1, 2.5]}
|
||||
|
||||
def test_reading_graph_with_single_element_list_property(self):
|
||||
with byte_file() as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""
|
||||
graph [
|
||||
node [
|
||||
id 0
|
||||
label "n1"
|
||||
properties "_networkx_list_start"
|
||||
properties "element"
|
||||
]
|
||||
]
|
||||
"""
|
||||
).encode("ascii")
|
||||
)
|
||||
f.seek(0)
|
||||
graph = nx.read_gml(f)
|
||||
assert graph.nodes(data=True)["n1"] == {"properties": ["element"]}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("coll", ([], ()))
|
||||
def test_stringize_empty_list_tuple(coll):
|
||||
G = nx.path_graph(2)
|
||||
G.nodes[0]["test"] = coll # test serializing an empty collection
|
||||
f = io.BytesIO()
|
||||
nx.write_gml(G, f) # Smoke test - should not raise
|
||||
f.seek(0)
|
||||
H = nx.read_gml(f)
|
||||
assert H.nodes["0"]["test"] == coll # Check empty list round-trips properly
|
||||
# Check full round-tripping. Note that nodes are loaded as strings by
|
||||
# default, so there needs to be some remapping prior to comparison
|
||||
H = nx.relabel_nodes(H, {"0": 0, "1": 1})
|
||||
assert nx.utils.graphs_equal(G, H)
|
||||
# Same as above, but use destringizer for node remapping. Should have no
|
||||
# effect on node attr
|
||||
f.seek(0)
|
||||
H = nx.read_gml(f, destringizer=int)
|
||||
assert nx.utils.graphs_equal(G, H)
|
||||
@@ -1,169 +0,0 @@
|
||||
import tempfile
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
import networkx.readwrite.graph6 as g6
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
class TestGraph6Utils:
|
||||
def test_n_data_n_conversion(self):
|
||||
for i in [0, 1, 42, 62, 63, 64, 258047, 258048, 7744773, 68719476735]:
|
||||
assert g6.data_to_n(g6.n_to_data(i))[0] == i
|
||||
assert g6.data_to_n(g6.n_to_data(i))[1] == []
|
||||
assert g6.data_to_n(g6.n_to_data(i) + [42, 43])[1] == [42, 43]
|
||||
|
||||
|
||||
class TestFromGraph6Bytes:
|
||||
def test_from_graph6_bytes(self):
|
||||
data = b"DF{"
|
||||
G = nx.from_graph6_bytes(data)
|
||||
assert nodes_equal(G.nodes(), [0, 1, 2, 3, 4])
|
||||
assert edges_equal(
|
||||
G.edges(), [(0, 3), (0, 4), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
|
||||
)
|
||||
|
||||
def test_read_equals_from_bytes(self):
|
||||
data = b"DF{"
|
||||
G = nx.from_graph6_bytes(data)
|
||||
fh = BytesIO(data)
|
||||
Gin = nx.read_graph6(fh)
|
||||
assert nodes_equal(G.nodes(), Gin.nodes())
|
||||
assert edges_equal(G.edges(), Gin.edges())
|
||||
|
||||
|
||||
class TestReadGraph6:
|
||||
def test_read_many_graph6(self):
|
||||
"""Test for reading many graphs from a file into a list."""
|
||||
data = b"DF{\nD`{\nDqK\nD~{\n"
|
||||
fh = BytesIO(data)
|
||||
glist = nx.read_graph6(fh)
|
||||
assert len(glist) == 4
|
||||
for G in glist:
|
||||
assert sorted(G) == list(range(5))
|
||||
|
||||
|
||||
class TestWriteGraph6:
|
||||
"""Unit tests for writing a graph to a file in graph6 format."""
|
||||
|
||||
def test_null_graph(self):
|
||||
result = BytesIO()
|
||||
nx.write_graph6(nx.null_graph(), result)
|
||||
assert result.getvalue() == b">>graph6<<?\n"
|
||||
|
||||
def test_trivial_graph(self):
|
||||
result = BytesIO()
|
||||
nx.write_graph6(nx.trivial_graph(), result)
|
||||
assert result.getvalue() == b">>graph6<<@\n"
|
||||
|
||||
def test_complete_graph(self):
|
||||
result = BytesIO()
|
||||
nx.write_graph6(nx.complete_graph(4), result)
|
||||
assert result.getvalue() == b">>graph6<<C~\n"
|
||||
|
||||
def test_large_complete_graph(self):
|
||||
result = BytesIO()
|
||||
nx.write_graph6(nx.complete_graph(67), result, header=False)
|
||||
assert result.getvalue() == b"~?@B" + b"~" * 368 + b"w\n"
|
||||
|
||||
def test_no_header(self):
|
||||
result = BytesIO()
|
||||
nx.write_graph6(nx.complete_graph(4), result, header=False)
|
||||
assert result.getvalue() == b"C~\n"
|
||||
|
||||
def test_complete_bipartite_graph(self):
|
||||
result = BytesIO()
|
||||
G = nx.complete_bipartite_graph(6, 9)
|
||||
nx.write_graph6(G, result, header=False)
|
||||
# The expected encoding here was verified by Sage.
|
||||
assert result.getvalue() == b"N??F~z{~Fw^_~?~?^_?\n"
|
||||
|
||||
@pytest.mark.parametrize("G", (nx.MultiGraph(), nx.DiGraph()))
|
||||
def test_no_directed_or_multi_graphs(self, G):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
nx.write_graph6(G, BytesIO())
|
||||
|
||||
def test_length(self):
|
||||
for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
|
||||
g = nx.random_graphs.gnm_random_graph(i, i * i // 4, seed=i)
|
||||
gstr = BytesIO()
|
||||
nx.write_graph6(g, gstr, header=False)
|
||||
# Strip the trailing newline.
|
||||
gstr = gstr.getvalue().rstrip()
|
||||
assert len(gstr) == ((i - 1) * i // 2 + 5) // 6 + (1 if i < 63 else 4)
|
||||
|
||||
def test_roundtrip(self):
|
||||
for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
|
||||
G = nx.random_graphs.gnm_random_graph(i, i * i // 4, seed=i)
|
||||
f = BytesIO()
|
||||
nx.write_graph6(G, f)
|
||||
f.seek(0)
|
||||
H = nx.read_graph6(f)
|
||||
assert nodes_equal(G.nodes(), H.nodes())
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
|
||||
def test_write_path(self):
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
g6.write_graph6_file(nx.null_graph(), f)
|
||||
f.seek(0)
|
||||
assert f.read() == b">>graph6<<?\n"
|
||||
|
||||
@pytest.mark.parametrize("edge", ((0, 1), (1, 2), (1, 42)))
|
||||
def test_relabeling(self, edge):
|
||||
G = nx.Graph([edge])
|
||||
f = BytesIO()
|
||||
nx.write_graph6(G, f)
|
||||
f.seek(0)
|
||||
assert f.read() == b">>graph6<<A_\n"
|
||||
|
||||
|
||||
class TestToGraph6Bytes:
|
||||
def test_null_graph(self):
|
||||
G = nx.null_graph()
|
||||
assert g6.to_graph6_bytes(G) == b">>graph6<<?\n"
|
||||
|
||||
def test_trivial_graph(self):
|
||||
G = nx.trivial_graph()
|
||||
assert g6.to_graph6_bytes(G) == b">>graph6<<@\n"
|
||||
|
||||
def test_complete_graph(self):
|
||||
assert g6.to_graph6_bytes(nx.complete_graph(4)) == b">>graph6<<C~\n"
|
||||
|
||||
def test_large_complete_graph(self):
|
||||
G = nx.complete_graph(67)
|
||||
assert g6.to_graph6_bytes(G, header=False) == b"~?@B" + b"~" * 368 + b"w\n"
|
||||
|
||||
def test_no_header(self):
|
||||
G = nx.complete_graph(4)
|
||||
assert g6.to_graph6_bytes(G, header=False) == b"C~\n"
|
||||
|
||||
def test_complete_bipartite_graph(self):
|
||||
G = nx.complete_bipartite_graph(6, 9)
|
||||
assert g6.to_graph6_bytes(G, header=False) == b"N??F~z{~Fw^_~?~?^_?\n"
|
||||
|
||||
@pytest.mark.parametrize("G", (nx.MultiGraph(), nx.DiGraph()))
|
||||
def test_no_directed_or_multi_graphs(self, G):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
g6.to_graph6_bytes(G)
|
||||
|
||||
def test_length(self):
|
||||
for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
|
||||
G = nx.random_graphs.gnm_random_graph(i, i * i // 4, seed=i)
|
||||
# Strip the trailing newline.
|
||||
gstr = g6.to_graph6_bytes(G, header=False).rstrip()
|
||||
assert len(gstr) == ((i - 1) * i // 2 + 5) // 6 + (1 if i < 63 else 4)
|
||||
|
||||
def test_roundtrip(self):
|
||||
for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
|
||||
G = nx.random_graphs.gnm_random_graph(i, i * i // 4, seed=i)
|
||||
data = g6.to_graph6_bytes(G)
|
||||
H = nx.from_graph6_bytes(data.rstrip())
|
||||
assert nodes_equal(G.nodes(), H.nodes())
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
|
||||
@pytest.mark.parametrize("edge", ((0, 1), (1, 2), (1, 42)))
|
||||
def test_relabeling(self, edge):
|
||||
G = nx.Graph([edge])
|
||||
assert g6.to_graph6_bytes(G) == b">>graph6<<A_\n"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
||||
import io
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestLEDA:
|
||||
def test_parse_leda(self):
|
||||
data = """#header section \nLEDA.GRAPH \nstring\nint\n-1\n#nodes section\n5 \n|{v1}| \n|{v2}| \n|{v3}| \n|{v4}| \n|{v5}| \n\n#edges section\n7 \n1 2 0 |{4}| \n1 3 0 |{3}| \n2 3 0 |{2}| \n3 4 0 |{3}| \n3 5 0 |{7}| \n4 5 0 |{6}| \n5 1 0 |{foo}|"""
|
||||
G = nx.parse_leda(data)
|
||||
G = nx.parse_leda(data.split("\n"))
|
||||
assert sorted(G.nodes()) == ["v1", "v2", "v3", "v4", "v5"]
|
||||
assert sorted(G.edges(data=True)) == [
|
||||
("v1", "v2", {"label": "4"}),
|
||||
("v1", "v3", {"label": "3"}),
|
||||
("v2", "v3", {"label": "2"}),
|
||||
("v3", "v4", {"label": "3"}),
|
||||
("v3", "v5", {"label": "7"}),
|
||||
("v4", "v5", {"label": "6"}),
|
||||
("v5", "v1", {"label": "foo"}),
|
||||
]
|
||||
|
||||
def test_read_LEDA(self):
|
||||
fh = io.BytesIO()
|
||||
data = """#header section \nLEDA.GRAPH \nstring\nint\n-1\n#nodes section\n5 \n|{v1}| \n|{v2}| \n|{v3}| \n|{v4}| \n|{v5}| \n\n#edges section\n7 \n1 2 0 |{4}| \n1 3 0 |{3}| \n2 3 0 |{2}| \n3 4 0 |{3}| \n3 5 0 |{7}| \n4 5 0 |{6}| \n5 1 0 |{foo}|"""
|
||||
G = nx.parse_leda(data)
|
||||
fh.write(data.encode("UTF-8"))
|
||||
fh.seek(0)
|
||||
Gin = nx.read_leda(fh)
|
||||
assert sorted(G.nodes()) == sorted(Gin.nodes())
|
||||
assert sorted(G.edges()) == sorted(Gin.edges())
|
||||
@@ -1,62 +0,0 @@
|
||||
import io
|
||||
|
||||
import networkx as nx
|
||||
from networkx.readwrite.p2g import read_p2g, write_p2g
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestP2G:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.Graph(name="test")
|
||||
e = [("a", "b"), ("b", "c"), ("c", "d"), ("d", "e"), ("e", "f"), ("a", "f")]
|
||||
cls.G.add_edges_from(e)
|
||||
cls.G.add_node("g")
|
||||
cls.DG = nx.DiGraph(cls.G)
|
||||
|
||||
def test_read_p2g(self):
|
||||
s = b"""\
|
||||
name
|
||||
3 4
|
||||
a
|
||||
1 2
|
||||
b
|
||||
|
||||
c
|
||||
0 2
|
||||
"""
|
||||
bytesIO = io.BytesIO(s)
|
||||
G = read_p2g(bytesIO)
|
||||
assert G.name == "name"
|
||||
assert sorted(G) == ["a", "b", "c"]
|
||||
edges = [(str(u), str(v)) for u, v in G.edges()]
|
||||
assert edges_equal(G.edges(), [("a", "c"), ("a", "b"), ("c", "a"), ("c", "c")])
|
||||
|
||||
def test_write_p2g(self):
|
||||
s = b"""foo
|
||||
3 2
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
3
|
||||
|
||||
"""
|
||||
fh = io.BytesIO()
|
||||
G = nx.DiGraph()
|
||||
G.name = "foo"
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
write_p2g(G, fh)
|
||||
fh.seek(0)
|
||||
r = fh.read()
|
||||
assert r == s
|
||||
|
||||
def test_write_read_p2g(self):
|
||||
fh = io.BytesIO()
|
||||
G = nx.DiGraph()
|
||||
G.name = "foo"
|
||||
G.add_edges_from([("a", "b"), ("b", "c")])
|
||||
write_p2g(G, fh)
|
||||
fh.seek(0)
|
||||
H = read_p2g(fh)
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
@@ -1,130 +0,0 @@
|
||||
"""
|
||||
Pajek tests
|
||||
"""
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
class TestPajek:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.data = """*network Tralala\n*vertices 4\n 1 "A1" 0.0938 0.0896 ellipse x_fact 1 y_fact 1\n 2 "Bb" 0.8188 0.2458 ellipse x_fact 1 y_fact 1\n 3 "C" 0.3688 0.7792 ellipse x_fact 1\n 4 "D2" 0.9583 0.8563 ellipse x_fact 1\n*arcs\n1 1 1 h2 0 w 3 c Blue s 3 a1 -130 k1 0.6 a2 -130 k2 0.6 ap 0.5 l "Bezier loop" lc BlueViolet fos 20 lr 58 lp 0.3 la 360\n2 1 1 h2 0 a1 120 k1 1.3 a2 -120 k2 0.3 ap 25 l "Bezier arc" lphi 270 la 180 lr 19 lp 0.5\n1 2 1 h2 0 a1 40 k1 2.8 a2 30 k2 0.8 ap 25 l "Bezier arc" lphi 90 la 0 lp 0.65\n4 2 -1 h2 0 w 1 k1 -2 k2 250 ap 25 l "Circular arc" c Red lc OrangeRed\n3 4 1 p Dashed h2 0 w 2 c OliveGreen ap 25 l "Straight arc" lc PineGreen\n1 3 1 p Dashed h2 0 w 5 k1 -1 k2 -20 ap 25 l "Oval arc" c Brown lc Black\n3 3 -1 h1 6 w 1 h2 12 k1 -2 k2 -15 ap 0.5 l "Circular loop" c Red lc OrangeRed lphi 270 la 180"""
|
||||
cls.G = nx.MultiDiGraph()
|
||||
cls.G.add_nodes_from(["A1", "Bb", "C", "D2"])
|
||||
cls.G.add_edges_from(
|
||||
[
|
||||
("A1", "A1"),
|
||||
("A1", "Bb"),
|
||||
("A1", "C"),
|
||||
("Bb", "A1"),
|
||||
("C", "C"),
|
||||
("C", "D2"),
|
||||
("D2", "Bb"),
|
||||
]
|
||||
)
|
||||
|
||||
cls.G.graph["name"] = "Tralala"
|
||||
(fd, cls.fname) = tempfile.mkstemp()
|
||||
with os.fdopen(fd, "wb") as fh:
|
||||
fh.write(cls.data.encode("UTF-8"))
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
os.unlink(cls.fname)
|
||||
|
||||
def test_parse_pajek_simple(self):
|
||||
# Example without node positions or shape
|
||||
data = """*Vertices 2\n1 "1"\n2 "2"\n*Edges\n1 2\n2 1"""
|
||||
G = nx.parse_pajek(data)
|
||||
assert sorted(G.nodes()) == ["1", "2"]
|
||||
assert edges_equal(G.edges(), [("1", "2"), ("1", "2")])
|
||||
|
||||
def test_parse_pajek(self):
|
||||
G = nx.parse_pajek(self.data)
|
||||
assert sorted(G.nodes()) == ["A1", "Bb", "C", "D2"]
|
||||
assert edges_equal(
|
||||
G.edges(),
|
||||
[
|
||||
("A1", "A1"),
|
||||
("A1", "Bb"),
|
||||
("A1", "C"),
|
||||
("Bb", "A1"),
|
||||
("C", "C"),
|
||||
("C", "D2"),
|
||||
("D2", "Bb"),
|
||||
],
|
||||
)
|
||||
|
||||
def test_parse_pajet_mat(self):
|
||||
data = """*Vertices 3\n1 "one"\n2 "two"\n3 "three"\n*Matrix\n1 1 0\n0 1 0\n0 1 0\n"""
|
||||
G = nx.parse_pajek(data)
|
||||
assert set(G.nodes()) == {"one", "two", "three"}
|
||||
assert G.nodes["two"] == {"id": "2"}
|
||||
assert edges_equal(
|
||||
set(G.edges()),
|
||||
{("one", "one"), ("two", "one"), ("two", "two"), ("two", "three")},
|
||||
)
|
||||
|
||||
def test_read_pajek(self):
|
||||
G = nx.parse_pajek(self.data)
|
||||
Gin = nx.read_pajek(self.fname)
|
||||
assert sorted(G.nodes()) == sorted(Gin.nodes())
|
||||
assert edges_equal(G.edges(), Gin.edges())
|
||||
assert self.G.graph == Gin.graph
|
||||
for n in G:
|
||||
assert G.nodes[n] == Gin.nodes[n]
|
||||
|
||||
def test_write_pajek(self):
|
||||
import io
|
||||
|
||||
G = nx.parse_pajek(self.data)
|
||||
fh = io.BytesIO()
|
||||
nx.write_pajek(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_pajek(fh)
|
||||
assert nodes_equal(list(G), list(H))
|
||||
assert edges_equal(list(G.edges()), list(H.edges()))
|
||||
# Graph name is left out for now, therefore it is not tested.
|
||||
# assert_equal(G.graph, H.graph)
|
||||
|
||||
def test_ignored_attribute(self):
|
||||
import io
|
||||
|
||||
G = nx.Graph()
|
||||
fh = io.BytesIO()
|
||||
G.add_node(1, int_attr=1)
|
||||
G.add_node(2, empty_attr=" ")
|
||||
G.add_edge(1, 2, int_attr=2)
|
||||
G.add_edge(2, 3, empty_attr=" ")
|
||||
|
||||
import warnings
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
nx.write_pajek(G, fh)
|
||||
assert len(w) == 4
|
||||
|
||||
def test_noname(self):
|
||||
# Make sure we can parse a line such as: *network
|
||||
# Issue #952
|
||||
line = "*network\n"
|
||||
other_lines = self.data.split("\n")[1:]
|
||||
data = line + "\n".join(other_lines)
|
||||
G = nx.parse_pajek(data)
|
||||
|
||||
def test_unicode(self):
|
||||
import io
|
||||
|
||||
G = nx.Graph()
|
||||
name1 = chr(2344) + chr(123) + chr(6543)
|
||||
name2 = chr(5543) + chr(1543) + chr(324)
|
||||
G.add_edge(name1, "Radiohead", foo=name2)
|
||||
fh = io.BytesIO()
|
||||
nx.write_pajek(G, fh)
|
||||
fh.seek(0)
|
||||
H = nx.read_pajek(fh)
|
||||
assert nodes_equal(list(G), list(H))
|
||||
assert edges_equal(list(G.edges()), list(H.edges()))
|
||||
assert G.graph == H.graph
|
||||
@@ -1,173 +0,0 @@
|
||||
import tempfile
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
class TestSparseGraph6:
|
||||
def test_from_sparse6_bytes(self):
|
||||
data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM"
|
||||
G = nx.from_sparse6_bytes(data)
|
||||
assert nodes_equal(
|
||||
sorted(G.nodes()),
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
|
||||
)
|
||||
assert edges_equal(
|
||||
G.edges(),
|
||||
[
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(0, 3),
|
||||
(1, 12),
|
||||
(1, 14),
|
||||
(2, 13),
|
||||
(2, 15),
|
||||
(3, 16),
|
||||
(3, 17),
|
||||
(4, 7),
|
||||
(4, 9),
|
||||
(4, 11),
|
||||
(5, 6),
|
||||
(5, 8),
|
||||
(5, 9),
|
||||
(6, 10),
|
||||
(6, 11),
|
||||
(7, 8),
|
||||
(7, 10),
|
||||
(8, 12),
|
||||
(9, 15),
|
||||
(10, 14),
|
||||
(11, 13),
|
||||
(12, 16),
|
||||
(13, 17),
|
||||
(14, 17),
|
||||
(15, 16),
|
||||
],
|
||||
)
|
||||
|
||||
def test_from_bytes_multigraph_graph(self):
|
||||
graph_data = b":An"
|
||||
G = nx.from_sparse6_bytes(graph_data)
|
||||
assert type(G) == nx.Graph
|
||||
multigraph_data = b":Ab"
|
||||
M = nx.from_sparse6_bytes(multigraph_data)
|
||||
assert type(M) == nx.MultiGraph
|
||||
|
||||
def test_read_sparse6(self):
|
||||
data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM"
|
||||
G = nx.from_sparse6_bytes(data)
|
||||
fh = BytesIO(data)
|
||||
Gin = nx.read_sparse6(fh)
|
||||
assert nodes_equal(G.nodes(), Gin.nodes())
|
||||
assert edges_equal(G.edges(), Gin.edges())
|
||||
|
||||
def test_read_many_graph6(self):
|
||||
# Read many graphs into list
|
||||
data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM\n" b":Q___dCfDEdcEgcbEGbFIaJ`JaHN`IM"
|
||||
fh = BytesIO(data)
|
||||
glist = nx.read_sparse6(fh)
|
||||
assert len(glist) == 2
|
||||
for G in glist:
|
||||
assert nodes_equal(
|
||||
G.nodes(),
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
|
||||
)
|
||||
|
||||
|
||||
class TestWriteSparse6:
|
||||
"""Unit tests for writing graphs in the sparse6 format.
|
||||
|
||||
Most of the test cases were checked against the sparse6 encoder in Sage.
|
||||
|
||||
"""
|
||||
|
||||
def test_null_graph(self):
|
||||
G = nx.null_graph()
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:?\n"
|
||||
|
||||
def test_trivial_graph(self):
|
||||
G = nx.trivial_graph()
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:@\n"
|
||||
|
||||
def test_empty_graph(self):
|
||||
G = nx.empty_graph(5)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:D\n"
|
||||
|
||||
def test_large_empty_graph(self):
|
||||
G = nx.empty_graph(68)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:~?@C\n"
|
||||
|
||||
def test_very_large_empty_graph(self):
|
||||
G = nx.empty_graph(258049)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:~~???~?@\n"
|
||||
|
||||
def test_complete_graph(self):
|
||||
G = nx.complete_graph(4)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
assert result.getvalue() == b">>sparse6<<:CcKI\n"
|
||||
|
||||
def test_no_header(self):
|
||||
G = nx.complete_graph(4)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result, header=False)
|
||||
assert result.getvalue() == b":CcKI\n"
|
||||
|
||||
def test_padding(self):
|
||||
codes = (b":Cdv", b":DaYn", b":EaYnN", b":FaYnL", b":GaYnLz")
|
||||
for n, code in enumerate(codes, start=4):
|
||||
G = nx.path_graph(n)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result, header=False)
|
||||
assert result.getvalue() == code + b"\n"
|
||||
|
||||
def test_complete_bipartite(self):
|
||||
G = nx.complete_bipartite_graph(6, 9)
|
||||
result = BytesIO()
|
||||
nx.write_sparse6(G, result)
|
||||
# Compared with sage
|
||||
expected = b">>sparse6<<:Nk" + b"?G`cJ" * 9 + b"\n"
|
||||
assert result.getvalue() == expected
|
||||
|
||||
def test_read_write_inverse(self):
|
||||
for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
|
||||
m = min(2 * i, i * i // 2)
|
||||
g = nx.random_graphs.gnm_random_graph(i, m, seed=i)
|
||||
gstr = BytesIO()
|
||||
nx.write_sparse6(g, gstr, header=False)
|
||||
# Strip the trailing newline.
|
||||
gstr = gstr.getvalue().rstrip()
|
||||
g2 = nx.from_sparse6_bytes(gstr)
|
||||
assert g2.order() == g.order()
|
||||
assert edges_equal(g2.edges(), g.edges())
|
||||
|
||||
def test_no_directed_graphs(self):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
nx.write_sparse6(nx.DiGraph(), BytesIO())
|
||||
|
||||
def test_write_path(self):
|
||||
# On Windows, we can't reopen a file that is open
|
||||
# So, for test we get a valid name from tempfile but close it.
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
fullfilename = f.name
|
||||
# file should be closed now, so write_sparse6 can open it
|
||||
nx.write_sparse6(nx.null_graph(), fullfilename)
|
||||
fh = open(fullfilename, mode="rb")
|
||||
assert fh.read() == b">>sparse6<<:?\n"
|
||||
fh.close()
|
||||
import os
|
||||
|
||||
os.remove(fullfilename)
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user