We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Behavior of `nx.union_all` when `graphs=[]`
I'm running into a case where I'm passing in an empty list to `nx.union_all`, and it returns a None type. 

While this is not necessarily the wrong thing to do, it is not documented.

Intuitively, I would expect the result of union with no inputs to be an empty graph, but the issue here is that you don't know what type the graph should be. Therefore I think the best behavior would be to raise a ValueError indicating that the input cannot be empty. This would make it more clear where the code is failing. 

Current behavior:

```python

>>> nx.union_all([nx.path_graph([1, 2])])
<networkx.classes.graph.Graph at 0x7f6fb15d1ac8>

>>> nx.union_all([nx.path_graph([1, 2]), nx.path_graph([3, 4])])
<networkx.classes.graph.Graph at 0x7f6fb1477ac8>

>>> print(nx.union_all([]))
None

```

Proposed Behavior:

```python
>>> print(nx.union_all([]))
ValueError: Cannot union_all an empty list
```
Behavior of `nx.union_all` when `graphs=[]`
I'm running into a case where I'm passing in an empty list to `nx.union_all`, and it returns a None type. 

While this is not necessarily the wrong thing to do, it is not documented.

Intuitively, I would expect the result of union with no inputs to be an empty graph, but the issue here is that you don't know what type the graph should be. Therefore I think the best behavior would be to raise a ValueError indicating that the input cannot be empty. This would make it more clear where the code is failing. 

Current behavior:

```python

>>> nx.union_all([nx.path_graph([1, 2])])
<networkx.classes.graph.Graph at 0x7f6fb15d1ac8>

>>> nx.union_all([nx.path_graph([1, 2]), nx.path_graph([3, 4])])
<networkx.classes.graph.Graph at 0x7f6fb1477ac8>

>>> print(nx.union_all([]))
None

```

Proposed Behavior:

```python
>>> print(nx.union_all([]))
ValueError: Cannot union_all an empty list
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `networkx/algorithms/operators/all.py`
Content:
```
1 """Operations on many graphs.
2 """
3 #    Copyright (C) 2013 by
4 #    Aric Hagberg <hagberg@lanl.gov>
5 #    Dan Schult <dschult@colgate.edu>
6 #    Pieter Swart <swart@lanl.gov>
7 #    All rights reserved.
8 #    BSD license.
9 try:
10     from itertools import izip_longest as zip_longest
11 except ImportError:  # Python3 has zip_longest
12     from itertools import zip_longest
13 import networkx as nx
14 
15 __author__ = """\n""".join(['Robert King <kingrobertking@gmail.com>',
16                             'Aric Hagberg <aric.hagberg@gmail.com>'])
17 
18 __all__ = ['union_all', 'compose_all', 'disjoint_union_all',
19            'intersection_all']
20 
21 
22 def union_all(graphs, rename=(None,)):
23     """Return the union of all graphs.
24 
25     The graphs must be disjoint, otherwise an exception is raised.
26 
27     Parameters
28     ----------
29     graphs : list of graphs
30        List of NetworkX graphs
31 
32     rename : bool , default=(None, None)
33        Node names of G and H can be changed by specifying the tuple
34        rename=('G-','H-') (for example).  Node "u" in G is then renamed
35        "G-u" and "v" in H is renamed "H-v".
36 
37     Returns
38     -------
39     U : a graph with the same type as the first graph in list
40 
41     Notes
42     -----
43     To force a disjoint union with node relabeling, use
44     disjoint_union_all(G,H) or convert_node_labels_to integers().
45 
46     Graph, edge, and node attributes are propagated to the union graph.
47     If a graph attribute is present in multiple graphs, then the value
48     from the last graph in the list with that attribute is used.
49 
50     See Also
51     --------
52     union
53     disjoint_union_all
54     """
55     graphs_names = zip_longest(graphs, rename)
56     U, gname = next(graphs_names)
57     for H, hname in graphs_names:
58         U = nx.union(U, H, (gname, hname))
59         gname = None
60     return U
61 
62 
63 def disjoint_union_all(graphs):
64     """Return the disjoint union of all graphs.
65 
66     This operation forces distinct integer node labels starting with 0
67     for the first graph in the list and numbering consecutively.
68 
69     Parameters
70     ----------
71     graphs : list
72        List of NetworkX graphs
73 
74     Returns
75     -------
76     U : A graph with the same type as the first graph in list
77 
78     Notes
79     -----
80     It is recommended that the graphs be either all directed or all undirected.
81 
82     Graph, edge, and node attributes are propagated to the union graph.
83     If a graph attribute is present in multiple graphs, then the value
84     from the last graph in the list with that attribute is used.
85     """
86     graphs = iter(graphs)
87     U = next(graphs)
88     for H in graphs:
89         U = nx.disjoint_union(U, H)
90     return U
91 
92 
93 def compose_all(graphs):
94     """Return the composition of all graphs.
95 
96     Composition is the simple union of the node sets and edge sets.
97     The node sets of the supplied graphs need not be disjoint.
98 
99     Parameters
100     ----------
101     graphs : list
102        List of NetworkX graphs
103 
104     Returns
105     -------
106     C : A graph with the same type as the first graph in list
107 
108     Notes
109     -----
110     It is recommended that the supplied graphs be either all directed or all
111     undirected.
112 
113     Graph, edge, and node attributes are propagated to the union graph.
114     If a graph attribute is present in multiple graphs, then the value
115     from the last graph in the list with that attribute is used.
116     """
117     graphs = iter(graphs)
118     C = next(graphs)
119     for H in graphs:
120         C = nx.compose(C, H)
121     return C
122 
123 
124 def intersection_all(graphs):
125     """Return a new graph that contains only the edges that exist in
126     all graphs.
127 
128     All supplied graphs must have the same node set.
129 
130     Parameters
131     ----------
132     graphs : list
133        List of NetworkX graphs
134 
135     Returns
136     -------
137     R : A new graph with the same type as the first graph in list
138 
139     Notes
140     -----
141     Attributes from the graph, nodes, and edges are not copied to the new
142     graph.
143     """
144     graphs = iter(graphs)
145     R = next(graphs)
146     for H in graphs:
147         R = nx.intersection(R, H)
148     return R
149
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/networkx/algorithms/operators/all.py b/networkx/algorithms/operators/all.py
--- a/networkx/algorithms/operators/all.py
+++ b/networkx/algorithms/operators/all.py
@@ -38,6 +38,11 @@
     -------
     U : a graph with the same type as the first graph in list
 
+    Raises
+    ------
+    ValueError
+       If `graphs` is an empty list.
+
     Notes
     -----
     To force a disjoint union with node relabeling, use
@@ -52,6 +57,8 @@
     union
     disjoint_union_all
     """
+    if not graphs:
+        raise ValueError('cannot apply union_all to an empty list')
     graphs_names = zip_longest(graphs, rename)
     U, gname = next(graphs_names)
     for H, hname in graphs_names:
@@ -75,6 +82,11 @@
     -------
     U : A graph with the same type as the first graph in list
 
+    Raises
+    ------
+    ValueError
+       If `graphs` is an empty list.
+
     Notes
     -----
     It is recommended that the graphs be either all directed or all undirected.
@@ -83,6 +95,8 @@
     If a graph attribute is present in multiple graphs, then the value
     from the last graph in the list with that attribute is used.
     """
+    if not graphs:
+        raise ValueError('cannot apply disjoint_union_all to an empty list')
     graphs = iter(graphs)
     U = next(graphs)
     for H in graphs:
@@ -105,6 +119,11 @@
     -------
     C : A graph with the same type as the first graph in list
 
+    Raises
+    ------
+    ValueError
+       If `graphs` is an empty list.
+
     Notes
     -----
     It is recommended that the supplied graphs be either all directed or all
@@ -114,6 +133,8 @@
     If a graph attribute is present in multiple graphs, then the value
     from the last graph in the list with that attribute is used.
     """
+    if not graphs:
+        raise ValueError('cannot apply compose_all to an empty list')
     graphs = iter(graphs)
     C = next(graphs)
     for H in graphs:
@@ -136,11 +157,18 @@
     -------
     R : A new graph with the same type as the first graph in list
 
+    Raises
+    ------
+    ValueError
+       If `graphs` is an empty list.
+
     Notes
     -----
     Attributes from the graph, nodes, and edges are not copied to the new
     graph.
     """
+    if not graphs:
+        raise ValueError('cannot apply intersection_all to an empty list')
     graphs = iter(graphs)
     R = next(graphs)
     for H in graphs:

{"golden_diff": "diff --git a/networkx/algorithms/operators/all.py b/networkx/algorithms/operators/all.py\n--- a/networkx/algorithms/operators/all.py\n+++ b/networkx/algorithms/operators/all.py\n@@ -38,6 +38,11 @@\n     -------\n     U : a graph with the same type as the first graph in list\n \n+    Raises\n+    ------\n+    ValueError\n+       If `graphs` is an empty list.\n+\n     Notes\n     -----\n     To force a disjoint union with node relabeling, use\n@@ -52,6 +57,8 @@\n     union\n     disjoint_union_all\n     \"\"\"\n+    if not graphs:\n+        raise ValueError('cannot apply union_all to an empty list')\n     graphs_names = zip_longest(graphs, rename)\n     U, gname = next(graphs_names)\n     for H, hname in graphs_names:\n@@ -75,6 +82,11 @@\n     -------\n     U : A graph with the same type as the first graph in list\n \n+    Raises\n+    ------\n+    ValueError\n+       If `graphs` is an empty list.\n+\n     Notes\n     -----\n     It is recommended that the graphs be either all directed or all undirected.\n@@ -83,6 +95,8 @@\n     If a graph attribute is present in multiple graphs, then the value\n     from the last graph in the list with that attribute is used.\n     \"\"\"\n+    if not graphs:\n+        raise ValueError('cannot apply disjoint_union_all to an empty list')\n     graphs = iter(graphs)\n     U = next(graphs)\n     for H in graphs:\n@@ -105,6 +119,11 @@\n     -------\n     C : A graph with the same type as the first graph in list\n \n+    Raises\n+    ------\n+    ValueError\n+       If `graphs` is an empty list.\n+\n     Notes\n     -----\n     It is recommended that the supplied graphs be either all directed or all\n@@ -114,6 +133,8 @@\n     If a graph attribute is present in multiple graphs, then the value\n     from the last graph in the list with that attribute is used.\n     \"\"\"\n+    if not graphs:\n+        raise ValueError('cannot apply compose_all to an empty list')\n     graphs = iter(graphs)\n     C = next(graphs)\n     for H in graphs:\n@@ -136,11 +157,18 @@\n     -------\n     R : A new graph with the same type as the first graph in list\n \n+    Raises\n+    ------\n+    ValueError\n+       If `graphs` is an empty list.\n+\n     Notes\n     -----\n     Attributes from the graph, nodes, and edges are not copied to the new\n     graph.\n     \"\"\"\n+    if not graphs:\n+        raise ValueError('cannot apply intersection_all to an empty list')\n     graphs = iter(graphs)\n     R = next(graphs)\n     for H in graphs:\n", "issue": "Behavior of `nx.union_all` when `graphs=[]`\nI'm running into a case where I'm passing in an empty list to `nx.union_all`, and it returns a None type. \r\n\r\nWhile this is not necessarily the wrong thing to do, it is not documented.\r\n\r\nIntuitively, I would expect the result of union with no inputs to be an empty graph, but the issue here is that you don't know what type the graph should be. Therefore I think the best behavior would be to raise a ValueError indicating that the input cannot be empty. This would make it more clear where the code is failing. \r\n\r\nCurrent behavior:\r\n\r\n```python\r\n\r\n>>> nx.union_all([nx.path_graph([1, 2])])\r\n<networkx.classes.graph.Graph at 0x7f6fb15d1ac8>\r\n\r\n>>> nx.union_all([nx.path_graph([1, 2]), nx.path_graph([3, 4])])\r\n<networkx.classes.graph.Graph at 0x7f6fb1477ac8>\r\n\r\n>>> print(nx.union_all([]))\r\nNone\r\n\r\n```\r\n\r\nProposed Behavior:\r\n\r\n```python\r\n>>> print(nx.union_all([]))\r\nValueError: Cannot union_all an empty list\r\n```\nBehavior of `nx.union_all` when `graphs=[]`\nI'm running into a case where I'm passing in an empty list to `nx.union_all`, and it returns a None type. \r\n\r\nWhile this is not necessarily the wrong thing to do, it is not documented.\r\n\r\nIntuitively, I would expect the result of union with no inputs to be an empty graph, but the issue here is that you don't know what type the graph should be. Therefore I think the best behavior would be to raise a ValueError indicating that the input cannot be empty. This would make it more clear where the code is failing. \r\n\r\nCurrent behavior:\r\n\r\n```python\r\n\r\n>>> nx.union_all([nx.path_graph([1, 2])])\r\n<networkx.classes.graph.Graph at 0x7f6fb15d1ac8>\r\n\r\n>>> nx.union_all([nx.path_graph([1, 2]), nx.path_graph([3, 4])])\r\n<networkx.classes.graph.Graph at 0x7f6fb1477ac8>\r\n\r\n>>> print(nx.union_all([]))\r\nNone\r\n\r\n```\r\n\r\nProposed Behavior:\r\n\r\n```python\r\n>>> print(nx.union_all([]))\r\nValueError: Cannot union_all an empty list\r\n```\n", "before_files": [{"content": "\"\"\"Operations on many graphs.\n\"\"\"\n#    Copyright (C) 2013 by\n#    Aric Hagberg <hagberg@lanl.gov>\n#    Dan Schult <dschult@colgate.edu>\n#    Pieter Swart <swart@lanl.gov>\n#    All rights reserved.\n#    BSD license.\ntry:\n    from itertools import izip_longest as zip_longest\nexcept ImportError:  # Python3 has zip_longest\n    from itertools import zip_longest\nimport networkx as nx\n\n__author__ = \"\"\"\\n\"\"\".join(['Robert King <kingrobertking@gmail.com>',\n                            'Aric Hagberg <aric.hagberg@gmail.com>'])\n\n__all__ = ['union_all', 'compose_all', 'disjoint_union_all',\n           'intersection_all']\n\n\ndef union_all(graphs, rename=(None,)):\n    \"\"\"Return the union of all graphs.\n\n    The graphs must be disjoint, otherwise an exception is raised.\n\n    Parameters\n    ----------\n    graphs : list of graphs\n       List of NetworkX graphs\n\n    rename : bool , default=(None, None)\n       Node names of G and H can be changed by specifying the tuple\n       rename=('G-','H-') (for example).  Node \"u\" in G is then renamed\n       \"G-u\" and \"v\" in H is renamed \"H-v\".\n\n    Returns\n    -------\n    U : a graph with the same type as the first graph in list\n\n    Notes\n    -----\n    To force a disjoint union with node relabeling, use\n    disjoint_union_all(G,H) or convert_node_labels_to integers().\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n\n    See Also\n    --------\n    union\n    disjoint_union_all\n    \"\"\"\n    graphs_names = zip_longest(graphs, rename)\n    U, gname = next(graphs_names)\n    for H, hname in graphs_names:\n        U = nx.union(U, H, (gname, hname))\n        gname = None\n    return U\n\n\ndef disjoint_union_all(graphs):\n    \"\"\"Return the disjoint union of all graphs.\n\n    This operation forces distinct integer node labels starting with 0\n    for the first graph in the list and numbering consecutively.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    U : A graph with the same type as the first graph in list\n\n    Notes\n    -----\n    It is recommended that the graphs be either all directed or all undirected.\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n    \"\"\"\n    graphs = iter(graphs)\n    U = next(graphs)\n    for H in graphs:\n        U = nx.disjoint_union(U, H)\n    return U\n\n\ndef compose_all(graphs):\n    \"\"\"Return the composition of all graphs.\n\n    Composition is the simple union of the node sets and edge sets.\n    The node sets of the supplied graphs need not be disjoint.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    C : A graph with the same type as the first graph in list\n\n    Notes\n    -----\n    It is recommended that the supplied graphs be either all directed or all\n    undirected.\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n    \"\"\"\n    graphs = iter(graphs)\n    C = next(graphs)\n    for H in graphs:\n        C = nx.compose(C, H)\n    return C\n\n\ndef intersection_all(graphs):\n    \"\"\"Return a new graph that contains only the edges that exist in\n    all graphs.\n\n    All supplied graphs must have the same node set.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    R : A new graph with the same type as the first graph in list\n\n    Notes\n    -----\n    Attributes from the graph, nodes, and edges are not copied to the new\n    graph.\n    \"\"\"\n    graphs = iter(graphs)\n    R = next(graphs)\n    for H in graphs:\n        R = nx.intersection(R, H)\n    return R\n", "path": "networkx/algorithms/operators/all.py"}], "after_files": [{"content": "\"\"\"Operations on many graphs.\n\"\"\"\n#    Copyright (C) 2013 by\n#    Aric Hagberg <hagberg@lanl.gov>\n#    Dan Schult <dschult@colgate.edu>\n#    Pieter Swart <swart@lanl.gov>\n#    All rights reserved.\n#    BSD license.\ntry:\n    from itertools import izip_longest as zip_longest\nexcept ImportError:  # Python3 has zip_longest\n    from itertools import zip_longest\nimport networkx as nx\n\n__author__ = \"\"\"\\n\"\"\".join(['Robert King <kingrobertking@gmail.com>',\n                            'Aric Hagberg <aric.hagberg@gmail.com>'])\n\n__all__ = ['union_all', 'compose_all', 'disjoint_union_all',\n           'intersection_all']\n\n\ndef union_all(graphs, rename=(None,)):\n    \"\"\"Return the union of all graphs.\n\n    The graphs must be disjoint, otherwise an exception is raised.\n\n    Parameters\n    ----------\n    graphs : list of graphs\n       List of NetworkX graphs\n\n    rename : bool , default=(None, None)\n       Node names of G and H can be changed by specifying the tuple\n       rename=('G-','H-') (for example).  Node \"u\" in G is then renamed\n       \"G-u\" and \"v\" in H is renamed \"H-v\".\n\n    Returns\n    -------\n    U : a graph with the same type as the first graph in list\n\n    Raises\n    ------\n    ValueError\n       If `graphs` is an empty list.\n\n    Notes\n    -----\n    To force a disjoint union with node relabeling, use\n    disjoint_union_all(G,H) or convert_node_labels_to integers().\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n\n    See Also\n    --------\n    union\n    disjoint_union_all\n    \"\"\"\n    if not graphs:\n        raise ValueError('cannot apply union_all to an empty list')\n    graphs_names = zip_longest(graphs, rename)\n    U, gname = next(graphs_names)\n    for H, hname in graphs_names:\n        U = nx.union(U, H, (gname, hname))\n        gname = None\n    return U\n\n\ndef disjoint_union_all(graphs):\n    \"\"\"Return the disjoint union of all graphs.\n\n    This operation forces distinct integer node labels starting with 0\n    for the first graph in the list and numbering consecutively.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    U : A graph with the same type as the first graph in list\n\n    Raises\n    ------\n    ValueError\n       If `graphs` is an empty list.\n\n    Notes\n    -----\n    It is recommended that the graphs be either all directed or all undirected.\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n    \"\"\"\n    if not graphs:\n        raise ValueError('cannot apply disjoint_union_all to an empty list')\n    graphs = iter(graphs)\n    U = next(graphs)\n    for H in graphs:\n        U = nx.disjoint_union(U, H)\n    return U\n\n\ndef compose_all(graphs):\n    \"\"\"Return the composition of all graphs.\n\n    Composition is the simple union of the node sets and edge sets.\n    The node sets of the supplied graphs need not be disjoint.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    C : A graph with the same type as the first graph in list\n\n    Raises\n    ------\n    ValueError\n       If `graphs` is an empty list.\n\n    Notes\n    -----\n    It is recommended that the supplied graphs be either all directed or all\n    undirected.\n\n    Graph, edge, and node attributes are propagated to the union graph.\n    If a graph attribute is present in multiple graphs, then the value\n    from the last graph in the list with that attribute is used.\n    \"\"\"\n    if not graphs:\n        raise ValueError('cannot apply compose_all to an empty list')\n    graphs = iter(graphs)\n    C = next(graphs)\n    for H in graphs:\n        C = nx.compose(C, H)\n    return C\n\n\ndef intersection_all(graphs):\n    \"\"\"Return a new graph that contains only the edges that exist in\n    all graphs.\n\n    All supplied graphs must have the same node set.\n\n    Parameters\n    ----------\n    graphs : list\n       List of NetworkX graphs\n\n    Returns\n    -------\n    R : A new graph with the same type as the first graph in list\n\n    Raises\n    ------\n    ValueError\n       If `graphs` is an empty list.\n\n    Notes\n    -----\n    Attributes from the graph, nodes, and edges are not copied to the new\n    graph.\n    \"\"\"\n    if not graphs:\n        raise ValueError('cannot apply intersection_all to an empty list')\n    graphs = iter(graphs)\n    R = next(graphs)\n    for H in graphs:\n        R = nx.intersection(R, H)\n    return R\n", "path": "networkx/algorithms/operators/all.py"}]}