Repository: networkx/networkx

Issue:
Use AdjListOuterDict instead of NodeDict for DiGraph's succ and pred?
Hi networkx folks,

I found the init function of DiGraph [here](https://github.com/networkx/networkx/blob/master/networkx/classes/digraph.py#L303) is interesting. Instead of using `adjlist_outer_dict_factory`, the `node_dict_factory` is used. Is this a bug? My use case is try to hook network's DiGraph to notify my other components of when a node and edge is being added to the graph. My current solution is to subclass the DiGraph and replace the four dict structures with my own dict. However, because of this logic, it is harder to distinguish between node and edge addition/removal. Would you please have a look? Thank you.

-Minjie


Discussion:
Yup --- That is a bug.  That should be ```adjlist_outer_dict_factory```.

Thank you!
Thanks for the response. Look forward to the fix!

Resolving patch:
diff --git a/networkx/classes/digraph.py b/networkx/classes/digraph.py
--- a/networkx/classes/digraph.py
+++ b/networkx/classes/digraph.py
@@ -290,18 +290,18 @@ def __init__(self, incoming_graph_data=None, **attr):
         {'day': 'Friday'}
 
         """
-        self.node_dict_factory = ndf = self.node_dict_factory
+        self.node_dict_factory = self.node_dict_factory
         self.adjlist_outer_dict_factory = self.adjlist_outer_dict_factory
         self.adjlist_inner_dict_factory = self.adjlist_inner_dict_factory
         self.edge_attr_dict_factory = self.edge_attr_dict_factory
 
         self.graph = {}  # dictionary for graph attributes
-        self._node = ndf()  # dictionary for node attributes
+        self._node = self.node_dict_factory()  # dictionary for node attr
         # We store two adjacency lists:
         # the  predecessors of node n are stored in the dict self._pred
         # the successors of node n are stored in the dict self._succ=self._adj
-        self._adj = ndf()  # empty adjacency dictionary
-        self._pred = ndf()  # predecessor
+        self._adj = self.adjlist_outer_dict_factory()  # empty adjacency dict
+        self._pred = self.adjlist_outer_dict_factory()  # predecessor
         self._succ = self._adj  # successor
 
         # attempt to load graph with data


Test patch:
diff --git a/networkx/classes/tests/test_special.py b/networkx/classes/tests/test_special.py
--- a/networkx/classes/tests/test_special.py
+++ b/networkx/classes/tests/test_special.py
@@ -8,6 +8,47 @@
 from test_multidigraph import TestMultiDiGraph
 
 
+def test_factories():
+    class mydict1(dict):
+        pass
+
+    class mydict2(dict):
+        pass
+
+    class mydict3(dict):
+        pass
+
+    class mydict4(dict):
+        pass
+
+    class mydict5(dict):
+        pass
+
+    for Graph in (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph):
+        # print("testing class: ", Graph.__name__)
+        class MyGraph(Graph):
+            node_dict_factory = mydict1
+            adjlist_outer_dict_factory = mydict2
+            adjlist_inner_dict_factory = mydict3
+            edge_key_dict_factory = mydict4
+            edge_attr_dict_factory = mydict5
+        G = MyGraph()
+        assert_is_instance(G._node, mydict1)
+        assert_is_instance(G._adj, mydict2)
+        G.add_node(1)
+        assert_is_instance(G._adj[1], mydict3)
+        if G.is_directed():
+            assert_is_instance(G._pred, mydict2)
+            assert_is_instance(G._succ, mydict2)
+            assert_is_instance(G._pred[1], mydict3)
+        G.add_edge(1, 2)
+        if G.is_multigraph():
+            assert_is_instance(G._adj[1][2], mydict4)
+            assert_is_instance(G._adj[1][2][0], mydict5)
+        else:
+            assert_is_instance(G._adj[1][2], mydict5)
+
+
 class SpecialGraphTester(TestGraph):
     def setUp(self):
         TestGraph.setUp(self)