Repository: networkx/networkx

Issue:
Reverse breaks DiGraphs with default-hashed objects
The NetworkX documentation [states that graph nodes can be any hashable object](https://networkx.github.io/documentation/networkx-1.10/reference/introduction.html#networkx-basics), and the glossary [defines hashable](https://networkx.github.io/documentation/networkx-1.10/reference/glossary.html#term-hashable) per the Python definition (that is, implements `__hash__` and a comparison method). It goes out of its way to state that instances of user-defined classes are hashable (and unique) by default:

> All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. **Objects which are instances of user-defined classes are hashable by default; they all compare unequal, and their hash value is their id().**

That would seem to suggest that NetworkX supports graphs made of default-hashed objects (and nodes are considered the same if they're reference-equal). However, I found that the `reverse` method doesn't respect this property. Example:

```python
import networkx as nx

class Unique(object):
    pass

u = Unique()

g = nx.DiGraph()
g.add_edge("A", u)
assert "A" in g
assert u in g # passes
g.nodes() # ['A', <__main__.Unique object at 0x102e0fe10>]
g.edges() # [('A', <__main__.Unique object at 0x102e0fe10>)]

rev = g.reverse()
assert "A" in rev
assert u in rev # fails ಠ_ಠ
rev.nodes() # ['A', <__main__.Unique object at 0x102e0fd10>]
rev.edges() # [(<__main__.Unique object at 0x102e0fe10>, 'A')]
# Unique address is different in nodes() and edges(): `fd10` vs `fe10` ಠ_ಠ
```

What seems to happen is that `reverse` "deep copies" the graph (this is where it calls `Unique.__new__`, at least), and then seemingly doesn't keep track of objects that it has already copied.


Discussion:
See #2282.
@hagberg I think this is a slightly different issue, one with DiGraph.reverse. The test case here should be something like

```python
    def test_reverse_hashable(self):
        class Foo(object): pass
        x = Foo()
        y = Foo()
        G = nx.DiGraph()
        G.add_edge(x, y)
        self.assertCountEqual(G.nodes(), G.reverse().nodes())
        self.assertCountEqual(map(reversed, G.edges()), G.reverse().edges())
```
Is the contract for `DiGraph.reverse` supposed to be that the nodes are the exact same objects?
@hagberg #2282 looks different to me. The core issue was that distinct objects with the same hash that compared equal were referenced inconsistently between nodes and edges. The reporter said that this was probably not a bug, and I'd tend to agree with that, since the graph contract is that nodes are distinguished with their hash and equality property.

In this case, `reverse` appears to make *two copies of one single object* whose hash and equality are derived from its `id()`, destroying the equality relationship in the process. That result is inconsistent with the promise that NetworkX graphs can take objects that use the default hash and equality.
I see what you are saying.  You are right - this is different than that earlier issue and it is a bug.
I think the fix should be in digraph.reverse()
```python
#            H.node=deepcopy(self.node)
            for n in self.node:
                H.node[n]=deepcopy(self.node[n])
```

Thanks for your careful look at this.

This just needs a PR with @hagberg fix and add @jfinkels test to the tests.
I appreciate that this is getting attention. Unfortunately, my company makes it absurdly hard to contribute source code to open-source projects. Pointing out issues is about as much as I can do, right now. 😕

Resolving patch:
diff --git a/networkx/classes/digraph.py b/networkx/classes/digraph.py
--- a/networkx/classes/digraph.py
+++ b/networkx/classes/digraph.py
@@ -1124,7 +1124,8 @@ def reverse(self, copy=True):
             H.add_edges_from((v, u, deepcopy(d)) for u, v, d
                              in self.edges(data=True))
             H.graph = deepcopy(self.graph)
-            H._node = deepcopy(self._node)
+            for n in self._node:
+                H._node[n] = deepcopy(self._node[n])
         else:
             self._pred, self._succ = self._succ, self._pred
             self._adj = self._succ


Test patch:
diff --git a/networkx/classes/tests/test_digraph.py b/networkx/classes/tests/test_digraph.py
--- a/networkx/classes/tests/test_digraph.py
+++ b/networkx/classes/tests/test_digraph.py
@@ -1,173 +1,192 @@
 #!/usr/bin/env python
-from nose.tools import *
-import networkx
+
+from nose.tools import assert_equal
+from nose.tools import assert_false
+from nose.tools import assert_true
+from nose.tools import assert_raises
+
+
+import networkx as nx
+from networkx.testing import assert_nodes_equal
 from test_graph import BaseGraphTester, BaseAttrGraphTester, TestGraph
 from test_graph import TestEdgeSubgraph as TestGraphEdgeSubgraph
 
+
 class BaseDiGraphTester(BaseGraphTester):
     def test_has_successor(self):
-        G=self.K3
-        assert_equal(G.has_successor(0,1),True)
-        assert_equal(G.has_successor(0,-1),False)
+        G = self.K3
+        assert_equal(G.has_successor(0, 1), True)
+        assert_equal(G.has_successor(0, -1), False)
 
     def test_successors(self):
-        G=self.K3
-        assert_equal(sorted(G.successors(0)),[1,2])
-        assert_raises((KeyError,networkx.NetworkXError), G.successors,-1)
+        G = self.K3
+        assert_equal(sorted(G.successors(0)), [1, 2])
+        assert_raises((KeyError, nx.NetworkXError), G.successors, -1)
 
     def test_has_predecessor(self):
-        G=self.K3
-        assert_equal(G.has_predecessor(0,1),True)
-        assert_equal(G.has_predecessor(0,-1),False)
+        G = self.K3
+        assert_equal(G.has_predecessor(0, 1), True)
+        assert_equal(G.has_predecessor(0, -1), False)
 
     def test_predecessors(self):
-        G=self.K3
-        assert_equal(sorted(G.predecessors(0)),[1,2])
-        assert_raises((KeyError,networkx.NetworkXError), G.predecessors,-1)
+        G = self.K3
+        assert_equal(sorted(G.predecessors(0)), [1, 2])
+        assert_raises((KeyError, nx.NetworkXError), G.predecessors, -1)
 
     def test_edges(self):
-        G=self.K3
-        assert_equal(sorted(G.edges()),[(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)])
-        assert_equal(sorted(G.edges(0)),[(0,1),(0,2)])
+        G = self.K3
+        assert_equal(sorted(G.edges()), [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)])
+        assert_equal(sorted(G.edges(0)), [(0, 1), (0, 2)])
         assert_equal(sorted(G.edges([0, 1])), [(0, 1), (0, 2), (1, 0), (1, 2)])
-        assert_raises((KeyError,networkx.NetworkXError), G.edges,-1)
+        assert_raises((KeyError, nx.NetworkXError), G.edges, -1)
 
     def test_edges_data(self):
-        G=self.K3
-        all_edges = [(0,1,{}),(0,2,{}),(1,0,{}),(1,2,{}),(2,0,{}),(2,1,{})]
+        G = self.K3
+        all_edges = [(0, 1, {}), (0, 2, {}), (1, 0, {}), (1, 2, {}), (2, 0, {}), (2, 1, {})]
         assert_equal(sorted(G.edges(data=True)), all_edges)
         assert_equal(sorted(G.edges(0, data=True)), all_edges[:2])
         assert_equal(sorted(G.edges([0, 1], data=True)), all_edges[:4])
-        assert_raises((KeyError,networkx.NetworkXError), G.edges, -1, True)
+        assert_raises((KeyError, nx.NetworkXError), G.edges, -1, True)
 
     def test_out_edges(self):
-        G=self.K3
-        assert_equal(sorted(G.out_edges()),
-                     [(0,1),(0,2),(1,0),(1,2),(2,0),(2,1)])
-        assert_equal(sorted(G.out_edges(0)),[(0,1),(0,2)])
-        assert_raises((KeyError,networkx.NetworkXError), G.out_edges,-1)
+        G = self.K3
+        assert_equal(sorted(G.out_edges()), [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)])
+        assert_equal(sorted(G.out_edges(0)), [(0, 1), (0, 2)])
+        assert_raises((KeyError, nx.NetworkXError), G.out_edges, -1)
 
     def test_out_edges_dir(self):
