示例#1
0
    def __init__(self, parent, main):
        GeneralConfigPage.__init__(self, parent, main)
        self.cus_exec_radio = None
        self.pyexec_edit = None
        self.cus_exec_combo = None

        # Python executable selection (initializing default values as well)
        executable = self.get_option('executable', get_python_executable())
        if self.get_option('default'):
            executable = get_python_executable()

        if not osp.isfile(executable):
            # This is absolutely necessary, in case the Python interpreter
            # executable has been moved since last Spyder execution (following
            # a Python distribution upgrade for example)
            self.set_option('executable', get_python_executable())
        elif executable.endswith('pythonw.exe'):
            # That should not be necessary because this case is already taken
            # care of by the `get_python_executable` function but, this was
            # implemented too late, so we have to fix it here too, in case
            # the Python executable has already been set with pythonw.exe:
            self.set_option('executable',
                            executable.replace("pythonw.exe", "python.exe"))

        if not self.get_option('default'):
            if not self.get_option('custom_interpreter'):
                self.set_option('custom_interpreter', ' ')
            self.set_custom_interpreters_list(executable)
            self.validate_custom_interpreters_list()
示例#2
0
    def __init__(self, parent, main):
        GeneralConfigPage.__init__(self, parent, main)
        self.cus_exec_radio = None
        self.pyexec_edit = None
        self.cus_exec_combo = None

        # Python executable selection (initializing default values as well)
        executable = self.get_option('executable', get_python_executable())
        if self.get_option('default'):
            executable = get_python_executable()

        if not osp.isfile(executable):
            # This is absolutely necessary, in case the Python interpreter
            # executable has been moved since last Spyder execution (following
            # a Python distribution upgrade for example)
            self.set_option('executable', get_python_executable())
        elif executable.endswith('pythonw.exe'):
            # That should not be necessary because this case is already taken
            # care of by the `get_python_executable` function but, this was
            # implemented too late, so we have to fix it here too, in case
            # the Python executable has already been set with pythonw.exe:
            self.set_option('executable',
                            executable.replace("pythonw.exe", "python.exe"))

        if not self.get_option('default'):
            if not self.get_option('custom_interpreter'):
                self.set_option('custom_interpreter', ' ')
            self.set_custom_interpreters_list(executable)
            self.validate_custom_interpreters_list()
示例#3
0
    def argv(self):
        """Command to start kernels"""
        # Python interpreter used to start kernels
        if CONF.get('main_interpreter', 'default'):
            pyexec = get_python_executable()
        else:
            # Avoid IPython adding the virtualenv on which Spyder is running
            # to the kernel sys.path
            os.environ.pop('VIRTUAL_ENV', None)
            pyexec = CONF.get('main_interpreter', 'executable')
            if not is_python_interpreter(pyexec):
                pyexec = get_python_executable()
                CONF.set('main_interpreter', 'executable', '')
                CONF.set('main_interpreter', 'default', True)
                CONF.set('main_interpreter', 'custom', False)

        # Fixes Issue #3427
        if os.name == 'nt':
            dir_pyexec = osp.dirname(pyexec)
            pyexec_w = osp.join(dir_pyexec, 'pythonw.exe')
            if osp.isfile(pyexec_w):
                pyexec = pyexec_w

        # Command used to start kernels
        kernel_cmd = [
            pyexec,
            '-m',
            'spyder_kernels.console',
            '-f',
            '{connection_file}'
        ]

        return kernel_cmd
示例#4
0
    def argv(self):
        """Command to start kernels"""
        # Python interpreter used to start kernels
        if CONF.get('main_interpreter', 'default'):
            pyexec = get_python_executable()
        else:
            # Avoid IPython adding the virtualenv on which Spyder is running
            # to the kernel sys.path
            os.environ.pop('VIRTUAL_ENV', None)
            pyexec = CONF.get('main_interpreter', 'executable')
            if not is_python_interpreter(pyexec):
                pyexec = get_python_executable()
                CONF.set('main_interpreter', 'executable', '')
                CONF.set('main_interpreter', 'default', True)
                CONF.set('main_interpreter', 'custom', False)

        # Fixes Issue #3427
        if os.name == 'nt':
            dir_pyexec = osp.dirname(pyexec)
            pyexec_w = osp.join(dir_pyexec, 'pythonw.exe')
            if osp.isfile(pyexec_w):
                pyexec = pyexec_w

        # Command used to start kernels
        kernel_cmd = [
            pyexec, '-m', 'spyder_kernels.console', '-f', '{connection_file}'
        ]

        return kernel_cmd
示例#5
0
    def get_main_interpreter(self):
        if self.get_conf('default'):
            return get_python_executable()
        else:
            executable = osp.normpath(self.get_conf('custom_interpreter'))

            # Check if custom interpreter is still present
            if osp.isfile(executable):
                return executable
            else:
                return get_python_executable()
示例#6
0
    def argv(self):
        """Command to start kernels"""
        # Python interpreter used to start kernels
        if CONF.get('main_interpreter', 'default'):
            pyexec = get_python_executable()
        else:
            # Avoid IPython adding the virtualenv on which Spyder is running
            # to the kernel sys.path
            os.environ.pop('VIRTUAL_ENV', None)
            pyexec = CONF.get('main_interpreter', 'executable')
            if not is_python_interpreter(pyexec):
                pyexec = get_python_executable()
                CONF.set('main_interpreter', 'executable', '')
                CONF.set('main_interpreter', 'default', True)
                CONF.set('main_interpreter', 'custom', False)

        # Part of spyder-ide/spyder#11819
        is_different = is_different_interpreter(pyexec)

        # Fixes spyder-ide/spyder#3427.
        if os.name == 'nt':
            dir_pyexec = osp.dirname(pyexec)
            pyexec_w = osp.join(dir_pyexec, 'pythonw.exe')
            if osp.isfile(pyexec_w):
                pyexec = pyexec_w

        # Command used to start kernels
        if is_different and is_conda_env(pyexec=pyexec):
            # If this is a conda environment we need to call an intermediate
            # activation script to correctly activate the spyder-kernel

            # If changes are needed on this section make sure you also update
            # the activation scripts at spyder/plugins/ipythonconsole/scripts/
            kernel_cmd = [
                get_activation_script(),  # This is bundled with Spyder
                get_conda_activation_script(),
                get_conda_env_path(pyexec),  # Might be external
                pyexec,
                '{connection_file}',
            ]
        else:
            kernel_cmd = [
                pyexec, '-m', 'spyder_kernels.console', '-f',
                '{connection_file}'
            ]
        logger.info('Kernel command: {}'.format(kernel_cmd))

        return kernel_cmd
示例#7
0
def test():
    """Run widget test"""
    from spyder.utils.qthelpers import qapplication
    import inspect
    import tempfile
    from unittest.mock import MagicMock

    primes_sc = inspect.getsource(primes)
    fd, script = tempfile.mkstemp(suffix='.py')
    with os.fdopen(fd, 'w') as f:
        f.write("# -*- coding: utf-8 -*-" + "\n\n")
        f.write(primes_sc + "\n\n")
        f.write("primes(100000)")

    plugin_mock = MagicMock()
    plugin_mock.CONF_SECTION = 'profiler'

    app = qapplication(test_time=5)
    widget = ProfilerWidget('test', plugin=plugin_mock)
    widget._setup()
    widget.setup()
    widget.get_conf('executable',
                    get_python_executable(),
                    section='main_interpreter')
    widget.resize(800, 600)
    widget.show()
    widget.analyze(script)
    sys.exit(app.exec_())
