Repository: spyder-ide/spyder

Issue:
Handle connection errors when quitting Kite outside Spyder
## Description

Connection errors raise when quitting Kite outside Spyder


### What steps will reproduce the problem?

<!--- You can use Markdown here --->
#### Issue 1: from the plugin
1. Check you are not running Kite
2. Start Spyder
3. Error (although only sometimes)

#### Issue 2: from the client
1. Start Spyder (without code completion enable from the LSP)
2. Quit Kite
3. Try to get a code completion
4. Error

### Traceback
####  Issue 1: from the plugin
```python-traceback
Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 159, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 80, in create_connection
    raise err
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 70, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1016, in _send_output
    self.send(msg)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 956, in send
    self.connect()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 181, in connect
    conn = self._new_conn()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 168, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x00000202597E62B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/languages (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000202597E62B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\app\mainwindow.py", line 3596, in main
    mainwindow = run_spyder(app, options, args)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\app\mainwindow.py", line 3438, in run_spyder
    main.setup()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\app\mainwindow.py", line 944, in setup
    self.completions.start()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\plugin.py", line 216, in start
    client_info['plugin'].start()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\plugin.py", line 65, in start
    self.client.start()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 51, in start
    self.languages = self.get_languages()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 65, in get_languages
    success, response = self.perform_http_request(verb, url)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 72, in perform_http_request
    http_response = http_method(url, json=params)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/languages (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000202597E62B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))

```

####  Issue 2: from the client
```python-traceback
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 159, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 80, in create_connection
    raise err
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 70, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1016, in _send_output
    self.send(msg)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 956, in send
    self.connect()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 181, in connect
    conn = self._new_conn()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 168, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x000001DC9AC169E8>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/event (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DC9AC169E8>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 100, in perform_request
    response = handler(params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\decorators.py", line 23, in wrapper
    response = self.send(method, params, url_params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 89, in send
    http_verb, path, params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 72, in perform_http_request
    http_response = http_method(url, json=params)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/event (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DC9AC169E8>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))
Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 159, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 80, in create_connection
    raise err
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 70, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1016, in _send_output
    self.send(msg)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 956, in send
    self.connect()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 181, in connect
    conn = self._new_conn()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 168, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x000001DCA12BBCC0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/event (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DCA12BBCC0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 100, in perform_request
    response = handler(params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\decorators.py", line 23, in wrapper
    response = self.send(method, params, url_params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 89, in send
    http_verb, path, params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 72, in perform_http_request
    http_response = http_method(url, json=params)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/event (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DCA12BBCC0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))
Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 159, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 80, in create_connection
    raise err
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\connection.py", line 70, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 1016, in _send_output
    self.send(msg)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\http\client.py", line 956, in send
    self.connect()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 181, in connect
    conn = self._new_conn()
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connection.py", line 168, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x000001DCA12BE2B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\urllib3\util\retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/complete (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DCA12BE2B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 100, in perform_request
    response = handler(params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\decorators.py", line 23, in wrapper
    response = self.send(method, params, url_params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 89, in send
    http_verb, path, params)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\kite\client.py", line 72, in perform_http_request
    http_response = http_method(url, json=params)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=46624): Max retries exceeded with url: /clientapi/editor/complete (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001DCA12BE2B0>: Failed to establish a new connection: [WinError 10061] No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión'))
```

## Versions

* Spyder version: 4.0.0.dev0 63090f415
* Python version: 3.7.3
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 10

### Dependencies

```
pygments >=2.0    :  2.4.2 (OK)
qdarkstyle >=2.6.4:  2.7 (OK)
sphinx >=0.6.6    :  2.1.2 (OK)
pyls >=0.27.0     :  0.28.3 (OK)
nbconvert >=4.0   :  5.5.0 (OK)
pandas >=0.13.1   :  0.24.2 (OK)
numpy >=1.7       :  1.16.4 (OK)
pympler >=0.7     :  None (NOK)
sympy >=0.7.3     :  1.4 (OK)
cython >=0.21     :  None (NOK)
qtconsole >=4.5.2 :  4.5.2 (OK)
IPython >=4.0     :  7.7.0 (OK)
matplotlib >=2.0.0:  3.1.0 (OK)
pylint >=0.25     :  2.3.1 (OK)
```



Discussion:

Resolving patch:
diff --git a/spyder/plugins/completion/kite/client.py b/spyder/plugins/completion/kite/client.py
--- a/spyder/plugins/completion/kite/client.py
+++ b/spyder/plugins/completion/kite/client.py
@@ -63,13 +63,18 @@ def stop(self):
     def get_languages(self):
         verb, url = KITE_ENDPOINTS.LANGUAGES_ENDPOINT
         success, response = self.perform_http_request(verb, url)
+        if response is None:
+            response = []
         return response
 
     def perform_http_request(self, verb, url, params=None):
         response = None
         success = False
         http_method = getattr(self.endpoint, verb)
-        http_response = http_method(url, json=params)
+        try:
+            http_response = http_method(url, json=params)
+        except Exception:
+            return False, None
         success = http_response.status_code == 200
         if success:
             try:


Test patch: