def get_versions(reporev=True): """Get version information for components used by Spyder""" import sys import platform import qtpy import qtpy.QtCore from spyder.utils.conda import is_conda_env from spyder.config.base import is_pynsist, running_in_mac_app revision = branch = None if reporev: if running_in_mac_app(): revision = os.environ.get('SPY_COMMIT', None) branch = os.environ.get('SPY_BRANCH', None) else: from spyder.utils import vcs revision, branch = vcs.get_git_revision( os.path.dirname(__current_directory__)) if is_pynsist() or running_in_mac_app(): installer = 'standalone' elif is_conda_env(pyexec=sys.executable): installer = 'conda' else: installer = 'pip' return { 'spyder': __version__, 'installer': installer, 'python': platform.python_version(), # "2.7.3" 'bitness': 64 if sys.maxsize > 2**32 else 32, 'qt': qtpy.QtCore.__version__, 'qt_api': qtpy.API_NAME, # PyQt5 'qt_api_ver': (qtpy.PYSIDE_VERSION if qtpy.API == "pyside2" else qtpy.PYQT_VERSION), 'system': platform.system(), # Linux, Windows, ... 'release': platform.release(), # XP, 10.6, 2.2.0, etc. 'revision': revision, # '9fdf926eccce', 'branch': branch, # '4.x' or master }
def qapplication(translate=True, test_time=3): """ Return QApplication instance Creates it if it doesn't already exist test_time: Time to maintain open the application when testing. It's given in seconds """ if running_in_mac_app(): SpyderApplication = MacApplication else: SpyderApplication = QApplication app = SpyderApplication.instance() if app is None: # Set Application name for Gnome 3 # https://groups.google.com/forum/#!topic/pyside/24qxvwfrRDs app = SpyderApplication(['Spyder']) # Set application name for KDE (See issue 2207) app.setApplicationName('Spyder') if translate: install_translator(app) test_ci = os.environ.get('TEST_CI_WIDGETS', None) if test_ci is not None: timer_shutdown = QTimer(app) timer_shutdown.timeout.connect(app.quit) timer_shutdown.start(test_time*1000) return app
def get_list_pyenv_envs(): """Return the list of all pyenv envs found in the system.""" global PYENV_ENV_LIST_CACHE env_list = {} pyenv = find_program('pyenv') if pyenv is None: return env_list cmdstr = ' '.join([pyenv, 'versions', '--bare', '--skip-aliases']) try: out, __ = run_shell_command(cmdstr, env={}).communicate() out = out.decode() except Exception: out = '' out = out.split('\n') for env in out: data = env.split(osp.sep) path = get_pyenv_path(data[-1]) if data[-1] == '': name = 'internal' if running_in_mac_app(path) else 'system' else: name = 'pyenv: {}'.format(data[-1]) version = ('Python 2.7' if data[-1] == '' else 'Python {}'.format(data[0])) env_list[name] = (path, version) PYENV_ENV_LIST_CACHE = env_list return env_list
def __init__(self, ipyclient, additional_options, interpreter_versions, is_external_kernel, is_spyder_kernel, handlers, *args, **kw): # To override the Qt widget used by RichJupyterWidget self.custom_control = ControlWidget self.custom_page_control = PageControlWidget self.custom_edit = True self.spyder_kernel_comm = KernelComm() self.spyder_kernel_comm.sig_exception_occurred.connect( self.sig_exception_occurred) super(ShellWidget, self).__init__(*args, **kw) self.ipyclient = ipyclient self.additional_options = additional_options self.interpreter_versions = interpreter_versions self.is_external_kernel = is_external_kernel self.is_spyder_kernel = is_spyder_kernel self._cwd = '' # Keyboard shortcuts # Registered here to use shellwidget as the parent self.shortcuts = self.create_shortcuts() # Set the color of the matched parentheses here since the qtconsole # uses a hard-coded value that is not modified when the color scheme is # set in the qtconsole constructor. See spyder-ide/spyder#4806. self.set_bracket_matcher_color_scheme(self.syntax_style) self.shutting_down = False self.kernel_manager = None self.kernel_client = None handlers.update({ 'pdb_state': self.set_pdb_state, 'pdb_execute': self.pdb_execute, 'show_pdb_output': self.show_pdb_output, 'get_pdb_settings': self.get_pdb_settings, 'set_debug_state': self.set_debug_state, 'update_syspath': self.update_syspath, 'do_where': self.do_where, 'pdb_input': self.pdb_input, 'request_interrupt_eventloop': self.request_interrupt_eventloop, }) for request_id in handlers: self.spyder_kernel_comm.register_call_handler( request_id, handlers[request_id]) self._execute_queue = [] self.executed.connect(self.pop_execute_queue) # Show a message in our installers to explain users how to use # modules that don't come with them. self.show_modules_message = is_pynsist() or running_in_mac_app() self.shutdown_lock = Lock()
def _process_interpreter_env_info(self): """Process conda environment information.""" out, err = self._get_interpreter_env_info() out = out or err # Anaconda base python prints to stderr out = out.split('\n')[0] parts = out.split() if len(parts) >= 2: out = ' '.join(parts[:2]) if is_conda_env(pyexec=self._interpreter): envs_folder = os.path.sep + 'envs' + os.path.sep if envs_folder in self._interpreter: if os.name == 'nt': env = os.path.dirname(self._interpreter) else: env = os.path.dirname(os.path.dirname(self._interpreter)) env = os.path.basename(env) else: env = 'base' env = 'conda: ' + env elif running_in_mac_app(self._interpreter): env = 'internal' else: env = 'venv' # Update when additional environments are supported text = '{env} ({version})'.format(env=env, version=out) return text
def _start(self): """Start the code analysis.""" self.start_spinner() self.output = "" self.error_output = "" self._process = process = QProcess(self) process.setProcessChannelMode(QProcess.SeparateChannels) process.setWorkingDirectory(getcwd_or_home()) process.readyReadStandardOutput.connect(self._read_output) process.readyReadStandardError.connect( lambda: self._read_output(error=True)) process.finished.connect( lambda ec, es=QProcess.ExitStatus: self._finished(ec, es)) command_args = self.get_command(self.get_filename()) processEnvironment = QProcessEnvironment() processEnvironment.insert("PYTHONIOENCODING", "utf8") # resolve spyder-ide/spyder#14262 if running_in_mac_app(): pyhome = os.environ.get("PYTHONHOME") processEnvironment.insert("PYTHONHOME", pyhome) process.setProcessEnvironment(processEnvironment) process.start(sys.executable, command_args) running = process.waitForStarted() if not running: self.stop_spinner() QMessageBox.critical( self, _("Error"), _("Process failed to start"), )
def qapplication(translate=True, test_time=3): """ Return QApplication instance Creates it if it doesn't already exist test_time: Time to maintain open the application when testing. It's given in seconds """ if running_in_mac_app(): SpyderApplication = MacApplication else: SpyderApplication = QApplication app = SpyderApplication.instance() if app is None: # Set Application name for Gnome 3 # https://groups.google.com/forum/#!topic/pyside/24qxvwfrRDs app = SpyderApplication(['Spyder']) # Set application name for KDE (See issue 2207) app.setApplicationName('Spyder') if translate: install_translator(app) test_ci = os.environ.get('TEST_CI_WIDGETS', None) if test_ci is not None: timer_shutdown = QTimer(app) timer_shutdown.timeout.connect(app.quit) timer_shutdown.start(test_time * 1000) return app
def on_mainwindow_visible(self): # Open project passed on the command line or reopen last one. cli_options = self.get_command_line_options() initial_cwd = self._main.get_initial_working_directory() if cli_options.project is not None: # This doesn't work for our Mac app if not running_in_mac_app(): logger.debug('Opening project from the command line') project = osp.normpath( osp.join(initial_cwd, cli_options.project) ) self.open_project( project, workdir=cli_options.working_directory ) else: logger.debug('Reopening project from last session') self.reopen_last_project()
def qapplication(translate=True, test_time=3): """ Return QApplication instance Creates it if it doesn't already exist test_time: Time to maintain open the application when testing. It's given in seconds """ if sys.platform == "darwin": SpyderApplication = MacApplication else: SpyderApplication = QApplication app = SpyderApplication.instance() if app is None: # Set Application name for Gnome 3 # https://groups.google.com/forum/#!topic/pyside/24qxvwfrRDs app = SpyderApplication(['Spyder']) # Set application name for KDE. See spyder-ide/spyder#2207. app.setApplicationName('Spyder') if (sys.platform == "darwin" and not running_in_mac_app() and CONF.get('main', 'mac_open_file', False)): # Register app if setting is set register_app_launchservices() if translate: install_translator(app) test_ci = os.environ.get('TEST_CI_WIDGETS', None) if test_ci is not None: timer_shutdown = QTimer(app) timer_shutdown.timeout.connect(app.quit) timer_shutdown.start(test_time * 1000) return app
def generate_python_config(self): """ Update Python server configuration with the options saved in our config system. """ python_config = PYTHON_CONFIG.copy() # Server options cmd = self.get_conf('advanced/module', 'pylsp') host = self.get_conf('advanced/host', '127.0.0.1') port = self.get_conf('advanced/port', 2087) # Pycodestyle cs_exclude = self.get_conf('pycodestyle/exclude', '').split(',') cs_filename = self.get_conf('pycodestyle/filename', '').split(',') cs_select = self.get_conf('pycodestyle/select', '').split(',') cs_ignore = self.get_conf('pycodestyle/ignore', '').split(',') cs_max_line_length = self.get_conf('pycodestyle/max_line_length', 79) pycodestyle = { 'enabled': self.get_conf('pycodestyle'), 'exclude': [exclude.strip() for exclude in cs_exclude if exclude], 'filename': [filename.strip() for filename in cs_filename if filename], 'select': [select.strip() for select in cs_select if select], 'ignore': [ignore.strip() for ignore in cs_ignore if ignore], 'hangClosing': False, 'maxLineLength': cs_max_line_length } # Linting - Pyflakes pyflakes = {'enabled': self.get_conf('pyflakes')} # Pydocstyle convention = self.get_conf('pydocstyle/convention') if convention == 'Custom': ds_ignore = self.get_conf('pydocstyle/ignore', '').split(',') ds_select = self.get_conf('pydocstyle/select', '').split(',') ds_add_ignore = [] ds_add_select = [] else: ds_ignore = [] ds_select = [] ds_add_ignore = self.get_conf('pydocstyle/ignore', '').split(',') ds_add_select = self.get_conf('pydocstyle/select', '').split(',') pydocstyle = { 'enabled': self.get_conf('pydocstyle'), 'convention': convention, 'addIgnore': [ignore.strip() for ignore in ds_add_ignore if ignore], 'addSelect': [select.strip() for select in ds_add_select if select], 'ignore': [ignore.strip() for ignore in ds_ignore if ignore], 'select': [select.strip() for select in ds_select if select], 'match': self.get_conf('pydocstyle/match'), 'matchDir': self.get_conf('pydocstyle/match_dir') } # Autoformatting configuration formatter = self.get_conf('formatting') # This is necessary because PyLSP third-party plugins can only be # disabled with their module name. formatter = 'pylsp_black' if formatter == 'black' else formatter # Enabling/disabling formatters formatters = ['autopep8', 'yapf', 'pylsp_black'] formatter_options = { fmt: { 'enabled': fmt == formatter } for fmt in formatters } # Setting max line length for formatters # The autopep8 plugin shares the same maxLineLength value with the # pycodestyle one. That's why it's not necessary to set it here. # NOTE: We need to use `black` and not `pylsp_black` because that's # the options' namespace of that plugin. formatter_options['black'] = {'line_length': cs_max_line_length} # PyLS-Spyder configuration group_cells = self.get_conf('group_cells', section='outline_explorer') display_block_comments = self.get_conf('show_comments', section='outline_explorer') pyls_spyder_options = { 'enable_block_comments': display_block_comments, 'group_cells': group_cells } # Jedi configuration env_vars = os.environ.copy() # Ensure env is indepependent of PyLSP's env_vars.pop('PYTHONPATH', None) if self.get_conf('default', section='main_interpreter'): # If not explicitly set, jedi uses PyLSP's sys.path instead of # sys.executable's sys.path. This may be a bug in jedi. environment = sys.executable else: environment = self.get_conf('executable', section='main_interpreter') # External interpreter cannot have PYTHONHOME if running_in_mac_app(): env_vars.pop('PYTHONHOME', None) jedi = { 'environment': environment, 'extra_paths': self.get_conf('spyder_pythonpath', section='main', default=[]), 'env_vars': env_vars, } jedi_completion = { 'enabled': self.get_conf('code_completion'), 'include_params': self.get_conf('enable_code_snippets', section='completions') } jedi_signature_help = {'enabled': self.get_conf('jedi_signature_help')} jedi_definition = { 'enabled': self.get_conf('jedi_definition'), 'follow_imports': self.get_conf('jedi_definition/follow_imports') } # Advanced external_server = self.get_conf('advanced/external') stdio = self.get_conf('advanced/stdio') # Setup options in json python_config['cmd'] = cmd if host in self.LOCALHOST and not stdio: python_config['args'] = ('--host {host} --port {port} --tcp ' '--check-parent-process') else: python_config['args'] = '--check-parent-process' python_config['external'] = external_server python_config['stdio'] = stdio python_config['host'] = host python_config['port'] = port # Updating options plugins = python_config['configurations']['pylsp']['plugins'] plugins['pycodestyle'].update(pycodestyle) plugins['pyflakes'].update(pyflakes) plugins['pydocstyle'].update(pydocstyle) plugins['pyls_spyder'].update(pyls_spyder_options) plugins['jedi'].update(jedi) plugins['jedi_completion'].update(jedi_completion) plugins['jedi_signature_help'].update(jedi_signature_help) plugins['jedi_definition'].update(jedi_definition) plugins['preload']['modules'] = self.get_conf('preload_modules') plugins.update(formatter_options) return python_config
#----------------------------------------------------------------------------- # Globals and constants #----------------------------------------------------------------------------- # Path to the modules database MODULES_PATH = get_conf_path('db') # Time in seconds after which we give up if os.name == 'nt': TIMEOUT_GIVEUP = 30 else: TIMEOUT_GIVEUP = 20 # Py2app only uses .pyc files for the stdlib when optimize=0, # so we need to add it as another suffix here if running_in_mac_app(): suffixes = imp.get_suffixes() + [('.pyc', 'rb', '2')] else: suffixes = imp.get_suffixes() # Regular expression for the python import statement import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)' r'(?P<package>[/\\]__init__)?' r'(?P<suffix>%s)$' % r'|'.join(re.escape(s[0]) for s in suffixes)) # Modules database modules_db = PickleShareDB(MODULES_PATH) #----------------------------------------------------------------------------- # Utility functions
def create_process(self): self.shell.clear() self.process = QProcess(self) if self.merge_output_channels: self.process.setProcessChannelMode(QProcess.MergedChannels) else: self.process.setProcessChannelMode(QProcess.SeparateChannels) self.shell.wait_for_ready_read.connect( lambda: self.process.waitForReadyRead(250)) # Working directory if self.wdir is not None: self.process.setWorkingDirectory(self.wdir) #-------------------------Python specific------------------------------ # Python arguments p_args = ['-u'] if DEBUG >= 3: p_args += ['-v'] p_args += get_python_args(self.fname, self.python_args, self.interact_action.isChecked(), self.debug_action.isChecked(), self.arguments) env = [to_text_string(_path) for _path in self.process.systemEnvironment()] if self.pythonstartup: env.append('PYTHONSTARTUP=%s' % self.pythonstartup) #-------------------------Python specific------------------------------- # Post mortem debugging if self.post_mortem_action.isChecked(): env.append('SPYDER_EXCEPTHOOK=True') # Set standard input/output encoding for Python consoles # (IPython handles it on its own) # See http://stackoverflow.com/q/26312400/438386, specifically # the comments of Martijn Pieters if not self.is_ipykernel: env.append('PYTHONIOENCODING=UTF-8') # Monitor if self.monitor_enabled: env.append('SPYDER_SHELL_ID=%s' % id(self)) env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout) env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state) from spyder.widgets.externalshell import introspection introspection_server = introspection.start_introspection_server() introspection_server.register(self) notification_server = introspection.start_notification_server() self.notification_thread = notification_server.register(self) self.notification_thread.sig_pdb.connect( lambda fname, lineno: self.sig_pdb.emit(fname, lineno)) self.notification_thread.new_ipython_kernel.connect( lambda args: self.create_ipython_client.emit(args)) self.notification_thread.open_file.connect( lambda fname, lineno: self.open_file.emit(fname, lineno)) if self.namespacebrowser is not None: self.configure_namespacebrowser() env.append('SPYDER_I_PORT=%d' % introspection_server.port) env.append('SPYDER_N_PORT=%d' % notification_server.port) # External modules options if not self.is_ipykernel: env.append('ETS_TOOLKIT=%s' % self.ets_backend) if self.mpl_backend is not None: backends = {0: 'Automatic', 1: 'None', 2: 'TkAgg'} env.append('SPY_MPL_BACKEND=%s' % backends[self.mpl_backend]) if self.qt_api and not self.is_ipykernel: env.append('QT_API=%s' % self.qt_api) env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr) # # Socket-based alternative (see input hook in sitecustomize.py): # if self.install_qt_inputhook: # from PyQt4.QtNetwork import QLocalServer # self.local_server = QLocalServer() # self.local_server.listen(str(id(self))) # User Module Deleter if self.is_interpreter: env.append('UMR_ENABLED=%r' % self.umr_enabled) env.append('UMR_NAMELIST=%s' % ','.join(self.umr_namelist)) env.append('UMR_VERBOSE=%r' % self.umr_verbose) env.append('MATPLOTLIB_ION=True') else: if self.interact: env.append('MATPLOTLIB_ION=True') else: env.append('MATPLOTLIB_ION=False') # IPython kernel env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel) # External interpreter env.append('EXTERNAL_INTERPRETER=%r' % self.external_interpreter) # Add sitecustomize path to path list pathlist = [] scpath = osp.dirname(osp.abspath(__file__)) pathlist.append(scpath) # Adding Spyder path pathlist += self.path # Adding path list to PYTHONPATH environment variable add_pathlist_to_PYTHONPATH(env, pathlist) #-------------------------Python specific------------------------------ self.process.readyReadStandardOutput.connect(self.write_output) self.process.readyReadStandardError.connect(self.write_error) self.process.finished.connect(lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.sig_finished.connect(self.dialog_manager.close_all) self.terminate_button.clicked.connect(self.process.terminate) self.kill_button.clicked.connect(self.process.kill) #-------------------------Python specific------------------------------ # Fixes for our Mac app: # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app, # but their values are messing sys.path for external interpreters # (e.g. EPD) so we need to remove them from the environment. # 2. Set PYTHONPATH again but without grabbing entries defined in the # environment (Fixes Issue 1321) # 3. Remove PYTHONOPTIMIZE from env so that we can have assert # statements working with our interpreters (See Issue 1281) if running_in_mac_app(): if MAC_APP_NAME not in self.pythonexecutable: env = [p for p in env if not (p.startswith('PYTHONPATH') or \ p.startswith('PYTHONHOME'))] # 1. add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=True) # 2. env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')] # 3. processEnvironment = QProcessEnvironment() for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) self.process.start(self.pythonexecutable, p_args) #-------------------------Python specific------------------------------ running = self.process.waitForStarted(3000) self.set_running_state(running) if not running: if self.is_ipykernel: self.ipython_kernel_start_error.emit( _("The kernel failed to start!! That's all we know... " "Please close this console and open a new one.")) else: QMessageBox.critical(self, _("Error"), _("A Python console failed to start!")) else: self.shell.setFocus() self.started.emit() return self.process
def create_window(WindowClass, app, splash, options, args): """ Create and show Spyder's main window and start QApplication event loop. Parameters ---------- WindowClass: QMainWindow Subclass to instantiate the Window. app: QApplication Instance to start the application. splash: QSplashScreen Splash screen instamce. options: argparse.Namespace Command line options passed to Spyder args: list List of file names passed to the Spyder executable in the command line. """ # Main window main = WindowClass(splash, options) try: main.setup() except BaseException: if main.console is not None: try: main.console.exit_interpreter() except BaseException: pass raise main.pre_visible_setup() main.show() main.post_visible_setup() if main.console: namespace = CONF.get('internal_console', 'namespace', {}) main.console.start_interpreter(namespace) main.console.set_namespace_item('spy', Spy(app=app, window=main)) # Propagate current configurations to all configuration observers CONF.notify_all_observers() # Don't show icons in menus for Mac if sys.platform == 'darwin': QCoreApplication.setAttribute(Qt.AA_DontShowIconsInMenus, True) # Open external files with our Mac app if running_in_mac_app(): app.sig_open_external_file.connect(main.open_external_file) app._has_started = True if hasattr(app, '_pending_file_open'): if args: args = app._pending_file_open + args else: args = app._pending_file_open # Open external files passed as args if args: for a in args: main.open_external_file(a) # To give focus again to the last focused widget after restoring # the window app.focusChanged.connect(main.change_last_focused_widget) if not running_under_pytest(): app.exec_() return main
def __init__(self, parent=None, is_report=False): QDialog.__init__(self, parent) self.is_report = is_report # Set to true to run tests on the dialog. This is the default # in the test function at the end of this file. self._testing = False self.setWindowTitle(_("Issue reporter")) self._github_org = 'spyder-ide' self._github_repo = 'spyder' # To save the traceback sent to the internal console self.error_traceback = "" # Dialog main label if self.is_report: title = _("Please fill the following information") else: title = _("Spyder has encountered an internal problem!") self.main_label = QLabel( _("<h3>{title}</h3>" "Before reporting this problem, <i>please</i> consult our " "comprehensive " "<b><a href=\"{trouble_url}\">Troubleshooting Guide</a></b> " "which should help solve most issues, and search for " "<b><a href=\"{project_url}\">known bugs</a></b> " "matching your error message or problem description for a " "quicker solution.").format(title=title, trouble_url=__trouble_url__, project_url=__project_url__)) self.main_label.setOpenExternalLinks(True) self.main_label.setWordWrap(True) self.main_label.setAlignment(Qt.AlignJustify) self.main_label.setStyleSheet('font-size: 12px;') # Issue title self.title = QLineEdit() self.title.textChanged.connect(self._contents_changed) self.title_chars_label = QLabel( _("{} more characters " "to go...").format(TITLE_MIN_CHARS)) form_layout = QFormLayout() form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) red_asterisk = '<font color="Red">*</font>' title_label = QLabel(_("<b>Title</b>: {}").format(red_asterisk)) form_layout.setWidget(0, QFormLayout.LabelRole, title_label) form_layout.setWidget(0, QFormLayout.FieldRole, self.title) # Description steps_header = QLabel( _("<b>Steps to reproduce:</b> {}").format(red_asterisk)) self.steps_text = QLabel( _("Please enter a detailed step-by-step " "description (in English) of what led up to " "the problem below. Issue reports without a " "clear way to reproduce them will be closed.")) self.steps_text.setWordWrap(True) self.steps_text.setAlignment(Qt.AlignJustify) self.steps_text.setStyleSheet('font-size: 12px;') # Field to input the description of the problem self.input_description = DescriptionWidget(self) # Only allow to submit to Github if we have a long enough description self.input_description.textChanged.connect(self._contents_changed) # Widget to show errors self.details = ShowErrorWidget(self) self.details.set_pythonshell_font(get_font()) self.details.hide() self.description_minimum_length = DESC_MIN_CHARS self.require_minimum_length = True # Label to show missing chars self.initial_chars = len(self.input_description.toPlainText()) self.desc_chars_label = QLabel( _("{} more characters " "to go...").format(self.description_minimum_length)) # Checkbox to dismiss future errors self.dismiss_box = QCheckBox( _("Hide all future errors during this " "session")) # Checkbox to include IPython console environment self.include_env = QCheckBox(_("Include IPython console environment")) # Dialog buttons gh_icon = ima.icon('github') self.submit_btn = QPushButton(gh_icon, _('Submit to Github')) self.submit_btn.setEnabled(False) self.submit_btn.clicked.connect(self._submit_to_github) self.details_btn = QPushButton(_('Show details')) self.details_btn.clicked.connect(self._show_details) if self.is_report: self.details_btn.hide() self.close_btn = QPushButton(_('Close')) self.close_btn.clicked.connect(self.reject) # Buttons layout buttons_layout = QHBoxLayout() buttons_layout.addWidget(self.submit_btn) buttons_layout.addWidget(self.details_btn) buttons_layout.addWidget(self.close_btn) # Main layout layout = QVBoxLayout() layout.addWidget(self.main_label) layout.addSpacing(20) layout.addLayout(form_layout) layout.addWidget(self.title_chars_label) layout.addSpacing(12) layout.addWidget(steps_header) layout.addSpacing(-1) layout.addWidget(self.steps_text) layout.addSpacing(1) layout.addWidget(self.input_description) layout.addWidget(self.details) layout.addWidget(self.desc_chars_label) layout.addSpacing(15) if not self.is_report: layout.addWidget(self.dismiss_box) # Only provide checkbox if not an installer default interpreter if (not (is_pynsist() or running_in_mac_app()) or not self.get_conf('default', section='main_interpreter')): layout.addWidget(self.include_env) layout.addSpacing(15) layout.addLayout(buttons_layout) layout.setContentsMargins(25, 20, 25, 10) self.setLayout(layout) self.resize(570, 600) self.title.setFocus() # Set Tab key focus order self.setTabOrder(self.title, self.input_description)
def create_process(self): self.shell.clear() self.process = QProcess(self) if self.merge_output_channels: self.process.setProcessChannelMode(QProcess.MergedChannels) else: self.process.setProcessChannelMode(QProcess.SeparateChannels) self.shell.wait_for_ready_read.connect( lambda: self.process.waitForReadyRead(250)) # Working directory if self.wdir is not None: self.process.setWorkingDirectory(self.wdir) #-------------------------Python specific------------------------------ # Python arguments p_args = ['-u'] if DEBUG >= 3: p_args += ['-v'] p_args += get_python_args(self.fname, self.python_args, self.interact_action.isChecked(), self.debug_action.isChecked(), self.arguments) env = [ to_text_string(_path) for _path in self.process.systemEnvironment() ] if self.pythonstartup: env.append('PYTHONSTARTUP=%s' % self.pythonstartup) #-------------------------Python specific------------------------------- # Post mortem debugging if self.post_mortem_action.isChecked(): env.append('SPYDER_EXCEPTHOOK=True') # Set standard input/output encoding for Python consoles # See http://stackoverflow.com/q/26312400/438386, specifically # the comments of Martijn Pieters env.append('PYTHONIOENCODING=UTF-8') # Monitor if self.monitor_enabled: env.append('SPYDER_SHELL_ID=%s' % id(self)) env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout) env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state) from spyder.widgets.externalshell import introspection introspection_server = introspection.start_introspection_server() introspection_server.register(self) notification_server = introspection.start_notification_server() self.notification_thread = notification_server.register(self) self.notification_thread.sig_pdb.connect( lambda fname, lineno: self.sig_pdb.emit(fname, lineno)) self.notification_thread.open_file.connect( lambda fname, lineno: self.open_file.emit(fname, lineno)) if self.namespacebrowser is not None: self.configure_namespacebrowser() env.append('SPYDER_I_PORT=%d' % introspection_server.port) env.append('SPYDER_N_PORT=%d' % notification_server.port) # External modules options env.append('ETS_TOOLKIT=%s' % self.ets_backend) if self.mpl_backend is not None: backends = {0: 'Automatic', 1: 'None', 2: 'TkAgg'} env.append('SPY_MPL_BACKEND=%s' % backends[self.mpl_backend]) if self.qt_api: env.append('QT_API=%s' % self.qt_api) env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr) # # Socket-based alternative (see input hook in sitecustomize.py): # if self.install_qt_inputhook: # from PyQt4.QtNetwork import QLocalServer # self.local_server = QLocalServer() # self.local_server.listen(str(id(self))) # User Module Deleter if self.is_interpreter: env.append('UMR_ENABLED=%r' % self.umr_enabled) env.append('UMR_NAMELIST=%s' % ','.join(self.umr_namelist)) env.append('UMR_VERBOSE=%r' % self.umr_verbose) env.append('MATPLOTLIB_ION=True') else: if self.interact: env.append('MATPLOTLIB_ION=True') else: env.append('MATPLOTLIB_ION=False') # External interpreter env.append('EXTERNAL_INTERPRETER=%r' % self.external_interpreter) # Add sitecustomize path to path list pathlist = [] spy_path = get_module_source_path('spyder') sc_path = osp.join(spy_path, 'utils', 'site') pathlist.append(sc_path) # Adding Spyder path pathlist += self.path # Adding path list to PYTHONPATH environment variable add_pathlist_to_PYTHONPATH(env, pathlist) #-------------------------Python specific------------------------------ self.process.readyReadStandardOutput.connect(self.write_output) self.process.readyReadStandardError.connect(self.write_error) self.process.finished.connect( lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.sig_finished.connect(self.dialog_manager.close_all) self.terminate_button.clicked.connect(self.process.terminate) self.kill_button.clicked.connect(self.process.kill) #-------------------------Python specific------------------------------ # Fixes for our Mac app: # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app, # but their values are messing sys.path for external interpreters # (e.g. EPD) so we need to remove them from the environment. # 2. Set PYTHONPATH again but without grabbing entries defined in the # environment (Fixes Issue 1321) # 3. Remove PYTHONOPTIMIZE from env so that we can have assert # statements working with our interpreters (See Issue 1281) if running_in_mac_app(): if MAC_APP_NAME not in self.pythonexecutable: env = [p for p in env if not (p.startswith('PYTHONPATH') or \ p.startswith('PYTHONHOME'))] # 1. add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=True) # 2. env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')] # 3. processEnvironment = QProcessEnvironment() for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) self.process.start(self.pythonexecutable, p_args) #-------------------------Python specific------------------------------ running = self.process.waitForStarted(3000) self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("A Python console failed to start!")) else: self.shell.setFocus() self.started.emit() return self.process
def main(): #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attribute must # be set before creating the application. #========================================================================== env = os.environ.copy() 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: env['QT_SCALE_FACTOR'] = f[0] else: env['QT_SCREEN_SCALE_FACTORS'] = factors else: env['QT_SCALE_FACTOR'] = '' env['QT_SCREEN_SCALE_FACTORS'] = '' # Splash screen # ------------------------------------------------------------------------- # Start Qt Splash to inform the user of the current status app = qapplication() restarter = Restarter() APP_ICON = QIcon(get_image_path("spyder")) app.setWindowIcon(APP_ICON) restarter.set_splash_message(_('Closing Spyder')) # Get variables spyder_args = env.pop('SPYDER_ARGS', None) pid = env.pop('SPYDER_PID', None) is_bootstrap = env.pop('SPYDER_IS_BOOTSTRAP', None) reset = env.pop('SPYDER_RESET', 'False') # Get the spyder base folder based on this file spyder_dir = osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__)))) if not any([spyder_args, pid, is_bootstrap, reset]): error = "This script can only be called from within a Spyder instance" raise RuntimeError(error) # Variables were stored as string literals in the environment, so to use # them we need to parse them in a safe manner. is_bootstrap = ast.literal_eval(is_bootstrap) pid = ast.literal_eval(pid) args = ast.literal_eval(spyder_args) reset = ast.literal_eval(reset) # SPYDER_DEBUG takes presedence over SPYDER_ARGS if '--debug' in args: args.remove('--debug') for level in ['minimal', 'verbose']: arg = f'--debug-info={level}' if arg in args: args.remove(arg) # Enforce the --new-instance flag when running spyder if '--new-instance' not in args: if is_bootstrap and '--' not in args: args = args + ['--', '--new-instance'] else: args.append('--new-instance') # Create the arguments needed for resetting if '--' in args: args_reset = ['--', '--reset'] else: args_reset = ['--reset'] # Build the base command if running_in_mac_app(sys.executable): exe = env['EXECUTABLEPATH'] command = [f'"{exe}"'] else: if is_bootstrap: script = osp.join(spyder_dir, 'bootstrap.py') else: script = osp.join(spyder_dir, 'spyder', 'app', 'start.py') command = [f'"{sys.executable}"', f'"{script}"'] # Adjust the command and/or arguments to subprocess depending on the OS shell = not IS_WINDOWS # Before launching a new Spyder instance we need to make sure that the # previous one has closed. We wait for a fixed and "reasonable" amount of # time and check, otherwise an error is launched wait_time = 90 if IS_WINDOWS else 30 # Seconds for counter in range(int(wait_time / SLEEP_TIME)): if not is_pid_running(pid): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The old spyder instance took too long to close and restart aborts restarter.launch_error_message(error_type=CLOSE_ERROR) # Reset Spyder (if required) # ------------------------------------------------------------------------- if reset: restarter.set_splash_message(_('Resetting Spyder to defaults')) try: p = subprocess.Popen(' '.join(command + args_reset), shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: p.communicate() pid_reset = p.pid # Before launching a new Spyder instance we need to make sure that the # reset subprocess has closed. We wait for a fixed and "reasonable" # amount of time and check, otherwise an error is launched. wait_time = 20 # Seconds for counter in range(int(wait_time / SLEEP_TIME)): if not is_pid_running(pid_reset): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The reset subprocess took too long and it is killed try: p.kill() except OSError as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: restarter.launch_error_message(error_type=RESET_ERROR) # Restart # ------------------------------------------------------------------------- restarter.set_splash_message(_('Restarting')) try: subprocess.Popen(' '.join(command + args), shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESTART_ERROR, error=error)
def start(self, wdir=None, args=None, pythonpath=None): """ Start the profiling process. Parameters ---------- wdir: str Working directory path string. Default is None. args: list Arguments to pass to the profiling process. Default is None. pythonpath: str Python path string. Default is None. """ filename = to_text_string(self.filecombo.currentText()) if wdir is None: wdir = self._last_wdir if wdir is None: wdir = osp.basename(filename) if args is None: args = self._last_args if args is None: args = [] if pythonpath is None: pythonpath = self._last_pythonpath self._last_wdir = wdir self._last_args = args self._last_pythonpath = pythonpath self.datelabel.setText(_('Profiling, please wait...')) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(wdir) self.process.readyReadStandardOutput.connect(self._read_output) self.process.readyReadStandardError.connect( lambda: self._read_output(error=True)) self.process.finished.connect( lambda ec, es=QProcess.ExitStatus: self._finished(ec, es)) self.process.finished.connect(self.stop_spinner) # Start with system environment proc_env = QProcessEnvironment() for k, v in os.environ.items(): proc_env.insert(k, v) proc_env.insert("PYTHONIOENCODING", "utf8") proc_env.remove('PYTHONPATH') if pythonpath is not None: proc_env.insert('PYTHONPATH', os.pathsep.join(pythonpath)) self.process.setProcessEnvironment(proc_env) executable = self.get_conf('executable', section='main_interpreter') if not running_in_mac_app(executable): env = self.process.processEnvironment() env.remove('PYTHONHOME') self.process.setProcessEnvironment(env) self.output = '' self.error_output = '' self.running = True self.start_spinner() p_args = ['-m', 'cProfile', '-o', self.DATAPATH] if os.name == 'nt': # On Windows, one has to replace backslashes by slashes to avoid # confusion with escape characters (otherwise, for example, '\t' # will be interpreted as a tabulation): p_args.append(osp.normpath(filename).replace(os.sep, '/')) else: p_args.append(filename) if args: p_args.extend(shell_split(args)) self.process.start(executable, p_args) running = self.process.waitForStarted() if not running: QMessageBox.critical( self, _("Error"), _("Process failed to start"), ) self.update_actions()
def env(self): """Env vars for kernels""" default_interpreter = CONF.get('main_interpreter', 'default') env_vars = os.environ.copy() # Avoid IPython adding the virtualenv on which Spyder is running # to the kernel sys.path env_vars.pop('VIRTUAL_ENV', None) pathlist = CONF.get('main', 'spyder_pythonpath', default=[]) # Add spyder-kernels subrepo path to pathlist if DEV or running_under_pytest(): repo_path = osp.normpath(osp.join(HERE, '..', '..', '..', '..')) subrepo_path = osp.join(repo_path, 'external-deps', 'spyder-kernels') if running_under_pytest(): # Oddly pathlist is not set as an empty list when running # under pytest pathlist = [subrepo_path] else: pathlist += [subrepo_path] + pathlist # Create PYTHONPATH env entry to add it to the kernel pypath = add_pathlist_to_PYTHONPATH([], pathlist, ipyconsole=True, drop_env=True) # Add our PYTHONPATH to env_vars env_vars.update(pypath) # Environment variables that we need to pass to our sitecustomize umr_namelist = CONF.get('main_interpreter', 'umr/namelist') env_vars.update({ '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 # macOS app considerations if running_in_mac_app() and not default_interpreter: env_vars.pop('PYTHONHOME', None) # Making all env_vars strings clean_env_vars = clean_env(env_vars) return clean_env_vars
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 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 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()
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()
def run_python_script_in_terminal(fname, wdir, args, interact, debug, python_args, executable=None, pypath=None): """ Run Python script in an external system terminal. :str wdir: working directory, may be empty. """ if executable is None: executable = get_python_executable() env = {**os.environ} env.pop('PYTHONPATH', None) if pypath is not None: pypath = os.pathsep.join(pypath) env['PYTHONPATH'] = pypath # Quote fname in case it has spaces (all platforms) fname = f'"{fname}"' wdir = None if not wdir else wdir # Cannot be empty string p_args = get_python_args(fname, python_args, interact, debug, args) if os.name == 'nt': if wdir is not None: # wdir can come with / as os.sep, so we need to take care of it. wdir = wdir.replace('/', '\\') # python_exe must be quoted in case it has spaces cmd = f'start cmd.exe /K ""{executable}" ' cmd += ' '.join(p_args) + '"' + ' ^&^& exit' try: run_shell_command(cmd, cwd=wdir, env=env) except WindowsError: from qtpy.QtWidgets import QMessageBox from spyder.config.base import _ QMessageBox.critical( None, _('Run'), _("It was not possible to run this file in " "an external terminal"), QMessageBox.Ok) elif sys.platform.startswith('linux'): programs = [{ 'cmd': 'gnome-terminal', 'execute-option': '-x' }, { 'cmd': 'konsole', 'execute-option': '-e' }, { 'cmd': 'xfce4-terminal', 'execute-option': '-x' }, { 'cmd': 'xterm', 'execute-option': '-e' }] for program in programs: if is_program_installed(program['cmd']): cmd = [program['cmd'], program['execute-option'], executable] cmd.extend(p_args) run_shell_command(' '.join(cmd), cwd=wdir, env=env) return elif sys.platform == 'darwin': f = tempfile.NamedTemporaryFile('wt', prefix='run_spyder_', suffix='.sh', dir=get_temp_dir(), delete=False) if wdir: f.write('cd "{}"\n'.format(wdir)) if running_in_mac_app(executable): f.write(f'export PYTHONHOME={os.environ["PYTHONHOME"]}\n') if pypath is not None: f.write(f'export PYTHONPATH={pypath}\n') f.write(' '.join([executable] + p_args)) f.close() os.chmod(f.name, 0o777) def run_terminal_thread(): proc = run_shell_command(f'open -a Terminal.app {f.name}') # Prevent race condition time.sleep(3) proc.wait() os.remove(f.name) thread = threading.Thread(target=run_terminal_thread) thread.start() else: raise NotImplementedError
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 options, args = (CLI_OPTIONS, CLI_ARGS) # This is to allow reset without reading our conf file if options.reset_config_files: # <!> Remove all configuration files! reset_config_files() return from spyder.config.manager import CONF # 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 attribute 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': # Fixes launching issues with Big Sur (spyder-ide/spyder#14222) os.environ['QT_MAC_WANTS_LAYER'] = '1' # 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 spyder-ide/spyder#3730. os.environ['EVENT_NOKQUEUE'] = '1' else: # Prevent our kernels to crash when Python fails to identify # the system locale. # Fixes spyder-ide/spyder#7051. try: from locale import getlocale getlocale() except ValueError: # This can fail on Windows. See spyder-ide/spyder#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] _filename = 'spyder-debug.log' if options.debug_output == 'file': _filepath = osp.realpath(_filename) else: _filepath = get_conf_path(_filename) os.environ['SPYDER_DEBUG_FILE'] = _filepath if options.paths: from spyder.config.base import get_conf_paths sys.stdout.write('\nconfig:' + '\n') for path in reversed(get_conf_paths()): sys.stdout.write('\t' + path + '\n') sys.stdout.write('\n' ) return 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 spyder-ide/spyder#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(options, args) else: mainwindow.main(options, args) return if lock_created: # Start a new instance from spyder.app import mainwindow if running_under_pytest(): return mainwindow.main(options, args) else: mainwindow.main(options, args) 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 use the --new-instance option") else: from spyder.app import mainwindow if running_under_pytest(): return mainwindow.main(options, args) else: mainwindow.main(options, args)
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. """ # Renaming old configuration files (the '.' prefix has been removed) # (except for .spyder.ini --> spyder.ini, which is done in config/user.py) if DEV is None: cpath = get_conf_path() for fname in os.listdir(cpath): if fname.startswith('.'): old, new = osp.join(cpath, fname), osp.join(cpath, fname[1:]) try: os.rename(old, new) except OSError: pass # Parse command line options options, args = get_options() # Store variable to be used in self.restart (restart spyder instance) os.environ['SPYDER_ARGS'] = str(sys.argv[1:]) 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 mainwindow.main() return if lock_created: # Start a new instance from spyder.app import mainwindow 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 mainwindow.main()
def setup_page(self): self.ICON = ima.icon('genprefs') newcb = self.create_checkbox # --- Interface general_group = QGroupBox(_("General")) languages = LANGUAGE_CODES.items() language_choices = sorted([(val, key) for key, val in languages]) language_combo = self.create_combobox(_('Language:'), language_choices, 'interface_language', restart=True) opengl_options = ['Automatic', 'Desktop', 'Software', 'GLES'] opengl_choices = list( zip(opengl_options, [c.lower() for c in opengl_options])) opengl_combo = self.create_combobox(_('Rendering engine:'), opengl_choices, 'opengl', restart=True) single_instance_box = newcb(_("Use a single instance"), 'single_instance', tip=_("Set this to open external<br> " "Python files in an already running " "instance (Requires a restart)")) prompt_box = newcb(_("Prompt when exiting"), 'prompt_on_exit') popup_console_box = newcb( _("Show internal Spyder errors to report " "them to Github"), 'show_internal_errors') check_updates = newcb(_("Check for updates on startup"), 'check_updates_on_startup') # Decide if it's possible to activate or not single instance mode if running_in_mac_app(): self.set_option("single_instance", True) single_instance_box.setEnabled(False) comboboxes_advanced_layout = QHBoxLayout() cbs_adv_grid = QGridLayout() cbs_adv_grid.addWidget(language_combo.label, 0, 0) cbs_adv_grid.addWidget(language_combo.combobox, 0, 1) cbs_adv_grid.addWidget(opengl_combo.label, 1, 0) cbs_adv_grid.addWidget(opengl_combo.combobox, 1, 1) comboboxes_advanced_layout.addLayout(cbs_adv_grid) comboboxes_advanced_layout.addStretch(1) general_layout = QVBoxLayout() general_layout.addLayout(comboboxes_advanced_layout) general_layout.addWidget(single_instance_box) general_layout.addWidget(prompt_box) general_layout.addWidget(popup_console_box) general_layout.addWidget(check_updates) general_group.setLayout(general_layout) # --- Theme interface_group = QGroupBox(_("Interface")) vertdock_box = newcb(_("Vertical title bars in panes"), 'vertical_dockwidget_titlebars') verttabs_box = newcb(_("Vertical tabs in panes"), 'vertical_tabs') animated_box = newcb(_("Animated toolbars and panes"), 'animated_docks') tear_off_box = newcb(_("Tear off menus"), 'tear_off_menus', tip=_("Set this to detach any<br> " "menu from the main window")) margin_box = newcb(_("Custom margin for panes:"), 'use_custom_margin') margin_spin = self.create_spinbox("", _("pixels"), 'custom_margin', default=0, min_=0, max_=30) margin_box.toggled.connect(margin_spin.spinbox.setEnabled) margin_box.toggled.connect(margin_spin.slabel.setEnabled) margin_spin.spinbox.setEnabled(self.get_option('use_custom_margin')) margin_spin.slabel.setEnabled(self.get_option('use_custom_margin')) cursor_box = newcb(_("Cursor blinking:"), 'use_custom_cursor_blinking') cursor_spin = self.create_spinbox( "", _("ms"), 'custom_cursor_blinking', default=QApplication.cursorFlashTime(), min_=0, max_=5000, step=100) cursor_box.toggled.connect(cursor_spin.spinbox.setEnabled) cursor_box.toggled.connect(cursor_spin.slabel.setEnabled) cursor_spin.spinbox.setEnabled( self.get_option('use_custom_cursor_blinking')) cursor_spin.slabel.setEnabled( self.get_option('use_custom_cursor_blinking')) margins_cursor_layout = QGridLayout() margins_cursor_layout.addWidget(margin_box, 0, 0) margins_cursor_layout.addWidget(margin_spin.spinbox, 0, 1) margins_cursor_layout.addWidget(margin_spin.slabel, 0, 2) margins_cursor_layout.addWidget(cursor_box, 1, 0) margins_cursor_layout.addWidget(cursor_spin.spinbox, 1, 1) margins_cursor_layout.addWidget(cursor_spin.slabel, 1, 2) margins_cursor_layout.setColumnStretch(2, 100) # Layout interface interface_layout = QVBoxLayout() interface_layout.addWidget(vertdock_box) interface_layout.addWidget(verttabs_box) interface_layout.addWidget(animated_box) interface_layout.addWidget(tear_off_box) interface_layout.addLayout(margins_cursor_layout) interface_group.setLayout(interface_layout) if sys.platform == "darwin": def set_open_file(state): if state: register_app_launchservices() else: restore_launchservices() macOS_group = QGroupBox(_("macOS integration")) mac_open_file_box = newcb( _("Open files from Finder with Spyder"), 'mac_open_file', tip=_("Register Spyder with the Launch Services")) mac_open_file_box.toggled.connect(set_open_file) macOS_layout = QVBoxLayout() macOS_layout.addWidget(mac_open_file_box) if als.get_bundle_identifier() is None: # Disable setting mac_open_file_box.setDisabled(True) macOS_layout.addWidget( QLabel( _('Launch Spyder with <code>python.app</code> to enable' ' Apple event integrations.'))) macOS_group.setLayout(macOS_layout) # --- Status bar sbar_group = QGroupBox(_("Status bar")) show_status_bar = newcb(_("Show status bar"), 'show_status_bar') memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable', tip=self.main.mem_status.toolTip()) memory_spin = self.create_spinbox("", _(" ms"), 'memory_usage/timeout', min_=100, max_=1000000, step=100) memory_box.toggled.connect(memory_spin.setEnabled) memory_spin.setEnabled(self.get_option('memory_usage/enable')) memory_box.setEnabled(self.main.mem_status.is_supported()) memory_spin.setEnabled(self.main.mem_status.is_supported()) cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable', tip=self.main.cpu_status.toolTip()) cpu_spin = self.create_spinbox("", _(" ms"), 'cpu_usage/timeout', min_=100, max_=1000000, step=100) cpu_box.toggled.connect(cpu_spin.setEnabled) cpu_spin.setEnabled(self.get_option('cpu_usage/enable')) cpu_box.setEnabled(self.main.cpu_status.is_supported()) cpu_spin.setEnabled(self.main.cpu_status.is_supported()) status_bar_o = self.get_option('show_status_bar') show_status_bar.toggled.connect(memory_box.setEnabled) show_status_bar.toggled.connect(memory_spin.setEnabled) show_status_bar.toggled.connect(cpu_box.setEnabled) show_status_bar.toggled.connect(cpu_spin.setEnabled) memory_box.setEnabled(status_bar_o) memory_spin.setEnabled(status_bar_o) cpu_box.setEnabled(status_bar_o) cpu_spin.setEnabled(status_bar_o) # Layout status bar cpu_memory_layout = QGridLayout() cpu_memory_layout.addWidget(memory_box, 0, 0) cpu_memory_layout.addWidget(memory_spin, 0, 1) cpu_memory_layout.addWidget(cpu_box, 1, 0) cpu_memory_layout.addWidget(cpu_spin, 1, 1) sbar_layout = QVBoxLayout() sbar_layout.addWidget(show_status_bar) sbar_layout.addLayout(cpu_memory_layout) sbar_group.setLayout(sbar_layout) # --- Screen resolution Group (hidpi) screen_resolution_group = QGroupBox(_("Screen resolution")) screen_resolution_bg = QButtonGroup(screen_resolution_group) screen_resolution_label = QLabel( _("Configuration for high DPI " "screens<br><br>" "Please see " "<a href=\"{0}\">{0}</a><> " "for more information about " "these options (in " "English).").format(HDPI_QT_PAGE)) screen_resolution_label.setWordWrap(True) screen_resolution_label.setOpenExternalLinks(True) normal_radio = self.create_radiobutton( _("Normal"), 'normal_screen_resolution', button_group=screen_resolution_bg) auto_scale_radio = self.create_radiobutton( _("Enable auto high DPI scaling"), 'high_dpi_scaling', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays"), restart=True) custom_scaling_radio = self.create_radiobutton( _("Set a custom high DPI scaling"), 'high_dpi_custom_scale_factor', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays when " "auto scaling does not work"), restart=True) custom_scaling_edit = self.create_lineedit( "", 'high_dpi_custom_scale_factors', tip=_("Enter values for different screens " "separated by semicolons ';'.\n" "Float values are supported"), alignment=Qt.Horizontal, regex=r"[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*", restart=True) normal_radio.toggled.connect(custom_scaling_edit.setDisabled) auto_scale_radio.toggled.connect(custom_scaling_edit.setDisabled) custom_scaling_radio.toggled.connect(custom_scaling_edit.setEnabled) # Layout Screen resolution screen_resolution_layout = QVBoxLayout() screen_resolution_layout.addWidget(screen_resolution_label) screen_resolution_inner_layout = QGridLayout() screen_resolution_inner_layout.addWidget(normal_radio, 0, 0) screen_resolution_inner_layout.addWidget(auto_scale_radio, 1, 0) screen_resolution_inner_layout.addWidget(custom_scaling_radio, 2, 0) screen_resolution_inner_layout.addWidget(custom_scaling_edit, 2, 1) screen_resolution_layout.addLayout(screen_resolution_inner_layout) screen_resolution_group.setLayout(screen_resolution_layout) if sys.platform == "darwin": interface_tab = self.create_tab(screen_resolution_group, interface_group, macOS_group) else: interface_tab = self.create_tab(screen_resolution_group, interface_group) tabs = QTabWidget() tabs.addTab(interface_tab, _("Interface")) tabs.addTab(self.create_tab(general_group, sbar_group), _("Advanced settings")) vlayout = QVBoxLayout() vlayout.addWidget(tabs) self.setLayout(vlayout)
def env(self): """Env vars for kernels""" default_interpreter = self.get_conf('default', section='main_interpreter') env_vars = os.environ.copy() # Avoid IPython adding the virtualenv on which Spyder is running # to the kernel sys.path env_vars.pop('VIRTUAL_ENV', None) # Add spyder-kernels subrepo path to PYTHONPATH if (DEV or running_under_pytest()) and not running_in_ci(): repo_path = osp.normpath(osp.join(HERE, '..', '..', '..', '..')) subrepo_path = osp.join(repo_path, 'external-deps', 'spyder-kernels') env_vars.update({'PYTHONPATH': subrepo_path}) # List of paths declared by the user, plus project's path, to # add to PYTHONPATH pathlist = self.get_conf('spyder_pythonpath', default=[], section='main') pypath = os.pathsep.join(pathlist) # List of modules to exclude from our UMR umr_namelist = self.get_conf('umr/namelist', section='main_interpreter') # Environment variables that we need to pass to the kernel env_vars.update({ 'SPY_EXTERNAL_INTERPRETER': not default_interpreter, 'SPY_UMR_ENABLED': self.get_conf('umr/enabled', section='main_interpreter'), 'SPY_UMR_VERBOSE': self.get_conf('umr/verbose', section='main_interpreter'), 'SPY_UMR_NAMELIST': ','.join(umr_namelist), 'SPY_RUN_LINES_O': self.get_conf('startup/run_lines'), 'SPY_PYLAB_O': self.get_conf('pylab'), 'SPY_BACKEND_O': self.get_conf('pylab/backend'), 'SPY_AUTOLOAD_PYLAB_O': self.get_conf('pylab/autoload'), 'SPY_FORMAT_O': self.get_conf('pylab/inline/figure_format'), 'SPY_BBOX_INCHES_O': self.get_conf('pylab/inline/bbox_inches'), 'SPY_RESOLUTION_O': self.get_conf('pylab/inline/resolution'), 'SPY_WIDTH_O': self.get_conf('pylab/inline/width'), 'SPY_HEIGHT_O': self.get_conf('pylab/inline/height'), 'SPY_USE_FILE_O': self.get_conf('startup/use_run_file'), 'SPY_RUN_FILE_O': self.get_conf('startup/run_file'), 'SPY_AUTOCALL_O': self.get_conf('autocall'), 'SPY_GREEDY_O': self.get_conf('greedy_completer'), 'SPY_JEDI_O': self.get_conf('jedi_completer'), 'SPY_SYMPY_O': self.get_conf('symbolic_math'), 'SPY_TESTING': running_under_pytest() or get_safe_mode(), 'SPY_HIDE_CMD': self.get_conf('hide_cmd_windows'), 'SPY_PYTHONPATH': pypath }) 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 # App considerations if (running_in_mac_app() or is_pynsist()) and not default_interpreter: env_vars.pop('PYTHONHOME', None) env_vars.pop('PYTHONPATH', None) # Remove this variable because it prevents starting kernels for # external interpreters when present. # Fixes spyder-ide/spyder#13252 env_vars.pop('PYTHONEXECUTABLE', None) # Making all env_vars strings clean_env_vars = clean_env(env_vars) return clean_env_vars
def generate_python_config(self): """ Update Python server configuration with the options saved in our config system. """ python_config = PYTHON_CONFIG.copy() # Server options cmd = self.get_conf('advanced/module', 'pylsp') host = self.get_conf('advanced/host', '127.0.0.1') port = self.get_conf('advanced/port', 2087) # Pycodestyle cs_exclude = self.get_conf('pycodestyle/exclude', '').split(',') cs_filename = self.get_conf('pycodestyle/filename', '').split(',') cs_select = self.get_conf('pycodestyle/select', '').split(',') cs_ignore = self.get_conf('pycodestyle/ignore', '').split(',') cs_max_line_length = self.get_conf('pycodestyle/max_line_length', 79) pycodestyle = { 'enabled': self.get_conf('pycodestyle'), 'exclude': [exclude.strip() for exclude in cs_exclude if exclude], 'filename': [filename.strip() for filename in cs_filename if filename], 'select': [select.strip() for select in cs_select if select], 'ignore': [ignore.strip() for ignore in cs_ignore if ignore], 'hangClosing': False, 'maxLineLength': cs_max_line_length } # Linting - Pyflakes pyflakes = {'enabled': self.get_conf('pyflakes')} # Pydocstyle convention = self.get_conf('pydocstyle/convention') if convention == 'Custom': ds_ignore = self.get_conf('pydocstyle/ignore', '').split(',') ds_select = self.get_conf('pydocstyle/select', '').split(',') ds_add_ignore = [] ds_add_select = [] else: ds_ignore = [] ds_select = [] ds_add_ignore = self.get_conf('pydocstyle/ignore', '').split(',') ds_add_select = self.get_conf('pydocstyle/select', '').split(',') pydocstyle = { 'enabled': self.get_conf('pydocstyle'), 'convention': convention, 'addIgnore': [ignore.strip() for ignore in ds_add_ignore if ignore], 'addSelect': [select.strip() for select in ds_add_select if select], 'ignore': [ignore.strip() for ignore in ds_ignore if ignore], 'select': [select.strip() for select in ds_select if select], 'match': self.get_conf('pydocstyle/match'), 'matchDir': self.get_conf('pydocstyle/match_dir') } # Autoformatting configuration formatter = self.get_conf('formatting') formatter = 'pyls_black' if formatter == 'black' else formatter formatters = ['autopep8', 'yapf', 'pyls_black'] formatter_options = { fmt: { 'enabled': fmt == formatter } for fmt in formatters } if formatter == 'pyls_black': formatter_options['pyls_black']['line_length'] = cs_max_line_length # PyLS-Spyder configuration group_cells = self.get_conf('group_cells', section='outline_explorer') display_block_comments = self.get_conf('show_comments', section='outline_explorer') pyls_spyder_options = { 'enable_block_comments': display_block_comments, 'group_cells': group_cells } # Jedi configuration if self.get_conf('default', section='main_interpreter'): environment = None env_vars = None else: environment = self.get_conf('custom_interpreter', section='main_interpreter') env_vars = os.environ.copy() # external interpreter should not use internal PYTHONPATH env_vars.pop('PYTHONPATH', None) if running_in_mac_app(): env_vars.pop('PYTHONHOME', None) jedi = { 'environment': environment, 'extra_paths': self.get_conf('spyder_pythonpath', section='main', default=[]), 'env_vars': env_vars, } jedi_completion = { 'enabled': self.get_conf('code_completion'), 'include_params': self.get_conf('enable_code_snippets', section='completions') } jedi_signature_help = {'enabled': self.get_conf('jedi_signature_help')} jedi_definition = { 'enabled': self.get_conf('jedi_definition'), 'follow_imports': self.get_conf('jedi_definition/follow_imports') } # Advanced external_server = self.get_conf('advanced/external') stdio = self.get_conf('advanced/stdio') # Setup options in json python_config['cmd'] = cmd if host in self.LOCALHOST and not stdio: python_config['args'] = ('--host {host} --port {port} --tcp ' '--check-parent-process') else: python_config['args'] = '--check-parent-process' python_config['external'] = external_server python_config['stdio'] = stdio python_config['host'] = host python_config['port'] = port plugins = python_config['configurations']['pylsp']['plugins'] plugins['pycodestyle'].update(pycodestyle) plugins['pyflakes'].update(pyflakes) plugins['pydocstyle'].update(pydocstyle) plugins['pyls_spyder'].update(pyls_spyder_options) plugins['jedi'].update(jedi) plugins['jedi_completion'].update(jedi_completion) plugins['jedi_signature_help'].update(jedi_signature_help) plugins['jedi_definition'].update(jedi_definition) plugins['preload']['modules'] = self.get_conf('preload_modules') for formatter in formatters: plugins[formatter] = formatter_options[formatter] return python_config
def setup_page(self): self.ICON = ima.icon('genprefs') newcb = self.create_checkbox # --- Interface general_group = QGroupBox(_("General")) languages = LANGUAGE_CODES.items() language_choices = sorted([(val, key) for key, val in languages]) language_combo = self.create_combobox(_('Language:'), language_choices, 'interface_language', restart=True) opengl_options = ['Automatic', 'Desktop', 'Software', 'GLES'] opengl_choices = list(zip(opengl_options, [c.lower() for c in opengl_options])) opengl_combo = self.create_combobox(_('Rendering engine:'), opengl_choices, 'opengl', restart=True) single_instance_box = newcb(_("Use a single instance"), 'single_instance', tip=_("Set this to open external<br> " "Python files in an already running " "instance (Requires a restart)")) prompt_box = newcb(_("Prompt when exiting"), 'prompt_on_exit') popup_console_box = newcb(_("Show internal Spyder errors to report " "them to Github"), 'show_internal_errors') check_updates = newcb(_("Check for updates on startup"), 'check_updates_on_startup') # Decide if it's possible to activate or not single instance mode if running_in_mac_app(): self.set_option("single_instance", True) single_instance_box.setEnabled(False) comboboxes_advanced_layout = QHBoxLayout() cbs_adv_grid = QGridLayout() cbs_adv_grid.addWidget(language_combo.label, 0, 0) cbs_adv_grid.addWidget(language_combo.combobox, 0, 1) cbs_adv_grid.addWidget(opengl_combo.label, 1, 0) cbs_adv_grid.addWidget(opengl_combo.combobox, 1, 1) comboboxes_advanced_layout.addLayout(cbs_adv_grid) comboboxes_advanced_layout.addStretch(1) general_layout = QVBoxLayout() general_layout.addLayout(comboboxes_advanced_layout) general_layout.addWidget(single_instance_box) general_layout.addWidget(prompt_box) general_layout.addWidget(popup_console_box) general_layout.addWidget(check_updates) general_group.setLayout(general_layout) # --- Theme interface_group = QGroupBox(_("Interface")) vertdock_box = newcb(_("Vertical title bars in panes"), 'vertical_dockwidget_titlebars') verttabs_box = newcb(_("Vertical tabs in panes"), 'vertical_tabs') animated_box = newcb(_("Animated toolbars and panes"), 'animated_docks') tear_off_box = newcb(_("Tear off menus"), 'tear_off_menus', tip=_("Set this to detach any<br> " "menu from the main window")) margin_box = newcb(_("Custom margin for panes:"), 'use_custom_margin') margin_spin = self.create_spinbox("", _("pixels"), 'custom_margin', 0, 0, 30) margin_box.toggled.connect(margin_spin.spinbox.setEnabled) margin_box.toggled.connect(margin_spin.slabel.setEnabled) margin_spin.spinbox.setEnabled(self.get_option('use_custom_margin')) margin_spin.slabel.setEnabled(self.get_option('use_custom_margin')) cursor_box = newcb(_("Cursor blinking:"), 'use_custom_cursor_blinking') cursor_spin = self.create_spinbox( "", _("ms"), 'custom_cursor_blinking', default=QApplication.cursorFlashTime(), min_=0, max_=5000, step=100) cursor_box.toggled.connect(cursor_spin.spinbox.setEnabled) cursor_box.toggled.connect(cursor_spin.slabel.setEnabled) cursor_spin.spinbox.setEnabled( self.get_option('use_custom_cursor_blinking')) cursor_spin.slabel.setEnabled( self.get_option('use_custom_cursor_blinking')) margins_cursor_layout = QGridLayout() margins_cursor_layout.addWidget(margin_box, 0, 0) margins_cursor_layout.addWidget(margin_spin.spinbox, 0, 1) margins_cursor_layout.addWidget(margin_spin.slabel, 0, 2) margins_cursor_layout.addWidget(cursor_box, 1, 0) margins_cursor_layout.addWidget(cursor_spin.spinbox, 1, 1) margins_cursor_layout.addWidget(cursor_spin.slabel, 1, 2) margins_cursor_layout.setColumnStretch(2, 100) # Layout interface interface_layout = QVBoxLayout() interface_layout.addWidget(vertdock_box) interface_layout.addWidget(verttabs_box) interface_layout.addWidget(animated_box) interface_layout.addWidget(tear_off_box) interface_layout.addLayout(margins_cursor_layout) interface_group.setLayout(interface_layout) # --- Status bar sbar_group = QGroupBox(_("Status bar")) show_status_bar = newcb(_("Show status bar"), 'show_status_bar') memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable', tip=self.main.mem_status.toolTip()) memory_spin = self.create_spinbox("", _(" ms"), 'memory_usage/timeout', min_=100, max_=1000000, step=100) memory_box.toggled.connect(memory_spin.setEnabled) memory_spin.setEnabled(self.get_option('memory_usage/enable')) memory_box.setEnabled(self.main.mem_status.is_supported()) memory_spin.setEnabled(self.main.mem_status.is_supported()) cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable', tip=self.main.cpu_status.toolTip()) cpu_spin = self.create_spinbox("", _(" ms"), 'cpu_usage/timeout', min_=100, max_=1000000, step=100) cpu_box.toggled.connect(cpu_spin.setEnabled) cpu_spin.setEnabled(self.get_option('cpu_usage/enable')) cpu_box.setEnabled(self.main.cpu_status.is_supported()) cpu_spin.setEnabled(self.main.cpu_status.is_supported()) status_bar_o = self.get_option('show_status_bar') show_status_bar.toggled.connect(memory_box.setEnabled) show_status_bar.toggled.connect(memory_spin.setEnabled) show_status_bar.toggled.connect(cpu_box.setEnabled) show_status_bar.toggled.connect(cpu_spin.setEnabled) memory_box.setEnabled(status_bar_o) memory_spin.setEnabled(status_bar_o) cpu_box.setEnabled(status_bar_o) cpu_spin.setEnabled(status_bar_o) # Layout status bar cpu_memory_layout = QGridLayout() cpu_memory_layout.addWidget(memory_box, 0, 0) cpu_memory_layout.addWidget(memory_spin, 0, 1) cpu_memory_layout.addWidget(cpu_box, 1, 0) cpu_memory_layout.addWidget(cpu_spin, 1, 1) sbar_layout = QVBoxLayout() sbar_layout.addWidget(show_status_bar) sbar_layout.addLayout(cpu_memory_layout) sbar_group.setLayout(sbar_layout) # --- Screen resolution Group (hidpi) screen_resolution_group = QGroupBox(_("Screen resolution")) screen_resolution_bg = QButtonGroup(screen_resolution_group) screen_resolution_label = QLabel(_("Configuration for high DPI " "screens<br><br>" "Please see " "<a href=\"{0}\">{0}</a><> " "for more information about " "these options (in " "English).").format(HDPI_QT_PAGE)) screen_resolution_label.setWordWrap(True) normal_radio = self.create_radiobutton( _("Normal"), 'normal_screen_resolution', button_group=screen_resolution_bg) auto_scale_radio = self.create_radiobutton( _("Enable auto high DPI scaling"), 'high_dpi_scaling', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays"), restart=True) custom_scaling_radio = self.create_radiobutton( _("Set a custom high DPI scaling"), 'high_dpi_custom_scale_factor', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays when " "auto scaling does not work"), restart=True) custom_scaling_edit = self.create_lineedit( "", 'high_dpi_custom_scale_factors', tip=_("Enter values for different screens " "separated by semicolons ';', " "float values are supported"), alignment=Qt.Horizontal, regex=r"[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*", restart=True) normal_radio.toggled.connect(custom_scaling_edit.setDisabled) auto_scale_radio.toggled.connect(custom_scaling_edit.setDisabled) custom_scaling_radio.toggled.connect(custom_scaling_edit.setEnabled) # Layout Screen resolution screen_resolution_layout = QVBoxLayout() screen_resolution_layout.addWidget(screen_resolution_label) screen_resolution_inner_layout = QGridLayout() screen_resolution_inner_layout.addWidget(normal_radio, 0, 0) screen_resolution_inner_layout.addWidget(auto_scale_radio, 1, 0) screen_resolution_inner_layout.addWidget(custom_scaling_radio, 2, 0) screen_resolution_inner_layout.addWidget(custom_scaling_edit, 2, 1) screen_resolution_layout.addLayout(screen_resolution_inner_layout) screen_resolution_group.setLayout(screen_resolution_layout) tabs = QTabWidget() tabs.addTab(self.create_tab(screen_resolution_group, interface_group), _("Interface")) tabs.addTab(self.create_tab(general_group, sbar_group), _("Advanced Settings")) vlayout = QVBoxLayout() vlayout.addWidget(tabs) self.setLayout(vlayout)
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 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')) os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCREEN_SCALE_FACTORS'] = '' 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 mainwindow.main() return if lock_created: # Start a new instance from spyder.app import mainwindow 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 mainwindow.main()
def run_python_script_in_terminal(fname, wdir, args, interact, debug, python_args, executable=None): """ Run Python script in an external system terminal. :str wdir: working directory, may be empty. """ if executable is None: executable = get_python_executable() # If fname or python_exe contains spaces, it can't be ran on Windows, so we # have to enclose them in quotes. Also wdir can come with / as os.sep, so # we need to take care of it. if os.name == 'nt': fname = '"' + fname + '"' wdir = wdir.replace('/', '\\') executable = '"' + executable + '"' p_args = [executable] p_args += get_python_args(fname, python_args, interact, debug, args) if os.name == 'nt': cmd = 'start cmd.exe /K "' if wdir: cmd += 'cd ' + wdir + ' && ' cmd += ' '.join(p_args) + '"' + ' ^&^& exit' # Command line and cwd have to be converted to the filesystem # encoding before passing them to subprocess, but only for # Python 2. # See https://bugs.python.org/issue1759845#msg74142 and # spyder-ide/spyder#1856. if PY2: cmd = encoding.to_fs_from_unicode(cmd) wdir = encoding.to_fs_from_unicode(wdir) try: if wdir: run_shell_command(cmd, cwd=wdir) else: run_shell_command(cmd) except WindowsError: from qtpy.QtWidgets import QMessageBox from spyder.config.base import _ QMessageBox.critical( None, _('Run'), _("It was not possible to run this file in " "an external terminal"), QMessageBox.Ok) elif sys.platform.startswith('linux'): programs = [ { 'cmd': 'gnome-terminal', 'wdir-option': '--working-directory', 'execute-option': '-x' }, { 'cmd': 'konsole', 'wdir-option': '--workdir', 'execute-option': '-e' }, { 'cmd': 'xfce4-terminal', 'wdir-option': '--working-directory', 'execute-option': '-x' }, { 'cmd': 'xterm', 'wdir-option': None, 'execute-option': '-e' }, ] for program in programs: if is_program_installed(program['cmd']): arglist = [] if program['wdir-option'] and wdir: arglist += [program['wdir-option'], wdir] arglist.append(program['execute-option']) arglist += p_args if wdir: run_program(program['cmd'], arglist, cwd=wdir) else: run_program(program['cmd'], arglist) return elif sys.platform == 'darwin': f = tempfile.NamedTemporaryFile('wt', prefix='run_spyder_', suffix='.sh', dir=get_temp_dir(), delete=False) if wdir: f.write('cd {}\n'.format(wdir)) if running_in_mac_app(executable): f.write(f'export PYTHONHOME={os.environ["PYTHONPATH"]}\n') f.write(' '.join(p_args)) f.close() os.chmod(f.name, 0o777) def run_terminal_thread(): proc = run_shell_command('open -a Terminal.app ' + f.name, env={}) # Prevent race condition time.sleep(3) proc.wait() os.remove(f.name) thread = threading.Thread(target=run_terminal_thread) thread.start() else: raise NotImplementedError
QProxyStyle, QPushButton, QStyle, QToolButton, QVBoxLayout, QWidget) # Local imports from spyder.config.base import running_in_mac_app from spyder.config.manager import CONF from spyder.py3compat import configparser, is_text_string, to_text_string, PY2 from spyder.utils.icon_manager import ima from spyder.utils import programs from spyder.utils.image_path_manager import get_image_path from spyder.utils.palette import QStylePalette from spyder.utils.registries import ACTION_REGISTRY, TOOLBUTTON_REGISTRY from spyder.widgets.waitingspinner import QWaitingSpinner # Third party imports if sys.platform == "darwin" and not running_in_mac_app(): import applaunchservices as als if PY2: from urllib import unquote else: from urllib.parse import unquote # Note: How to redirect a signal from widget *a* to widget *b* ? # ---- # It has to be done manually: # * typing 'SIGNAL("clicked()")' works # * typing 'signalstr = "clicked()"; SIGNAL(signalstr)' won't work # Here is an example of how to do it: # (self.listwidget is widget *a* and self is widget *b*)
SYMPY_REQVER = '>=0.7.3' # ============================================================================= # Descriptions # NOTE: We declare our dependencies in **alphabetical** order # If some dependencies are limited to some systems only, add a 'display' key. # See 'applaunchservices' for an example. # ============================================================================= # List of descriptions DESCRIPTIONS = [ {'modname': "applaunchservices", 'package_name': "applaunchservices", 'features': _("Notify macOS that Spyder can open Python files"), 'required_version': APPLAUNCHSERVICES_REQVER, 'display': sys.platform == "darwin" and not running_in_mac_app()}, {'modname': "atomicwrites", 'package_name': "atomicwrites", 'features': _("Atomic file writes in the Editor"), 'required_version': ATOMICWRITES_REQVER}, {'modname': "chardet", 'package_name': "chardet", 'features': _("Character encoding auto-detection for the Editor"), 'required_version': CHARDET_REQVER}, {'modname': "cloudpickle", 'package_name': "cloudpickle", 'features': _("Handle communications between kernel and frontend"), 'required_version': CLOUDPICKLE_REQVER}, {'modname': "cookiecutter", 'package_name': "cookiecutter", 'features': _("Create projects from cookiecutter templates"),
def createEditor(self, parent, option, index, object_explorer=False): """Overriding method createEditor""" val_type = index.sibling(index.row(), 1).data() self.sig_open_editor.emit() if index.column() < 3: return None if self.show_warning(index): answer = QMessageBox.warning( self.parent(), _("Warning"), _("Opening this variable can be slow\n\n" "Do you want to continue anyway?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: return None try: value = self.get_value(index) if value is None: return None except ImportError as msg: self.sig_editor_shown.emit() module = str(msg).split("'")[1] if module in ['pandas', 'numpy']: if module == 'numpy': val_type = 'array' else: val_type = 'dataframe, series' message = _("Spyder is unable to show the {val_type} or object" " you're trying to view because <tt>{module}</tt>" " is not installed. ") if running_in_mac_app(): message += _("Please consider using the full version of " "the Spyder MacOS application.<br>") else: message += _("Please install this package in your Spyder " "environment.<br>") QMessageBox.critical( self.parent(), _("Error"), message.format(val_type=val_type, module=module)) return else: if running_in_mac_app() or is_pynsist(): message = _("Spyder is unable to show the variable you're" " trying to view because the module " "<tt>{module}</tt> is not supported in the " "Spyder Lite application.<br>") else: message = _("Spyder is unable to show the variable you're" " trying to view because the module " "<tt>{module}</tt> is not found in your " "Spyder environment. Please install this " "package in this environment.<br>") QMessageBox.critical(self.parent(), _("Error"), message.format(module=module)) return except Exception as msg: QMessageBox.critical( self.parent(), _("Error"), _("Spyder was unable to retrieve the value of " "this variable from the console.<br><br>" "The error message was:<br>" "%s") % to_text_string(msg)) return key = index.model().get_key(index) readonly = (isinstance(value, (tuple, set)) or self.parent().readonly or not is_known_type(value)) # CollectionsEditor for a list, tuple, dict, etc. if isinstance(value, (list, set, tuple, dict)) and not object_explorer: from spyder.widgets.collectionseditor import CollectionsEditor editor = CollectionsEditor(parent=parent) editor.setup(value, key, icon=self.parent().windowIcon(), readonly=readonly) self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for a Numpy array elif (isinstance(value, (ndarray, MaskedArray)) and ndarray is not FakeObject and not object_explorer): editor = ArrayEditor(parent=parent) if not editor.setup_and_check(value, title=key, readonly=readonly): return self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for an images elif (isinstance(value, Image) and ndarray is not FakeObject and Image is not FakeObject and not object_explorer): arr = array(value) editor = ArrayEditor(parent=parent) if not editor.setup_and_check(arr, title=key, readonly=readonly): return conv_func = lambda arr: Image.fromarray(arr, mode=value.mode) self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly, conv=conv_func)) return None # DataFrameEditor for a pandas dataframe, series or index elif (isinstance(value, (DataFrame, Index, Series)) and DataFrame is not FakeObject and not object_explorer): editor = DataFrameEditor(parent=parent) if not editor.setup_and_check(value, title=key): return editor.dataModel.set_format(index.model().dataframe_format) editor.sig_option_changed.connect(self.change_option) self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QDateEdit and QDateTimeEdit for a dates or datetime respectively elif isinstance(value, datetime.date) and not object_explorer: if readonly: self.sig_editor_shown.emit() return None else: if isinstance(value, datetime.datetime): editor = QDateTimeEdit(value, parent=parent) # Needed to handle NaT values # See spyder-ide/spyder#8329 try: value.time() except ValueError: self.sig_editor_shown.emit() return None else: editor = QDateEdit(value, parent=parent) editor.setCalendarPopup(True) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) self.sig_editor_shown.emit() return editor # TextEditor for a long string elif is_text_string(value) and len(value) > 40 and not object_explorer: te = TextEditor(None, parent=parent) if te.setup_and_check(value): editor = TextEditor(value, key, readonly=readonly, parent=parent) self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QLineEdit for an individual value (int, float, short string, etc) elif is_editable_type(value) and not object_explorer: if readonly: self.sig_editor_shown.emit() return None else: editor = QLineEdit(parent=parent) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) editor.setAlignment(Qt.AlignLeft) # This is making Spyder crash because the QLineEdit that it's # been modified is removed and a new one is created after # evaluation. So the object on which this method is trying to # act doesn't exist anymore. # editor.returnPressed.connect(self.commitAndCloseEditor) self.sig_editor_shown.emit() return editor # ObjectExplorer for an arbitrary Python object else: show_callable_attributes = index.model().show_callable_attributes show_special_attributes = index.model().show_special_attributes dataframe_format = index.model().dataframe_format if show_callable_attributes is None: show_callable_attributes = False if show_special_attributes is None: show_special_attributes = False from spyder.plugins.variableexplorer.widgets.objectexplorer \ import ObjectExplorer editor = ObjectExplorer( value, name=key, parent=parent, show_callable_attributes=show_callable_attributes, show_special_attributes=show_special_attributes, dataframe_format=dataframe_format, readonly=readonly) editor.sig_option_changed.connect(self.change_option) self.create_dialog( editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None
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 options, args = get_options() # Store variable to be used in self.restart (restart spyder instance) os.environ['SPYDER_ARGS'] = str(sys.argv[1:]) 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 mainwindow.main() return if lock_created: # Start a new instance from spyder.app import mainwindow 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 mainwindow.main()