class KiteCompletionPlugin(SpyderCompletionPlugin): COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] self.client = KiteClient(None) self.kite_process = None self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_NAME)) @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) def send_request(self, language, req_type, req, req_id): if language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) def start_client(self, language): return language in self.available_languages def start(self): installed, path = self._check_if_kite_installed() if installed: logger.debug('Kite was found on the system: {0}'.format(path)) running = self._check_if_kite_running() if not running: logger.debug('Starting Kite service...') self.kite_process = run_program(path) self.client.start() def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def _check_if_kite_installed(self): path = '' if os.name == 'nt': path = 'C:\\Program Files\\Kite\\kited.exe' elif sys.platform.startswith('linux'): path = osp.expanduser('~/.local/share/kite/kited') elif sys.platform == 'darwin': path = '/opt/kite/kited' return osp.exists(osp.realpath(path)), path def _check_if_kite_running(self): running = False for proc in psutil.process_iter(attrs=['pid', 'name', 'username']): if 'kited' in proc.name(): logger.debug('Kite process already ' 'running with PID {0}'.format(proc.pid)) running = True break return running
class KiteCompletionPlugin(SpyderCompletionPlugin): COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] enable_code_snippets = CONF.get('lsp-server', 'code_snippets') self.client = KiteClient(None, enable_code_snippets) self.kite_process = None self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_NAME)) @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) def send_request(self, language, req_type, req, req_id): if language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) def start_client(self, language): return language in self.available_languages def start(self): installed, path = check_if_kite_installed() if installed: logger.debug('Kite was found on the system: {0}'.format(path)) running = check_if_kite_running() if not running: logger.debug('Starting Kite service...') self.kite_process = run_program(path) self.client.start() def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def update_configuration(self): enable_code_snippets = CONF.get('lsp-server', 'code_snippets') self.client.enable_code_snippets = enable_code_snippets
class KiteCompletionPlugin(SpyderCompletionPlugin): COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] self.client = KiteClient(None) self.kite_process = None self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_NAME)) @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) def send_request(self, language, req_type, req, req_id): if language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) def start_client(self, language): return language in self.available_languages def start(self): installed, path = self._check_if_kite_installed() if installed: logger.debug('Kite was found on the system: {0}'.format(path)) running = self._check_if_kite_running() if not running: logger.debug('Starting Kite service...') self.kite_process = run_program(path) self.client.start() def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def _check_if_kite_installed(self): path = '' if os.name == 'nt': path = 'C:\\Program Files\\Kite\\kited.exe' elif sys.platform.startswith('linux'): path = osp.expanduser('~/.local/share/kite/kited') elif sys.platform == 'darwin': path = self._locate_kite_darwin() return osp.exists(osp.realpath(path)), path def _check_if_kite_running(self): running = False for proc in psutil.process_iter(attrs=['pid', 'name', 'username']): if self._is_proc_kite(proc): logger.debug('Kite process already ' 'running with PID {0}'.format(proc.pid)) running = True break return running @staticmethod def _locate_kite_darwin(): """ Looks up where Kite.app is installed on macOS systems. The bundle ID is checked first and if nothing is found or an error occurs, the default path is used. """ default_path = '/Applications/Kite.app' path = None try: out = subprocess.check_output( ['mdfind', 'kMDItemCFBundleIdentifier="com.kite.Kite"']) installed = len(out) > 0 path = (out.decode('utf-8', 'replace').strip().split('\n')[0] if installed else default_path) except (subprocess.CalledProcessError, UnicodeDecodeError) as ex: # Use the default path path = default_path finally: return path @staticmethod def _is_proc_kite(proc): if os.name == 'nt' or sys.platform.startswith('linux'): return 'kited' in proc.name() else: return proc.name() == 'Kite'
class KiteCompletionPlugin(SpyderCompletionPlugin): CONF_SECTION = 'kite' CONF_FILE = False COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] self.client = KiteClient(None) self.kite_process = None # Installation dialog self.installation_thread = KiteInstallationThread(self) self.installer = KiteInstallerDialog(parent, self.installation_thread) # Status widget statusbar = parent.statusBar() # MainWindow status bar self.open_file_updated = False self.status_widget = KiteStatusWidget(None, statusbar, self) # Signals self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_status_response_ready[str].connect(self.set_status) self.client.sig_status_response_ready[dict].connect(self.set_status) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_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) self.installation_thread.sig_installation_status.connect( self.set_status) self.status_widget.sig_clicked.connect(self.show_installation_dialog) # self.main.sig_setup_finished.connect(self.mainwindow_setup_finished) # Config self.update_configuration() @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) self._kite_onboarding() @Slot() def mainwindow_setup_finished(self): """ This is called after the main window setup finishes to show Kite's installation dialog and onboarding if necessary. """ self._kite_onboarding() show_dialog = self.get_option('show_installation_dialog') if show_dialog: # Only show the dialog once at startup self.set_option('show_installation_dialog', False) self.show_installation_dialog() @Slot(str) @Slot(dict) def set_status(self, status): """Show Kite status for the current file.""" self.status_widget.set_value(status) @Slot() def show_installation_dialog(self): """Show installation dialog.""" installed, path = check_if_kite_installed() if not installed and not running_under_pytest(): self.installer.show() def send_request(self, language, req_type, req, req_id): if self.enabled and language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) else: self.sig_response_ready.emit(self.COMPLETION_CLIENT_NAME, req_id, {}) def send_status_request(self, filename): """Request status for the given file.""" if not self.is_installing(): self.client.sig_perform_status_request.emit(filename) def start_client(self, language): return language in self.available_languages def start(self): try: if not self.enabled: return installed, path = check_if_kite_installed() if not installed: return logger.debug('Kite was found on the system: {0}'.format(path)) running = check_if_kite_running() if running: return logger.debug('Starting Kite service...') self.kite_process = run_program(path) except OSError: installed, path = check_if_kite_installed() logger.debug( 'Error starting Kite service at {path}...'.format(path=path)) if self.get_option('show_installation_error_message'): box = MessageCheckBox(icon=QMessageBox.Critical, parent=self.main) box.setWindowTitle(_("Kite installation error")) box.set_checkbox_text(_("Don't show again.")) box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) box.set_checked(False) box.set_check_visible(True) box.setText( _("It seems that your Kite installation is faulty. " "If you want to use Kite, please remove the " "directory that appears bellow, " "and try a reinstallation:<br><br>" "<code>{kite_dir}</code>").format( kite_dir=osp.dirname(path))) box.exec_() # Update checkbox based on user interaction self.set_option('show_installation_error_message', not box.is_checked()) finally: # Always start client to support possibly undetected Kite builds self.client.start() def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def update_configuration(self): self.client.enable_code_snippets = CONF.get('lsp-server', 'code_snippets') self.enabled = self.get_option('enable') self._show_onboarding = self.get_option('show_onboarding') def is_installing(self): """Check if an installation is taking place.""" return (self.installation_thread.isRunning() and not self.installation_thread.cancelled) def installation_cancelled_or_errored(self): """Check if an installation was cancelled or failed.""" return self.installation_thread.cancelled_or_errored() def _kite_onboarding(self): """Request the onboarding file.""" # No need to check installed status, # since the get_onboarding_file call fails fast. if not self.enabled: return if not self._show_onboarding: return if self.main.is_setting_up: return if not self.available_languages: return # Don't send another request until this request fails. self._show_onboarding = False self.client.sig_perform_onboarding_request.emit() @Slot(str) def _show_onboarding_file(self, onboarding_file): """ Opens the onboarding file, which is retrieved from the Kite HTTP endpoint. This skips onboarding if onboarding is not possible yet or has already been displayed before. """ if not onboarding_file: # retry self._show_onboarding = True return self.set_option('show_onboarding', False) self.main.open_file(onboarding_file) @Slot(str, object) def _wrong_response_error(self, method, resp): QMessageBox.critical( self.main, _('Kite error'), _("The Kite completion engine returned an unexpected result " "for the request <tt>{0}</tt>: <br><br><tt>{1}</tt><br><br>" "Please make sure that your Kite installation is correct. " "In the meantime, Spyder will disable the Kite client to " "prevent further errors. For more information, please " "visit the <a href='https://help.kite.com/'>Kite help " "center</a>").format(method, resp)) self.set_option('enable', False)
class KiteCompletionPlugin(SpyderCompletionPlugin): CONF_SECTION = 'kite' CONF_FILE = False COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] self.client = KiteClient(None) self.kite_process = None # Installation dialog self.installation_thread = KiteInstallationThread(self) self.installer = KiteInstallerDialog(parent, self.installation_thread) # Status widget statusbar = parent.statusBar() # MainWindow status bar self.open_file_updated = False self.status_widget = KiteStatusWidget(None, statusbar, self) # Signals self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_status_response_ready[str].connect(self.set_status) self.client.sig_status_response_ready[dict].connect(self.set_status) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_NAME)) self.installation_thread.sig_installation_status.connect( self.set_status) self.status_widget.sig_clicked.connect(self.show_installation_dialog) self.main.sig_setup_finished.connect(self.mainwindow_setup_finished) # Config self.update_configuration() @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) @Slot() def mainwindow_setup_finished(self): """ This is called after the main window setup finishes to show Kite's installation dialog and onboarding if necessary. """ show_dialog = self.get_option('show_installation_dialog') if show_dialog: # Only show the dialog once at startup self.set_option('show_installation_dialog', False) self.show_installation_dialog() @Slot(str) @Slot(dict) def set_status(self, status): """Show Kite status for the current file.""" self.status_widget.set_value(status) @Slot() def show_installation_dialog(self): """Show installation dialog.""" installed, path = check_if_kite_installed() if not installed and not running_under_pytest(): self.installer.show() def send_request(self, language, req_type, req, req_id): if self.enabled and language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) else: self.sig_response_ready.emit(self.COMPLETION_CLIENT_NAME, req_id, {}) def send_status_request(self, filename): """Request status for the given file.""" if not self.is_installing(): self.client.sig_perform_status_request.emit(filename) def start_client(self, language): return language in self.available_languages def start(self): # Always start client to support possibly undetected Kite builds self.client.start() if not self.enabled: return installed, path = check_if_kite_installed() if not installed: return logger.debug('Kite was found on the system: {0}'.format(path)) running = check_if_kite_running() if running: return logger.debug('Starting Kite service...') self.kite_process = run_program(path) def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def update_configuration(self): self.client.enable_code_snippets = CONF.get('lsp-server', 'code_snippets') self.enabled = self.get_option('enable') def is_installing(self): """Check if an installation is taking place.""" return (self.installation_thread.isRunning() and not self.installation_thread.cancelled) def installation_cancelled_or_errored(self): """Check if an installation was cancelled or failed.""" return self.installation_thread.cancelled_or_errored()
class KiteCompletionPlugin(SpyderCompletionPlugin): CONF_SECTION = 'kite' CONF_FILE = False COMPLETION_CLIENT_NAME = 'kite' def __init__(self, parent): SpyderCompletionPlugin.__init__(self, parent) self.available_languages = [] self.client = KiteClient(None) self.kite_process = None self.kite_installation_thread = KiteInstallationThread(self) # TODO: Connect thread status to status bar self.kite_installer = KiteInstallerDialog( parent, self.kite_installation_thread) self.client.sig_client_started.connect(self.http_client_ready) self.client.sig_response_ready.connect( functools.partial(self.sig_response_ready.emit, self.COMPLETION_CLIENT_NAME)) self.kite_installation_thread.sig_installation_status.connect( lambda status: self.client.start() if status == FINISHED else None) self.main.sig_setup_finished.connect(self.mainwindow_setup_finished) self.update_configuration() @Slot(list) def http_client_ready(self, languages): logger.debug('Kite client is available for {0}'.format(languages)) self.available_languages = languages self.sig_plugin_ready.emit(self.COMPLETION_CLIENT_NAME) @Slot() def mainwindow_setup_finished(self): """ Called when the setup of the main window finished to let us do onboarding if necessary """ self._show_installation_dialog() def _show_installation_dialog(self): """Show installation dialog.""" kite_installation_enabled = self.get_option('show_installation_dialog') installed, path = check_if_kite_installed() if (not installed and kite_installation_enabled and not running_under_pytest()): self.kite_installer.show() self.kite_installer.center() def send_request(self, language, req_type, req, req_id): if self.enabled and language in self.available_languages: self.client.sig_perform_request.emit(req_id, req_type, req) else: self.sig_response_ready.emit(self.COMPLETION_CLIENT_NAME, req_id, {}) def start_client(self, language): return language in self.available_languages def start(self): # Always start client to support possibly undetected Kite builds self.client.start() if not self.enabled: return installed, path = check_if_kite_installed() if not installed: return logger.debug('Kite was found on the system: {0}'.format(path)) running = check_if_kite_running() if running: return logger.debug('Starting Kite service...') self.kite_process = run_program(path) def shutdown(self): self.client.stop() if self.kite_process is not None: self.kite_process.kill() def update_configuration(self): self.client.enable_code_snippets = CONF.get('lsp-server', 'code_snippets') self.enabled = self.get_option('enable') def is_installing(self): """Check if an installation is taking place.""" return self.kite_installation_thread.isRunning()