-        G=self.P3
-        assert_equal(sorted(G.out_edges()),[(0, 1), (1, 2)])
-        assert_equal(sorted(G.out_edges(0)),[(0, 1)])
-        assert_equal(sorted(G.out_edges(2)),[])
+        G = self.P3
+        assert_equal(sorted(G.out_edges()), [(0, 1), (1, 2)])
+        assert_equal(sorted(G.out_edges(0)), [(0, 1)])
+        assert_equal(sorted(G.out_edges(2)), [])
 
     def test_out_edges_data(self):
-        G=networkx.DiGraph([(0, 1, {'data' : 0}), (1, 0, {})])
-        assert_equal(sorted(G.out_edges(data=True)), [(0, 1, {'data' : 0}), (1, 0, {})])
-        assert_equal(sorted(G.out_edges(0, data=True)), [(0, 1, {'data' : 0})])
+        G = nx.DiGraph([(0, 1, {'data': 0}), (1, 0, {})])
+        assert_equal(sorted(G.out_edges(data=True)), [(0, 1, {'data': 0}), (1, 0, {})])
+        assert_equal(sorted(G.out_edges(0, data=True)), [(0, 1, {'data': 0})])
         assert_equal(sorted(G.out_edges(data='data')), [(0, 1, 0), (1, 0, None)])
         assert_equal(sorted(G.out_edges(0, data='data')), [(0, 1, 0)])
 
     def test_in_edges_dir(self):
