We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
GraphItem fails to draw if no edges
The following code errors:

``` py
import numpy as np
import pyqtgraph as pg
from PyQt4.QtGui import QApplication

app = QApplication([])

item = pg.GraphItem()
item.setData(adj=np.array([], dtype=int),
             pos=np.array([[0.1, 0.1],
                           [0.9, 0.9]]))
item.generatePicture()
```

```
Traceback (most recent call last):
  File "/tmp/test_graphitem.py", line 11, in <module>
    item.generatePicture()
  File "/usr/lib/python3/dist-packages/pyqtgraph/graphicsItems/GraphItem.py", line 122, in generatePicture
    pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))
IndexError: tuple index out of range
```

The problem is that empty `pos[adj]` doesn't have three dimensions. To mitigate it, I had to also pass `setData(..., pen=None)`. It makes my code way uglier to have to take care of this in several places, to say the least.

**OT**: I find pyqtgraph's code in general full of really complex invariants, and such an important project would probably benefit hugely from a more dedicated maintainer in the coming era. As you seem to be more passionately invested elsewhere nowadays, have you ever considered searching for your eventual replacement yet? :smiley:


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyqtgraph/graphicsItems/GraphItem.py`
Content:
```
1 from .. import functions as fn
2 from .GraphicsObject import GraphicsObject
3 from .ScatterPlotItem import ScatterPlotItem
4 from ..Qt import QtGui, QtCore
5 import numpy as np
6 from .. import getConfigOption
7 
8 __all__ = ['GraphItem']
9 
10 
11 class GraphItem(GraphicsObject):
12     """A GraphItem displays graph information as
13     a set of nodes connected by lines (as in 'graph theory', not 'graphics'). 
14     Useful for drawing networks, trees, etc.
15     """
16 
17     def __init__(self, **kwds):
18         GraphicsObject.__init__(self)
19         self.scatter = ScatterPlotItem()
20         self.scatter.setParentItem(self)
21         self.adjacency = None
22         self.pos = None
23         self.picture = None
24         self.pen = 'default'
25         self.setData(**kwds)
26         
27     def setData(self, **kwds):
28         """
29         Change the data displayed by the graph. 
30         
31         ==============  =======================================================================
32         **Arguments:**
33         pos             (N,2) array of the positions of each node in the graph.
34         adj             (M,2) array of connection data. Each row contains indexes
35                         of two nodes that are connected or None to hide lines
36         pen             The pen to use when drawing lines between connected
37                         nodes. May be one of:
38                      
39                         * QPen
40                         * a single argument to pass to pg.mkPen
41                         * a record array of length M
42                           with fields (red, green, blue, alpha, width). Note
43                           that using this option may have a significant performance
44                           cost.
45                         * None (to disable connection drawing)
46                         * 'default' to use the default foreground color.
47                      
48         symbolPen       The pen(s) used for drawing nodes.
49         symbolBrush     The brush(es) used for drawing nodes.
50         ``**opts``      All other keyword arguments are given to
51                         :func:`ScatterPlotItem.setData() <pyqtgraph.ScatterPlotItem.setData>`
52                         to affect the appearance of nodes (symbol, size, brush,
53                         etc.)
54         ==============  =======================================================================
55         """
56         if 'adj' in kwds:
57             self.adjacency = kwds.pop('adj')
58             if self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':
59                 raise Exception("adjacency must be None or an array of either int or unsigned type.")
60             self._update()
61         if 'pos' in kwds:
62             self.pos = kwds['pos']
63             self._update()
64         if 'pen' in kwds:
65             self.setPen(kwds.pop('pen'))
66             self._update()
67             
68         if 'symbolPen' in kwds:    
69             kwds['pen'] = kwds.pop('symbolPen')
70         if 'symbolBrush' in kwds:    
71             kwds['brush'] = kwds.pop('symbolBrush')
72         self.scatter.setData(**kwds)
73         self.informViewBoundsChanged()
74 
75     def _update(self):
76         self.picture = None
77         self.prepareGeometryChange()
78         self.update()
79 
80     def setPen(self, *args, **kwargs):
81         """
82         Set the pen used to draw graph lines.
83         May be: 
84         
85         * None to disable line drawing
86         * Record array with fields (red, green, blue, alpha, width)
87         * Any set of arguments and keyword arguments accepted by 
88           :func:`mkPen <pyqtgraph.mkPen>`.
89         * 'default' to use the default foreground color.
90         """
91         if len(args) == 1 and len(kwargs) == 0:
92             self.pen = args[0]
93         else:
94             self.pen = fn.mkPen(*args, **kwargs)
95         self.picture = None
96         self.update()
97 
98     def generatePicture(self):
99         self.picture = QtGui.QPicture()
100         if self.pen is None or self.pos is None or self.adjacency is None:
101             return
102         
103         p = QtGui.QPainter(self.picture)
104         try:
105             pts = self.pos[self.adjacency]
106             pen = self.pen
107             if isinstance(pen, np.ndarray):
108                 lastPen = None
109                 for i in range(pts.shape[0]):
110                     pen = self.pen[i]
111                     if np.any(pen != lastPen):
112                         lastPen = pen
113                         if pen.dtype.fields is None:
114                             p.setPen(fn.mkPen(color=(pen[0], pen[1], pen[2], pen[3]), width=1))                            
115                         else:
116                             p.setPen(fn.mkPen(color=(pen['red'], pen['green'], pen['blue'], pen['alpha']), width=pen['width']))
117                     p.drawLine(QtCore.QPointF(*pts[i][0]), QtCore.QPointF(*pts[i][1]))
118             else:
119                 if pen == 'default':
120                     pen = getConfigOption('foreground')
121                 p.setPen(fn.mkPen(pen))
122                 pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))
123                 path = fn.arrayToQPath(x=pts[:,0], y=pts[:,1], connect='pairs')
124                 p.drawPath(path)
125         finally:
126             p.end()
127 
128     def paint(self, p, *args):
129         if self.picture == None:
130             self.generatePicture()
131         if getConfigOption('antialias') is True:
132             p.setRenderHint(p.Antialiasing)
133         self.picture.play(p)
134         
135     def boundingRect(self):
136         return self.scatter.boundingRect()
137         
138     def dataBounds(self, *args, **kwds):
139         return self.scatter.dataBounds(*args, **kwds)
140     
141     def pixelPadding(self):
142         return self.scatter.pixelPadding()
143         
144         
145         
146         
147 
148
```
--- 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/pyqtgraph/graphicsItems/GraphItem.py b/pyqtgraph/graphicsItems/GraphItem.py
--- a/pyqtgraph/graphicsItems/GraphItem.py
+++ b/pyqtgraph/graphicsItems/GraphItem.py
@@ -55,7 +55,9 @@
         """
         if 'adj' in kwds:
             self.adjacency = kwds.pop('adj')
-            if self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':
+            if hasattr(self.adjacency, '__len__') and len(self.adjacency) == 0:
+                self.adjacency = None
+            elif self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':
                 raise Exception("adjacency must be None or an array of either int or unsigned type.")
             self._update()
         if 'pos' in kwds:
@@ -140,8 +142,3 @@
     
     def pixelPadding(self):
         return self.scatter.pixelPadding()
-        
-        
-        
-        
-

{"golden_diff": "diff --git a/pyqtgraph/graphicsItems/GraphItem.py b/pyqtgraph/graphicsItems/GraphItem.py\n--- a/pyqtgraph/graphicsItems/GraphItem.py\n+++ b/pyqtgraph/graphicsItems/GraphItem.py\n@@ -55,7 +55,9 @@\n         \"\"\"\n         if 'adj' in kwds:\n             self.adjacency = kwds.pop('adj')\n-            if self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':\n+            if hasattr(self.adjacency, '__len__') and len(self.adjacency) == 0:\n+                self.adjacency = None\n+            elif self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':\n                 raise Exception(\"adjacency must be None or an array of either int or unsigned type.\")\n             self._update()\n         if 'pos' in kwds:\n@@ -140,8 +142,3 @@\n     \n     def pixelPadding(self):\n         return self.scatter.pixelPadding()\n-        \n-        \n-        \n-        \n-\n", "issue": "GraphItem fails to draw if no edges\nThe following code errors:\n\n``` py\nimport numpy as np\nimport pyqtgraph as pg\nfrom PyQt4.QtGui import QApplication\n\napp = QApplication([])\n\nitem = pg.GraphItem()\nitem.setData(adj=np.array([], dtype=int),\n             pos=np.array([[0.1, 0.1],\n                           [0.9, 0.9]]))\nitem.generatePicture()\n```\n\n```\nTraceback (most recent call last):\n  File \"/tmp/test_graphitem.py\", line 11, in <module>\n    item.generatePicture()\n  File \"/usr/lib/python3/dist-packages/pyqtgraph/graphicsItems/GraphItem.py\", line 122, in generatePicture\n    pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))\nIndexError: tuple index out of range\n```\n\nThe problem is that empty `pos[adj]` doesn't have three dimensions. To mitigate it, I had to also pass `setData(..., pen=None)`. It makes my code way uglier to have to take care of this in several places, to say the least.\n\n**OT**: I find pyqtgraph's code in general full of really complex invariants, and such an important project would probably benefit hugely from a more dedicated maintainer in the coming era. As you seem to be more passionately invested elsewhere nowadays, have you ever considered searching for your eventual replacement yet? :smiley:\n\n", "before_files": [{"content": "from .. import functions as fn\nfrom .GraphicsObject import GraphicsObject\nfrom .ScatterPlotItem import ScatterPlotItem\nfrom ..Qt import QtGui, QtCore\nimport numpy as np\nfrom .. import getConfigOption\n\n__all__ = ['GraphItem']\n\n\nclass GraphItem(GraphicsObject):\n    \"\"\"A GraphItem displays graph information as\n    a set of nodes connected by lines (as in 'graph theory', not 'graphics'). \n    Useful for drawing networks, trees, etc.\n    \"\"\"\n\n    def __init__(self, **kwds):\n        GraphicsObject.__init__(self)\n        self.scatter = ScatterPlotItem()\n        self.scatter.setParentItem(self)\n        self.adjacency = None\n        self.pos = None\n        self.picture = None\n        self.pen = 'default'\n        self.setData(**kwds)\n        \n    def setData(self, **kwds):\n        \"\"\"\n        Change the data displayed by the graph. \n        \n        ==============  =======================================================================\n        **Arguments:**\n        pos             (N,2) array of the positions of each node in the graph.\n        adj             (M,2) array of connection data. Each row contains indexes\n                        of two nodes that are connected or None to hide lines\n        pen             The pen to use when drawing lines between connected\n                        nodes. May be one of:\n                     \n                        * QPen\n                        * a single argument to pass to pg.mkPen\n                        * a record array of length M\n                          with fields (red, green, blue, alpha, width). Note\n                          that using this option may have a significant performance\n                          cost.\n                        * None (to disable connection drawing)\n                        * 'default' to use the default foreground color.\n                     \n        symbolPen       The pen(s) used for drawing nodes.\n        symbolBrush     The brush(es) used for drawing nodes.\n        ``**opts``      All other keyword arguments are given to\n                        :func:`ScatterPlotItem.setData() <pyqtgraph.ScatterPlotItem.setData>`\n                        to affect the appearance of nodes (symbol, size, brush,\n                        etc.)\n        ==============  =======================================================================\n        \"\"\"\n        if 'adj' in kwds:\n            self.adjacency = kwds.pop('adj')\n            if self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':\n                raise Exception(\"adjacency must be None or an array of either int or unsigned type.\")\n            self._update()\n        if 'pos' in kwds:\n            self.pos = kwds['pos']\n            self._update()\n        if 'pen' in kwds:\n            self.setPen(kwds.pop('pen'))\n            self._update()\n            \n        if 'symbolPen' in kwds:    \n            kwds['pen'] = kwds.pop('symbolPen')\n        if 'symbolBrush' in kwds:    \n            kwds['brush'] = kwds.pop('symbolBrush')\n        self.scatter.setData(**kwds)\n        self.informViewBoundsChanged()\n\n    def _update(self):\n        self.picture = None\n        self.prepareGeometryChange()\n        self.update()\n\n    def setPen(self, *args, **kwargs):\n        \"\"\"\n        Set the pen used to draw graph lines.\n        May be: \n        \n        * None to disable line drawing\n        * Record array with fields (red, green, blue, alpha, width)\n        * Any set of arguments and keyword arguments accepted by \n          :func:`mkPen <pyqtgraph.mkPen>`.\n        * 'default' to use the default foreground color.\n        \"\"\"\n        if len(args) == 1 and len(kwargs) == 0:\n            self.pen = args[0]\n        else:\n            self.pen = fn.mkPen(*args, **kwargs)\n        self.picture = None\n        self.update()\n\n    def generatePicture(self):\n        self.picture = QtGui.QPicture()\n        if self.pen is None or self.pos is None or self.adjacency is None:\n            return\n        \n        p = QtGui.QPainter(self.picture)\n        try:\n            pts = self.pos[self.adjacency]\n            pen = self.pen\n            if isinstance(pen, np.ndarray):\n                lastPen = None\n                for i in range(pts.shape[0]):\n                    pen = self.pen[i]\n                    if np.any(pen != lastPen):\n                        lastPen = pen\n                        if pen.dtype.fields is None:\n                            p.setPen(fn.mkPen(color=(pen[0], pen[1], pen[2], pen[3]), width=1))                            \n                        else:\n                            p.setPen(fn.mkPen(color=(pen['red'], pen['green'], pen['blue'], pen['alpha']), width=pen['width']))\n                    p.drawLine(QtCore.QPointF(*pts[i][0]), QtCore.QPointF(*pts[i][1]))\n            else:\n                if pen == 'default':\n                    pen = getConfigOption('foreground')\n                p.setPen(fn.mkPen(pen))\n                pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))\n                path = fn.arrayToQPath(x=pts[:,0], y=pts[:,1], connect='pairs')\n                p.drawPath(path)\n        finally:\n            p.end()\n\n    def paint(self, p, *args):\n        if self.picture == None:\n            self.generatePicture()\n        if getConfigOption('antialias') is True:\n            p.setRenderHint(p.Antialiasing)\n        self.picture.play(p)\n        \n    def boundingRect(self):\n        return self.scatter.boundingRect()\n        \n    def dataBounds(self, *args, **kwds):\n        return self.scatter.dataBounds(*args, **kwds)\n    \n    def pixelPadding(self):\n        return self.scatter.pixelPadding()\n        \n        \n        \n        \n\n", "path": "pyqtgraph/graphicsItems/GraphItem.py"}], "after_files": [{"content": "from .. import functions as fn\nfrom .GraphicsObject import GraphicsObject\nfrom .ScatterPlotItem import ScatterPlotItem\nfrom ..Qt import QtGui, QtCore\nimport numpy as np\nfrom .. import getConfigOption\n\n__all__ = ['GraphItem']\n\n\nclass GraphItem(GraphicsObject):\n    \"\"\"A GraphItem displays graph information as\n    a set of nodes connected by lines (as in 'graph theory', not 'graphics'). \n    Useful for drawing networks, trees, etc.\n    \"\"\"\n\n    def __init__(self, **kwds):\n        GraphicsObject.__init__(self)\n        self.scatter = ScatterPlotItem()\n        self.scatter.setParentItem(self)\n        self.adjacency = None\n        self.pos = None\n        self.picture = None\n        self.pen = 'default'\n        self.setData(**kwds)\n        \n    def setData(self, **kwds):\n        \"\"\"\n        Change the data displayed by the graph. \n        \n        ==============  =======================================================================\n        **Arguments:**\n        pos             (N,2) array of the positions of each node in the graph.\n        adj             (M,2) array of connection data. Each row contains indexes\n                        of two nodes that are connected or None to hide lines\n        pen             The pen to use when drawing lines between connected\n                        nodes. May be one of:\n                     \n                        * QPen\n                        * a single argument to pass to pg.mkPen\n                        * a record array of length M\n                          with fields (red, green, blue, alpha, width). Note\n                          that using this option may have a significant performance\n                          cost.\n                        * None (to disable connection drawing)\n                        * 'default' to use the default foreground color.\n                     \n        symbolPen       The pen(s) used for drawing nodes.\n        symbolBrush     The brush(es) used for drawing nodes.\n        ``**opts``      All other keyword arguments are given to\n                        :func:`ScatterPlotItem.setData() <pyqtgraph.ScatterPlotItem.setData>`\n                        to affect the appearance of nodes (symbol, size, brush,\n                        etc.)\n        ==============  =======================================================================\n        \"\"\"\n        if 'adj' in kwds:\n            self.adjacency = kwds.pop('adj')\n            if hasattr(self.adjacency, '__len__') and len(self.adjacency) == 0:\n                self.adjacency = None\n            elif self.adjacency is not None and self.adjacency.dtype.kind not in 'iu':\n                raise Exception(\"adjacency must be None or an array of either int or unsigned type.\")\n            self._update()\n        if 'pos' in kwds:\n            self.pos = kwds['pos']\n            self._update()\n        if 'pen' in kwds:\n            self.setPen(kwds.pop('pen'))\n            self._update()\n            \n        if 'symbolPen' in kwds:    \n            kwds['pen'] = kwds.pop('symbolPen')\n        if 'symbolBrush' in kwds:    \n            kwds['brush'] = kwds.pop('symbolBrush')\n        self.scatter.setData(**kwds)\n        self.informViewBoundsChanged()\n\n    def _update(self):\n        self.picture = None\n        self.prepareGeometryChange()\n        self.update()\n\n    def setPen(self, *args, **kwargs):\n        \"\"\"\n        Set the pen used to draw graph lines.\n        May be: \n        \n        * None to disable line drawing\n        * Record array with fields (red, green, blue, alpha, width)\n        * Any set of arguments and keyword arguments accepted by \n          :func:`mkPen <pyqtgraph.mkPen>`.\n        * 'default' to use the default foreground color.\n        \"\"\"\n        if len(args) == 1 and len(kwargs) == 0:\n            self.pen = args[0]\n        else:\n            self.pen = fn.mkPen(*args, **kwargs)\n        self.picture = None\n        self.update()\n\n    def generatePicture(self):\n        self.picture = QtGui.QPicture()\n        if self.pen is None or self.pos is None or self.adjacency is None:\n            return\n        \n        p = QtGui.QPainter(self.picture)\n        try:\n            pts = self.pos[self.adjacency]\n            pen = self.pen\n            if isinstance(pen, np.ndarray):\n                lastPen = None\n                for i in range(pts.shape[0]):\n                    pen = self.pen[i]\n                    if np.any(pen != lastPen):\n                        lastPen = pen\n                        if pen.dtype.fields is None:\n                            p.setPen(fn.mkPen(color=(pen[0], pen[1], pen[2], pen[3]), width=1))                            \n                        else:\n                            p.setPen(fn.mkPen(color=(pen['red'], pen['green'], pen['blue'], pen['alpha']), width=pen['width']))\n                    p.drawLine(QtCore.QPointF(*pts[i][0]), QtCore.QPointF(*pts[i][1]))\n            else:\n                if pen == 'default':\n                    pen = getConfigOption('foreground')\n                p.setPen(fn.mkPen(pen))\n                pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))\n                path = fn.arrayToQPath(x=pts[:,0], y=pts[:,1], connect='pairs')\n                p.drawPath(path)\n        finally:\n            p.end()\n\n    def paint(self, p, *args):\n        if self.picture == None:\n            self.generatePicture()\n        if getConfigOption('antialias') is True:\n            p.setRenderHint(p.Antialiasing)\n        self.picture.play(p)\n        \n    def boundingRect(self):\n        return self.scatter.boundingRect()\n        \n    def dataBounds(self, *args, **kwds):\n        return self.scatter.dataBounds(*args, **kwds)\n    \n    def pixelPadding(self):\n        return self.scatter.pixelPadding()\n", "path": "pyqtgraph/graphicsItems/GraphItem.py"}]}