Repository: networkx/networkx

Issue:
DiGraph.__init__ does not allow sets
I find it very convenient to be able to initialise graphs using:
```python
>>> import networkx as nx  # version 2.2
>>> G = nx.DiGraph([(1, 2), (3, 4)])
>>> G = nx.DiGraph(((1, 2), (3, 4)))
```
However sets do not work and I don't understand why they have been disallowed:
```python
>>> import networkx as nx
>>> G = nx.DiGraph({(1, 2), (3, 4)})  # fails with frozenset too
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/networkx/classes/digraph.py", line 309, in __init__
    convert.to_networkx_graph(incoming_graph_data, create_using=self)
  File "/usr/lib/python3/dist-packages/networkx/convert.py", line 161, in to_networkx_graph
    "Input is not a known data type for conversion.")
networkx.exception.NetworkXError: Input is not a known data type for conversion.
```
Shouldn't DiGraph (and Graph, etc.) accept *any* iterable of tuples?


Discussion:
Graphs with nodes that are 2-tuples (like geometric graphs) are iterables of tuples, and dict-of-dict constructs are also acceptable input but should not be treated as iterables of tuples.
I haven't thought carefully about whether sets of tuples should be handled.  Probably -- (the set object became part of standard python after our initial creation and I don't know if we revisited sets of edges after it became more popular..... maybe now is the time. :)
Looks like #3907 solves this issue for sets (but not for frozensets). I suspect the fix is as simple as adding the 'frozenset' to the is_instance check at the same spot.

Resolving patch:
diff --git a/networkx/convert.py b/networkx/convert.py
--- a/networkx/convert.py
+++ b/networkx/convert.py
@@ -17,6 +17,7 @@
 """
 import warnings
 import networkx as nx
+from collections.abc import Collection, Generator, Iterator
 
 __all__ = [
     "to_networkx_graph",
@@ -50,7 +51,9 @@ def to_networkx_graph(data, create_using=None, multigraph_input=False):
          any NetworkX graph
          dict-of-dicts
          dict-of-lists
-         container (ie set, list, tuple, iterator) of edges
+         container (e.g. set, list, tuple) of edges
+         iterator (e.g. itertools.chain) that produces edges
+         generator of edges
          Pandas DataFrame (row per edge)
          numpy matrix
          numpy ndarray
@@ -106,16 +109,6 @@ def to_networkx_graph(data, create_using=None, multigraph_input=False):
             except Exception as e:
                 raise TypeError("Input is not known type.") from e
 
-    # list or generator of edges
-
-    if isinstance(data, (list, tuple, set)) or any(
-        hasattr(data, attr) for attr in ["_adjdict", "next", "__next__"]
-    ):
-        try:
-            return from_edgelist(data, create_using=create_using)
-        except Exception as e:
-            raise nx.NetworkXError("Input is not a valid edge list") from e
-
     # Pandas DataFrame
     try:
         import pandas as pd
@@ -167,6 +160,16 @@ def to_networkx_graph(data, create_using=None, multigraph_input=False):
     except ImportError:
         warnings.warn("scipy not found, skipping conversion test.", ImportWarning)
 
+    # Note: most general check - should remain last in order of execution
+    # Includes containers (e.g. list, set, dict, etc.), generators, and
+    # iterators (e.g. itertools.chain) of edges
+
+    if isinstance(data, (Collection, Generator, Iterator)):
+        try:
+            return from_edgelist(data, create_using=create_using)
+        except Exception as e:
+            raise nx.NetworkXError("Input is not a valid edge list") from e
+
     raise nx.NetworkXError("Input is not a known data type for conversion.")
 
 


Test patch: