Repository: spyder-ide/spyder

Issue:
Kite support migration issues
- [x] Enabling/disabling action not affecting the status bar (if you had already Kite installed seems like)

After unchecking the enable kite config (and after restarting Spyder) I still see the Kite logo and base text in the status bar:
![image](https://user-images.githubusercontent.com/16781833/110163442-4f3db800-7df0-11eb-9f31-160dc9186ed7.png)

Enabling/disabling Kite:

![kite](https://user-images.githubusercontent.com/16781833/110163694-aba0d780-7df0-11eb-8548-06c105bd7858.gif)

_Originally posted by @dalthviz in https://github.com/spyder-ide/spyder/issues/14314#issuecomment-791629790_

- [x] Seems like the status bar is always showing the `Kite: Initializing message` and checking the copilot Kite says that was unable to detect Spyder installed (if you had already Kite installed seems like):
![image](https://user-images.githubusercontent.com/16781833/110292382-65fd2e00-7fed-11eb-858c-8594f507c11e.png)

Also, probably the screenshot available in the Kite help page should be updated to add the new preferences layout in Spyder 5

- [x] After installation (uninstalling Kite and resetting Spyder preferences first) I didn't see the on bording message appearing
- [x] I was unable to trigger the call-to-action after checking the option in the preferences (I had to restart Spyder first)
- [x] Clicking the `Learn more` button in the call-to-action ends up throwing an exception:
```
Traceback (most recent call last):
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\completion\providers\kite\widgets\calltoaction.py", line 135, in _learn_more
    kite = self.parent().completions.get_client('kite')
AttributeError: 'CompletionPlugin' object has no attribute 'get_client'
```

Just in case, I did all of this testing on Windows and to trigger the call-to-action I used this code:

```python
import matplotlib.pyplot as plt
fig = plt.figure()
fig.add
```


Discussion:

Resolving patch:
diff --git a/spyder/plugins/completion/providers/kite/provider.py b/spyder/plugins/completion/providers/kite/provider.py
--- a/spyder/plugins/completion/providers/kite/provider.py
+++ b/spyder/plugins/completion/providers/kite/provider.py
@@ -65,10 +65,6 @@ def __init__(self, parent, config):
             functools.partial(self.sig_response_ready.emit,
                               self.COMPLETION_PROVIDER_NAME))
 
-        self.client.sig_response_ready.connect(self._kite_onboarding)
-        self.client.sig_status_response_ready.connect(self._kite_onboarding)
-        self.client.sig_onboarding_response_ready.connect(
-            self._show_onboarding_file)
         self.client.sig_client_wrong_response.connect(
             self._wrong_response_error)
 
@@ -136,6 +132,10 @@ def shutdown(self):
     def on_mainwindow_visible(self):
         self.sig_call_statusbar.emit(
             KiteStatusWidget.ID, 'mainwindow_setup_finished', tuple(), {})
+        self.client.sig_response_ready.connect(self._kite_onboarding)
+        self.client.sig_status_response_ready.connect(self._kite_onboarding)
+        self.client.sig_onboarding_response_ready.connect(
+            self._show_onboarding_file)
 
     @Slot(list)
     def http_client_ready(self, languages):
@@ -155,6 +155,12 @@ def file_opened_closed_or_updated(self, filename, _language):
         """Request status for the given file."""
         self.client.sig_perform_status_request.emit(filename)
 
+    @on_conf_change(
+        section='completions', option=('enabled_providers', 'kite'))
+    def on_kite_enable_changed(self, value):
+        self.sig_call_statusbar.emit(
+            KiteStatusWidget.ID, 'set_value', (None,), {})
+
     @on_conf_change(section='completions', option='enable_code_snippets')
     def on_code_snippets_changed(self, value):
         if running_under_pytest():
@@ -195,8 +201,8 @@ def _show_onboarding_file(self, onboarding_file):
             # retry
             self._show_onboarding = True
             return
-        self.set_conf('show_onboarding', False)
         self.sig_open_file.emit(onboarding_file)
+        self.set_conf('show_onboarding', False)
 
     @Slot(str, object)
     def _wrong_response_error(self, method, resp):
diff --git a/spyder/plugins/completion/providers/kite/widgets/calltoaction.py b/spyder/plugins/completion/providers/kite/widgets/calltoaction.py
--- a/spyder/plugins/completion/providers/kite/widgets/calltoaction.py
+++ b/spyder/plugins/completion/providers/kite/widgets/calltoaction.py
@@ -8,8 +8,8 @@
 from qtpy.QtWidgets import (QLabel, QVBoxLayout, QFrame,
                             QHBoxLayout, QPushButton)
 
+from spyder.api.config.mixins import SpyderConfigurationAccessor
 from spyder.config.base import _
-from spyder.config.manager import CONF
 from spyder.plugins.completion.providers.kite.bloomfilter import (
     KiteBloomFilter)
 from spyder.plugins.completion.providers.kite.parsing import (
@@ -21,13 +21,16 @@
 from spyder.utils.icon_manager import is_dark_interface
 from spyder.utils.palette import QStylePalette
 
+
 COVERAGE_MESSAGE = (
     _("No completions found."
       " Get completions for this case and more by installing Kite.")
 )
 
 
-class KiteCallToAction(QFrame):
+class KiteCallToAction(QFrame, SpyderConfigurationAccessor):
+    CONF_SECTION = 'completions'
+
     def __init__(self, textedit, ancestor):
         super(KiteCallToAction, self).__init__(ancestor)
         self.textedit = textedit
@@ -57,13 +60,10 @@ def __init__(self, textedit, ancestor):
         actions.setLayout(actions_layout)
 
         self._install_button = QPushButton(_("Install Kite"))
-        self._learn_button = QPushButton(_("Learn More"))
         self._dismiss_button = QPushButton(_("Dismiss Forever"))
         self._install_button.clicked.connect(self._install_kite)
-        self._learn_button.clicked.connect(self._learn_more)
         self._dismiss_button.clicked.connect(self._dismiss_forever)
         actions_layout.addWidget(self._install_button)
-        actions_layout.addWidget(self._learn_button)
         actions_layout.addWidget(self._dismiss_button)
 
         # main layout: message + horizontally aligned links
@@ -76,7 +76,7 @@ def __init__(self, textedit, ancestor):
         main_layout.addWidget(actions)
         main_layout.addStretch()
 
-        self._enabled = CONF.get('completions', 'kite_call_to_action')
+        self._enabled = self.get_conf('kite_call_to_action')
         self._escaped = False
         self.hide()
 
@@ -94,7 +94,7 @@ def handle_mouse_press(self, event):
         self.hide()
 
     def handle_processed_completions(self, completions):
-        if not self._enabled:
+        if not self.get_conf('kite_call_to_action'):
             return
         if self._escaped:
             return
@@ -130,18 +130,10 @@ def _is_valid_ident_key(self, key):
     def _dismiss_forever(self):
         self.hide()
         self._enabled = False
-        CONF.set('completions', 'kite_call_to_action', False)
-
-    def _learn_more(self):
-        self.hide()
-        self._enabled = False
-        kite = self.parent().completions.get_client('kite')
-        kite.installer.welcome()
-        kite.installer.show()
+        self.set_conf('kite_call_to_action', False)
 
     def _install_kite(self):
         self.hide()
         self._enabled = False
-        kite = self.parent().completions.get_client('kite')
-        kite.installer.install()
-        kite.installer.show()
+        kite = self.parent().completions.get_provider('kite')
+        kite.show_kite_installation()


Test patch: