We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TypeError when starting Kite client
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

installed spyder 4.0.1 using "conda update spyder". Had previously installed spyder 4.0.0 using "conda install spyder=4.0.0" and could not get past the starting-to-open state. python is at 3.7.3

### Traceback
```python-traceback
  File "C:\Progra~1\Anaconda3\lib\site-packages\spyder\plugins\completion\kite\client.py", line 108, in get_status
    self.sig_status_response_ready[dict].emit(kite_status)
TypeError: KiteClient.sig_status_response_ready[dict].emit(): argument 1 has unexpected type 'str'
```

## Versions

* Spyder version: 4.0.1 
* Python version: 3.7.3
* Qt version: 5.12.5
* PyQt5 version: 5.12.3
* Operating System: Windows 10

### Dependencies

```
atomicwrites >=1.2.0         :  1.3.0 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
cloudpickle >=0.5.0          :  1.2.2 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
intervaltree                 :  None (OK)
IPython >=4.0                :  7.11.1 (OK)
jedi =0.14.1                 :  0.14.1 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
numpydoc >=0.6.0             :  0.9.2 (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
psutil >=0.3                 :  5.6.7 (OK)
pygments >=2.0               :  2.5.2 (OK)
pylint >=0.25                :  2.4.4 (OK)
pyls >=0.31.2;<0.32.0        :  0.31.4 (OK)
zmq >=17                     :  18.1.1 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
qtawesome >=0.5.7            :  0.6.0 (OK)
qtconsole >=4.6.0            :  4.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
rtree >=0.8.3                :  0.9.3 (OK)
sphinx >=0.6.6               :  2.3.1 (OK)
spyder_kernels >=1.8.1;<2.0.0:  1.8.1 (OK)
watchdog                     :  None (OK)
cython >=0.21                :  None (NOK)
matplotlib >=2.0.0           :  None (NOK)
numpy >=1.7                  :  1.17.3 (OK)
pandas >=0.13.1              :  None (NOK)
scipy >=0.17.0               :  1.3.1 (OK)
sympy >=0.7.3                :  None (NOK)
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `spyder/plugins/completion/kite/utils/status.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # Copyright © Spyder Project Contributors
4 # Licensed under the terms of the MIT License
5 # (see spyder/__init__.py for details)
6 
7 """Kite status functions."""
8 
9 # Standard library imports
10 import logging
11 import os
12 import os.path as osp
13 import subprocess
14 import sys
15 
16 # Third-party imports
17 import psutil
18 
19 NOT_INSTALLED = 'not installed'
20 RUNNING = 'ready'
21 NOT_RUNNING = 'not running'
22 
23 logger = logging.getLogger(__name__)
24 
25 
26 def check_if_kite_installed():
27     """Detect if kite is installed and return the installation path."""
28     path = ''
29     if os.name == 'nt':
30         path = 'C:\\Program Files\\Kite\\kited.exe'
31     elif sys.platform.startswith('linux'):
32         path = osp.expanduser('~/.local/share/kite/kited')
33     elif sys.platform == 'darwin':
34         path = locate_kite_darwin()
35     return osp.exists(osp.realpath(path)), path
36 
37 
38 def check_if_kite_running():
39     """Detect if kite is running."""
40     running = False
41     for proc in psutil.process_iter(attrs=['pid', 'name', 'username',
42                                            'status']):
43         if is_proc_kite(proc):
44             logger.debug('Kite process already '
45                          'running with PID {0}'.format(proc.pid))
46             running = True
47             break
48     return running
49 
50 
51 def locate_kite_darwin():
52     """
53     Looks up where Kite.app is installed on macOS systems. The bundle ID
54     is checked first and if nothing is found or an error occurs, the
55     default path is used.
56     """
57     default_path = '/Applications/Kite.app'
58     path = ''
59     try:
60         out = subprocess.check_output(
61             ['mdfind', 'kMDItemCFBundleIdentifier="com.kite.Kite"'])
62         installed = len(out) > 0
63         path = (out.decode('utf-8', 'replace').strip().split('\n')[0]
64                 if installed else default_path)
65     except (subprocess.CalledProcessError, UnicodeDecodeError):
66         # Use the default path
67         path = default_path
68     finally:
69         return path
70 
71 
72 def is_proc_kite(proc):
73     try:
74         # This is raising `ZombieProcess: psutil.ZombieProcess` on OSX
75         # if kite is not running.
76         name = proc.name()
77     except Exception:
78         name = ''
79 
80     if os.name == 'nt' or sys.platform.startswith('linux'):
81         is_kite = 'kited' in name and proc.status() != 'zombie'
82     else:
83         is_kite = 'Kite' == name
84 
85     return is_kite
86 
87 
88 def status():
89     """Kite completions status: not installed, ready, not running."""
90     kite_installed, _ = check_if_kite_installed()
91     if not kite_installed:
92         return NOT_INSTALLED
93     elif check_if_kite_running():
94         return RUNNING
95     else:
96         return NOT_RUNNING
97
```

Path: `spyder/plugins/completion/kite/client.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # Copyright © Spyder Project Contributors
4 # Licensed under the terms of the MIT License
5 # (see spyder/__init__.py for details)
6 
7 """Kite completions HTTP client."""
8 
9 # Standard library imports
10 import logging
11 try:
12     from urllib import quote  # Python 2
13 except ImportError:
14     from urllib.parse import quote  # Python 3
15 
16 # Third party imports
17 from qtpy.QtCore import QObject, QThread, Signal, QMutex
18 import requests
19 
20 # Local imports
21 from spyder.plugins.completion.kite import KITE_ENDPOINTS, KITE_REQUEST_MAPPING
22 from spyder.plugins.completion.kite.decorators import class_register
23 from spyder.plugins.completion.kite.providers import KiteMethodProviderMixIn
24 from spyder.plugins.completion.kite.utils.status import (
25     status, check_if_kite_running)
26 from spyder.py3compat import (
27     ConnectionError, ConnectionRefusedError, TEXT_TYPES)
28 
29 
30 logger = logging.getLogger(__name__)
31 
32 
33 @class_register
34 class KiteClient(QObject, KiteMethodProviderMixIn):
35     sig_response_ready = Signal(int, dict)
36     sig_client_started = Signal(list)
37     sig_client_not_responding = Signal()
38     sig_perform_request = Signal(int, str, object)
39     sig_perform_status_request = Signal(str)
40     sig_status_response_ready = Signal((str,), (dict,))
41     sig_perform_onboarding_request = Signal()
42     sig_onboarding_response_ready = Signal(str)
43 
44     def __init__(self, parent, enable_code_snippets=True):
45         QObject.__init__(self, parent)
46         self.endpoint = None
47         self.requests = {}
48         self.languages = []
49         self.mutex = QMutex()
50         self.opened_files = {}
51         self.opened_files_status = {}
52         self.thread_started = False
53         self.enable_code_snippets = enable_code_snippets
54         self.thread = QThread()
55         self.moveToThread(self.thread)
56         self.thread.started.connect(self.started)
57         self.sig_perform_request.connect(self.perform_request)
58         self.sig_perform_status_request.connect(self.get_status)
59         self.sig_perform_onboarding_request.connect(self.get_onboarding_file)
60 
61     def start(self):
62         if not self.thread_started:
63             self.thread.start()
64         logger.debug('Starting Kite HTTP session...')
65         self.endpoint = requests.Session()
66         self.languages = self.get_languages()
67         self.sig_client_started.emit(self.languages)
68 
69     def started(self):
70         self.thread_started = True
71 
72     def stop(self):
73         if self.thread_started:
74             logger.debug('Closing Kite HTTP session...')
75             self.endpoint.close()
76             self.thread.quit()
77 
78     def get_languages(self):
79         verb, url = KITE_ENDPOINTS.LANGUAGES_ENDPOINT
80         success, response = self.perform_http_request(verb, url)
81         if response is None:
82             response = ['python']
83         return response
84 
85     def _get_onboarding_file(self):
86         """Perform a request to get kite's onboarding file."""
87         verb, url = KITE_ENDPOINTS.ONBOARDING_ENDPOINT
88         success, response = self.perform_http_request(verb, url)
89         return response
90 
91     def get_onboarding_file(self):
92         """Get onboarding file."""
93         onboarding_file = self._get_onboarding_file()
94         self.sig_onboarding_response_ready.emit(onboarding_file)
95 
96     def _get_status(self, filename):
97         """Perform a request to get kite status for a file."""
98         verb, url = KITE_ENDPOINTS.STATUS_ENDPOINT
99         if filename:
100             url_params = {'filename': filename}
101         else:
102             url_params = {'filetype': 'python'}
103         success, response = self.perform_http_request(
104             verb, url, url_params=url_params)
105         return response
106 
107     def get_status(self, filename):
108         """Get kite status for a given filename."""
109         kite_status = self._get_status(filename)
110         if not filename or kite_status is None:
111             kite_status = status()
112             self.sig_status_response_ready[str].emit(kite_status)
113         else:
114             self.sig_status_response_ready[dict].emit(kite_status)
115 
116     def perform_http_request(self, verb, url, url_params=None, params=None):
117         response = None
118         http_method = getattr(self.endpoint, verb)
119         try:
120             http_response = http_method(url, params=url_params, json=params)
121         except Exception as error:
122             return False, None
123         success = http_response.status_code == 200
124         if success:
125             try:
126                 response = http_response.json()
127             except Exception:
128                 response = http_response.text
129                 response = None if response == '' else response
130         return success, response
131 
132     def send(self, method, params, url_params):
133         response = None
134         if self.endpoint is not None and method in KITE_REQUEST_MAPPING:
135             http_verb, path = KITE_REQUEST_MAPPING[method]
136             encoded_url_params = {
137                 key: quote(value) if isinstance(value, TEXT_TYPES) else value
138                 for (key, value) in url_params.items()}
139             path = path.format(**encoded_url_params)
140             try:
141                 success, response = self.perform_http_request(
142                     http_verb, path, params=params)
143             except (ConnectionRefusedError, ConnectionError):
144                 return response
145         return response
146 
147     def perform_request(self, req_id, method, params):
148         response = None
149         if method in self.sender_registry:
150             logger.debug('Perform {0} request with id {1}'.format(
151                 method, req_id))
152             handler_name = self.sender_registry[method]
153             handler = getattr(self, handler_name)
154             response = handler(params)
155             if method in self.handler_registry:
156                 converter_name = self.handler_registry[method]
157                 converter = getattr(self, converter_name)
158                 if response is not None:
159                     response = converter(response)
160         self.sig_response_ready.emit(req_id, response or {})
161
```
--- 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/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
@@ -18,6 +18,7 @@
 import requests
 
 # Local imports
+from spyder.config.base import _
 from spyder.plugins.completion.kite import KITE_ENDPOINTS, KITE_REQUEST_MAPPING
 from spyder.plugins.completion.kite.decorators import class_register
 from spyder.plugins.completion.kite.providers import KiteMethodProviderMixIn
@@ -102,14 +103,30 @@
             url_params = {'filetype': 'python'}
         success, response = self.perform_http_request(
             verb, url, url_params=url_params)
-        return response
+        return success, response
 
     def get_status(self, filename):
         """Get kite status for a given filename."""
-        kite_status = self._get_status(filename)
+        success_status, kite_status = self._get_status(filename)
         if not filename or kite_status is None:
             kite_status = status()
             self.sig_status_response_ready[str].emit(kite_status)
+        elif isinstance(kite_status, TEXT_TYPES):
+            if not success_status:
+                status_str = status(extra_status=' with errors')
+                long_str = _("<code>{error}</code><br><br>"
+                             "Note: If you are using a VPN, "
+                             "please don't route requests to "
+                             "localhost/127.0.0.1 with it").format(
+                                 error=kite_status)
+            else:
+                status_str = status()
+                long_str = kite_status
+            kite_status_dict = {
+                'status': status_str,
+                'short': status_str,
+                'long': long_str}
+            self.sig_status_response_ready[dict].emit(kite_status_dict)
         else:
             self.sig_status_response_ready[dict].emit(kite_status)
 
diff --git a/spyder/plugins/completion/kite/utils/status.py b/spyder/plugins/completion/kite/utils/status.py
--- a/spyder/plugins/completion/kite/utils/status.py
+++ b/spyder/plugins/completion/kite/utils/status.py
@@ -85,12 +85,12 @@
     return is_kite
 
 
-def status():
+def status(extra_status=''):
     """Kite completions status: not installed, ready, not running."""
     kite_installed, _ = check_if_kite_installed()
     if not kite_installed:
-        return NOT_INSTALLED
+        return NOT_INSTALLED + extra_status
     elif check_if_kite_running():
-        return RUNNING
+        return RUNNING + extra_status
     else:
-        return NOT_RUNNING
+        return NOT_RUNNING + extra_status

{"golden_diff": "diff --git a/spyder/plugins/completion/kite/client.py b/spyder/plugins/completion/kite/client.py\n--- a/spyder/plugins/completion/kite/client.py\n+++ b/spyder/plugins/completion/kite/client.py\n@@ -18,6 +18,7 @@\n import requests\n \n # Local imports\n+from spyder.config.base import _\n from spyder.plugins.completion.kite import KITE_ENDPOINTS, KITE_REQUEST_MAPPING\n from spyder.plugins.completion.kite.decorators import class_register\n from spyder.plugins.completion.kite.providers import KiteMethodProviderMixIn\n@@ -102,14 +103,30 @@\n             url_params = {'filetype': 'python'}\n         success, response = self.perform_http_request(\n             verb, url, url_params=url_params)\n-        return response\n+        return success, response\n \n     def get_status(self, filename):\n         \"\"\"Get kite status for a given filename.\"\"\"\n-        kite_status = self._get_status(filename)\n+        success_status, kite_status = self._get_status(filename)\n         if not filename or kite_status is None:\n             kite_status = status()\n             self.sig_status_response_ready[str].emit(kite_status)\n+        elif isinstance(kite_status, TEXT_TYPES):\n+            if not success_status:\n+                status_str = status(extra_status=' with errors')\n+                long_str = _(\"<code>{error}</code><br><br>\"\n+                             \"Note: If you are using a VPN, \"\n+                             \"please don't route requests to \"\n+                             \"localhost/127.0.0.1 with it\").format(\n+                                 error=kite_status)\n+            else:\n+                status_str = status()\n+                long_str = kite_status\n+            kite_status_dict = {\n+                'status': status_str,\n+                'short': status_str,\n+                'long': long_str}\n+            self.sig_status_response_ready[dict].emit(kite_status_dict)\n         else:\n             self.sig_status_response_ready[dict].emit(kite_status)\n \ndiff --git a/spyder/plugins/completion/kite/utils/status.py b/spyder/plugins/completion/kite/utils/status.py\n--- a/spyder/plugins/completion/kite/utils/status.py\n+++ b/spyder/plugins/completion/kite/utils/status.py\n@@ -85,12 +85,12 @@\n     return is_kite\n \n \n-def status():\n+def status(extra_status=''):\n     \"\"\"Kite completions status: not installed, ready, not running.\"\"\"\n     kite_installed, _ = check_if_kite_installed()\n     if not kite_installed:\n-        return NOT_INSTALLED\n+        return NOT_INSTALLED + extra_status\n     elif check_if_kite_running():\n-        return RUNNING\n+        return RUNNING + extra_status\n     else:\n-        return NOT_RUNNING\n+        return NOT_RUNNING + extra_status\n", "issue": "TypeError when starting Kite client\n## Description\n\n### What steps will reproduce the problem?\n\n<!--- You can use Markdown here --->\n\ninstalled spyder 4.0.1 using \"conda update spyder\". Had previously installed spyder 4.0.0 using \"conda install spyder=4.0.0\" and could not get past the starting-to-open state. python is at 3.7.3\n\n### Traceback\n```python-traceback\n  File \"C:\\Progra~1\\Anaconda3\\lib\\site-packages\\spyder\\plugins\\completion\\kite\\client.py\", line 108, in get_status\n    self.sig_status_response_ready[dict].emit(kite_status)\nTypeError: KiteClient.sig_status_response_ready[dict].emit(): argument 1 has unexpected type 'str'\n```\n\n## Versions\n\n* Spyder version: 4.0.1 \n* Python version: 3.7.3\n* Qt version: 5.12.5\n* PyQt5 version: 5.12.3\n* Operating System: Windows 10\n\n### Dependencies\n\n```\natomicwrites >=1.2.0         :  1.3.0 (OK)\r\nchardet >=2.0.0              :  3.0.4 (OK)\r\ncloudpickle >=0.5.0          :  1.2.2 (OK)\r\ndiff_match_patch >=20181111  :  20181111 (OK)\r\nintervaltree                 :  None (OK)\r\nIPython >=4.0                :  7.11.1 (OK)\r\njedi =0.14.1                 :  0.14.1 (OK)\r\nnbconvert >=4.0              :  5.6.1 (OK)\r\nnumpydoc >=0.6.0             :  0.9.2 (OK)\r\npexpect >=4.4.0              :  4.7.0 (OK)\r\npickleshare >=0.4            :  0.7.5 (OK)\r\npsutil >=0.3                 :  5.6.7 (OK)\r\npygments >=2.0               :  2.5.2 (OK)\r\npylint >=0.25                :  2.4.4 (OK)\r\npyls >=0.31.2;<0.32.0        :  0.31.4 (OK)\r\nzmq >=17                     :  18.1.1 (OK)\r\nqdarkstyle >=2.7             :  2.7 (OK)\r\nqtawesome >=0.5.7            :  0.6.0 (OK)\r\nqtconsole >=4.6.0            :  4.6.0 (OK)\r\nqtpy >=1.5.0                 :  1.9.0 (OK)\r\nrtree >=0.8.3                :  0.9.3 (OK)\r\nsphinx >=0.6.6               :  2.3.1 (OK)\r\nspyder_kernels >=1.8.1;<2.0.0:  1.8.1 (OK)\r\nwatchdog                     :  None (OK)\r\ncython >=0.21                :  None (NOK)\r\nmatplotlib >=2.0.0           :  None (NOK)\r\nnumpy >=1.7                  :  1.17.3 (OK)\r\npandas >=0.13.1              :  None (NOK)\r\nscipy >=0.17.0               :  1.3.1 (OK)\r\nsympy >=0.7.3                :  None (NOK)\r\n```\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n\"\"\"Kite status functions.\"\"\"\n\n# Standard library imports\nimport logging\nimport os\nimport os.path as osp\nimport subprocess\nimport sys\n\n# Third-party imports\nimport psutil\n\nNOT_INSTALLED = 'not installed'\nRUNNING = 'ready'\nNOT_RUNNING = 'not running'\n\nlogger = logging.getLogger(__name__)\n\n\ndef check_if_kite_installed():\n    \"\"\"Detect if kite is installed and return the installation path.\"\"\"\n    path = ''\n    if os.name == 'nt':\n        path = 'C:\\\\Program Files\\\\Kite\\\\kited.exe'\n    elif sys.platform.startswith('linux'):\n        path = osp.expanduser('~/.local/share/kite/kited')\n    elif sys.platform == 'darwin':\n        path = locate_kite_darwin()\n    return osp.exists(osp.realpath(path)), path\n\n\ndef check_if_kite_running():\n    \"\"\"Detect if kite is running.\"\"\"\n    running = False\n    for proc in psutil.process_iter(attrs=['pid', 'name', 'username',\n                                           'status']):\n        if is_proc_kite(proc):\n            logger.debug('Kite process already '\n                         'running with PID {0}'.format(proc.pid))\n            running = True\n            break\n    return running\n\n\ndef locate_kite_darwin():\n    \"\"\"\n    Looks up where Kite.app is installed on macOS systems. The bundle ID\n    is checked first and if nothing is found or an error occurs, the\n    default path is used.\n    \"\"\"\n    default_path = '/Applications/Kite.app'\n    path = ''\n    try:\n        out = subprocess.check_output(\n            ['mdfind', 'kMDItemCFBundleIdentifier=\"com.kite.Kite\"'])\n        installed = len(out) > 0\n        path = (out.decode('utf-8', 'replace').strip().split('\\n')[0]\n                if installed else default_path)\n    except (subprocess.CalledProcessError, UnicodeDecodeError):\n        # Use the default path\n        path = default_path\n    finally:\n        return path\n\n\ndef is_proc_kite(proc):\n    try:\n        # This is raising `ZombieProcess: psutil.ZombieProcess` on OSX\n        # if kite is not running.\n        name = proc.name()\n    except Exception:\n        name = ''\n\n    if os.name == 'nt' or sys.platform.startswith('linux'):\n        is_kite = 'kited' in name and proc.status() != 'zombie'\n    else:\n        is_kite = 'Kite' == name\n\n    return is_kite\n\n\ndef status():\n    \"\"\"Kite completions status: not installed, ready, not running.\"\"\"\n    kite_installed, _ = check_if_kite_installed()\n    if not kite_installed:\n        return NOT_INSTALLED\n    elif check_if_kite_running():\n        return RUNNING\n    else:\n        return NOT_RUNNING\n", "path": "spyder/plugins/completion/kite/utils/status.py"}, {"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n\"\"\"Kite completions HTTP client.\"\"\"\n\n# Standard library imports\nimport logging\ntry:\n    from urllib import quote  # Python 2\nexcept ImportError:\n    from urllib.parse import quote  # Python 3\n\n# Third party imports\nfrom qtpy.QtCore import QObject, QThread, Signal, QMutex\nimport requests\n\n# Local imports\nfrom spyder.plugins.completion.kite import KITE_ENDPOINTS, KITE_REQUEST_MAPPING\nfrom spyder.plugins.completion.kite.decorators import class_register\nfrom spyder.plugins.completion.kite.providers import KiteMethodProviderMixIn\nfrom spyder.plugins.completion.kite.utils.status import (\n    status, check_if_kite_running)\nfrom spyder.py3compat import (\n    ConnectionError, ConnectionRefusedError, TEXT_TYPES)\n\n\nlogger = logging.getLogger(__name__)\n\n\n@class_register\nclass KiteClient(QObject, KiteMethodProviderMixIn):\n    sig_response_ready = Signal(int, dict)\n    sig_client_started = Signal(list)\n    sig_client_not_responding = Signal()\n    sig_perform_request = Signal(int, str, object)\n    sig_perform_status_request = Signal(str)\n    sig_status_response_ready = Signal((str,), (dict,))\n    sig_perform_onboarding_request = Signal()\n    sig_onboarding_response_ready = Signal(str)\n\n    def __init__(self, parent, enable_code_snippets=True):\n        QObject.__init__(self, parent)\n        self.endpoint = None\n        self.requests = {}\n        self.languages = []\n        self.mutex = QMutex()\n        self.opened_files = {}\n        self.opened_files_status = {}\n        self.thread_started = False\n        self.enable_code_snippets = enable_code_snippets\n        self.thread = QThread()\n        self.moveToThread(self.thread)\n        self.thread.started.connect(self.started)\n        self.sig_perform_request.connect(self.perform_request)\n        self.sig_perform_status_request.connect(self.get_status)\n        self.sig_perform_onboarding_request.connect(self.get_onboarding_file)\n\n    def start(self):\n        if not self.thread_started:\n            self.thread.start()\n        logger.debug('Starting Kite HTTP session...')\n        self.endpoint = requests.Session()\n        self.languages = self.get_languages()\n        self.sig_client_started.emit(self.languages)\n\n    def started(self):\n        self.thread_started = True\n\n    def stop(self):\n        if self.thread_started:\n            logger.debug('Closing Kite HTTP session...')\n            self.endpoint.close()\n            self.thread.quit()\n\n    def get_languages(self):\n        verb, url = KITE_ENDPOINTS.LANGUAGES_ENDPOINT\n        success, response = self.perform_http_request(verb, url)\n        if response is None:\n            response = ['python']\n        return response\n\n    def _get_onboarding_file(self):\n        \"\"\"Perform a request to get kite's onboarding file.\"\"\"\n        verb, url = KITE_ENDPOINTS.ONBOARDING_ENDPOINT\n        success, response = self.perform_http_request(verb, url)\n        return response\n\n    def get_onboarding_file(self):\n        \"\"\"Get onboarding file.\"\"\"\n        onboarding_file = self._get_onboarding_file()\n        self.sig_onboarding_response_ready.emit(onboarding_file)\n\n    def _get_status(self, filename):\n        \"\"\"Perform a request to get kite status for a file.\"\"\"\n        verb, url = KITE_ENDPOINTS.STATUS_ENDPOINT\n        if filename:\n            url_params = {'filename': filename}\n        else:\n            url_params = {'filetype': 'python'}\n        success, response = self.perform_http_request(\n            verb, url, url_params=url_params)\n        return response\n\n    def get_status(self, filename):\n        \"\"\"Get kite status for a given filename.\"\"\"\n        kite_status = self._get_status(filename)\n        if not filename or kite_status is None:\n            kite_status = status()\n            self.sig_status_response_ready[str].emit(kite_status)\n        else:\n            self.sig_status_response_ready[dict].emit(kite_status)\n\n    def perform_http_request(self, verb, url, url_params=None, params=None):\n        response = None\n        http_method = getattr(self.endpoint, verb)\n        try:\n            http_response = http_method(url, params=url_params, json=params)\n        except Exception as error:\n            return False, None\n        success = http_response.status_code == 200\n        if success:\n            try:\n                response = http_response.json()\n            except Exception:\n                response = http_response.text\n                response = None if response == '' else response\n        return success, response\n\n    def send(self, method, params, url_params):\n        response = None\n        if self.endpoint is not None and method in KITE_REQUEST_MAPPING:\n            http_verb, path = KITE_REQUEST_MAPPING[method]\n            encoded_url_params = {\n                key: quote(value) if isinstance(value, TEXT_TYPES) else value\n                for (key, value) in url_params.items()}\n            path = path.format(**encoded_url_params)\n            try:\n                success, response = self.perform_http_request(\n                    http_verb, path, params=params)\n            except (ConnectionRefusedError, ConnectionError):\n                return response\n        return response\n\n    def perform_request(self, req_id, method, params):\n        response = None\n        if method in self.sender_registry:\n            logger.debug('Perform {0} request with id {1}'.format(\n                method, req_id))\n            handler_name = self.sender_registry[method]\n            handler = getattr(self, handler_name)\n            response = handler(params)\n            if method in self.handler_registry:\n                converter_name = self.handler_registry[method]\n                converter = getattr(self, converter_name)\n                if response is not None:\n                    response = converter(response)\n        self.sig_response_ready.emit(req_id, response or {})\n", "path": "spyder/plugins/completion/kite/client.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n\"\"\"Kite status functions.\"\"\"\n\n# Standard library imports\nimport logging\nimport os\nimport os.path as osp\nimport subprocess\nimport sys\n\n# Third-party imports\nimport psutil\n\nNOT_INSTALLED = 'not installed'\nRUNNING = 'ready'\nNOT_RUNNING = 'not running'\n\nlogger = logging.getLogger(__name__)\n\n\ndef check_if_kite_installed():\n    \"\"\"Detect if kite is installed and return the installation path.\"\"\"\n    path = ''\n    if os.name == 'nt':\n        path = 'C:\\\\Program Files\\\\Kite\\\\kited.exe'\n    elif sys.platform.startswith('linux'):\n        path = osp.expanduser('~/.local/share/kite/kited')\n    elif sys.platform == 'darwin':\n        path = locate_kite_darwin()\n    return osp.exists(osp.realpath(path)), path\n\n\ndef check_if_kite_running():\n    \"\"\"Detect if kite is running.\"\"\"\n    running = False\n    for proc in psutil.process_iter(attrs=['pid', 'name', 'username',\n                                           'status']):\n        if is_proc_kite(proc):\n            logger.debug('Kite process already '\n                         'running with PID {0}'.format(proc.pid))\n            running = True\n            break\n    return running\n\n\ndef locate_kite_darwin():\n    \"\"\"\n    Looks up where Kite.app is installed on macOS systems. The bundle ID\n    is checked first and if nothing is found or an error occurs, the\n    default path is used.\n    \"\"\"\n    default_path = '/Applications/Kite.app'\n    path = ''\n    try:\n        out = subprocess.check_output(\n            ['mdfind', 'kMDItemCFBundleIdentifier=\"com.kite.Kite\"'])\n        installed = len(out) > 0\n        path = (out.decode('utf-8', 'replace').strip().split('\\n')[0]\n                if installed else default_path)\n    except (subprocess.CalledProcessError, UnicodeDecodeError):\n        # Use the default path\n        path = default_path\n    finally:\n        return path\n\n\ndef is_proc_kite(proc):\n    try:\n        # This is raising `ZombieProcess: psutil.ZombieProcess` on OSX\n        # if kite is not running.\n        name = proc.name()\n    except Exception:\n        name = ''\n\n    if os.name == 'nt' or sys.platform.startswith('linux'):\n        is_kite = 'kited' in name and proc.status() != 'zombie'\n    else:\n        is_kite = 'Kite' == name\n\n    return is_kite\n\n\ndef status(extra_status=''):\n    \"\"\"Kite completions status: not installed, ready, not running.\"\"\"\n    kite_installed, _ = check_if_kite_installed()\n    if not kite_installed:\n        return NOT_INSTALLED + extra_status\n    elif check_if_kite_running():\n        return RUNNING + extra_status\n    else:\n        return NOT_RUNNING + extra_status\n", "path": "spyder/plugins/completion/kite/utils/status.py"}, {"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n\"\"\"Kite completions HTTP client.\"\"\"\n\n# Standard library imports\nimport logging\ntry:\n    from urllib import quote  # Python 2\nexcept ImportError:\n    from urllib.parse import quote  # Python 3\n\n# Third party imports\nfrom qtpy.QtCore import QObject, QThread, Signal, QMutex\nimport requests\n\n# Local imports\nfrom spyder.config.base import _\nfrom spyder.plugins.completion.kite import KITE_ENDPOINTS, KITE_REQUEST_MAPPING\nfrom spyder.plugins.completion.kite.decorators import class_register\nfrom spyder.plugins.completion.kite.providers import KiteMethodProviderMixIn\nfrom spyder.plugins.completion.kite.utils.status import (\n    status, check_if_kite_running)\nfrom spyder.py3compat import (\n    ConnectionError, ConnectionRefusedError, TEXT_TYPES)\n\n\nlogger = logging.getLogger(__name__)\n\n\n@class_register\nclass KiteClient(QObject, KiteMethodProviderMixIn):\n    sig_response_ready = Signal(int, dict)\n    sig_client_started = Signal(list)\n    sig_client_not_responding = Signal()\n    sig_perform_request = Signal(int, str, object)\n    sig_perform_status_request = Signal(str)\n    sig_status_response_ready = Signal((str,), (dict,))\n    sig_perform_onboarding_request = Signal()\n    sig_onboarding_response_ready = Signal(str)\n\n    def __init__(self, parent, enable_code_snippets=True):\n        QObject.__init__(self, parent)\n        self.endpoint = None\n        self.requests = {}\n        self.languages = []\n        self.mutex = QMutex()\n        self.opened_files = {}\n        self.opened_files_status = {}\n        self.thread_started = False\n        self.enable_code_snippets = enable_code_snippets\n        self.thread = QThread()\n        self.moveToThread(self.thread)\n        self.thread.started.connect(self.started)\n        self.sig_perform_request.connect(self.perform_request)\n        self.sig_perform_status_request.connect(self.get_status)\n        self.sig_perform_onboarding_request.connect(self.get_onboarding_file)\n\n    def start(self):\n        if not self.thread_started:\n            self.thread.start()\n        logger.debug('Starting Kite HTTP session...')\n        self.endpoint = requests.Session()\n        self.languages = self.get_languages()\n        self.sig_client_started.emit(self.languages)\n\n    def started(self):\n        self.thread_started = True\n\n    def stop(self):\n        if self.thread_started:\n            logger.debug('Closing Kite HTTP session...')\n            self.endpoint.close()\n            self.thread.quit()\n\n    def get_languages(self):\n        verb, url = KITE_ENDPOINTS.LANGUAGES_ENDPOINT\n        success, response = self.perform_http_request(verb, url)\n        if response is None:\n            response = ['python']\n        return response\n\n    def _get_onboarding_file(self):\n        \"\"\"Perform a request to get kite's onboarding file.\"\"\"\n        verb, url = KITE_ENDPOINTS.ONBOARDING_ENDPOINT\n        success, response = self.perform_http_request(verb, url)\n        return response\n\n    def get_onboarding_file(self):\n        \"\"\"Get onboarding file.\"\"\"\n        onboarding_file = self._get_onboarding_file()\n        self.sig_onboarding_response_ready.emit(onboarding_file)\n\n    def _get_status(self, filename):\n        \"\"\"Perform a request to get kite status for a file.\"\"\"\n        verb, url = KITE_ENDPOINTS.STATUS_ENDPOINT\n        if filename:\n            url_params = {'filename': filename}\n        else:\n            url_params = {'filetype': 'python'}\n        success, response = self.perform_http_request(\n            verb, url, url_params=url_params)\n        return success, response\n\n    def get_status(self, filename):\n        \"\"\"Get kite status for a given filename.\"\"\"\n        success_status, kite_status = self._get_status(filename)\n        if not filename or kite_status is None:\n            kite_status = status()\n            self.sig_status_response_ready[str].emit(kite_status)\n        elif isinstance(kite_status, TEXT_TYPES):\n            if not success_status:\n                status_str = status(extra_status=' with errors')\n                long_str = _(\"<code>{error}</code><br><br>\"\n                             \"Note: If you are using a VPN, \"\n                             \"please don't route requests to \"\n                             \"localhost/127.0.0.1 with it\").format(\n                                 error=kite_status)\n            else:\n                status_str = status()\n                long_str = kite_status\n            kite_status_dict = {\n                'status': status_str,\n                'short': status_str,\n                'long': long_str}\n            self.sig_status_response_ready[dict].emit(kite_status_dict)\n        else:\n            self.sig_status_response_ready[dict].emit(kite_status)\n\n    def perform_http_request(self, verb, url, url_params=None, params=None):\n        response = None\n        http_method = getattr(self.endpoint, verb)\n        try:\n            http_response = http_method(url, params=url_params, json=params)\n        except Exception as error:\n            return False, None\n        success = http_response.status_code == 200\n        if success:\n            try:\n                response = http_response.json()\n            except Exception:\n                response = http_response.text\n                response = None if response == '' else response\n        return success, response\n\n    def send(self, method, params, url_params):\n        response = None\n        if self.endpoint is not None and method in KITE_REQUEST_MAPPING:\n            http_verb, path = KITE_REQUEST_MAPPING[method]\n            encoded_url_params = {\n                key: quote(value) if isinstance(value, TEXT_TYPES) else value\n                for (key, value) in url_params.items()}\n            path = path.format(**encoded_url_params)\n            try:\n                success, response = self.perform_http_request(\n                    http_verb, path, params=params)\n            except (ConnectionRefusedError, ConnectionError):\n                return response\n        return response\n\n    def perform_request(self, req_id, method, params):\n        response = None\n        if method in self.sender_registry:\n            logger.debug('Perform {0} request with id {1}'.format(\n                method, req_id))\n            handler_name = self.sender_registry[method]\n            handler = getattr(self, handler_name)\n            response = handler(params)\n            if method in self.handler_registry:\n                converter_name = self.handler_registry[method]\n                converter = getattr(self, converter_name)\n                if response is not None:\n                    response = converter(response)\n        self.sig_response_ready.emit(req_id, response or {})\n", "path": "spyder/plugins/completion/kite/client.py"}]}