Repository: scikit-image/scikit-image

Issue:
Revert Travis config changes
## Description
Revert https://github.com/scikit-image/scikit-image/pull/2774 once https://github.com/scikit-image/scikit-image/pull/2766 is merged.


Discussion:

Resolving patch:
diff --git a/skimage/future/graph/graph_cut.py b/skimage/future/graph/graph_cut.py
--- a/skimage/future/graph/graph_cut.py
+++ b/skimage/future/graph/graph_cut.py
@@ -55,7 +55,7 @@ def cut_threshold(labels, rag, thresh, in_place=True):
         rag = rag.copy()
 
     # Because deleting edges while iterating through them produces an error.
-    to_remove = [(x, y) for x, y, d in rag.edges_iter(data=True)
+    to_remove = [(x, y) for x, y, d in rag.edges(data=True)
                  if d['weight'] >= thresh]
     rag.remove_edges_from(to_remove)
 
@@ -125,14 +125,14 @@ def cut_normalized(labels, rag, thresh=0.001, num_cuts=10, in_place=True,
     if not in_place:
         rag = rag.copy()
 
-    for node in rag.nodes_iter():
+    for node in rag.nodes():
         rag.add_edge(node, node, weight=max_edge)
 
     _ncut_relabel(rag, thresh, num_cuts)
 
     map_array = np.zeros(labels.max() + 1, dtype=labels.dtype)
     # Mapping from old labels to new
-    for n, d in rag.nodes_iter(data=True):
+    for n, d in rag.nodes(data=True):
         map_array[d['labels']] = d['ncut label']
 
     return map_array[labels]
@@ -231,7 +231,7 @@ def _label_all(rag, attr_name):
     """
     node = min(rag.nodes())
     new_label = rag.node[node]['labels'][0]
-    for n, d in rag.nodes_iter(data=True):
+    for n, d in rag.nodes(data=True):
         d[attr_name] = new_label
 
 
diff --git a/skimage/future/graph/graph_merge.py b/skimage/future/graph/graph_merge.py
--- a/skimage/future/graph/graph_merge.py
+++ b/skimage/future/graph/graph_merge.py
@@ -42,7 +42,7 @@ def _rename_node(graph, node_id, copy_id):
     """ Rename `node_id` in `graph` to `copy_id`. """
 
     graph._add_node_silent(copy_id)
-    graph.node[copy_id] = graph.node[node_id]
+    graph.node[copy_id].update(graph.node[node_id])
 
     for nbr in graph.neighbors(node_id):
         wt = graph[node_id][nbr]['weight']
@@ -96,7 +96,7 @@ def merge_hierarchical(labels, rag, thresh, rag_copy, in_place_merge,
         rag = rag.copy()
 
     edge_heap = []
-    for n1, n2, data in rag.edges_iter(data=True):
+    for n1, n2, data in rag.edges(data=True):
         # Push a valid edge in the heap
         wt = data['weight']
         heap_item = [wt, n1, n2, True]
@@ -130,7 +130,7 @@ def merge_hierarchical(labels, rag, thresh, rag_copy, in_place_merge,
             _revalidate_node_edges(rag, new_id, edge_heap)
 
     label_map = np.arange(labels.max() + 1)
-    for ix, (n, d) in enumerate(rag.nodes_iter(data=True)):
+    for ix, (n, d) in enumerate(rag.nodes(data=True)):
         for label in d['labels']:
             label_map[label] = ix
 
diff --git a/skimage/future/graph/rag.py b/skimage/future/graph/rag.py
--- a/skimage/future/graph/rag.py
+++ b/skimage/future/graph/rag.py
@@ -136,7 +136,7 @@ def __init__(self, label_image=None, connectivity=1, data=None, **attr):
         if self.number_of_nodes() == 0:
             self.max_id = 0
         else:
-            self.max_id = max(self.nodes_iter())
+            self.max_id = max(self.nodes())
 
         if label_image is not None:
             fp = ndi.generate_binary_structure(label_image.ndim, connectivity)
@@ -249,6 +249,28 @@ def copy(self):
         g.max_id = self.max_id
         return g
 
+    def fresh_copy(self):
+        """Return a fresh copy graph with the same data structure.
+
+        A fresh copy has no nodes, edges or graph attributes. It is
+        the same data structure as the current graph. This method is
+        typically used to create an empty version of the graph.
+
+        This is required when subclassing Graph with networkx v2 and
+        does not cause problems for v1. Here is more detail from
+        the network migrating from 1.x to 2.x document::
+
+            With the new GraphViews (SubGraph, ReversedGraph, etc)
+            you can't assume that ``G.__class__()`` will create a new
+            instance of the same graph type as ``G``. In fact, the
+            call signature for ``__class__`` differs depending on
+            whether ``G`` is a view or a base class. For v2.x you
+            should use ``G.fresh_copy()`` to create a null graph of
+            the correct type---ready to fill with nodes and edges.
+
+        """
+        return RAG()
+
     def next_id(self):
         """Returns the `id` for the new node to be inserted.
 
@@ -269,30 +291,6 @@ def _add_node_silent(self, n):
         .. seealso:: :func:`networkx.Graph.add_node`."""
         super(RAG, self).add_node(n)
 
-    def nodes_iter(self, *args, **kwargs):
-        """ Iterate over nodes
-
-        For compatibility with older versions of networkx.  Versions <= 1.11
-        have an ``nodes_iter`` method, but later versions return an iterator from
-        the nodes method, and lack ``nodes_iter``.
-        """
-        try:
-            return super(RAG, self).nodes_iter(*args, **kwargs)
-        except AttributeError:
-            return super(RAG, self).nodes(*args, **kwargs)
-
-    def edges_iter(self, *args, **kwargs):
-        """ Iterate over edges
-
-        For compatibility with older versions of networkx.  Versions <= 1.11
-        have an ``edges_iter`` method, but later versions return an iterator from
-        the edges method, and lack ``edges_iter``.
-        """
-        try:
-            return super(RAG, self).edges_iter(*args, **kwargs)
-        except AttributeError:
-            return super(RAG, self).edges(*args, **kwargs)
-
 
 def rag_mean_color(image, labels, connectivity=2, mode='distance',
                    sigma=255.0):
@@ -372,7 +370,7 @@ def rag_mean_color(image, labels, connectivity=2, mode='distance',
         graph.node[n]['mean color'] = (graph.node[n]['total color'] /
                                        graph.node[n]['pixel count'])
 
-    for x, y, d in graph.edges_iter(data=True):
+    for x, y, d in graph.edges(data=True):
         diff = graph.node[x]['mean color'] - graph.node[y]['mean color']
         diff = np.linalg.norm(diff)
         if mode == 'similarity':
@@ -529,7 +527,7 @@ def show_rag(labels, rag, image, border_color='black', edge_width=1.5,
     # offset is 1 so that regionprops does not ignore 0
     offset = 1
     map_array = np.arange(labels.max() + 1)
-    for n, d in rag.nodes_iter(data=True):
+    for n, d in rag.nodes(data=True):
         for label in d['labels']:
             map_array[label] = offset
         offset += 1
@@ -537,7 +535,7 @@ def show_rag(labels, rag, image, border_color='black', edge_width=1.5,
     rag_labels = map_array[labels]
     regions = measure.regionprops(rag_labels)
 
-    for (n, data), region in zip(rag.nodes_iter(data=True), regions):
+    for (n, data), region in zip(rag.nodes(data=True), regions):
         data['centroid'] = tuple(map(int, region['centroid']))
 
     cc = colors.ColorConverter()
@@ -551,10 +549,10 @@ def show_rag(labels, rag, image, border_color='black', edge_width=1.5,
     # The tuple[::-1] syntax reverses a tuple as matplotlib uses (x,y)
     # convention while skimage uses (row, column)
     lines = [[rag.node[n1]['centroid'][::-1], rag.node[n2]['centroid'][::-1]]
-             for (n1, n2) in rag.edges_iter()]
+             for (n1, n2) in rag.edges()]
 
     lc = LineCollection(lines, linewidths=edge_width, cmap=edge_cmap)
-    edge_weights = [d['weight'] for x, y, d in rag.edges_iter(data=True)]
+    edge_weights = [d['weight'] for x, y, d in rag.edges(data=True)]
     lc.set_array(np.array(edge_weights))
     ax.add_collection(lc)
 


Test patch:
diff --git a/skimage/future/graph/tests/test_rag.py b/skimage/future/graph/tests/test_rag.py
--- a/skimage/future/graph/tests/test_rag.py
+++ b/skimage/future/graph/tests/test_rag.py
@@ -32,14 +32,14 @@ def test_rag_merge():
     # We merge nodes and ensure that the minimum weight is chosen
     # when there is a conflict.
     g.merge_nodes(0, 2)
-    assert g.edge[1][2]['weight'] == 10
-    assert g.edge[2][3]['weight'] == 30
+    assert g.adj[1][2]['weight'] == 10
+    assert g.adj[2][3]['weight'] == 30
 
     # We specify `max_edge` as `weight_func` as ensure that maximum
     # weight is chosen in case on conflict
     gc.merge_nodes(0, 2, weight_func=max_edge)
-    assert gc.edge[1][2]['weight'] == 20
-    assert gc.edge[2][3]['weight'] == 40
+    assert gc.adj[1][2]['weight'] == 20
+    assert gc.adj[2][3]['weight'] == 40
 
     g.merge_nodes(1, 4)
     g.merge_nodes(2, 3)