示例#8
0
    def register(self):
        container = self.get_container()
        preferences = self.get_plugin(Plugins.Preferences)
        statusbar = self.get_plugin(Plugins.StatusBar)

        # Register conf page
        preferences.register_plugin_preferences(self)

        # Connect signal to open preferences
        container.sig_open_preferences_requested.connect(
            self._open_interpreter_preferences)

        # Report that the interpreter has changed
        container.sig_interpreter_changed.connect(
            self._main.sig_main_interpreter_changed)

        # Add custom interpreter to list of saved ones
        container.sig_add_to_custom_interpreters_requested.connect(
            self._add_to_custom_interpreters)

        # Add status widget
        if statusbar:
            statusbar.add_status_widget(self.interpreter_status)

        # Validate that the custom interpreter from the previous session
        # still exists
        if self.get_conf('custom'):
            interpreter = self.get_conf('custom_interpreter')
            if not osp.isfile(interpreter):
                self.set_conf('custom', False)
                self.set_conf('default', True)
                self.set_conf('executable', get_python_executable())
示例#9
0
    def __init__(self, plugin, parent):
        super().__init__(plugin, parent)
        self.apply_callback = self.perform_adjustments

        self.cus_exec_radio = None
        self.pyexec_edit = None
        self.cus_exec_combo = None

        conda_env = get_list_conda_envs_cache()
        pyenv_env = get_list_pyenv_envs_cache()
        envs = {**conda_env, **pyenv_env}
        valid_custom_list = self.get_option('custom_interpreters_list')
        for env in envs.keys():
            path, _ = envs[env]
            if path not in valid_custom_list:
                valid_custom_list.append(path)
        self.set_option('custom_interpreters_list', valid_custom_list)

        # add custom_interpreter to executable selection
        executable = self.get_option('executable')

        # check if the executable is valid - use Spyder's if not
        if self.get_option('default') or not osp.isfile(executable):
            executable = get_python_executable()
        elif not self.get_option('custom_interpreter'):
            self.set_option('custom_interpreter', ' ')

        plugin._add_to_custom_interpreters(executable)
        self.validate_custom_interpreters_list()
示例#10
0
def test_pytestrunner_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()
    mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    runner = PyTestRunner(None, 'results')
    config = Config('py.test', 'wdir')
    runner.start(config, ['pythondir'])

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    mock_process.setProcessEnvironment.assert_called_once_with(
        mock_environment)
    mock_process.start.assert_called_once_with(
        get_python_executable(), ['-m', 'pytest', '--junit-xml', 'results'])

    mock_environment.insert.assert_any_call('VAR', 'VALUE')
    # mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
    # TODO: Find out why above test fails
    mock_remove.called_once_with('results')
示例#11
0
    def start(self, config, pythonpath):
        """
        Start process which will run the unit test suite.

        The process is run in the working directory specified in 'config',
        with the directories in `pythonpath` added to the Python path for the
        test process. The test results are written to the file
        `self.resultfilename`. The standard output and error are also recorded.
        Once the process is finished, `self.finished()` will be called.

        Parameters
        ----------
        config : TestConfig
            Unit test configuration.
        pythonpath : list of str
            List of directories to be added to the Python path

        Raises
        ------
        RuntimeError
            If process failed to start.
        """
        self.process = self._prepare_process(config, pythonpath)
        executable = get_python_executable()
        p_args = self.create_argument_list()
        try:
            os.remove(self.resultfilename)
        except OSError:
            pass
        self.process.start(executable, p_args)
        running = self.process.waitForStarted()
        if not running:
            raise RuntimeError
示例#12
0
    def argv(self):
        """Command to start kernels"""
        # Python interpreter used to start kernels
        if self.default_interpreter:
            pyexec = get_python_executable()
        else:
            # Avoid IPython adding the virtualenv on which Spyder is running
            # to the kernel sys.path
            os.environ.pop('VIRTUAL_ENV', None)
            pyexec = CONF.get('main_interpreter', 'executable')

        # Fixes Issue #3427
        if os.name == 'nt':
            dir_pyexec = osp.dirname(pyexec)
            pyexec_w = osp.join(dir_pyexec, 'pythonw.exe')
            if osp.isfile(pyexec_w):
                pyexec = pyexec_w

        # Command used to start kernels
        utils_path = osp.join(self.spy_path, 'utils', 'ipython')
        kernel_cmd = [
            pyexec,
            osp.join("%s" % utils_path, "start_kernel.py"),
            '-f',
            '{connection_file}'
        ]

        return kernel_cmd
示例#13
0
    def start(self, config, pythonpath):
        """
        Start process which will run the unit test suite.

        The process is run in the working directory specified in 'config',
        with the directories in `pythonpath` added to the Python path for the
        test process. The test results are written to the file
        `self.resultfilename`. The standard output and error are also recorded.
        Once the process is finished, `self.finished()` will be called.

        Parameters
        ----------
        config : TestConfig
            Unit test configuration.
        pythonpath : list of str
            List of directories to be added to the Python path

        Raises
        ------
        RuntimeError
            If process failed to start.
        """
        self.process = self._prepare_process(config, pythonpath)
        executable = get_python_executable()
        p_args = self.create_argument_list()
        try:
            os.remove(self.resultfilename)
        except OSError:
            pass
        self.process.start(executable, p_args)
        running = self.process.waitForStarted()
        if not running:
            raise RuntimeError
示例#14
0
 def set_custom_interpreters_list(self, display_value, value):
     """Update the list of interpreters used and the current one."""
     custom_list = self.get_option('custom_list')
     if ((display_value, value) not in custom_list
             and value != get_python_executable()):
         custom_list.append((display_value, value))
         self.set_option('custom_list', custom_list)
示例#15
0
 def validate_custom_interpreters_list(self):
     """Check that the used custom interpreters are still valid."""
     custom_list = self.get_option('custom_interpreters_list')
     valid_custom_list = []
     for value in custom_list:
         if (osp.isfile(value) and programs.is_python_interpreter(value)
                 and value != get_python_executable()):
             valid_custom_list.append(value)
     self.set_option('custom_interpreters_list', valid_custom_list)
示例#16
0
 def register(self):
     # Validate that the custom interpreter from the previous session
     # still exists
     if self.get_conf_option('custom'):
         interpreter = self.get_conf_option('custom_interpreter')
         if not osp.isfile(interpreter):
             self.set_conf_option('custom', False)
             self.set_conf_option('default', True)
             self.set_conf_option('executable', get_python_executable())
示例#17
0
 def python_executable_switched(self, custom):
     """Python executable default/custom radio button has been toggled"""
     def_pyexec = get_python_executable()
     cust_pyexec = self.pyexec_edit.text()
     if not is_text_string(cust_pyexec):
         cust_pyexec = to_text_string(cust_pyexec.toUtf8(), 'utf-8')
     if def_pyexec != cust_pyexec:
         if custom:
             self.warn_python_compatibility(cust_pyexec)
示例#18
0
 def python_executable_switched(self, custom):
     """Python executable default/custom radio button has been toggled"""
     def_pyexec = get_python_executable()
     cust_pyexec = self.pyexec_edit.text()
     if not is_text_string(cust_pyexec):
         cust_pyexec = to_text_string(cust_pyexec.toUtf8(), 'utf-8')
     if def_pyexec != cust_pyexec:
         if custom:
             self.warn_python_compatibility(cust_pyexec)
示例#19
0
 def validate_custom_interpreters_list(self):
     """Check that the used custom interpreters are still valid."""
     custom_list = self.get_option('custom_interpreters_list')
     valid_custom_list = []
     for value in custom_list:
         if (osp.isfile(value) and programs.is_python_interpreter(value)
                 and value != get_python_executable()):
             valid_custom_list.append(value)
     self.set_option('custom_interpreters_list', valid_custom_list)
示例#20
0
    def get_interpreter():
        """
        Return the Python interpreter to be used in notebooks.

        This function looks in the Spyder configuration to determine and
        return the Python interpreter to be used in notebooks, which is the
        same as is used in consoles.

        Returns
        -------
        The file name of the interpreter
        """
        if CONF.get('main_interpreter', 'default'):
            pyexec = get_python_executable()
        else:
            pyexec = CONF.get('main_interpreter', 'executable')
            if not is_python_interpreter(pyexec):
                pyexec = get_python_executable()
        return pyexec
示例#21
0
    def __init__(self, plugin, parent):
        super().__init__(plugin, parent)
        self.apply_callback = self.perform_adjustments

        self.cus_exec_radio = None
        self.pyexec_edit = None
        self.cus_exec_combo = None

        conda_env = get_list_conda_envs_cache()
        pyenv_env = get_list_pyenv_envs_cache()
        envs = {**conda_env, **pyenv_env}
        valid_custom_list = self.get_option('custom_interpreters_list')
        for env in envs.keys():
            path, _ = envs[env]
            if path not in valid_custom_list:
                valid_custom_list.append(path)
        self.set_option('custom_interpreters_list', valid_custom_list)

        # Python executable selection (initializing default values as well)
        executable = self.get_option('executable', get_python_executable())
        if self.get_option('default'):
            executable = get_python_executable()

        if not osp.isfile(executable):
            # This is absolutely necessary, in case the Python interpreter
            # executable has been moved since last Spyder execution (following
            # a Python distribution upgrade for example)
            self.set_option('executable', get_python_executable())
        elif executable.endswith('pythonw.exe'):
            # That should not be necessary because this case is already taken
            # care of by the `get_python_executable` function but, this was
            # implemented too late, so we have to fix it here too, in case
            # the Python executable has already been set with pythonw.exe:
            self.set_option('executable',
                            executable.replace("pythonw.exe", "python.exe"))

        if not self.get_option('default'):
            if not self.get_option('custom_interpreter'):
                self.set_option('custom_interpreter', ' ')

            plugin._add_to_custom_interpreters(executable)
            self.validate_custom_interpreters_list()
示例#22
0
    def argv(self):
        """Command to start kernels"""
        # Python interpreter used to start kernels
        if CONF.get('main_interpreter', 'default'):
            pyexec = get_python_executable()
        else:
            pyexec = CONF.get('main_interpreter', 'executable')
            if not is_python_interpreter(pyexec):
                pyexec = get_python_executable()
                CONF.set('main_interpreter', 'executable', '')
                CONF.set('main_interpreter', 'default', True)
                CONF.set('main_interpreter', 'custom', False)

        # Part of spyder-ide/spyder#11819
        is_different = is_different_interpreter(pyexec)

        # Command used to start kernels
        if is_different and is_conda_env(pyexec=pyexec):
            # If this is a conda environment we need to call an intermediate
            # activation script to correctly activate the spyder-kernel

            # If changes are needed on this section make sure you also update
            # the activation scripts at spyder/plugins/ipythonconsole/scripts/
            kernel_cmd = [
                get_activation_script(),  # This is bundled with Spyder
                get_conda_activation_script(pyexec),
                get_conda_env_path(pyexec),  # Might be external
                pyexec,
                '{connection_file}',
            ]
        else:
            kernel_cmd = [
                pyexec,
                '-m',
                'spyder_kernels.console',
                '-f',
                '{connection_file}'
            ]
        logger.info('Kernel command: {}'.format(kernel_cmd))

        return kernel_cmd
示例#23
0
    def start(self, config, pythonpath):
        """
        Start process which will run the unit test suite.

        The process is run in the working directory specified in 'config',
        with the directories in `pythonpath` added to the Python path for the
        test process. The test results are written to the file
        `self.resultfilename`. The standard output and error are also recorded.
        Once the process is finished, `self.finished()` will be called.

        Parameters
        ----------
        config : TestConfig
            Unit test configuration.
        pythonpath : list of str
            List of directories to be added to the Python path

        Raises
        ------
        RuntimeError
            If process failed to start.
        """
        wdir = config.wdir

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.process.setWorkingDirectory(wdir)
        self.process.finished.connect(self.finished)

        if pythonpath is not None:
            env = [
                to_text_string(_pth)
                for _pth in self.process.systemEnvironment()
            ]
            add_pathlist_to_PYTHONPATH(env, pythonpath)
            processEnvironment = QProcessEnvironment()
            for envItem in env:
                envName, separator, envValue = envItem.partition('=')
                processEnvironment.insert(envName, envValue)
            self.process.setProcessEnvironment(processEnvironment)

        executable = get_python_executable()
        p_args = ['-m', self.module] + self.create_argument_list()

        try:
            os.remove(self.resultfilename)
        except OSError:
            pass

        self.process.start(executable, p_args)
        running = self.process.waitForStarted()
        if not running:
            raise RuntimeError
示例#24
0
 def python_executable_changed(self, pyexec):
     """Custom Python executable value has been changed"""
     if not self.cus_exec_radio.isChecked():
         return
     if not is_text_string(pyexec):
         pyexec = to_text_string(pyexec.toUtf8(), 'utf-8')
     if programs.is_python_interpreter(pyexec):
         self.warn_python_compatibility(pyexec)
     else:
         QMessageBox.warning(self, _('Warning'),
                 _("You selected an invalid Python interpreter for the "
                   "console so the previous interpreter will stay. Please "
                   "make sure to select a valid one."), QMessageBox.Ok)
         self.pyexec_edit.setText(get_python_executable())
         return
示例#25
0
 def python_executable_changed(self, pyexec):
     """Custom Python executable value has been changed"""
     if not self.cus_exec_radio.isChecked():
         return
     if not is_text_string(pyexec):
         pyexec = to_text_string(pyexec.toUtf8(), 'utf-8')
     if programs.is_python_interpreter(pyexec):
         self.warn_python_compatibility(pyexec)
     else:
         QMessageBox.warning(
             self, _('Warning'),
             _("You selected an invalid Python interpreter for the "
               "console so the previous interpreter will stay. Please "
               "make sure to select a valid one."), QMessageBox.Ok)
         self.pyexec_edit.setText(get_python_executable())
         return
def test_pytestrunner_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()
    mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    MockZMQStreamReader = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.pytestrunner.ZmqStreamReader',
        MockZMQStreamReader)
    mock_reader = MockZMQStreamReader()
    mock_reader.port = 42

    runner = PyTestRunner(None, 'results')
    config = Config('pytest', 'wdir')
    runner.start(config, ['pythondir'])

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    mock_process.setProcessEnvironment.assert_called_once_with(
        mock_environment)

    workerfile = os.path.abspath(
        os.path.join(os.path.dirname(__file__), os.pardir, 'pytestworker.py'))
    mock_process.start.assert_called_once_with(
            get_python_executable(), [workerfile, '42'])

    mock_environment.insert.assert_any_call('VAR', 'VALUE')
    # mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
    # TODO: Find out why above test fails
    mock_remove.called_once_with('results')

    assert runner.reader is mock_reader
示例#27
0
    def on_initialize(self):
        container = self.get_container()

        # Connect signal to open preferences
        container.sig_open_preferences_requested.connect(
            self._open_interpreter_preferences)

        # Add custom interpreter to list of saved ones
        container.sig_add_to_custom_interpreters_requested.connect(
            self._add_to_custom_interpreters)

        # Validate that the custom interpreter from the previous session
        # still exists
        if self.get_conf('custom'):
            interpreter = self.get_conf('custom_interpreter')
            if not osp.isfile(interpreter):
                self.set_conf('custom', False)
                self.set_conf('default', True)
                self.set_conf('executable', get_python_executable())
示例#28
0
def test_pytestrunner_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()
    mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    MockZMQStreamReader = Mock()
    monkeypatch.setattr('spyder_unittest.backend.pytestrunner.ZmqStreamReader',
                        MockZMQStreamReader)
    mock_reader = MockZMQStreamReader()
    mock_reader.port = 42

    runner = PyTestRunner(None, 'results')
    config = Config('pytest', 'wdir')
    runner.start(config, ['pythondir'])

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    mock_process.setProcessEnvironment.assert_called_once_with(
        mock_environment)

    workerfile = os.path.abspath(
        os.path.join(os.path.dirname(__file__), os.pardir, 'pytestworker.py'))
    mock_process.start.assert_called_once_with(get_python_executable(),
                                               [workerfile, '42'])

    mock_environment.insert.assert_any_call('VAR', 'VALUE')
    # mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
    # TODO: Find out why above test fails
    mock_remove.called_once_with('results')

    assert runner.reader is mock_reader
示例#29
0
    def __init__(self,
                 parent=None,
                 fname=None,
                 wdir=None,
                 interact=False,
                 debug=False,
                 post_mortem=False,
                 path=[],
                 python_args='',
                 arguments='',
                 stand_alone=None,
                 umr_enabled=True,
                 umr_namelist=[],
                 umr_verbose=True,
                 pythonstartup=None,
                 pythonexecutable=None,
                 external_interpreter=False,
                 monitor_enabled=True,
                 mpl_backend=None,
                 ets_backend='qt4',
                 qt_api=None,
                 merge_output_channels=False,
                 colorize_sys_stderr=False,
                 autorefresh_timeout=3000,
                 autorefresh_state=True,
                 light_background=True,
                 menu_actions=None,
                 show_buttons_inside=True,
                 show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside', 'pyqt5')

        self.namespacebrowser = None  # namespace browser widget!
        self.dialog_manager = DialogManager()

        self.stand_alone = stand_alone  # stand alone settings (None: plugin)
        self.interact = interact
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.external_interpreter = external_interpreter
        self.monitor_enabled = monitor_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umr_enabled = umr_enabled
        self.umr_namelist = umr_namelist
        self.umr_verbose = umr_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state

        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None

        ExternalShellBase.__init__(self,
                                   parent=parent,
                                   fname=fname,
                                   wdir=wdir,
                                   history_filename='history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert is_text_string(python_args)
            self.python_args = python_args

        assert is_text_string(arguments)
        self.arguments = arguments

        self.connection_file = None
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(self.interact)
        self.debug_action.setChecked(debug)

        self.introspection_socket = None
        self.is_interpreter = fname is None

        if self.is_interpreter:
            self.terminate_button.hide()

        self.post_mortem_action.setChecked(post_mortem
                                           and not self.is_interpreter)

        # Additional python path list
        self.path = path
        self.shell.path = path
    def start(self, wdir=None, args=None, pythonpath=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(self.finished)
        self.stop_button.clicked.connect(self.process.kill)

        if pythonpath is not None:
            env = [
                to_text_string(_pth)
                for _pth in self.process.systemEnvironment()
            ]
            add_pathlist_to_PYTHONPATH(env, pythonpath)
            processEnvironment = QProcessEnvironment()
            for envItem in env:
                envName, separator, envValue = envItem.partition('=')
                processEnvironment.insert(envName, envValue)
            self.process.setProcessEnvironment(processEnvironment)

        self.output = ''
        self.error_output = ''

        # remove previous results, since memory_profiler appends to output file
        # instead of replacing
        if osp.isfile(self.DATAPATH):
            os.remove(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):
            filename = osp.normpath(filename).replace(os.sep, '/')
            p_args = [
                '-m', 'memory_profiler', '-o', '"' + self.DATAPATH + '"',
                '"' + filename + '"'
            ]
            if args:
                p_args.extend(programs.shell_split(args))
            executable = get_python_executable()
            executable += ' ' + ' '.join(p_args)
            executable = executable.replace(os.sep, '/')
            self.process.start(executable)
        else:
            p_args = ['-m', 'memory_profiler', '-o', self.DATAPATH, filename]
            if args:
                p_args.extend(programs.shell_split(args))
            executable = get_python_executable()
            self.process.start(executable, p_args)

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                                 _("Process failed to start"))
示例#31
0
    def start(self,
              fname,
              wdir=None,
              args='',
              interact=False,
              debug=False,
              python=True,
              python_args='',
              post_mortem=True):
        """
        Start new console

        fname:
          string: filename of script to run
          None: open an interpreter
        wdir: working directory
        args: command line options of the Python script
        interact: inspect script interactively after its execution
        debug: run pdb
        python: True: Python interpreter, False: terminal
        python_args: additionnal Python interpreter command line options
                   (option "-u" is mandatory, see widgets.externalshell package)
        """
        # Note: fname is None <=> Python interpreter
        if fname is not None and not is_text_string(fname):
            fname = to_text_string(fname)
        if wdir is not None and not is_text_string(wdir):
            wdir = to_text_string(wdir)

        if fname is not None and fname in self.filenames:
            index = self.filenames.index(fname)
            if self.get_option('single_tab'):
                old_shell = self.shellwidgets[index]
                if old_shell.is_running():
                    runconfig = get_run_configuration(fname)
                    if runconfig is None or runconfig.show_kill_warning:
                        answer = QMessageBox.question(
                            self, self.get_plugin_title(),
                            _("%s is already running in a separate process.\n"
                              "Do you want to kill the process before starting "
                              "a new one?") % osp.basename(fname),
                            QMessageBox.Yes | QMessageBox.Cancel)
                    else:
                        answer = QMessageBox.Yes

                    if answer == QMessageBox.Yes:
                        old_shell.process.kill()
                        old_shell.process.waitForFinished()
                    else:
                        return
                self.close_console(index)
        else:
            index = self.tabwidget.count()

        # Creating a new external shell
        pythonpath = self.main.get_spyder_pythonpath()
        light_background = self.get_option('light_background')
        show_elapsed_time = self.get_option('show_elapsed_time')
        if python:
            if CONF.get('main_interpreter', 'default'):
                pythonexecutable = get_python_executable()
                external_interpreter = False
            else:
                pythonexecutable = CONF.get('main_interpreter', 'executable')
                external_interpreter = True
            if self.get_option('pythonstartup/default'):
                pythonstartup = None
            else:
                pythonstartup = self.get_option('pythonstartup', None)
            monitor_enabled = self.get_option('monitor/enabled')
            mpl_backend = self.get_option('matplotlib/backend/value')
            ets_backend = self.get_option('ets_backend')
            qt_api = self.get_option('qt/api')
            if qt_api not in ('pyqt', 'pyside', 'pyqt5'):
                qt_api = None
            merge_output_channels = self.get_option('merge_output_channels')
            colorize_sys_stderr = self.get_option('colorize_sys_stderr')
            umr_enabled = CONF.get('main_interpreter', 'umr/enabled')
            umr_namelist = CONF.get('main_interpreter', 'umr/namelist')
            umr_verbose = CONF.get('main_interpreter', 'umr/verbose')
            ar_timeout = CONF.get('variable_explorer', 'autorefresh/timeout')
            ar_state = CONF.get('variable_explorer', 'autorefresh')

            sa_settings = None
            shellwidget = ExternalPythonShell(
                self,
                fname,
                wdir,
                interact,
                debug,
                post_mortem=post_mortem,
                path=pythonpath,
                python_args=python_args,
                arguments=args,
                stand_alone=sa_settings,
                pythonstartup=pythonstartup,
                pythonexecutable=pythonexecutable,
                external_interpreter=external_interpreter,
                umr_enabled=umr_enabled,
                umr_namelist=umr_namelist,
                umr_verbose=umr_verbose,
                ets_backend=ets_backend,
                monitor_enabled=monitor_enabled,
                mpl_backend=mpl_backend,
                qt_api=qt_api,
                merge_output_channels=merge_output_channels,
                colorize_sys_stderr=colorize_sys_stderr,
                autorefresh_timeout=ar_timeout,
                autorefresh_state=ar_state,
                light_background=light_background,
                menu_actions=self.menu_actions,
                show_buttons_inside=False,
                show_elapsed_time=show_elapsed_time)
            shellwidget.sig_pdb.connect(
                lambda fname, lineno, shellwidget=shellwidget: self.
                pdb_has_stopped(fname, lineno, shellwidget))
            self.register_widget_shortcuts(shellwidget.shell)
        else:
            if os.name == 'posix':
                cmd = 'gnome-terminal'
                args = []
                if programs.is_program_installed(cmd):
                    if wdir:
                        args.extend(['--working-directory=%s' % wdir])
                    programs.run_program(cmd, args)
                    return
                cmd = 'konsole'
                if programs.is_program_installed(cmd):
                    if wdir:
                        args.extend(['--workdir', wdir])
                    programs.run_program(cmd, args)
                    return
            shellwidget = ExternalSystemShell(
                self,
                wdir,
                path=pythonpath,
                light_background=light_background,
                menu_actions=self.menu_actions,
                show_buttons_inside=False,
                show_elapsed_time=show_elapsed_time)

        # Code completion / calltips
        shellwidget.shell.setMaximumBlockCount(
            self.get_option('max_line_count'))
        shellwidget.shell.set_font(self.get_plugin_font())
        shellwidget.shell.toggle_wrap_mode(self.get_option('wrap'))
        shellwidget.shell.set_calltips(self.get_option('calltips'))
        shellwidget.shell.set_codecompletion_auto(
            self.get_option('codecompletion/auto'))
        shellwidget.shell.set_codecompletion_case(
            self.get_option('codecompletion/case_sensitive'))
        shellwidget.shell.set_codecompletion_enter(
            self.get_option('codecompletion/enter_key'))
        if python and self.help is not None:
            shellwidget.shell.set_help(self.help)
            shellwidget.shell.set_help_enabled(
                CONF.get('help', 'connect/python_console'))
        if self.historylog is not None:
            self.historylog.add_history(shellwidget.shell.history_filename)
            shellwidget.shell.append_to_history.connect(
                self.historylog.append_to_history)
            shellwidget.shell.go_to_error.connect(self.go_to_error)
            shellwidget.shell.focus_changed.connect(
                lambda: self.focus_changed.emit())
        if python:
            if self.main.editor is not None:
                shellwidget.open_file.connect(self.open_file_in_spyder)
            if fname is None:
                self.python_count += 1
                tab_name = "Python %d" % self.python_count
                tab_icon1 = ima.icon('python')
                tab_icon2 = ima.icon('python_t')
            else:
                tab_name = osp.basename(fname)
                tab_icon1 = ima.icon('run')
                tab_icon2 = ima.icon('terminated')
        else:
            fname = id(shellwidget)
            if os.name == 'nt':
                tab_name = _("Command Window")
            else:
                tab_name = _("Terminal")
            self.terminal_count += 1
            tab_name += (" %d" % self.terminal_count)
            tab_icon1 = ima.icon('cmdprompt')
            tab_icon2 = ima.icon('cmdprompt_t')
        self.shellwidgets.insert(index, shellwidget)
        self.filenames.insert(index, fname)
        self.icons.insert(index, (tab_icon1, tab_icon2))
        if index is None:
            index = self.tabwidget.addTab(shellwidget, tab_name)
        else:
            self.tabwidget.insertTab(index, shellwidget, tab_name)

        shellwidget.started.connect(
            lambda sid=id(shellwidget): self.process_started(sid))
        shellwidget.sig_finished.connect(
            lambda sid=id(shellwidget): self.process_finished(sid))
        self.find_widget.set_editor(shellwidget.shell)
        self.tabwidget.setTabToolTip(index, fname if wdir is None else wdir)
        self.tabwidget.setCurrentIndex(index)
        if self.dockwidget and not self.ismaximized:
            self.dockwidget.setVisible(True)
            self.dockwidget.raise_()

        shellwidget.set_icontext_visible(self.get_option('show_icontext'))

        # Start process and give focus to console
        shellwidget.start_shell()
示例#32
0
    def setup_page(self):
        interface_group = QGroupBox(_("Interface"))
        newcb = self.create_checkbox
        singletab_box = newcb(_("One tab per script"), 'single_tab')
        showtime_box = newcb(_("Show elapsed time"), 'show_elapsed_time')
        icontext_box = newcb(_("Show icons and text"), 'show_icontext')

        # Interface Group
        interface_layout = QVBoxLayout()
        interface_layout.addWidget(singletab_box)
        interface_layout.addWidget(showtime_box)
        interface_layout.addWidget(icontext_box)
        interface_group.setLayout(interface_layout)

        # Source Code Group
        display_group = QGroupBox(_("Source code"))
        buffer_spin = self.create_spinbox(_("Buffer: "),
                                          _(" lines"),
                                          'max_line_count',
                                          min_=0,
                                          max_=1000000,
                                          step=100,
                                          tip=_("Set maximum line count"))
        wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
        merge_channels_box = newcb(
            _("Merge process standard output/error channels"),
            'merge_output_channels',
            tip=_("Merging the output channels of the process means that\n"
                  "the standard error won't be written in red anymore,\n"
                  "but this has the effect of speeding up display."))
        colorize_sys_stderr_box = newcb(
            _("Colorize standard error channel using ANSI escape codes"),
            'colorize_sys_stderr',
            tip=_("This method is the only way to have colorized standard\n"
                  "error channel when the output channels have been "
                  "merged."))
        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setEnabled)
        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setChecked)
        colorize_sys_stderr_box.setEnabled(
            self.get_option('merge_output_channels'))

        display_layout = QVBoxLayout()
        display_layout.addWidget(buffer_spin)
        display_layout.addWidget(wrap_mode_box)
        display_layout.addWidget(merge_channels_box)
        display_layout.addWidget(colorize_sys_stderr_box)
        display_group.setLayout(display_layout)

        # Background Color Group
        bg_group = QGroupBox(_("Background color"))
        bg_label = QLabel(
            _("This option will be applied the next time "
              "a Python console or a terminal is opened."))
        bg_label.setWordWrap(True)
        lightbg_box = newcb(_("Light background (white color)"),
                            'light_background')
        bg_layout = QVBoxLayout()
        bg_layout.addWidget(bg_label)
        bg_layout.addWidget(lightbg_box)
        bg_group.setLayout(bg_layout)

        # Advanced settings
        source_group = QGroupBox(_("Source code"))
        completion_box = newcb(_("Automatic code completion"),
                               'codecompletion/auto')
        case_comp_box = newcb(_("Case sensitive code completion"),
                              'codecompletion/case_sensitive')
        comp_enter_box = newcb(_("Enter key selects completion"),
                               'codecompletion/enter_key')
        calltips_box = newcb(_("Display balloon tips"), 'calltips')

        source_layout = QVBoxLayout()
        source_layout.addWidget(completion_box)
        source_layout.addWidget(case_comp_box)
        source_layout.addWidget(comp_enter_box)
        source_layout.addWidget(calltips_box)
        source_group.setLayout(source_layout)

        # PYTHONSTARTUP replacement
        pystartup_group = QGroupBox(_("PYTHONSTARTUP replacement"))
        pystartup_bg = QButtonGroup(pystartup_group)
        pystartup_label = QLabel(
            _("This option will override the "
              "PYTHONSTARTUP environment variable which\n"
              "defines the script to be executed during "
              "the Python console startup."))
        def_startup_radio = self.create_radiobutton(
            _("Default PYTHONSTARTUP script"),
            'pythonstartup/default',
            button_group=pystartup_bg)
        cus_startup_radio = self.create_radiobutton(
            _("Use the following startup script:"),
            'pythonstartup/custom',
            button_group=pystartup_bg)
        pystartup_file = self.create_browsefile('', 'pythonstartup', '',
                                                filters=_("Python scripts")+\
                                                " (*.py)")
        def_startup_radio.toggled.connect(pystartup_file.setDisabled)
        cus_startup_radio.toggled.connect(pystartup_file.setEnabled)

        pystartup_layout = QVBoxLayout()
        pystartup_layout.addWidget(pystartup_label)
        pystartup_layout.addWidget(def_startup_radio)
        pystartup_layout.addWidget(cus_startup_radio)
        pystartup_layout.addWidget(pystartup_file)
        pystartup_group.setLayout(pystartup_layout)

        # Monitor Group
        monitor_group = QGroupBox(_("Monitor"))
        monitor_label = QLabel(
            _("The monitor provides introspection "
              "features to console: code completion, "
              "calltips and variable explorer. "
              "Because it relies on several modules, "
              "disabling the monitor may be useful "
              "to accelerate console startup."))
        monitor_label.setWordWrap(True)
        monitor_box = newcb(_("Enable monitor"), 'monitor/enabled')
        for obj in (completion_box, case_comp_box, comp_enter_box,
                    calltips_box):
            monitor_box.toggled.connect(obj.setEnabled)
            obj.setEnabled(self.get_option('monitor/enabled'))

        monitor_layout = QVBoxLayout()
        monitor_layout.addWidget(monitor_label)
        monitor_layout.addWidget(monitor_box)
        monitor_group.setLayout(monitor_layout)

        # Qt Group
        opts = [
            (_("Default library"), 'default'),
            ('PyQt5', 'pyqt5'),
            ('PyQt4', 'pyqt'),
            ('PySide', 'pyside'),
        ]
        qt_group = QGroupBox(_("Qt-Python Bindings"))
        qt_setapi_box = self.create_combobox(
            _("Library:") + "   ",
            opts,
            'qt/api',
            default='default',
            tip=_("This option will act on<br> "
                  "libraries such as Matplotlib, guidata "
                  "or ETS"))

        qt_layout = QVBoxLayout()
        qt_layout.addWidget(qt_setapi_box)
        qt_group.setLayout(qt_layout)

        # Matplotlib Group
        mpl_group = QGroupBox(_("Graphics"))
        mpl_label = QLabel(
            _("Decide which backend to use to display graphics. "
              "If unsure, please select the <b>Automatic</b> "
              "backend.<br><br>"
              "<b>Note:</b> We support a very limited number "
              "of backends in our Python consoles. If you "
              "prefer to work with a different one, please use "
              "an IPython console."))
        mpl_label.setWordWrap(True)

        backends = [("Automatic", 0), ("None", 1)]
        if not os.name == 'nt' and programs.is_module_installed('_tkinter'):
            backends.append(("Tkinter", 2))
        backends = tuple(backends)

        mpl_backend_box = self.create_combobox(
            _("Backend:") + "   ",
            backends,
            'matplotlib/backend/value',
            tip=_("This option will be applied the "
                  "next time a console is opened."))

        mpl_installed = programs.is_module_installed('matplotlib')
        mpl_layout = QVBoxLayout()
        mpl_layout.addWidget(mpl_label)
        mpl_layout.addWidget(mpl_backend_box)
        mpl_group.setLayout(mpl_layout)
        mpl_group.setEnabled(mpl_installed)

        # ETS Group
        ets_group = QGroupBox(_("Enthought Tool Suite"))
        ets_label = QLabel(
            _("Enthought Tool Suite (ETS) supports "
              "PyQt4 (qt4) and wxPython (wx) graphical "
              "user interfaces."))
        ets_label.setWordWrap(True)
        ets_edit = self.create_lineedit(_("ETS_TOOLKIT:"),
                                        'ets_backend',
                                        alignment=Qt.Horizontal)

        ets_layout = QVBoxLayout()
        ets_layout.addWidget(ets_label)
        ets_layout.addWidget(ets_edit)
        ets_group.setLayout(ets_layout)

        if CONF.get('main_interpreter', 'default'):
            interpreter = get_python_executable()
        else:
            interpreter = CONF.get('main_interpreter', 'executable')
        ets_group.setEnabled(
            programs.is_module_installed("enthought.etsconfig.api",
                                         interpreter=interpreter))

        tabs = QTabWidget()
        tabs.addTab(self.create_tab(interface_group, display_group, bg_group),
                    _("Display"))
        tabs.addTab(self.create_tab(monitor_group, source_group),
                    _("Introspection"))
        tabs.addTab(self.create_tab(pystartup_group), _("Advanced settings"))
        tabs.addTab(self.create_tab(qt_group, mpl_group, ets_group),
                    _("External modules"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
示例#33
0
 def set_custom_interpreters_list(self, value):
     """Update the list of interpreters used and the current one."""
     custom_list = self.get_option('custom_interpreters_list')
     if value not in custom_list and value != get_python_executable():
         custom_list.append(value)
         self.set_option('custom_interpreters_list', custom_list)
示例#34
0
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))
        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)
            # Prevent race condition
            time.sleep(3)
            proc.wait()
            os.remove(f.name)

        thread = threading.Thread(target=run_terminal_thread)
        thread.start()
    else:
        raise NotImplementedError
示例#35
0
    def setup_page(self):
        interface_group = QGroupBox(_("Interface"))
        newcb = self.create_checkbox
        singletab_box = newcb(_("One tab per script"), 'single_tab')
        showtime_box = newcb(_("Show elapsed time"), 'show_elapsed_time')
        icontext_box = newcb(_("Show icons and text"), 'show_icontext')

        # Interface Group
        interface_layout = QVBoxLayout()
        interface_layout.addWidget(singletab_box)
        interface_layout.addWidget(showtime_box)
        interface_layout.addWidget(icontext_box)
        interface_group.setLayout(interface_layout)
        
        # Source Code Group
        display_group = QGroupBox(_("Source code"))
        buffer_spin = self.create_spinbox(
                            _("Buffer: "), _(" lines"),
                            'max_line_count', min_=0, max_=1000000, step=100,
                            tip=_("Set maximum line count"))
        wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
        merge_channels_box = newcb(
               _("Merge process standard output/error channels"),
               'merge_output_channels',
               tip=_("Merging the output channels of the process means that\n"
                     "the standard error won't be written in red anymore,\n"
                     "but this has the effect of speeding up display."))
        colorize_sys_stderr_box = newcb(
               _("Colorize standard error channel using ANSI escape codes"),
               'colorize_sys_stderr',
               tip=_("This method is the only way to have colorized standard\n"
                     "error channel when the output channels have been "
                     "merged."))
        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setEnabled)
        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setChecked)
        colorize_sys_stderr_box.setEnabled(
                                    self.get_option('merge_output_channels'))
        
        display_layout = QVBoxLayout()
        display_layout.addWidget(buffer_spin)
        display_layout.addWidget(wrap_mode_box)
        display_layout.addWidget(merge_channels_box)
        display_layout.addWidget(colorize_sys_stderr_box)
        display_group.setLayout(display_layout)
        
        # Background Color Group
        bg_group = QGroupBox(_("Background color"))
        bg_label = QLabel(_("This option will be applied the next time "
                            "a Python console or a terminal is opened."))
        bg_label.setWordWrap(True)
        lightbg_box = newcb(_("Light background (white color)"),
                            'light_background')
        bg_layout = QVBoxLayout()
        bg_layout.addWidget(bg_label)
        bg_layout.addWidget(lightbg_box)
        bg_group.setLayout(bg_layout)

        # Advanced settings
        source_group = QGroupBox(_("Source code"))
        completion_box = newcb(_("Automatic code completion"),
                               'codecompletion/auto')
        case_comp_box = newcb(_("Case sensitive code completion"),
                              'codecompletion/case_sensitive')
        comp_enter_box = newcb(_("Enter key selects completion"),
                               'codecompletion/enter_key')
        calltips_box = newcb(_("Display balloon tips"), 'calltips')
        
        source_layout = QVBoxLayout()
        source_layout.addWidget(completion_box)
        source_layout.addWidget(case_comp_box)
        source_layout.addWidget(comp_enter_box)
        source_layout.addWidget(calltips_box)
        source_group.setLayout(source_layout)
        
        # PYTHONSTARTUP replacement
        pystartup_group = QGroupBox(_("PYTHONSTARTUP replacement"))
        pystartup_bg = QButtonGroup(pystartup_group)
        pystartup_label = QLabel(_("This option will override the "
                                   "PYTHONSTARTUP environment variable which\n"
                                   "defines the script to be executed during "
                                   "the Python console startup."))
        def_startup_radio = self.create_radiobutton(
                                        _("Default PYTHONSTARTUP script"),
                                        'pythonstartup/default',
                                        button_group=pystartup_bg)
        cus_startup_radio = self.create_radiobutton(
                                        _("Use the following startup script:"),
                                        'pythonstartup/custom',
                                        button_group=pystartup_bg)
        pystartup_file = self.create_browsefile('', 'pythonstartup', '',
                                                filters=_("Python scripts")+\
                                                " (*.py)")
        def_startup_radio.toggled.connect(pystartup_file.setDisabled)
        cus_startup_radio.toggled.connect(pystartup_file.setEnabled)
        
        pystartup_layout = QVBoxLayout()
        pystartup_layout.addWidget(pystartup_label)
        pystartup_layout.addWidget(def_startup_radio)
        pystartup_layout.addWidget(cus_startup_radio)
        pystartup_layout.addWidget(pystartup_file)
        pystartup_group.setLayout(pystartup_layout)
        
        # Monitor Group
        monitor_group = QGroupBox(_("Monitor"))
        monitor_label = QLabel(_("The monitor provides introspection "
                                 "features to console: code completion, "
                                 "calltips and variable explorer. "
                                 "Because it relies on several modules, "
                                 "disabling the monitor may be useful "
                                 "to accelerate console startup."))
        monitor_label.setWordWrap(True)
        monitor_box = newcb(_("Enable monitor"), 'monitor/enabled')
        for obj in (completion_box, case_comp_box, comp_enter_box,
                    calltips_box):
            monitor_box.toggled.connect(obj.setEnabled)
            obj.setEnabled(self.get_option('monitor/enabled'))
        
        monitor_layout = QVBoxLayout()
        monitor_layout.addWidget(monitor_label)
        monitor_layout.addWidget(monitor_box)
        monitor_group.setLayout(monitor_layout)
        
        # Qt Group
        opts = [
            (_("Default library"), 'default'),
            ('PyQt5', 'pyqt5'),
            ('PyQt4', 'pyqt'),
            ('PySide', 'pyside'),
        ]
        qt_group = QGroupBox(_("Qt-Python Bindings"))
        qt_setapi_box = self.create_combobox(
                         _("Library:") + "   ", opts,
                         'qt/api', default='default',
                         tip=_("This option will act on<br> "
                               "libraries such as Matplotlib, guidata "
                               "or ETS"))

        qt_layout = QVBoxLayout()
        qt_layout.addWidget(qt_setapi_box)
        qt_group.setLayout(qt_layout)

        # Matplotlib Group
        mpl_group = QGroupBox(_("Graphics"))
        mpl_label = QLabel(_("Decide which backend to use to display graphics. "
                              "If unsure, please select the <b>Automatic</b> "
                              "backend.<br><br>"
                              "<b>Note:</b> We support a very limited number "
                              "of backends in our Python consoles. If you "
                              "prefer to work with a different one, please use "
                              "an IPython console."))
        mpl_label.setWordWrap(True)

        backends = [(_("Automatic"), 0), (_("None"), 1)]
        if not os.name == 'nt' and programs.is_module_installed('_tkinter'):
            backends.append( ("Tkinter", 2) )
        backends = tuple(backends)

        mpl_backend_box = self.create_combobox( _("Backend:")+"   ", backends,
                                       'matplotlib/backend/value',
                                       tip=_("This option will be applied the "
                                             "next time a console is opened."))

        mpl_installed = programs.is_module_installed('matplotlib')
        mpl_layout = QVBoxLayout()
        mpl_layout.addWidget(mpl_label)
        mpl_layout.addWidget(mpl_backend_box)
        mpl_group.setLayout(mpl_layout)
        mpl_group.setEnabled(mpl_installed)

        # ETS Group
        ets_group = QGroupBox(_("Enthought Tool Suite"))
        ets_label = QLabel(_("Enthought Tool Suite (ETS) supports "
                             "PyQt4 (qt4) and wxPython (wx) graphical "
                             "user interfaces."))
        ets_label.setWordWrap(True)
        ets_edit = self.create_lineedit(_("ETS_TOOLKIT:"), 'ets_backend',
                                        alignment=Qt.Horizontal)

        ets_layout = QVBoxLayout()
        ets_layout.addWidget(ets_label)
        ets_layout.addWidget(ets_edit)
        ets_group.setLayout(ets_layout)

        if CONF.get('main_interpreter','default'):
            interpreter = get_python_executable()
        else:
            interpreter = CONF.get('main_interpreter', 'executable')
        ets_group.setEnabled(programs.is_module_installed(
                                                    "enthought.etsconfig.api",
                                                    interpreter=interpreter))

        tabs = QTabWidget()
        tabs.addTab(self.create_tab(interface_group, display_group,
                                    bg_group),
                    _("Display"))
        tabs.addTab(self.create_tab(monitor_group, source_group),
                    _("Introspection"))
        tabs.addTab(self.create_tab(pystartup_group), _("Advanced settings"))
        tabs.addTab(self.create_tab(qt_group, mpl_group, ets_group),
                    _("External modules"))
        
        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
