Repository: ethereum/web3.py

Issue:
web3.auto raises unclear exception if no client is live
* Version: 4.0.0-beta.1
* OS: linux


### What was wrong?

If no client is live, I expect w3 to return as `None` in this case, but instead I get an exception.
```
from web3.auto import w3
```

cc @Sebohe 

> ~/code/ethtoken/ethtoken/main.py in eip20_token(address, w3, **kwargs)
>      23     '''
>      24     if w3 is None:
> ---> 25         from web3.auto import w3
>      26         if w3 is None:
>      27             raise RuntimeError("Could not auto-detect web3 connection, please supply it as arg w3")
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/auto/__init__.py in <module>()
>       2 
>       3 for connector in ('ipc', 'http'):
> ----> 4     connection = importlib.import_module('web3.auto.' + connector)
>       5     if connection.w3:
>       6         w3 = connection.w3
> 
> /usr/lib/python3.5/importlib/__init__.py in import_module(name, package)
>     124                 break
>     125             level += 1
> --> 126     return _bootstrap._gcd_import(name[level:], package, level)
>     127 
>     128 
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/auto/ipc.py in <module>()
>      14 
>      15 
> ---> 16 w3 = connect()
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/auto/ipc.py in connect()
>       8 def connect():
>       9     w3 = Web3(IPCProvider(get_default_ipc_path()))
> ---> 10     if w3.isConnected():
>      11         return w3
>      12 
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/main.py in isConnected(self)
>     155     def isConnected(self):
>     156         for provider in self.providers:
> --> 157             if provider.isConnected():
>     158                 return True
>     159         else:
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/providers/base.py in isConnected(self)
>      73     def isConnected(self):
>      74         try:
> ---> 75             response = self.make_request('web3_clientVersion', [])
>      76         except IOError:
>      77             return False
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/providers/ipc.py in make_request(self, method, params)
>     139         request = self.encode_rpc_request(method, params)
>     140 
> --> 141         with self._lock, self._socket as sock:
>     142             sock.sendall(request)
>     143             raw_response = b""
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/providers/ipc.py in __enter__(self)
>      37     def __enter__(self):
>      38         if not self.sock:
> ---> 39             self.sock = get_ipc_socket(self.ipc_path)
>      40         return self.sock
>      41 
> 
> ~/code/ethtoken/venv/lib/python3.5/site-packages/web3/providers/ipc.py in get_ipc_socket(ipc_path, timeout)
>      24     else:
>      25         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
> ---> 26         sock.connect(ipc_path)
>      27         sock.settimeout(timeout)
>      28         return sock
> 
> TypeError: a bytes-like object is required, not 'NoneType'


### How can it be fixed?

* Add a new test to verify the situation, and prevent regressions
* `isConnected` should short-circuit with something like: `if self.ipc_path is None: return False`



Discussion:

Resolving patch:
diff --git a/web3/providers/ipc.py b/web3/providers/ipc.py
--- a/web3/providers/ipc.py
+++ b/web3/providers/ipc.py
@@ -35,6 +35,9 @@ def __init__(self, ipc_path):
         self.ipc_path = ipc_path
 
     def __enter__(self):
+        if not self.ipc_path:
+            raise FileNotFoundError("cannot connect to IPC socket at path: %r" % self.ipc_path)
+
         if not self.sock:
             self.sock = get_ipc_socket(self.ipc_path)
         return self.sock


Test patch:
diff --git a/tests/core/providers/test_ipc_provider.py b/tests/core/providers/test_ipc_provider.py
new file mode 100644
--- /dev/null
+++ b/tests/core/providers/test_ipc_provider.py
@@ -0,0 +1,11 @@
+from web3.providers.ipc import (
+    IPCProvider,
+)
+
+
+def test_ipc_no_path():
+    """
+    IPCProvider.isConnected() returns False when no path is supplied
+    """
+    ipc = IPCProvider(None)
+    assert ipc.isConnected() is False