-        G=self.P3
+        G = self.P3
         assert_equal(sorted(G.in_edges()), [(0, 1), (1, 2)])
         assert_equal(sorted(G.in_edges(0)), [])
-        assert_equal(sorted(G.in_edges(2)), [(1,2)])
+        assert_equal(sorted(G.in_edges(2)), [(1, 2)])
 
     def test_in_edges_data(self):
-        G=networkx.DiGraph([(0, 1, {'data' : 0}), (1, 0, {})])
-        assert_equal(sorted(G.in_edges(data=True)), [(0, 1, {'data' : 0}), (1, 0, {})])
-        assert_equal(sorted(G.in_edges(1, data=True)), [(0, 1, {'data' : 0})])
+        G = nx.DiGraph([(0, 1, {'data': 0}), (1, 0, {})])
+        assert_equal(sorted(G.in_edges(data=True)), [(0, 1, {'data': 0}), (1, 0, {})])
+        assert_equal(sorted(G.in_edges(1, data=True)), [(0, 1, {'data': 0})])
         assert_equal(sorted(G.in_edges(data='data')), [(0, 1, 0), (1, 0, None)])
         assert_equal(sorted(G.in_edges(1, data='data')), [(0, 1, 0)])
 
     def test_degree(self):
-        G=self.K3
-        assert_equal(sorted(G.degree()),[(0,4),(1,4),(2,4)])
-        assert_equal(dict(G.degree()),{0:4,1:4,2:4})
+        G = self.K3
+        assert_equal(sorted(G.degree()), [(0, 4), (1, 4), (2, 4)])
+        assert_equal(dict(G.degree()), {0: 4, 1: 4, 2: 4})
         assert_equal(G.degree(0), 4)
-        assert_equal(list(G.degree(iter([0]))), [(0, 4)]) #run through iterator
+        assert_equal(list(G.degree(iter([0]))), [
+                     (0, 4)])  # run through iterator
 
     def test_in_degree(self):
-        G=self.K3
-        assert_equal(sorted(G.in_degree()),[(0,2),(1,2),(2,2)])
-        assert_equal(dict(G.in_degree()),{0:2,1:2,2:2})
+        G = self.K3
+        assert_equal(sorted(G.in_degree()), [(0, 2), (1, 2), (2, 2)])
+        assert_equal(dict(G.in_degree()), {0: 2, 1: 2, 2: 2})
         assert_equal(G.in_degree(0), 2)
-        assert_equal(list(G.in_degree(iter([0]))), [(0, 2)]) #run through iterator
+        assert_equal(list(G.in_degree(iter([0]))), [(0, 2)])  # run through iterator
 
     def test_in_degree_weighted(self):
-        G=self.K3
-        G.add_edge(0,1,weight=0.3,other=1.2)
-        assert_equal(sorted(G.in_degree(weight='weight')),[(0,2),(1,1.3),(2,2)])
-        assert_equal(dict(G.in_degree(weight='weight')),{0:2,1:1.3,2:2})
-        assert_equal(G.in_degree(1,weight='weight'), 1.3)
-        assert_equal(sorted(G.in_degree(weight='other')),[(0,2),(1,2.2),(2,2)])
-        assert_equal(dict(G.in_degree(weight='other')),{0:2,1:2.2,2:2})
-        assert_equal(G.in_degree(1,weight='other'), 2.2)
-        assert_equal(list(G.in_degree(iter([1]),weight='other')), [(1, 2.2)])
+        G = self.K3
+        G.add_edge(0, 1, weight=0.3, other=1.2)
+        assert_equal(sorted(G.in_degree(weight='weight')), [(0, 2), (1, 1.3), (2, 2)])
+        assert_equal(dict(G.in_degree(weight='weight')), {0: 2, 1: 1.3, 2: 2})
+        assert_equal(G.in_degree(1, weight='weight'), 1.3)
+        assert_equal(sorted(G.in_degree(weight='other')), [(0, 2), (1, 2.2), (2, 2)])
+        assert_equal(dict(G.in_degree(weight='other')), {0: 2, 1: 2.2, 2: 2})
+        assert_equal(G.in_degree(1, weight='other'), 2.2)
+        assert_equal(list(G.in_degree(iter([1]), weight='other')), [(1, 2.2)])
 
     def test_out_degree_weighted(self):
-        G=self.K3
-        G.add_edge(0,1,weight=0.3,other=1.2)
-        assert_equal(sorted(G.out_degree(weight='weight')),[(0,1.3),(1,2),(2,2)])
-        assert_equal(dict(G.out_degree(weight='weight')),{0:1.3,1:2,2:2})
-        assert_equal(G.out_degree(0,weight='weight'), 1.3)
-        assert_equal(sorted(G.out_degree(weight='other')),[(0,2.2),(1,2),(2,2)])
-        assert_equal(dict(G.out_degree(weight='other')),{0:2.2,1:2,2:2})
-        assert_equal(G.out_degree(0,weight='other'), 2.2)
+        G = self.K3
+        G.add_edge(0, 1, weight=0.3, other=1.2)
+        assert_equal(sorted(G.out_degree(weight='weight')), [(0, 1.3), (1, 2), (2, 2)])
+        assert_equal(dict(G.out_degree(weight='weight')), {0: 1.3, 1: 2, 2: 2})
+        assert_equal(G.out_degree(0, weight='weight'), 1.3)
+        assert_equal(sorted(G.out_degree(weight='other')), [(0, 2.2), (1, 2), (2, 2)])
+        assert_equal(dict(G.out_degree(weight='other')), {0: 2.2, 1: 2, 2: 2})
+        assert_equal(G.out_degree(0, weight='other'), 2.2)
         assert_equal(list(G.out_degree(iter([0]), weight='other')), [(0, 2.2)])
 
     def test_out_degree(self):
-        G=self.K3
-        assert_equal(sorted(G.out_degree()),[(0,2),(1,2),(2,2)])
-        assert_equal(dict(G.out_degree()),{0:2,1:2,2:2})
+        G = self.K3
+        assert_equal(sorted(G.out_degree()), [(0, 2), (1, 2), (2, 2)])
+        assert_equal(dict(G.out_degree()), {0: 2, 1: 2, 2: 2})
         assert_equal(G.out_degree(0), 2)
         assert_equal(list(G.out_degree(iter([0]))), [(0, 2)])
 
     def test_size(self):
-        G=self.K3
-        assert_equal(G.size(),6)
-        assert_equal(G.number_of_edges(),6)
+        G = self.K3
+        assert_equal(G.size(), 6)
+        assert_equal(G.number_of_edges(), 6)
 
     def test_to_undirected_reciprocal(self):
-        G=self.Graph()
-        G.add_edge(1,2)
-        assert_true(G.to_undirected().has_edge(1,2))
-        assert_false(G.to_undirected(reciprocal=True).has_edge(1,2))
-        G.add_edge(2,1)
-        assert_true(G.to_undirected(reciprocal=True).has_edge(1,2))
+        G = self.Graph()
+        G.add_edge(1, 2)
+        assert_true(G.to_undirected().has_edge(1, 2))
+        assert_false(G.to_undirected(reciprocal=True).has_edge(1, 2))
+        G.add_edge(2, 1)
+        assert_true(G.to_undirected(reciprocal=True).has_edge(1, 2))
 
     def test_reverse_copy(self):