示例#36
0
    def __init__(self, parent=None, fname=None, wdir=None,
                 interact=False, debug=False, post_mortem=False,
                 path=[], python_args='',
                 ipykernel=False, arguments='', stand_alone=None,
                 umr_enabled=True, umr_namelist=[], umr_verbose=True,
                 pythonstartup=None, pythonexecutable=None,
                 external_interpreter=False,
                 monitor_enabled=True, mpl_backend=None, ets_backend='qt4',
                 qt_api=None, merge_output_channels=False,
                 colorize_sys_stderr=False, autorefresh_timeout=3000,
                 autorefresh_state=True, light_background=True,
                 menu_actions=None, show_buttons_inside=True,
                 show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside', 'pyqt5')

        self.namespacebrowser = None # namespace browser widget!
        self.dialog_manager = DialogManager()

        self.stand_alone = stand_alone # stand alone settings (None: plugin)
        self.interact = interact
        self.is_ipykernel = ipykernel
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.external_interpreter = external_interpreter
        self.monitor_enabled = monitor_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umr_enabled = umr_enabled
        self.umr_namelist = umr_namelist
        self.umr_verbose = umr_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state
                
        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None
        
        ExternalShellBase.__init__(self, parent=parent, fname=fname, wdir=wdir,
                                   history_filename='history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert is_text_string(python_args)
            self.python_args = python_args
        
        assert is_text_string(arguments)
        self.arguments = arguments
        
        self.connection_file = None

        if self.is_ipykernel:
            self.interact = False
            # Running our custom startup script for IPython kernels:
            # (see spyder/widgets/externalshell/start_ipython_kernel.py)
            self.fname = get_module_source_path(
                'spyder.widgets.externalshell', 'start_ipython_kernel.py')
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(self.interact)
        self.debug_action.setChecked(debug)
        
        
        self.introspection_socket = None
        self.is_interpreter = fname is None
        
        if self.is_interpreter:
            self.terminate_button.hide()
            
        self.post_mortem_action.setChecked(post_mortem and not self.is_interpreter)
        
        # Additional python path list
        self.path = path
        self.shell.path = path
示例#37
0
 def get_interpreter(self):
     """Get current interpreter."""
     if self.get_conf_option('default'):
         return get_python_executable()
     else:
         return self.get_conf_option('custom_interpreter')
示例#38
0
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 /c "cd %s && ' % wdir + ' '.join(p_args) + '"'
        # 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 Issue 1856
        if PY2:
            cmd = encoding.to_fs_from_unicode(cmd)
            wdir = encoding.to_fs_from_unicode(wdir)
        try:
            run_shell_command(cmd, cwd=wdir)
        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 os.name == 'posix':
        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
        # TODO: Add a fallback to OSX
    else:
        raise NotImplementedError
示例#39
0
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
示例#40
0
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 /c "cd %s && ' % wdir + ' '.join(p_args) + '"'
        # 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 Issue 1856
        if PY2:
            cmd = encoding.to_fs_from_unicode(cmd)
            wdir = encoding.to_fs_from_unicode(wdir)
        try:
            run_shell_command(cmd, cwd=wdir)
        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 os.name == 'posix':
        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
        # TODO: Add a fallback to OSX
    else:
        raise NotImplementedError
示例#41
0
    def start(self, fname, wdir=None, args='', interact=False, debug=False,
              python=True, python_args='', post_mortem=True):
        """
        Start new console

        fname:
          string: filename of script to run
          None: open an interpreter
        wdir: working directory
        args: command line options of the Python script
        interact: inspect script interactively after its execution
        debug: run pdb
        python: True: Python interpreter, False: terminal
        python_args: additionnal Python interpreter command line options
                   (option "-u" is mandatory, see widgets.externalshell package)
        """
        # Note: fname is None <=> Python interpreter
        if fname is not None and not is_text_string(fname):
            fname = to_text_string(fname)
        if wdir is not None and not is_text_string(wdir):
            wdir = to_text_string(wdir)
        
        if fname is not None and fname in self.filenames:
            index = self.filenames.index(fname)
            if self.get_option('single_tab'):
                old_shell = self.shellwidgets[index]
                if old_shell.is_running():
                    runconfig = get_run_configuration(fname)
                    if runconfig is None or runconfig.show_kill_warning:
                        answer = QMessageBox.question(self, self.get_plugin_title(),
                            _("%s is already running in a separate process.\n"
                              "Do you want to kill the process before starting "
                              "a new one?") % osp.basename(fname),
                            QMessageBox.Yes | QMessageBox.Cancel)
                    else:
                        answer = QMessageBox.Yes

                    if answer == QMessageBox.Yes:
                        old_shell.process.kill()
                        old_shell.process.waitForFinished()
                    else:
                        return
                self.close_console(index)
        else:
            index = self.tabwidget.count()

        # Creating a new external shell
        pythonpath = self.main.get_spyder_pythonpath()
        light_background = self.get_option('light_background')
        show_elapsed_time = self.get_option('show_elapsed_time')
        if python:
            if CONF.get('main_interpreter', 'default'):
                pythonexecutable = get_python_executable()
                external_interpreter = False
            else:
                pythonexecutable = CONF.get('main_interpreter', 'executable')
                external_interpreter = True
            if self.get_option('pythonstartup/default'):
                pythonstartup = None
            else:
                pythonstartup = self.get_option('pythonstartup', None)
            monitor_enabled = self.get_option('monitor/enabled')
            mpl_backend = self.get_option('matplotlib/backend/value')
            ets_backend = self.get_option('ets_backend')
            qt_api = self.get_option('qt/api')
            if qt_api not in ('pyqt', 'pyside', 'pyqt5'):
                qt_api = None
            merge_output_channels = self.get_option('merge_output_channels')
            colorize_sys_stderr = self.get_option('colorize_sys_stderr')
            umr_enabled = CONF.get('main_interpreter', 'umr/enabled')
            umr_namelist = CONF.get('main_interpreter', 'umr/namelist')
            umr_verbose = CONF.get('main_interpreter', 'umr/verbose')
            ar_timeout = CONF.get('variable_explorer', 'autorefresh/timeout')
            ar_state = CONF.get('variable_explorer', 'autorefresh')

            sa_settings = None
            shellwidget = ExternalPythonShell(self, fname, wdir,
                           interact, debug, post_mortem=post_mortem,
                           path=pythonpath,
                           python_args=python_args,
                           arguments=args, stand_alone=sa_settings,
                           pythonstartup=pythonstartup,
                           pythonexecutable=pythonexecutable,
                           external_interpreter=external_interpreter,
                           umr_enabled=umr_enabled, umr_namelist=umr_namelist,
                           umr_verbose=umr_verbose, ets_backend=ets_backend,
                           monitor_enabled=monitor_enabled,
                           mpl_backend=mpl_backend, qt_api=qt_api,
                           merge_output_channels=merge_output_channels,
                           colorize_sys_stderr=colorize_sys_stderr,
                           autorefresh_timeout=ar_timeout,
                           autorefresh_state=ar_state,
                           light_background=light_background,
                           menu_actions=self.menu_actions,
                           show_buttons_inside=False,
                           show_elapsed_time=show_elapsed_time)
            shellwidget.sig_pdb.connect(
                              lambda fname, lineno, shellwidget=shellwidget:
                              self.pdb_has_stopped(fname, lineno, shellwidget))
            self.register_widget_shortcuts(shellwidget.shell)
        else:
            if os.name == 'posix':
                cmd = 'gnome-terminal'
                args = []
                if programs.is_program_installed(cmd):
                    if wdir:
                        args.extend(['--working-directory=%s' % wdir])
                    programs.run_program(cmd, args)
                    return
                cmd = 'konsole'
                if programs.is_program_installed(cmd):
                    if wdir:
                        args.extend(['--workdir', wdir])
                    programs.run_program(cmd, args)
                    return
            shellwidget = ExternalSystemShell(self, wdir, path=pythonpath,
                                          light_background=light_background,
                                          menu_actions=self.menu_actions,
                                          show_buttons_inside=False,
                                          show_elapsed_time=show_elapsed_time)
        
        # Code completion / calltips
        shellwidget.shell.setMaximumBlockCount(
                                            self.get_option('max_line_count') )
        shellwidget.shell.set_font( self.get_plugin_font() )
        shellwidget.shell.toggle_wrap_mode( self.get_option('wrap') )
        shellwidget.shell.set_calltips( self.get_option('calltips') )
        shellwidget.shell.set_codecompletion_auto(
                            self.get_option('codecompletion/auto') )
        shellwidget.shell.set_codecompletion_case(
                            self.get_option('codecompletion/case_sensitive') )
        shellwidget.shell.set_codecompletion_enter(
                            self.get_option('codecompletion/enter_key') )
        if python and self.help is not None:
            shellwidget.shell.set_help(self.help)
            shellwidget.shell.set_help_enabled(
                               CONF.get('help', 'connect/python_console'))
        if self.historylog is not None:
            self.historylog.add_history(shellwidget.shell.history_filename)
            shellwidget.shell.append_to_history.connect(
                                             self.historylog.append_to_history)
            shellwidget.shell.go_to_error.connect(self.go_to_error)
            shellwidget.shell.focus_changed.connect(        
                                             lambda: self.focus_changed.emit())
        if python:
            if self.main.editor is not None:
                shellwidget.open_file.connect(self.open_file_in_spyder)
            if fname is None:
                self.python_count += 1
                tab_name = "Python %d" % self.python_count
                tab_icon1 = ima.icon('python')
                tab_icon2 = ima.icon('python_t')
            else:
                tab_name = osp.basename(fname)
                tab_icon1 = ima.icon('run')
                tab_icon2 = ima.icon('terminated')
        else:
            fname = id(shellwidget)
            if os.name == 'nt':
                tab_name = _("Command Window")
            else:
                tab_name = _("Terminal")
            self.terminal_count += 1
            tab_name += (" %d" % self.terminal_count)
            tab_icon1 = ima.icon('cmdprompt')
            tab_icon2 = ima.icon('cmdprompt_t')
        self.shellwidgets.insert(index, shellwidget)
        self.filenames.insert(index, fname)
        self.icons.insert(index, (tab_icon1, tab_icon2))
        if index is None:
            index = self.tabwidget.addTab(shellwidget, tab_name)
        else:
            self.tabwidget.insertTab(index, shellwidget, tab_name)
        
        shellwidget.started.connect(
                     lambda sid=id(shellwidget): self.process_started(sid))
        shellwidget.sig_finished.connect(
                     lambda sid=id(shellwidget): self.process_finished(sid))
        self.find_widget.set_editor(shellwidget.shell)
        self.tabwidget.setTabToolTip(index, fname if wdir is None else wdir)
        self.tabwidget.setCurrentIndex(index)
        if self.dockwidget and not self.ismaximized:
            self.dockwidget.setVisible(True)
            self.dockwidget.raise_()

        shellwidget.set_icontext_visible(self.get_option('show_icontext'))

        # Start process and give focus to console
        shellwidget.start_shell()