def reset_namespace(self, warning=False, message=False): """Reset the namespace by removing all names defined by the user.""" # Don't show the warning when running our tests. if running_under_pytest(): warning = False if warning: reset_str = _("Remove all variables") warn_str = _("All user-defined variables will be removed. " "Are you sure you want to proceed?") box = MessageCheckBox(icon=QMessageBox.Warning, parent=self) box.setWindowTitle(reset_str) box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) box.setDefaultButton(QMessageBox.Yes) box.set_checkbox_text(_("Don't show again.")) box.set_checked(False) box.set_check_visible(True) box.setText(warn_str) box.buttonClicked.connect( lambda button: self.handle_reset_message_answer( box, button, message)) box.show() else: self._perform_reset(message)
def _create_project(self, root_path, project_type=EmptyProject.ID, packages=None): """Create a new project.""" project_types = self.get_project_types() if project_type in project_types: project_type_class = project_types[project_type] project = project_type_class(root_path, project_type_class._PARENT_PLUGIN) created_succesfully, message = project.create_project() if not created_succesfully: QMessageBox.warning(self, "Project creation", message) shutil.rmtree(root_path, ignore_errors=True) return # TODO: In a subsequent PR return a value and emit based on that self.sig_project_created.emit(root_path, project_type, packages) self.open_project(path=root_path, project=project) else: if not running_under_pytest(): QMessageBox.critical( self, _('Error'), _("<b>{}</b> is not a registered Spyder project " "type!").format(project_type))
def start_client(self, language): """Start an LSP client for a given language.""" # To keep track if the client was started. started = False if language in self.clients: language_client = self.clients[language] queue = self.register_queue[language] # Don't start LSP services when testing unless we demand # them. if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): return started started = language_client['status'] == self.RUNNING # Start client heartbeat timer = QTimer(self) self.clients_hearbeat[language] = timer timer.setInterval(self.TIME_HEARTBEAT) timer.timeout.connect(lambda: self.check_heartbeat(language)) timer.start() if language_client['status'] == self.STOPPED: config = language_client['config'] # If we're trying to connect to an external server, # verify that it's listening before creating a # client for it. if config['external']: host = config['host'] port = config['port'] response = check_connection_port(host, port) if not response: if self.show_no_external_server_warning: self.report_no_external_server( host, port, language) self.set_status(language, _("down")) return False language_client['instance'] = LSPClient( parent=self, server_settings=config, folder=self.get_root_path(language), language=language) self.register_client_instance(language_client['instance']) # Register that a client was started. logger.info("Starting LSP client for {}...".format(language)) language_client['instance'].start() language_client['status'] = self.RUNNING started = True for entry in queue: language_client['instance'].register_file(*entry) self.register_queue[language] = [] return started
def start_client(self, language): """Start an LSP client for a given language.""" started = False if language in self.clients: language_client = self.clients[language] queue = self.register_queue[language] # Don't start LSP services when testing unless we demand # them. if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): return started # Start client started = language_client['status'] == self.RUNNING if language_client['status'] == self.STOPPED: config = language_client['config'] language_client['instance'] = LSPClient( parent=self, server_settings=config, folder=self.get_root_path(language), language=language) self.register_client_instance(language_client['instance']) logger.info("Starting LSP client for {}...".format(language)) language_client['instance'].start() language_client['status'] = self.RUNNING for entry in queue: language_client.register_file(*entry) self.register_queue[language] = [] return started
def get_user_credentials(self): """Get user credentials with the login dialog.""" token = None remember_token = self._get_credentials_from_settings() valid_py_os = not (PY2 and sys.platform.startswith('linux')) if remember_token and valid_py_os: # Get token from keyring try: token = keyring.get_password('github', 'token') except Exception: # No safe keyring backend if self._show_msgbox: QMessageBox.warning( self.parent_widget, _('Failed to retrieve token'), _('It was not possible to retrieve ' 'your token. Please introduce it ' 'again.')) if not running_under_pytest(): credentials = DlgGitHubLogin.login(self.parent_widget, token, remember_token) if credentials['token'] and valid_py_os: self._store_token(credentials['token'], credentials['remember_token']) CONF.set('main', 'report_error/remember_token', credentials['remember_token']) else: return dict(token=token, remember_token=remember_token) return credentials
def __init__(self, block, text=None, fold_level=None, def_type=None, def_name=None, color=None): """ Args: text (str) fold_level (int) def_type (int): [CLASS, FUNCTION, STATEMENT, COMMENT, CELL] def_name (str) color (PyQt.QtGui.QTextCharFormat) """ super(OutlineExplorerData, self).__init__() self.text = text self.fold_level = fold_level self.def_type = def_type self.def_name = def_name self.color = color if running_under_pytest(): # block might be a dummy self.block = block else: # Copy the text block to make sure it is not deleted self.block = QTextBlock(block)
def on_code_snippets_changed(self, value): if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): return self.client.enable_code_snippets = self.get_conf( 'enable_code_snippets', section='completions')
def is_spyder_process(pid): """ Test whether given PID belongs to a Spyder process. This is checked by testing the first three command line arguments. This function returns a bool. If there is no process with this PID or its command line cannot be accessed (perhaps because the process is owned by another user), then the function returns False. """ try: p = psutil.Process(int(pid)) # Valid names for main script names = set([ 'spyder', 'spyder3', 'spyder.exe', 'spyder3.exe', 'bootstrap.py', 'spyder-script.py', 'Spyder.launch.pyw' ]) if running_under_pytest(): names.add('runtests.py') # Check the first three command line arguments arguments = set(os.path.basename(arg) for arg in p.cmdline()[:3]) conditions = [names & arguments] return any(conditions) except (psutil.NoSuchProcess, psutil.AccessDenied): return False
def register(self): """Start all available completion providers.""" preferences = self.get_plugin(Plugins.Preferences) preferences.register_plugin_preferences(self) container = self.get_container() statusbar = self.get_plugin(Plugins.StatusBar) if statusbar: for sb in container.all_statusbar_widgets(): statusbar.add_status_widget(sb) if self.main: self.main.sig_pythonpath_changed.connect( self.sig_pythonpath_changed) # Do not start providers on tests unless necessary if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): # Prevent providers from receiving configuration updates for provider_name in self.providers: provider_info = self.providers[provider_name] CONF.unobserve_configuration(provider_info['instance']) return self.start_all_providers()
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 get_user_credentials(self): """Get user credentials with the login dialog.""" password = None token = None (username, remember_me, remember_token) = self._get_credentials_from_settings() valid_py_os = not (PY2 and sys.platform.startswith('linux')) if username and remember_me and valid_py_os: # Get password from keyring try: password = keyring.get_password('github', username) except Exception: # No safe keyring backend if self._show_msgbox: QMessageBox.warning(self.parent_widget, _('Failed to retrieve password'), _('It was not possible to retrieve ' 'your password. Please introduce ' 'it again.')) if remember_token and valid_py_os: # Get token from keyring try: token = keyring.get_password('github', 'token') except Exception: # No safe keyring backend if self._show_msgbox: QMessageBox.warning(self.parent_widget, _('Failed to retrieve token'), _('It was not possible to retrieve ' 'your token. Please introduce it ' 'again.')) if not running_under_pytest(): credentials = DlgGitHubLogin.login(self.parent_widget, username, password, token, remember_me, remember_token) if (credentials['username'] and credentials['password'] and valid_py_os): self._store_credentials(credentials['username'], credentials['password'], credentials['remember']) CONF.set('main', 'report_error/remember_me', credentials['remember']) if credentials['token'] and valid_py_os: self._store_token(credentials['token'], credentials['remember_token']) CONF.set('main', 'report_error/remember_token', credentials['remember_token']) else: return dict(username=username, password=password, token='', remember=remember_me, remember_token=remember_token) return credentials
def restart_kernel(self): """ Restart the associated kernel. Took this code from the qtconsole project Licensed under the BSD license """ sw = self.shellwidget if not running_under_pytest() and self.ask_before_restart: message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) else: result = None if (result == QMessageBox.Yes or running_under_pytest() or not self.ask_before_restart): if sw.kernel_manager: if self.infowidget.isVisible(): self.infowidget.hide() sw.show() try: # Close comm sw.spyder_kernel_comm.close() sw.kernel_manager.restart_kernel(stderr=self.stderr_handle) # Reopen comm sw.spyder_kernel_comm.open_comm(sw.kernel_client) except RuntimeError as e: sw._append_plain_text(_('Error restarting kernel: %s\n') % e, before_prompt=True) else: # For spyder-ide/spyder#6235, IPython was changing the # setting of %colors on windows by assuming it was using a # dark background. This corrects it based on the scheme. self.set_color_scheme(sw.syntax_style) sw._append_html(_("<br>Restarting kernel...\n<hr><br>"), before_prompt=False) else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True)
def restart_kernel(self): """ Restart the associated kernel. Took this code from the qtconsole project Licensed under the BSD license """ sw = self.shellwidget if not running_under_pytest() and self.ask_before_restart: message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) else: result = None if (result == QMessageBox.Yes or running_under_pytest() or not self.ask_before_restart): if sw.kernel_manager: if self.infowidget.isVisible(): self.infowidget.hide() sw.show() try: sw.kernel_manager.restart_kernel( stderr=self.stderr_handle) except RuntimeError as e: sw._append_plain_text( _('Error restarting kernel: %s\n') % e, before_prompt=True ) else: # For issue 6235. IPython was changing the setting of # %colors on windows by assuming it was using a dark # background. This corrects it based on the scheme. self.set_color_scheme(sw.syntax_style) sw._append_html(_("<br>Restarting kernel...\n<hr><br>"), before_prompt=False) else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True )
def shutdown(self): """Shutdown kernel""" if self.get_kernel() is not None and not self.slave: now = True # This avoids some flakyness with our Cython tests if running_under_pytest(): now = False self.shellwidget.kernel_manager.shutdown_kernel(now=now) if self.shellwidget.kernel_client is not None: background(self.shellwidget.kernel_client.stop_channels)
def update_snippets(self, snippets): if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): return self.config = snippets snippet_info = {} for language in SUPPORTED_LANGUAGES_PY: snippet_info[language] = snippets.get(language, {}) self.snippets_actor.sig_update_snippets.emit(snippet_info)
def start_server(self): """Start server.""" # This is not necessary if we're trying to connect to an # external server if self.external_server or self.stdio: return logger.info('Starting server: {0}'.format(' '.join(self.server_args))) # Create server process self.server = QProcess(self) env = self.server.processEnvironment() # Use local PyLS instead of site-packages one. if DEV or running_under_pytest(): running_in_ci = bool(os.environ.get('CI')) if os.name != 'nt' or os.name == 'nt' and not running_in_ci: env.insert('PYTHONPATH', os.pathsep.join(sys.path)[:]) # Adjustments for the Python language server. if self.language == 'python': # Set the PyLS current working to an empty dir inside # our config one. This avoids the server to pick up user # files such as random.py or string.py instead of the # standard library modules named the same. cwd = osp.join(get_conf_path(), 'lsp_paths', 'cwd') if not osp.exists(cwd): os.makedirs(cwd) # On Windows, some modules (notably Matplotlib) # cause exceptions if they cannot get the user home. # So, we need to pass the USERPROFILE env variable to # the PyLS. if os.name == "nt" and "USERPROFILE" in os.environ: env.insert("USERPROFILE", os.environ["USERPROFILE"]) else: # There's no need to define a cwd for other servers. cwd = None # Most LSP servers spawn other processes, which may require # some environment variables. for var in os.environ: env.insert(var, os.environ[var]) logger.info('Server process env variables: {0}'.format(env.keys())) # Setup server self.server.setProcessEnvironment(env) self.server.errorOccurred.connect(self.handle_process_errors) self.server.setWorkingDirectory(cwd) self.server.setProcessChannelMode(QProcess.MergedChannels) if self.server_log_file is not None: self.server.setStandardOutputFile(self.server_log_file) # Start server self.server.start(self.server_args[0], self.server_args[1:])
def start_transport(self): """Start transport layer.""" logger.info('Starting transport for {1}: {0}'.format( ' '.join(self.transport_args), self.language)) # Create transport process self.transport = QProcess(self) env = self.transport.processEnvironment() # Most LSP servers spawn other processes other than Python, which may # require some environment variables if self.language != 'python' and self.stdio: for var in os.environ: env.insert(var, os.environ[var]) logger.info('Transport process env variables: {0}'.format( env.keys())) self.transport.setProcessEnvironment(env) # Modifying PYTHONPATH to run transport in development mode or # tests if (DEV or running_under_pytest()) and not running_in_ci(): sys_path = self._clean_sys_path() if running_under_pytest(): env.insert('PYTHONPATH', os.pathsep.join(sys_path)[:]) else: env.insert('PYTHONPATH', os.pathsep.join(sys_path)[1:]) self.transport.setProcessEnvironment(env) # Set up transport self.transport.errorOccurred.connect(self.handle_process_errors) if self.stdio: self.transport.setProcessChannelMode(QProcess.SeparateChannels) if self.transport_log_file is not None: self.transport.setStandardErrorFile(self.transport_log_file) else: self.transport.setProcessChannelMode(QProcess.MergedChannels) if self.transport_log_file is not None: self.transport.setStandardOutputFile(self.transport_log_file) # Start transport self.transport.start(self.transport_args[0], self.transport_args[1:])
def start_transport(self): """Start transport layer.""" self.transport_args = list(map(str, self.transport_args)) logger.info('Starting transport: {0}'.format(' '.join( self.transport_args))) self.transport = QProcess(self) self.transport.errorOccurred.connect(self.handle_process_errors) # Modifying PYTHONPATH to run transport in development mode or # tests if DEV or running_under_pytest(): env = QProcessEnvironment() if running_under_pytest(): env.insert('PYTHONPATH', os.pathsep.join(sys.path)[:]) else: env.insert('PYTHONPATH', os.pathsep.join(sys.path)[1:]) self.transport.setProcessEnvironment(env) # Set transport log file transport_log_file = None if get_debug_level() > 0: transport_log_fname = 'transport_{0}_{1}.log'.format( self.language, os.getpid()) transport_log_file = get_conf_path( osp.join('lsp_logs', transport_log_fname)) if not osp.exists(osp.dirname(transport_log_file)): os.makedirs(osp.dirname(transport_log_file)) # Set channel properties if self.stdio: self.transport_args += self.server_args self.transport.setProcessChannelMode(QProcess.SeparateChannels) if transport_log_file is not None: self.transport.setStandardErrorFile(transport_log_file) else: self.transport.setProcessChannelMode(QProcess.MergedChannels) if transport_log_file is not None: self.transport.setStandardOutputFile(transport_log_file) # Start transport self.transport.start(self.transport_args[0], self.transport_args[1:])
def on_mainwindow_visible(self): """Actions after the mainwindow in visible.""" # Show dialog with missing dependencies if not running_under_pytest(): # This avoids computing missing deps before the window is fully up timer_report_deps = QTimer(self) timer_report_deps.setInterval(2000) timer_report_deps.setSingleShot(True) timer_report_deps.timeout.connect( self.get_container().report_missing_dependencies) timer_report_deps.start()
def create_splash_screen(): """Create splash screen.""" if not running_under_pytest(): splash = QSplashScreen(QPixmap(get_image_path('splash'))) splash_font = splash.font() splash_font.setPixelSize(14) splash.setFont(splash_font) else: splash = None return splash
def shutdown(self): """Shutdown kernel""" if self.get_kernel() is not None and not self.slave: now = True # This avoids some flakyness with our Cython tests if running_under_pytest(): now = False self.shellwidget.spyder_kernel_comm.close() self.shellwidget.kernel_manager.shutdown_kernel(now=now) self.shellwidget.pdb_history_file.save_thread.stop() if self.shellwidget.kernel_client is not None: self.shellwidget.kernel_client.stop_channels()
def on_mainwindow_visible(self): """Actions after the mainwindow in visible.""" container = self.get_container() # Show dialog with missing dependencies if not running_under_pytest(): container.compute_dependencies() # Check for updates if DEV is None and self.get_conf('check_updates_on_startup'): container.give_updates_feedback = False container.check_updates(startup=True)
def find_internal_plugins(): """ Find available plugins based on setup.py entry points. In DEV mode we parse the `setup.py` file directly. """ internal_plugins = {} # If DEV, look for entry points in setup.py file for internal plugins # and then look on the system for the rest if DEV is not None or running_under_pytest(): HERE = os.path.abspath(os.path.dirname(__file__)) base_path = os.path.dirname(os.path.dirname(HERE)) setup_path = os.path.join(base_path, "setup.py") if not os.path.isfile(setup_path): raise Exception( 'No "setup.py" file found and running in DEV mode!') with open(setup_path, "r") as fh: lines = fh.read().split("\n") start = None end = None for idx, line in enumerate(lines): if line.startswith("spyder_plugins_entry_points"): start = idx + 1 continue if start is not None: if line.startswith("]"): end = idx + 1 break internal_plugins = {} entry_points_list = "[" + "\n".join(lines[start:end]) spyder_plugin_entry_points = ast.literal_eval(entry_points_list) for entry_point in spyder_plugin_entry_points: try: name, module = entry_point.split(" = ") name = name.strip() module = module.strip() module, class_name = module.split(":") except Exception: logger.error( '"setup.py" entry point "{entry_point}" is malformed!' "".format(entry_point=entry_point)) try: mod = importlib.import_module(module) internal_plugins[name] = getattr(mod, class_name, None) except (ModuleNotFoundError, ImportError): pass return internal_plugins
def restart_kernel(self): """ Restart the associated kernel. Took this code from the qtconsole project Licensed under the BSD license """ sw = self.shellwidget if not running_under_pytest() and self.ask_before_restart: message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) else: result = None if (result == QMessageBox.Yes or running_under_pytest() or not self.ask_before_restart): if sw.kernel_manager: if self.infowidget.isVisible(): self.infowidget.hide() self._show_loading_page() # Close comm sw.spyder_kernel_comm.close() self.restart_thread = QThread() self.restart_thread.run = self._restart_thread_main self.restart_thread.error = None self.restart_thread.finished.connect( lambda: self._finalise_restart(True)) self.restart_thread.start() else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True ) self._hide_loading_page()
def show_tour_message(self, force=False): """ Show message about starting the tour the first time Spyder starts. Parameters ---------- force: bool Force the display of the tour message. """ should_show_tour = self.get_conf('show_tour_message') if force or (should_show_tour and not running_under_pytest() and not get_safe_mode()): self.set_conf('show_tour_message', False) self.get_container().show_tour_message()
def send(self, method, params, kind): """Send message to transport.""" if self.is_down(): return if ClientConstants.CANCEL in params: return _id = self.request_seq if kind == MessageKind.REQUEST: msg = { 'id': self.request_seq, 'method': method, 'params': params } self.req_status[self.request_seq] = method elif kind == MessageKind.RESPONSE: msg = { 'id': self.request_seq, 'result': params } elif kind == MessageKind.NOTIFICATION: msg = { 'method': method, 'params': params } logger.debug('Perform request {0} with id {1}'.format(method, _id)) # Save requests to check their ordering. if running_under_pytest(): self._requests.append((_id, method)) # Try sending a message. If the send queue is full, keep trying for a # a second before giving up. timeout = 1 start_time = time.time() timeout_time = start_time + timeout while True: try: self.zmq_out_socket.send_pyobj(msg, flags=zmq.NOBLOCK) self.request_seq += 1 return int(_id) except zmq.error.Again: if time.time() > timeout_time: self.sig_went_down.emit(self.language) return # The send queue is full! wait 0.1 seconds before retrying. if self.initialized: logger.warning("The send queue is full! Retrying...") time.sleep(.1)
def check_heartbeat(self, language): """ Check if client or server for a given language are down. """ # This avoids an odd error when running our tests. if running_under_pytest(): if not getattr(self, 'clients', None): return client = self.clients[language] status = client['status'] instance = client.get('instance', None) if instance is not None: if instance.is_down() or status != self.RUNNING: instance.sig_went_down.emit(language)
def on_initialize(self): if self.main: self.main.sig_pythonpath_changed.connect( self.sig_pythonpath_changed) # Do not start providers on tests unless necessary if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): # Prevent providers from receiving configuration updates for provider_name in self.providers: provider_info = self.providers[provider_name] CONF.unobserve_configuration(provider_info['instance']) return self.start_all_providers()
def run_vcs_tool(path, action): """If path is a valid VCS repository, run the corresponding VCS tool Supported VCS actions: 'commit', 'browse' Return False if the VCS tool is not installed""" info = get_vcs_info(get_vcs_root(path)) tools = info['actions'][action] for tool, args in tools: if programs.find_program(tool): if not running_under_pytest(): programs.run_program(tool, args, cwd=path) else: return True return else: cmdnames = [name for name, args in tools] raise ActionToolNotFound(info['name'], action, cmdnames)
def _submit_to_github(self): """Action to take when pressing the submit button.""" # Getting description and traceback title = self.title.text() description = self.input_description.toPlainText() traceback = self.error_traceback[:-1] # Remove last EOL # Render issue if traceback: issue_text = self.render_issue(description=description, traceback=traceback) else: issue_text = description try: if running_under_pytest(): org = 'ccordoba12' else: org = self._github_org repo = self._github_repo github_backend = GithubBackend(org, repo, parent_widget=self) github_report = github_backend.send_report(title, issue_text) if github_report: self.close() except Exception: ret = QMessageBox.question( self, _('Error'), _("An error occurred while trying to send the issue to " "Github automatically. Would you like to open it " "manually?<br><br>" "If so, please make sure to paste your clipboard " "into the issue report box that will appear in a new " "browser tab before clicking <i>Submit</i> on that " "page."), ) if ret in [QMessageBox.Yes, QMessageBox.Ok]: QApplication.clipboard().setText(issue_text) issue_body = ( " \n<!--- *** BEFORE SUBMITTING: PASTE CLIPBOARD HERE " "TO COMPLETE YOUR REPORT *** ---!>\n") self.open_web_report(body=issue_body, title=title)
def try_recover_from_autosave(self): """ Offer to recover files from autosave. Read pid files to get a list of files that can possibly be recovered, then ask the user what to do with these files, and finally remove the pid files. """ files_to_recover, pidfiles = self.get_files_to_recover() parent = self.editor if running_under_pytest() else self.editor.main dialog = RecoveryDialog(files_to_recover, parent=parent) dialog.exec_if_nonempty() self.recover_files_to_open = dialog.files_to_open[:] for pidfile in pidfiles: try: os.remove(pidfile) except (IOError, OSError): pass
def perform_request(self, req_id, method, params): response = None if method in self.sender_registry: logger.debug('Perform request {0} with id {1}'.format( method, req_id)) handler_name = self.sender_registry[method] handler = getattr(self, handler_name) response = handler(params) if method in self.handler_registry: converter_name = self.handler_registry[method] converter = getattr(self, converter_name) if response is not None: response = converter(response) if not isinstance(response, (dict, type(None))): if not running_under_pytest(): self.sig_client_wrong_response.emit(method, response) else: self.sig_response_ready.emit(req_id, response or {})
def start_client(self, language): """Start an LSP client for a given language.""" started = False if language in self.clients: language_client = self.clients[language] queue = self.register_queue[language] # Don't start LSP services when testing unless we demand # them. if running_under_pytest(): if not os.environ.get('SPY_TEST_USE_INTROSPECTION'): return started # Start client started = language_client['status'] == self.RUNNING if language_client['status'] == self.STOPPED: config = language_client['config'] if not config['external']: port = select_port(default_port=config['port']) config['port'] = port language_client['instance'] = LSPClient( parent=self, server_settings=config, folder=self.get_root_path(language), language=language ) # Connect signals emitted by the client to the methods that # can handle them if self.main and self.main.editor: language_client['instance'].sig_initialize.connect( self.main.editor.register_lsp_server_settings) logger.info("Starting LSP client for {}...".format(language)) language_client['instance'].start() language_client['status'] = self.RUNNING for entry in queue: language_client.register_file(*entry) self.register_queue[language] = [] return started
def env(self): """Env vars for kernels""" # Add our PYTHONPATH to the kernel pathlist = CONF.get('main', 'spyder_pythonpath', default=[]) default_interpreter = CONF.get('main_interpreter', 'default') pypath = add_pathlist_to_PYTHONPATH([], pathlist, ipyconsole=True, drop_env=False) # Environment variables that we need to pass to our sitecustomize umr_namelist = CONF.get('main_interpreter', 'umr/namelist') if PY2: original_list = umr_namelist[:] for umr_n in umr_namelist: try: umr_n.encode('utf-8') except UnicodeDecodeError: umr_namelist.remove(umr_n) if original_list != umr_namelist: CONF.set('main_interpreter', 'umr/namelist', umr_namelist) env_vars = { 'SPY_EXTERNAL_INTERPRETER': not default_interpreter, 'SPY_UMR_ENABLED': CONF.get('main_interpreter', 'umr/enabled'), 'SPY_UMR_VERBOSE': CONF.get('main_interpreter', 'umr/verbose'), 'SPY_UMR_NAMELIST': ','.join(umr_namelist), 'SPY_RUN_LINES_O': CONF.get('ipython_console', 'startup/run_lines'), 'SPY_PYLAB_O': CONF.get('ipython_console', 'pylab'), 'SPY_BACKEND_O': CONF.get('ipython_console', 'pylab/backend'), 'SPY_AUTOLOAD_PYLAB_O': CONF.get('ipython_console', 'pylab/autoload'), 'SPY_FORMAT_O': CONF.get('ipython_console', 'pylab/inline/figure_format'), 'SPY_BBOX_INCHES_O': CONF.get('ipython_console', 'pylab/inline/bbox_inches'), 'SPY_RESOLUTION_O': CONF.get('ipython_console', 'pylab/inline/resolution'), 'SPY_WIDTH_O': CONF.get('ipython_console', 'pylab/inline/width'), 'SPY_HEIGHT_O': CONF.get('ipython_console', 'pylab/inline/height'), 'SPY_USE_FILE_O': CONF.get('ipython_console', 'startup/use_run_file'), 'SPY_RUN_FILE_O': CONF.get('ipython_console', 'startup/run_file'), 'SPY_AUTOCALL_O': CONF.get('ipython_console', 'autocall'), 'SPY_GREEDY_O': CONF.get('ipython_console', 'greedy_completer'), 'SPY_JEDI_O': CONF.get('ipython_console', 'jedi_completer'), 'SPY_SYMPY_O': CONF.get('ipython_console', 'symbolic_math'), 'SPY_TESTING': running_under_pytest() or SAFE_MODE, 'SPY_HIDE_CMD': CONF.get('ipython_console', 'hide_cmd_windows') } if self.is_pylab is True: env_vars['SPY_AUTOLOAD_PYLAB_O'] = True env_vars['SPY_SYMPY_O'] = False env_vars['SPY_RUN_CYTHON'] = False if self.is_sympy is True: env_vars['SPY_AUTOLOAD_PYLAB_O'] = False env_vars['SPY_SYMPY_O'] = True env_vars['SPY_RUN_CYTHON'] = False if self.is_cython is True: env_vars['SPY_AUTOLOAD_PYLAB_O'] = False env_vars['SPY_SYMPY_O'] = False env_vars['SPY_RUN_CYTHON'] = True # Add our PYTHONPATH to env_vars env_vars.update(pypath) # Making all env_vars strings for key,var in iteritems(env_vars): if PY2: # Try to convert vars first to utf-8. try: unicode_var = to_text_string(var) except UnicodeDecodeError: # If that fails, try to use the file system # encoding because one of our vars is our # PYTHONPATH, and that contains file system # directories try: unicode_var = to_unicode_from_fs(var) except: # If that also fails, make the var empty # to be able to start Spyder. # See https://stackoverflow.com/q/44506900/438386 # for details. unicode_var = '' env_vars[key] = to_binary_string(unicode_var, encoding='utf-8') else: env_vars[key] = to_text_string(var) return env_vars
def lock(self): """ Acquire this lock. @rtype: C{bool} @return: True if the lock is acquired, false otherwise. @raise: Any exception os.symlink() may raise, other than EEXIST. """ clean = True while True: try: symlink(str(os.getpid()), self.name) except OSError as e: if _windows and e.errno in (errno.EACCES, errno.EIO): # The lock is in the middle of being deleted because we're # on Windows where lock removal isn't atomic. Give up, we # don't know how long this is going to take. return False if e.errno == errno.EEXIST: try: pid = readlink(self.name) except OSError as e: if e.errno == errno.ENOENT: # The lock has vanished, try to claim it in the # next iteration through the loop. continue raise except IOError as e: if _windows and e.errno == errno.EACCES: # The lock is in the middle of being # deleted because we're on Windows where # lock removal isn't atomic. Give up, we # don't know how long this is going to # take. return False raise try: if kill is not None: kill(int(pid), 0) # Verify that the running process corresponds to # a Spyder one p = psutil.Process(int(pid)) # Valid names for main script names = set(['spyder', 'spyder3', 'spyder.exe', 'spyder3.exe', 'bootstrap.py', 'spyder-script.py']) if running_under_pytest(): names.add('runtests.py') # Check the first three command line arguments arguments = set(os.path.basename(arg) for arg in p.cmdline()[:3]) conditions = [names & arguments] if not any(conditions): raise(OSError(errno.ESRCH, 'No such process')) except OSError as e: if e.errno == errno.ESRCH: # The owner has vanished, try to claim it in the # next iteration through the loop. try: rmlink(self.name) except OSError as e: if e.errno == errno.ENOENT: # Another process cleaned up the lock. # Race them to acquire it in the next # iteration through the loop. continue raise clean = False continue raise return False raise self.locked = True self.clean = clean return True
def main(): """ Start Spyder application. If single instance mode is turned on (default behavior) and an instance of Spyder is already running, this will just parse and send command line options to the application. """ # Parse command line options if running_under_pytest(): try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 options = Mock() options.new_instance = False options.reset_config_files = False options.debug_info = None args = None else: options, args = get_options() # Store variable to be used in self.restart (restart spyder instance) os.environ['SPYDER_ARGS'] = str(sys.argv[1:]) #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #========================================================================== if CONF.get('main', 'high_dpi_custom_scale_factor'): factors = str(CONF.get('main', 'high_dpi_custom_scale_factors')) f = list(filter(None, factors.split(';'))) if len(f) == 1: os.environ['QT_SCALE_FACTOR'] = f[0] else: os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCALE_FACTOR'] = '' os.environ['QT_SCREEN_SCALE_FACTORS'] = '' if sys.platform == 'darwin': # Prevent Spyder from crashing in macOS if locale is not defined LANG = os.environ.get('LANG') LC_ALL = os.environ.get('LC_ALL') if bool(LANG) and not bool(LC_ALL): LC_ALL = LANG elif not bool(LANG) and bool(LC_ALL): LANG = LC_ALL else: LANG = LC_ALL = 'en_US.UTF-8' os.environ['LANG'] = LANG os.environ['LC_ALL'] = LC_ALL # Don't show useless warning in the terminal where Spyder # was started # See issue 3730 os.environ['EVENT_NOKQUEUE'] = '1' else: # Prevent our kernels to crash when Python fails to identify # the system locale. # Fixes issue 7051. try: from locale import getlocale getlocale() except ValueError: # This can fail on Windows. See issue 6886 try: os.environ['LANG'] = 'C' os.environ['LC_ALL'] = 'C' except Exception: pass if options.debug_info: levels = {'minimal': '2', 'verbose': '3'} os.environ['SPYDER_DEBUG'] = levels[options.debug_info] if CONF.get('main', 'single_instance') and not options.new_instance \ and not options.reset_config_files and not running_in_mac_app(): # Minimal delay (0.1-0.2 secs) to avoid that several # instances started at the same time step in their # own foots while trying to create the lock file time.sleep(random.randrange(1000, 2000, 90)/10000.) # Lock file creation lock_file = get_conf_path('spyder.lock') lock = lockfile.FilesystemLock(lock_file) # Try to lock spyder.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file try: lock_created = lock.lock() except: # If locking fails because of errors in the lockfile # module, try to remove a possibly stale spyder.lock. # This is reported to solve all problems with # lockfile (See issue 2363) try: if os.name == 'nt': if osp.isdir(lock_file): import shutil shutil.rmtree(lock_file, ignore_errors=True) else: if osp.islink(lock_file): os.unlink(lock_file) except: pass # Then start Spyder as usual and *don't* continue # executing this script because it doesn't make # sense from spyder.app import mainwindow if running_under_pytest(): return mainwindow.main() else: mainwindow.main() return if lock_created: # Start a new instance from spyder.app import mainwindow if running_under_pytest(): return mainwindow.main() else: mainwindow.main() else: # Pass args to Spyder or print an informative # message if args: send_args_to_spyder(args) else: print("Spyder is already running. If you want to open a new \n" "instance, please pass to it the --new-instance option") else: from spyder.app import mainwindow if running_under_pytest(): return mainwindow.main() else: mainwindow.main()