Repository: clarketm/wait-for-it

Issue:
Exception when connecting to an unreachable local host.
```console
wait-for-it -s localhost:1234
```
```
[*] Waiting 15 seconds for localhost:1234
Traceback (most recent call last):
  File "/usr/local/bin/wait-for-it", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 98, in cli
    _connect_all_serial(service, timeout)
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 183, in _connect_all_serial
    connect(service, timeout)
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 191, in connect
    _asyncio_run(_wait_until_available_and_report(reporter, host, port))
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 24, in _asyncio_run
    return asyncio.run(*args, **kvargs)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 51, in _wait_until_available_and_report
    await _wait_until_available(host, port)
  File "/usr/local/lib/python3.8/site-packages/wait_for_it/wait_for_it.py", line 39, in _wait_until_available
    _reader, writer = await asyncio.open_connection(host, port)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/streams.py", line 52, in open_connection
    transport, _ = await loop.create_connection(
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 1033, in create_connection
    raise OSError('Multiple exceptions: {}'.format(
OSError: Multiple exceptions: [Errno 61] Connect call failed ('127.0.0.1', 1234), [Errno 61] Connect call failed ('::1', 1234, 0, 0)
```

Discussion:

Patch:
diff --git a/wait_for_it/wait_for_it.py b/wait_for_it/wait_for_it.py
index b9f7549..95e856a 100644
--- a/wait_for_it/wait_for_it.py
+++ b/wait_for_it/wait_for_it.py
@@ -54,7 +54,7 @@ async def _wait_until_available(host, port):
             if sys.version_info[:2] >= (3, 7):
                 await writer.wait_closed()
             break
-        except (socket.gaierror, ConnectionError):
+        except (socket.gaierror, ConnectionError, OSError, TypeError):
             pass
         await asyncio.sleep(1)
 


Test patch:
diff --git a/wait_for_it/test_wait_for_it.py b/wait_for_it/test_wait_for_it.py
index 42e0e72..2baa4bc 100644
--- a/wait_for_it/test_wait_for_it.py
+++ b/wait_for_it/test_wait_for_it.py
@@ -51,10 +51,10 @@ def _start_server_thread():
     return server
 
 
-def _occupy_free_tcp_port():
+def _occupy_free_tcp_port(host):
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    sock.bind(("127.0.0.1", _ANY_FREE_PORT))
-    host, port = sock.getsockname()
+    sock.bind((host, _ANY_FREE_PORT))
+    _, port = sock.getsockname()
     return host, port, sock
 
 
@@ -100,9 +100,18 @@ class CliTest(TestCase):
         finally:
             server.stop()
 
-    @parameterized.expand([("parallel", ["-p"], 2), ("serial", [], 1)])
-    def test_service_unavailable(self, _label, extra_argv, expected_report_count):
-        host, port, sock = _occupy_free_tcp_port()
+    @parameterized.expand(
+        [
+            ("parallel", ["-p"], 2, "127.0.0.1"),
+            ("parallel", ["-p"], 2, "0.0.0.0"),
+            ("parallel", ["-p"], 2, "localhost"),
+            ("serial", [], 1, "127.0.0.1"),
+            ("serial", [], 1, "0.0.0.0"),
+            ("serial", [], 1, "localhost"),
+        ]
+    )
+    def test_service_unavailable(self, _label, extra_argv, expected_report_count, host):
+        _, port, sock = _occupy_free_tcp_port(host)
         try:
             result = self._runner.invoke(
                 cli,