We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
redis._compat: global name 'InterruptedError' is not defined
In the [compat module](https://github.com/andymccurdy/redis-py/blob/master/redis/_compat.py), this code is broken:
```python
# For Python older than 3.5, retry EINTR.
if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and
                               sys.version_info[1] < 5):
    # Adapted from https://bugs.python.org/review/23863/patch/14532/54418
    import socket
    import time
    import errno

    from select import select as _select

    def select(rlist, wlist, xlist, timeout):
        while True:
            try:
                return _select(rlist, wlist, xlist, timeout)
            except InterruptedError:
                continue
```

The problem is that it uses `InterruptedError`, but this exception only exists in Python 3, not Python 2.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `redis/_compat.py`
Content:
```
1 """Internal module for Python 2 backwards compatibility."""
2 import sys
3 
4 # For Python older than 3.5, retry EINTR.
5 if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and
6                                sys.version_info[1] < 5):
7     # Adapted from https://bugs.python.org/review/23863/patch/14532/54418
8     import socket
9     import time
10     import errno
11 
12     from select import select as _select
13 
14     def select(rlist, wlist, xlist, timeout):
15         while True:
16             try:
17                 return _select(rlist, wlist, xlist, timeout)
18             except InterruptedError:
19                 continue
20 
21     # Wrapper for handling interruptable system calls.
22     def _retryable_call(s, func, *args, **kwargs):
23         # Some modules (SSL) use the _fileobject wrapper directly and
24         # implement a smaller portion of the socket interface, thus we
25         # need to let them continue to do so.
26         timeout, deadline = None, 0.0
27         attempted = False
28         try:
29             timeout = s.gettimeout()
30         except AttributeError:
31             pass
32 
33         if timeout:
34             deadline = time.time() + timeout
35 
36         try:
37             while True:
38                 if attempted and timeout:
39                     now = time.time()
40                     if now >= deadline:
41                         raise socket.error(errno.EWOULDBLOCK, "timed out")
42                     else:
43                         # Overwrite the timeout on the socket object
44                         # to take into account elapsed time.
45                         s.settimeout(deadline - now)
46                 try:
47                     attempted = True
48                     return func(*args, **kwargs)
49                 except socket.error as e:
50                     if e.args[0] == errno.EINTR:
51                         continue
52                     raise
53         finally:
54             # Set the existing timeout back for future
55             # calls.
56             if timeout:
57                 s.settimeout(timeout)
58 
59     def recv(sock, *args, **kwargs):
60         return _retryable_call(sock, sock.recv, *args, **kwargs)
61 
62     def recv_into(sock, *args, **kwargs):
63         return _retryable_call(sock, sock.recv_into, *args, **kwargs)
64 
65 else:  # Python 3.5 and above automatically retry EINTR
66     from select import select
67 
68     def recv(sock, *args, **kwargs):
69         return sock.recv(*args, **kwargs)
70 
71     def recv_into(sock, *args, **kwargs):
72         return sock.recv_into(*args, **kwargs)
73 
74 if sys.version_info[0] < 3:
75     from urllib import unquote
76     from urlparse import parse_qs, urlparse
77     from itertools import imap, izip
78     from string import letters as ascii_letters
79     from Queue import Queue
80     try:
81         from cStringIO import StringIO as BytesIO
82     except ImportError:
83         from StringIO import StringIO as BytesIO
84 
85     # special unicode handling for python2 to avoid UnicodeDecodeError
86     def safe_unicode(obj, *args):
87         """ return the unicode representation of obj """
88         try:
89             return unicode(obj, *args)
90         except UnicodeDecodeError:
91             # obj is byte string
92             ascii_text = str(obj).encode('string_escape')
93             return unicode(ascii_text)
94 
95     def iteritems(x):
96         return x.iteritems()
97 
98     def iterkeys(x):
99         return x.iterkeys()
100 
101     def itervalues(x):
102         return x.itervalues()
103 
104     def nativestr(x):
105         return x if isinstance(x, str) else x.encode('utf-8', 'replace')
106 
107     def u(x):
108         return x.decode()
109 
110     def b(x):
111         return x
112 
113     def next(x):
114         return x.next()
115 
116     def byte_to_chr(x):
117         return x
118 
119     unichr = unichr
120     xrange = xrange
121     basestring = basestring
122     unicode = unicode
123     bytes = str
124     long = long
125 else:
126     from urllib.parse import parse_qs, unquote, urlparse
127     from io import BytesIO
128     from string import ascii_letters
129     from queue import Queue
130 
131     def iteritems(x):
132         return iter(x.items())
133 
134     def iterkeys(x):
135         return iter(x.keys())
136 
137     def itervalues(x):
138         return iter(x.values())
139 
140     def byte_to_chr(x):
141         return chr(x)
142 
143     def nativestr(x):
144         return x if isinstance(x, str) else x.decode('utf-8', 'replace')
145 
146     def u(x):
147         return x
148 
149     def b(x):
150         return x.encode('latin-1') if not isinstance(x, bytes) else x
151 
152     next = next
153     unichr = chr
154     imap = map
155     izip = zip
156     xrange = range
157     basestring = str
158     unicode = str
159     safe_unicode = str
160     bytes = bytes
161     long = int
162 
163 try:  # Python 3
164     from queue import LifoQueue, Empty, Full
165 except ImportError:
166     from Queue import Empty, Full
167     try:  # Python 2.6 - 2.7
168         from Queue import LifoQueue
169     except ImportError:  # Python 2.5
170         from Queue import Queue
171         # From the Python 2.7 lib. Python 2.5 already extracted the core
172         # methods to aid implementating different queue organisations.
173 
174         class LifoQueue(Queue):
175             "Override queue methods to implement a last-in first-out queue."
176 
177             def _init(self, maxsize):
178                 self.maxsize = maxsize
179                 self.queue = []
180 
181             def _qsize(self, len=len):
182                 return len(self.queue)
183 
184             def _put(self, item):
185                 self.queue.append(item)
186 
187             def _get(self):
188                 return self.queue.pop()
189
```
--- 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/redis/_compat.py b/redis/_compat.py
--- a/redis/_compat.py
+++ b/redis/_compat.py
@@ -1,6 +1,12 @@
 """Internal module for Python 2 backwards compatibility."""
+import errno
 import sys
 
+try:
+    InterruptedError = InterruptedError
+except:
+    InterruptedError = OSError
+
 # For Python older than 3.5, retry EINTR.
 if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and
                                sys.version_info[1] < 5):
@@ -15,8 +21,12 @@
         while True:
             try:
                 return _select(rlist, wlist, xlist, timeout)
-            except InterruptedError:
-                continue
+            except InterruptedError as e:
+                # Python 2 does not define InterruptedError, instead
+                # try to catch an OSError with errno == EINTR == 4.
+                if getattr(e, 'errno', None) == getattr(errno, 'EINTR', 4):
+                    continue
+                raise
 
     # Wrapper for handling interruptable system calls.
     def _retryable_call(s, func, *args, **kwargs):

{"golden_diff": "diff --git a/redis/_compat.py b/redis/_compat.py\n--- a/redis/_compat.py\n+++ b/redis/_compat.py\n@@ -1,6 +1,12 @@\n \"\"\"Internal module for Python 2 backwards compatibility.\"\"\"\n+import errno\n import sys\n \n+try:\n+    InterruptedError = InterruptedError\n+except:\n+    InterruptedError = OSError\n+\n # For Python older than 3.5, retry EINTR.\n if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and\n                                sys.version_info[1] < 5):\n@@ -15,8 +21,12 @@\n         while True:\n             try:\n                 return _select(rlist, wlist, xlist, timeout)\n-            except InterruptedError:\n-                continue\n+            except InterruptedError as e:\n+                # Python 2 does not define InterruptedError, instead\n+                # try to catch an OSError with errno == EINTR == 4.\n+                if getattr(e, 'errno', None) == getattr(errno, 'EINTR', 4):\n+                    continue\n+                raise\n \n     # Wrapper for handling interruptable system calls.\n     def _retryable_call(s, func, *args, **kwargs):\n", "issue": "redis._compat: global name 'InterruptedError' is not defined\nIn the [compat module](https://github.com/andymccurdy/redis-py/blob/master/redis/_compat.py), this code is broken:\r\n```python\r\n# For Python older than 3.5, retry EINTR.\r\nif sys.version_info[0] < 3 or (sys.version_info[0] == 3 and\r\n                               sys.version_info[1] < 5):\r\n    # Adapted from https://bugs.python.org/review/23863/patch/14532/54418\r\n    import socket\r\n    import time\r\n    import errno\r\n\r\n    from select import select as _select\r\n\r\n    def select(rlist, wlist, xlist, timeout):\r\n        while True:\r\n            try:\r\n                return _select(rlist, wlist, xlist, timeout)\r\n            except InterruptedError:\r\n                continue\r\n```\r\n\r\nThe problem is that it uses `InterruptedError`, but this exception only exists in Python 3, not Python 2.\n", "before_files": [{"content": "\"\"\"Internal module for Python 2 backwards compatibility.\"\"\"\nimport sys\n\n# For Python older than 3.5, retry EINTR.\nif sys.version_info[0] < 3 or (sys.version_info[0] == 3 and\n                               sys.version_info[1] < 5):\n    # Adapted from https://bugs.python.org/review/23863/patch/14532/54418\n    import socket\n    import time\n    import errno\n\n    from select import select as _select\n\n    def select(rlist, wlist, xlist, timeout):\n        while True:\n            try:\n                return _select(rlist, wlist, xlist, timeout)\n            except InterruptedError:\n                continue\n\n    # Wrapper for handling interruptable system calls.\n    def _retryable_call(s, func, *args, **kwargs):\n        # Some modules (SSL) use the _fileobject wrapper directly and\n        # implement a smaller portion of the socket interface, thus we\n        # need to let them continue to do so.\n        timeout, deadline = None, 0.0\n        attempted = False\n        try:\n            timeout = s.gettimeout()\n        except AttributeError:\n            pass\n\n        if timeout:\n            deadline = time.time() + timeout\n\n        try:\n            while True:\n                if attempted and timeout:\n                    now = time.time()\n                    if now >= deadline:\n                        raise socket.error(errno.EWOULDBLOCK, \"timed out\")\n                    else:\n                        # Overwrite the timeout on the socket object\n                        # to take into account elapsed time.\n                        s.settimeout(deadline - now)\n                try:\n                    attempted = True\n                    return func(*args, **kwargs)\n                except socket.error as e:\n                    if e.args[0] == errno.EINTR:\n                        continue\n                    raise\n        finally:\n            # Set the existing timeout back for future\n            # calls.\n            if timeout:\n                s.settimeout(timeout)\n\n    def recv(sock, *args, **kwargs):\n        return _retryable_call(sock, sock.recv, *args, **kwargs)\n\n    def recv_into(sock, *args, **kwargs):\n        return _retryable_call(sock, sock.recv_into, *args, **kwargs)\n\nelse:  # Python 3.5 and above automatically retry EINTR\n    from select import select\n\n    def recv(sock, *args, **kwargs):\n        return sock.recv(*args, **kwargs)\n\n    def recv_into(sock, *args, **kwargs):\n        return sock.recv_into(*args, **kwargs)\n\nif sys.version_info[0] < 3:\n    from urllib import unquote\n    from urlparse import parse_qs, urlparse\n    from itertools import imap, izip\n    from string import letters as ascii_letters\n    from Queue import Queue\n    try:\n        from cStringIO import StringIO as BytesIO\n    except ImportError:\n        from StringIO import StringIO as BytesIO\n\n    # special unicode handling for python2 to avoid UnicodeDecodeError\n    def safe_unicode(obj, *args):\n        \"\"\" return the unicode representation of obj \"\"\"\n        try:\n            return unicode(obj, *args)\n        except UnicodeDecodeError:\n            # obj is byte string\n            ascii_text = str(obj).encode('string_escape')\n            return unicode(ascii_text)\n\n    def iteritems(x):\n        return x.iteritems()\n\n    def iterkeys(x):\n        return x.iterkeys()\n\n    def itervalues(x):\n        return x.itervalues()\n\n    def nativestr(x):\n        return x if isinstance(x, str) else x.encode('utf-8', 'replace')\n\n    def u(x):\n        return x.decode()\n\n    def b(x):\n        return x\n\n    def next(x):\n        return x.next()\n\n    def byte_to_chr(x):\n        return x\n\n    unichr = unichr\n    xrange = xrange\n    basestring = basestring\n    unicode = unicode\n    bytes = str\n    long = long\nelse:\n    from urllib.parse import parse_qs, unquote, urlparse\n    from io import BytesIO\n    from string import ascii_letters\n    from queue import Queue\n\n    def iteritems(x):\n        return iter(x.items())\n\n    def iterkeys(x):\n        return iter(x.keys())\n\n    def itervalues(x):\n        return iter(x.values())\n\n    def byte_to_chr(x):\n        return chr(x)\n\n    def nativestr(x):\n        return x if isinstance(x, str) else x.decode('utf-8', 'replace')\n\n    def u(x):\n        return x\n\n    def b(x):\n        return x.encode('latin-1') if not isinstance(x, bytes) else x\n\n    next = next\n    unichr = chr\n    imap = map\n    izip = zip\n    xrange = range\n    basestring = str\n    unicode = str\n    safe_unicode = str\n    bytes = bytes\n    long = int\n\ntry:  # Python 3\n    from queue import LifoQueue, Empty, Full\nexcept ImportError:\n    from Queue import Empty, Full\n    try:  # Python 2.6 - 2.7\n        from Queue import LifoQueue\n    except ImportError:  # Python 2.5\n        from Queue import Queue\n        # From the Python 2.7 lib. Python 2.5 already extracted the core\n        # methods to aid implementating different queue organisations.\n\n        class LifoQueue(Queue):\n            \"Override queue methods to implement a last-in first-out queue.\"\n\n            def _init(self, maxsize):\n                self.maxsize = maxsize\n                self.queue = []\n\n            def _qsize(self, len=len):\n                return len(self.queue)\n\n            def _put(self, item):\n                self.queue.append(item)\n\n            def _get(self):\n                return self.queue.pop()\n", "path": "redis/_compat.py"}], "after_files": [{"content": "\"\"\"Internal module for Python 2 backwards compatibility.\"\"\"\nimport errno\nimport sys\n\ntry:\n    InterruptedError = InterruptedError\nexcept:\n    InterruptedError = OSError\n\n# For Python older than 3.5, retry EINTR.\nif sys.version_info[0] < 3 or (sys.version_info[0] == 3 and\n                               sys.version_info[1] < 5):\n    # Adapted from https://bugs.python.org/review/23863/patch/14532/54418\n    import socket\n    import time\n    import errno\n\n    from select import select as _select\n\n    def select(rlist, wlist, xlist, timeout):\n        while True:\n            try:\n                return _select(rlist, wlist, xlist, timeout)\n            except InterruptedError as e:\n                # Python 2 does not define InterruptedError, instead\n                # try to catch an OSError with errno == EINTR == 4.\n                if getattr(e, 'errno', None) == getattr(errno, 'EINTR', 4):\n                    continue\n                raise\n\n    # Wrapper for handling interruptable system calls.\n    def _retryable_call(s, func, *args, **kwargs):\n        # Some modules (SSL) use the _fileobject wrapper directly and\n        # implement a smaller portion of the socket interface, thus we\n        # need to let them continue to do so.\n        timeout, deadline = None, 0.0\n        attempted = False\n        try:\n            timeout = s.gettimeout()\n        except AttributeError:\n            pass\n\n        if timeout:\n            deadline = time.time() + timeout\n\n        try:\n            while True:\n                if attempted and timeout:\n                    now = time.time()\n                    if now >= deadline:\n                        raise socket.error(errno.EWOULDBLOCK, \"timed out\")\n                    else:\n                        # Overwrite the timeout on the socket object\n                        # to take into account elapsed time.\n                        s.settimeout(deadline - now)\n                try:\n                    attempted = True\n                    return func(*args, **kwargs)\n                except socket.error as e:\n                    if e.args[0] == errno.EINTR:\n                        continue\n                    raise\n        finally:\n            # Set the existing timeout back for future\n            # calls.\n            if timeout:\n                s.settimeout(timeout)\n\n    def recv(sock, *args, **kwargs):\n        return _retryable_call(sock, sock.recv, *args, **kwargs)\n\n    def recv_into(sock, *args, **kwargs):\n        return _retryable_call(sock, sock.recv_into, *args, **kwargs)\n\nelse:  # Python 3.5 and above automatically retry EINTR\n    from select import select\n\n    def recv(sock, *args, **kwargs):\n        return sock.recv(*args, **kwargs)\n\n    def recv_into(sock, *args, **kwargs):\n        return sock.recv_into(*args, **kwargs)\n\nif sys.version_info[0] < 3:\n    from urllib import unquote\n    from urlparse import parse_qs, urlparse\n    from itertools import imap, izip\n    from string import letters as ascii_letters\n    from Queue import Queue\n    try:\n        from cStringIO import StringIO as BytesIO\n    except ImportError:\n        from StringIO import StringIO as BytesIO\n\n    # special unicode handling for python2 to avoid UnicodeDecodeError\n    def safe_unicode(obj, *args):\n        \"\"\" return the unicode representation of obj \"\"\"\n        try:\n            return unicode(obj, *args)\n        except UnicodeDecodeError:\n            # obj is byte string\n            ascii_text = str(obj).encode('string_escape')\n            return unicode(ascii_text)\n\n    def iteritems(x):\n        return x.iteritems()\n\n    def iterkeys(x):\n        return x.iterkeys()\n\n    def itervalues(x):\n        return x.itervalues()\n\n    def nativestr(x):\n        return x if isinstance(x, str) else x.encode('utf-8', 'replace')\n\n    def u(x):\n        return x.decode()\n\n    def b(x):\n        return x\n\n    def next(x):\n        return x.next()\n\n    def byte_to_chr(x):\n        return x\n\n    unichr = unichr\n    xrange = xrange\n    basestring = basestring\n    unicode = unicode\n    bytes = str\n    long = long\nelse:\n    from urllib.parse import parse_qs, unquote, urlparse\n    from io import BytesIO\n    from string import ascii_letters\n    from queue import Queue\n\n    def iteritems(x):\n        return iter(x.items())\n\n    def iterkeys(x):\n        return iter(x.keys())\n\n    def itervalues(x):\n        return iter(x.values())\n\n    def byte_to_chr(x):\n        return chr(x)\n\n    def nativestr(x):\n        return x if isinstance(x, str) else x.decode('utf-8', 'replace')\n\n    def u(x):\n        return x\n\n    def b(x):\n        return x.encode('latin-1') if not isinstance(x, bytes) else x\n\n    next = next\n    unichr = chr\n    imap = map\n    izip = zip\n    xrange = range\n    basestring = str\n    unicode = str\n    safe_unicode = str\n    bytes = bytes\n    long = int\n\ntry:  # Python 3\n    from queue import LifoQueue, Empty, Full\nexcept ImportError:\n    from Queue import Empty, Full\n    try:  # Python 2.6 - 2.7\n        from Queue import LifoQueue\n    except ImportError:  # Python 2.5\n        from Queue import Queue\n        # From the Python 2.7 lib. Python 2.5 already extracted the core\n        # methods to aid implementating different queue organisations.\n\n        class LifoQueue(Queue):\n            \"Override queue methods to implement a last-in first-out queue.\"\n\n            def _init(self, maxsize):\n                self.maxsize = maxsize\n                self.queue = []\n\n            def _qsize(self, len=len):\n                return len(self.queue)\n\n            def _put(self, item):\n                self.queue.append(item)\n\n            def _get(self):\n                return self.queue.pop()\n", "path": "redis/_compat.py"}]}