-        G=networkx.DiGraph([(0,1),(1,2)])
-        R=G.reverse()
-        assert_equal(sorted(R.edges()),[(1,0),(2,1)])
-        R.remove_edge(1,0)
-        assert_equal(sorted(R.edges()),[(2,1)])
-        assert_equal(sorted(G.edges()),[(0,1),(1,2)])
+        G = nx.DiGraph([(0, 1), (1, 2)])
+        R = G.reverse()
+        assert_equal(sorted(R.edges()), [(1, 0), (2, 1)])
+        R.remove_edge(1, 0)
+        assert_equal(sorted(R.edges()), [(2, 1)])
+        assert_equal(sorted(G.edges()), [(0, 1), (1, 2)])
 
     def test_reverse_nocopy(self):
-        G=networkx.DiGraph([(0,1),(1,2)])
-        R=G.reverse(copy=False)
-        assert_equal(sorted(R.edges()),[(1,0),(2,1)])
-        R.remove_edge(1,0)
-        assert_equal(sorted(R.edges()),[(2,1)])
-        assert_equal(sorted(G.edges()),[(2,1)])
-
-
-class BaseAttrDiGraphTester(BaseDiGraphTester,BaseAttrGraphTester):
+        G = nx.DiGraph([(0, 1), (1, 2)])
+        R = G.reverse(copy=False)
+        assert_equal(sorted(R.edges()), [(1, 0), (2, 1)])
+        R.remove_edge(1, 0)
+        assert_equal(sorted(R.edges()), [(2, 1)])
+        assert_equal(sorted(G.edges()), [(2, 1)])
+
+    def test_reverse_hashable(self):
+        class Foo(object):
+            pass
+        x = Foo()
+        y = Foo()
+        G = nx.DiGraph()
+        G.add_edge(x, y)
+        assert_nodes_equal(G.nodes(), G.reverse().nodes())
+        assert_equal([(y, x)], list(G.reverse().edges()))
+
+
+class BaseAttrDiGraphTester(BaseDiGraphTester, BaseAttrGraphTester):
     pass
 
 
-class TestDiGraph(BaseAttrDiGraphTester,TestGraph):
+class TestDiGraph(BaseAttrDiGraphTester, TestGraph):
     """Tests specific to dict-of-dict-of-dict digraph data structure"""
+
     def setUp(self):
-        self.Graph=networkx.DiGraph
+        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}}
+        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._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 = ({},{})
+        ed1, ed2 = ({}, {})
         self.P3 = self.Graph()
         self.P3._adj = {0: {1: ed1}, 1: {2: ed2}, 2: {}}
         self.P3._succ = self.P3._adj
@@ -178,48 +197,48 @@ def setUp(self):
         self.P3._node[2] = {}
 
     def test_data_input(self):
-        G=self.Graph(data={1:[2],2:[1]}, name="test")
-        assert_equal(G.name,"test")
-        assert_equal(sorted(G.adj.items()),[(1, {2: {}}), (2, {1: {}})])
-        assert_equal(sorted(G.succ.items()),[(1, {2: {}}), (2, {1: {}})])
-        assert_equal(sorted(G.pred.items()),[(1, {2: {}}), (2, {1: {}})])
+        G = self.Graph(data={1: [2], 2: [1]}, name="test")
+        assert_equal(G.name, "test")
+        assert_equal(sorted(G.adj.items()), [(1, {2: {}}), (2, {1: {}})])
+        assert_equal(sorted(G.succ.items()), [(1, {2: {}}), (2, {1: {}})])
+        assert_equal(sorted(G.pred.items()), [(1, {2: {}}), (2, {1: {}})])
 
     def test_add_edge(self):
-        G=self.Graph()
-        G.add_edge(0,1)
-        assert_equal(G.adj,{0: {1: {}}, 1: {}})
-        assert_equal(G.succ,{0: {1: {}}, 1: {}})
-        assert_equal(G.pred,{0: {}, 1: {0:{}}})
-        G=self.Graph()
-        G.add_edge(*(0,1))
-        assert_equal(G.adj,{0: {1: {}}, 1: {}})
-        assert_equal(G.succ,{0: {1: {}}, 1: {}})
-        assert_equal(G.pred,{0: {}, 1: {0:{}}})
+        G = self.Graph()
+        G.add_edge(0, 1)
+        assert_equal(G.adj, {0: {1: {}}, 1: {}})
+        assert_equal(G.succ, {0: {1: {}}, 1: {}})
+        assert_equal(G.pred, {0: {}, 1: {0: {}}})
+        G = self.Graph()
+        G.add_edge(*(0, 1))
+        assert_equal(G.adj, {0: {1: {}}, 1: {}})
+        assert_equal(G.succ, {0: {1: {}}, 1: {}})
+        assert_equal(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_equal(G.adj,{0: {1: {'data':2}, 2: {'data':3}}, 1: {}, 2: {}})
-        assert_equal(G.succ,{0: {1: {'data':2}, 2: {'data':3}}, 1: {}, 2: {}})
-        assert_equal(G.pred,{0: {}, 1: {0: {'data':2}}, 2: {0: {'data':3}}})
+        G = self.Graph()
+        G.add_edges_from([(0, 1), (0, 2, {'data': 3})], data=2)
+        assert_equal(G.adj, {0: {1: {'data': 2}, 2: {'data': 3}}, 1: {}, 2: {}})
+        assert_equal(G.succ, {0: {1: {'data': 2}, 2: {'data': 3}}, 1: {}, 2: {}})
+        assert_equal(G.pred, {0: {}, 1: {0: {'data': 2}}, 2: {0: {'data': 3}}})
 
-        assert_raises(networkx.NetworkXError, G.add_edges_from,[(0,)])  # too few in tuple
-        assert_raises(networkx.NetworkXError, G.add_edges_from,[(0,1,2,3)])  # too many in tuple
-        assert_raises(TypeError, G.add_edges_from,[0])  # not a tuple
+        assert_raises(nx.NetworkXError, G.add_edges_from, [(0,)])  # too few in tuple
+        assert_raises(nx.NetworkXError, G.add_edges_from, [(0, 1, 2, 3)])  # too many in tuple
+        assert_raises(TypeError, G.add_edges_from, [0])  # not a tuple
 
     def test_remove_edge(self):
-        G=self.K3
-        G.remove_edge(0,1)
-        assert_equal(G.succ,{0:{2:{}},1:{0:{},2:{}},2:{0:{},1:{}}})
-        assert_equal(G.pred,{0:{1:{}, 2:{}}, 1:{2:{}}, 2:{0:{},1:{}}})
-        assert_raises((KeyError,networkx.NetworkXError), G.remove_edge,-1,0)
+        G = self.K3
+        G.remove_edge(0, 1)
+        assert_equal(G.succ, {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}})
+        assert_equal(G.pred, {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}})
+        assert_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_equal(G.succ,{0:{2:{}},1:{0:{},2:{}},2:{0:{},1:{}}})
-        assert_equal(G.pred,{0:{1:{}, 2:{}}, 1:{2:{}}, 2:{0:{},1: {}}})
-        G.remove_edges_from([(0,0)]) # silent fail
+        G = self.K3
+        G.remove_edges_from([(0, 1)])
+        assert_equal(G.succ, {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}})
+        assert_equal(G.pred, {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}})
+        G.remove_edges_from([(0, 0)])  # silent fail
 
 
 class TestEdgeSubgraph(TestGraphEdgeSubgraph):
@@ -227,7 +246,7 @@ class TestEdgeSubgraph(TestGraphEdgeSubgraph):
 
     def setup(self):
         # Create a doubly-linked path graph on five nodes.
-        G = networkx.DiGraph(networkx.path_graph(5))
+        G = nx.DiGraph(nx.path_graph(5))
         # Add some node, edge, and graph attributes.
         for i in range(5):
             G.node[i]['name'] = 'node{}'.format(i)
@@ -244,7 +263,7 @@ def test_pred_succ(self):
         For more information, see GitHub issue #2370.
 
         """
-        G = networkx.DiGraph()
+        G = nx.DiGraph()
         G.add_edge(0, 1)
         H = G.edge_subgraph([(0, 1)])
         assert_equal(list(H.predecessors(0)), [])