Пример #1
0
def _init_key_config(parent):
    """Initialize the key config.

    Args:
        parent: The parent to use for the KeyConfigParser.
    """
    args = objreg.get('args')
    try:
        key_config = keyconf.KeyConfigParser(standarddir.config(), 'keys.conf',
                                             args.relaxed_config,
                                             parent=parent)
    except (keyconf.KeyConfigError, UnicodeDecodeError) as e:
        log.init.exception(e)
        errstr = "Error while reading key config:\n"
        if e.lineno is not None:
            errstr += "In line {}: ".format(e.lineno)
        error.handle_fatal_exc(e, args, "Error while reading key config!",
                               pre_text=errstr)
        # We didn't really initialize much so far, so we just quit hard.
        sys.exit(usertypes.Exit.err_key_config)
    else:
        objreg.register('key-config', key_config)
        if standarddir.config() is not None:
            save_manager = objreg.get('save-manager')
            filename = os.path.join(standarddir.config(), 'keys.conf')
            save_manager.add_saveable(
                'key-config', key_config.save, key_config.config_dirty,
                config_opt=('general', 'auto-save-config'), filename=filename,
                dirty=key_config.is_dirty)
Пример #2
0
    def _init_lineparser(self):
        bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks')
        os.makedirs(bookmarks_directory, exist_ok=True)

        bookmarks_subdir = os.path.join('bookmarks', 'urls')
        self._lineparser = lineparser.LineParser(
            standarddir.config(), bookmarks_subdir, parent=self)
Пример #3
0
    def __init__(self, parent=None):
        """Initialize and read quickmarks."""
        super().__init__(parent)

        self.marks = collections.OrderedDict()

        if standarddir.config() is None:
            self._lineparser = None
        else:
            self._lineparser = lineparser.LineParser(
                standarddir.config(), 'quickmarks', parent=self)
            for line in self._lineparser:
                if not line.strip():
                    # Ignore empty or whitespace-only lines.
                    continue
                try:
                    key, url = line.rsplit(maxsplit=1)
                except ValueError:
                    message.error('current', "Invalid quickmark '{}'".format(
                        line))
                else:
                    self.marks[key] = url
            filename = os.path.join(standarddir.config(), 'quickmarks')
            objreg.get('save-manager').add_saveable(
                'quickmark-manager', self.save, self.changed,
                filename=filename)
Пример #4
0
    def _init_lineparser(self):
        bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks')
        if not os.path.isdir(bookmarks_directory):
            os.makedirs(bookmarks_directory)

        bookmarks_subdir = os.path.join('bookmarks', 'urls')
        self._lineparser = lineparser.LineParser(
            standarddir.config(), bookmarks_subdir, parent=self)
Пример #5
0
def test_fake_mac_config(tmpdir, monkeypatch):
    """Test standardir.config on a fake Mac."""
    monkeypatch.setattr(sys, 'platform', 'darwin')
    monkeypatch.setenv('HOME', str(tmpdir))
    expected = str(tmpdir) + '/.qute_test'  # always with /
    standarddir._init_config(args=None)
    assert standarddir.config() == expected
Пример #6
0
 def test_config(self, monkeypatch, tmpdir):
     """Test config dir with XDG_CONFIG_HOME not set."""
     monkeypatch.setenv('HOME', str(tmpdir))
     monkeypatch.delenv('XDG_CONFIG_HOME', raising=False)
     standarddir.init(None)
     expected = tmpdir / '.config' / 'qutebrowser_test'
     assert standarddir.config() == str(expected)
Пример #7
0
 def test_config(self):
     """Test config dir with XDG_CONFIG_HOME not set."""
     env = {'HOME': self.temp_dir, 'XDG_CONFIG_HOME': None}
     with helpers.environ_set_temp(env):
         standarddir.init(None)
         expected = os.path.join(self.temp_dir, '.config', 'qutebrowser')
         self.assertEqual(standarddir.config(), expected)
Пример #8
0
 def validate(self, value):
     if not value:
         if self._none_ok:
             return
         else:
             raise configexc.ValidationError(value, "may not be empty!")
     value = os.path.expanduser(value)
     value = os.path.expandvars(value)
     try:
         if not os.path.isabs(value):
             cfgdir = standarddir.config()
             if cfgdir is None:
                 raise configexc.ValidationError(
                     value, "must be an absolute path when not using a "
                     "config directory!")
             elif not os.path.isfile(os.path.join(cfgdir, value)):
                 raise configexc.ValidationError(
                     value, "must be a valid path relative to the config "
                     "directory!")
             else:
                 return
         elif not os.path.isfile(value):
             raise configexc.ValidationError(
                 value, "must be a valid file!")
     except UnicodeEncodeError as e:
         raise configexc.ValidationError(value, e)
Пример #9
0
def run_async(tab, cmd, *args, win_id, env, verbose=False):
    """Run a userscript after dumping page html/source.

    Raises:
        UnsupportedError if userscripts are not supported on the current
        platform.
        NotFoundError if the command could not be found.

    Args:
        tab: The WebKitTab/WebEngineTab to get the source from.
        cmd: The userscript binary to run.
        *args: The arguments to pass to the userscript.
        win_id: The window id the userscript is executed in.
        env: A dictionary of variables to add to the process environment.
        verbose: Show notifications when the command started/exited.
    """
    tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                window=win_id)
    commandrunner = runners.CommandRunner(win_id, parent=tabbed_browser)

    if os.name == 'posix':
        runner = _POSIXUserscriptRunner(tabbed_browser)
    elif os.name == 'nt':  # pragma: no cover
        runner = _WindowsUserscriptRunner(tabbed_browser)
    else:  # pragma: no cover
        raise UnsupportedError

    runner.got_cmd.connect(
        lambda cmd:
        log.commands.debug("Got userscript command: {}".format(cmd)))
    runner.got_cmd.connect(commandrunner.run_safely)
    user_agent = config.get('network', 'user-agent')
    if user_agent is not None:
        env['QUTE_USER_AGENT'] = user_agent
    config_dir = standarddir.config()
    if config_dir is not None:
        env['QUTE_CONFIG_DIR'] = config_dir
    data_dir = standarddir.data()
    if data_dir is not None:
        env['QUTE_DATA_DIR'] = data_dir
    download_dir = downloads.download_dir()
    if download_dir is not None:
        env['QUTE_DOWNLOAD_DIR'] = download_dir
    cmd_path = os.path.expanduser(cmd)

    # if cmd is not given as an absolute path, look it up
    # ~/.local/share/qutebrowser/userscripts (or $XDG_DATA_DIR)
    if not os.path.isabs(cmd_path):
        log.misc.debug("{} is no absolute path".format(cmd_path))
        cmd_path = _lookup_path(cmd)
    elif not os.path.exists(cmd_path):
        raise NotFoundError(cmd_path)
    log.misc.debug("Userscript to run: {}".format(cmd_path))

    runner.finished.connect(commandrunner.deleteLater)
    runner.finished.connect(runner.deleteLater)

    runner.prepare_run(cmd_path, *args, env=env, verbose=verbose)
    tab.dump_async(runner.store_html)
    tab.dump_async(runner.store_text, plain=True)
Пример #10
0
def _init_misc():
    """Initialize misc. config-related files."""
    save_manager = objreg.get('save-manager')
    state_config = ini.ReadWriteConfigParser(standarddir.data(), 'state')
    for sect in ['general', 'geometry']:
        try:
            state_config.add_section(sect)
        except configparser.DuplicateSectionError:
            pass
    # See commit a98060e020a4ba83b663813a4b9404edb47f28ad.
    state_config['general'].pop('fooled', None)
    objreg.register('state-config', state_config)
    save_manager.add_saveable('state-config', state_config.save)

    # We need to import this here because lineparser needs config.
    from qutebrowser.misc import lineparser
    command_history = lineparser.LimitLineParser(
        standarddir.data(), 'cmd-history',
        limit=('completion', 'cmd-history-max-items'),
        parent=objreg.get('config'))
    objreg.register('command-history', command_history)
    save_manager.add_saveable('command-history', command_history.save,
                              command_history.changed)

    # Set the QSettings path to something like
    # ~/.config/qutebrowser/qsettings/qutebrowser/qutebrowser.conf so it
    # doesn't overwrite our config.
    #
    # This fixes one of the corruption issues here:
    # https://github.com/qutebrowser/qutebrowser/issues/515

    path = os.path.join(standarddir.config(), 'qsettings')
    for fmt in [QSettings.NativeFormat, QSettings.IniFormat]:
        QSettings.setPath(fmt, QSettings.UserScope, path)
Пример #11
0
def get_diff() -> str:
    """Get a HTML diff for the old config files."""
    old_conf_lines = []  # type: typing.MutableSequence[str]
    old_key_lines = []  # type: typing.MutableSequence[str]

    for filename, dest in [('qutebrowser.conf', old_conf_lines),
                           ('keys.conf', old_key_lines)]:
        path = os.path.join(standarddir.config(), filename)

        with open(path, 'r', encoding='utf-8') as f:
            for line in f:
                if not line.strip() or line.startswith('#'):
                    continue
                dest.append(line.rstrip())

    conf_delta = difflib.unified_diff(OLD_CONF.lstrip().splitlines(),
                                      old_conf_lines)
    key_delta = difflib.unified_diff(OLD_KEYS_CONF.lstrip().splitlines(),
                                     old_key_lines)

    conf_diff = '\n'.join(conf_delta)
    key_diff = '\n'.join(key_delta)

    # pylint: disable=no-member
    # WORKAROUND for https://bitbucket.org/logilab/pylint/issue/491/
    lexer = pygments.lexers.DiffLexer()
    formatter = pygments.formatters.HtmlFormatter(
        full=True, linenos='table',
        title='Diffing pre-1.0 default config with pre-1.0 modified config')
    # pylint: enable=no-member
    return pygments.highlight(conf_diff + key_diff, lexer, formatter)
Пример #12
0
 def test_confdir_none(self, mocker):
     """Test --confdir with None given."""
     # patch makedirs to a noop so we don't really create a directory
     mocker.patch('qutebrowser.utils.standarddir.os.makedirs')
     args = types.SimpleNamespace(confdir=None, cachedir=None, datadir=None,
                                  basedir=None)
     standarddir.init(args)
     assert standarddir.config().split(os.sep)[-1] == 'qute_test'
Пример #13
0
 def test_basedir_relative(self, tmpdir):
     """Test --basedir with a relative path."""
     basedir = (tmpdir / 'basedir')
     basedir.ensure(dir=True)
     with tmpdir.as_cwd():
         args = types.SimpleNamespace(basedir='basedir')
         standarddir.init(args)
         assert standarddir.config() == str(basedir / 'config')
Пример #14
0
 def transform(self, value):
     if not value:
         return None
     value = os.path.expanduser(value)
     value = os.path.expandvars(value)
     if not os.path.isabs(value):
         value = os.path.join(standarddir.config(), value)
     return value
Пример #15
0
def _path_info():
    """Get info about important path names.

    Return:
        A dictionary of descriptive to actual path names.
    """
    info = {
        'config': standarddir.config(),
        'data': standarddir.data(),
        'cache': standarddir.cache(),
        'runtime': standarddir.runtime(),
    }
    if standarddir.config() != standarddir.config(auto=True):
        info['auto config'] = standarddir.config(auto=True)
    if standarddir.data() != standarddir.data(system=True):
        info['system data'] = standarddir.data(system=True)
    return info
Пример #16
0
    def __init__(self, parent: QObject = None) -> None:
        super().__init__(parent)
        self._filename = os.path.join(standarddir.config(auto=True),
                                      'autoconfig.yml')
        self._dirty = False

        self._values = {}  # type: typing.Dict[str, configutils.Values]
        for name, opt in configdata.DATA.items():
            self._values[name] = configutils.Values(opt)
Пример #17
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self._filename = os.path.join(standarddir.config(auto=True),
                                      'autoconfig.yml')
        self._dirty = None

        self._values = {}
        for name, opt in configdata.DATA.items():
            self._values[name] = configutils.Values(opt)
Пример #18
0
 def transform(self, value):
     if not value:
         return None
     value = os.path.expanduser(value)
     value = os.path.expandvars(value)
     if not os.path.isabs(value):
         cfgdir = standarddir.config()
         assert cfgdir is not None
         value = os.path.join(cfgdir, value)
     return value
Пример #19
0
def _init_main_config(parent=None):
    """Initialize the main config.

    Args:
        parent: The parent to pass to ConfigManager.
    """
    args = objreg.get('args')
    config_obj = ConfigManager(parent=parent)
    try:
        config_obj.read(standarddir.config(), 'qutebrowser.conf',
                        relaxed=args.relaxed_config)
    except (configexc.Error, configparser.Error, UnicodeDecodeError) as e:
        log.init.exception(e)
        errstr = "Error while reading config:"
        try:
            errstr += "\n\n{} -> {}:".format(
                e.section, e.option)
        except AttributeError:
            pass
        errstr += "\n"
        error.handle_fatal_exc(e, args, "Error while reading config!",
                               pre_text=errstr)
        # We didn't really initialize much so far, so we just quit hard.
        sys.exit(usertypes.Exit.err_config)
    else:
        objreg.register('config', config_obj)
        if standarddir.config() is not None:
            filename = os.path.join(standarddir.config(), 'qutebrowser.conf')
            save_manager = objreg.get('save-manager')
            save_manager.add_saveable(
                'config', config_obj.save, config_obj.changed,
                config_opt=('general', 'auto-save-config'), filename=filename)
            for sect in config_obj.sections.values():
                for opt in sect.values.values():
                    if opt.values['conf'] is None:
                        # Option added to built-in defaults but not in user's
                        # config yet
                        save_manager.save('config', explicit=True, force=True)
                        return
Пример #20
0
    def config_write_py(self, filename: str = None,
                        force: bool = False, defaults: bool = False) -> None:
        """Write the current configuration to a config.py file.

        Args:
            filename: The file to write to, or None for the default config.py.
            force: Force overwriting existing files.
            defaults: Write the defaults instead of values configured via :set.
        """
        if filename is None:
            filename = os.path.join(standarddir.config(), 'config.py')
        else:
            if not os.path.isabs(filename):
                filename = os.path.join(standarddir.config(), filename)
            filename = os.path.expanduser(filename)

        if os.path.exists(filename) and not force:
            raise cmdutils.CommandError("{} already exists - use --force to "
                                        "overwrite!".format(filename))

        options = []  # type: typing.List
        if defaults:
            options = [(None, opt, opt.default)
                       for _name, opt in sorted(configdata.DATA.items())]
            bindings = dict(configdata.DATA['bindings.default'].default)
            commented = True
        else:
            for values in self._config:
                for scoped in values:
                    options.append((scoped.pattern, values.opt, scoped.value))
            bindings = dict(self._config.get_mutable_obj('bindings.commands'))
            commented = False

        writer = configfiles.ConfigPyWriter(options, bindings,
                                            commented=commented)
        try:
            writer.write(filename)
        except OSError as e:
            raise cmdutils.CommandError(str(e))
Пример #21
0
    def __init__(self):
        self._blocked_hosts = set()
        self._config_blocked_hosts = set()
        self._in_progress = []
        self._done_count = 0

        data_dir = standarddir.data()
        self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
        self._update_files()

        config_dir = standarddir.config()
        self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')

        config.instance.changed.connect(self._update_files)
Пример #22
0
def _path_info():
    """Get info about important path names.

    Return:
        A dictionary of descriptive to actual path names.
    """
    return {
        'config': standarddir.config(),
        'data': standarddir.data(),
        'system_data': standarddir.system_data(),
        'cache': standarddir.cache(),
        'download': standarddir.download(),
        'runtime': standarddir.runtime(),
    }
Пример #23
0
    def __init__(self):
        self._blocked_hosts = set()
        self._config_blocked_hosts = set()
        self._in_progress = []
        self._done_count = 0

        data_dir = standarddir.data()
        self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
        self.on_config_changed()

        config_dir = standarddir.config()
        self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')

        objreg.get('config').changed.connect(self.on_config_changed)
Пример #24
0
def _init_misc():
    """Initialize misc. config-related files."""
    save_manager = objreg.get("save-manager")
    state_config = ini.ReadWriteConfigParser(standarddir.data(), "state")
    for sect in ("general", "geometry"):
        try:
            state_config.add_section(sect)
        except configparser.DuplicateSectionError:
            pass
    # See commit a98060e020a4ba83b663813a4b9404edb47f28ad.
    state_config["general"].pop("fooled", None)
    objreg.register("state-config", state_config)
    save_manager.add_saveable("state-config", state_config.save)

    # We need to import this here because lineparser needs config.
    from qutebrowser.misc import lineparser

    command_history = lineparser.LimitLineParser(
        standarddir.data(), "cmd-history", limit=("completion", "cmd-history-max-items"), parent=objreg.get("config")
    )
    objreg.register("command-history", command_history)
    save_manager.add_saveable("command-history", command_history.save, command_history.changed)

    # Set the QSettings path to something like
    # ~/.config/qutebrowser/qsettings/qutebrowser/qutebrowser.conf so it
    # doesn't overwrite our config.
    #
    # This fixes one of the corruption issues here:
    # https://github.com/The-Compiler/qutebrowser/issues/515

    if standarddir.config() is None:
        path = os.devnull
    else:
        path = os.path.join(standarddir.config(), "qsettings")
    for fmt in (QSettings.NativeFormat, QSettings.IniFormat):
        QSettings.setPath(fmt, QSettings.UserScope, path)
Пример #25
0
def _init_key_config():
    """Initialize the key config."""
    try:
        key_config = keyconf.KeyConfigParser(standarddir.config(), 'keys.conf')
    except (keyconf.KeyConfigError, UnicodeDecodeError) as e:
        log.init.exception(e)
        errstr = "Error while reading key config:\n"
        if e.lineno is not None:
            errstr += "In line {}: ".format(e.lineno)
        errstr += str(e)
        msgbox = QMessageBox(QMessageBox.Critical,
                             "Error while reading key config!", errstr)
        msgbox.exec_()
        # We didn't really initialize much so far, so we just quit hard.
        sys.exit(1)
    else:
        objreg.register('key-config', key_config)
        if standarddir.config() is not None:
            save_manager = objreg.get('save-manager')
            filename = os.path.join(standarddir.config(), 'keys.conf')
            save_manager.add_saveable(
                'key-config', key_config.save, key_config.config_dirty,
                config_opt=('general', 'auto-save-config'), filename=filename,
                dirty=key_config.is_dirty)
Пример #26
0
def _init_main_config():
    """Initialize the main config."""
    try:
        app = objreg.get('app')
        args = objreg.get('args')
        config_obj = ConfigManager(standarddir.config(), 'qutebrowser.conf',
                                   args.relaxed_config, app)
    except (configexc.Error, configparser.Error, UnicodeDecodeError) as e:
        log.init.exception(e)
        errstr = "Error while reading config:"
        try:
            errstr += "\n\n{} -> {}:".format(
                e.section, e.option)  # pylint: disable=no-member
        except AttributeError:
            pass
        errstr += "\n{}".format(e)
        msgbox = QMessageBox(QMessageBox.Critical,
                             "Error while reading config!", errstr)
        msgbox.exec_()
        # We didn't really initialize much so far, so we just quit hard.
        sys.exit(1)
    else:
        objreg.register('config', config_obj)
        if standarddir.config() is not None:
            filename = os.path.join(standarddir.config(), 'qutebrowser.conf')
            save_manager = objreg.get('save-manager')
            save_manager.add_saveable(
                'config', config_obj.save, config_obj.changed,
                config_opt=('general', 'auto-save-config'), filename=filename)
            for sect in config_obj.sections.values():
                for opt in sect.values.values():
                    if opt.values['conf'] is None:
                        # Option added to built-in defaults but not in user's
                        # config yet
                        save_manager.save('config', explicit=True, force=True)
                        return
Пример #27
0
def init():
    """Initialize config storage not related to the main config."""
    global state
    state = StateConfig()
    state['general']['version'] = qutebrowser.__version__

    # Set the QSettings path to something like
    # ~/.config/qutebrowser/qsettings/qutebrowser/qutebrowser.conf so it
    # doesn't overwrite our config.
    #
    # This fixes one of the corruption issues here:
    # https://github.com/qutebrowser/qutebrowser/issues/515

    path = os.path.join(standarddir.config(auto=True), 'qsettings')
    for fmt in [QSettings.NativeFormat, QSettings.IniFormat]:
        QSettings.setPath(fmt, QSettings.UserScope, path)
Пример #28
0
    def transform(self, value):
        if not value:
            return None

        if standarddir.config() is None:
            # We can't call super().transform() here as this counts on the
            # validation previously ensuring that we don't have a relative path
            # when starting with -c "".
            path = None
        else:
            path = super().transform(value)

        if path is not None and os.path.exists(path):
            return QUrl.fromLocalFile(path)
        else:
            data = base64.b64encode(value.encode('utf-8')).decode('ascii')
            return QUrl("data:text/css;charset=utf-8;base64,{}".format(data))
Пример #29
0
    def __init__(self, parent=None):
        """Initialize and read quickmarks."""
        super().__init__(parent)

        self.marks = collections.OrderedDict()
        self._lineparser = None

        if standarddir.config() is None:
            return

        self._init_lineparser()
        for line in self._lineparser:
            if not line.strip():
                # Ignore empty or whitespace-only lines.
                continue
            self._parse_line(line)
        self._init_savemanager(objreg.get('save-manager'))
Пример #30
0
 def validate(self, value):
     self._basic_validation(value)
     if not value:
         return
     value = os.path.expanduser(value)
     value = os.path.expandvars(value)
     try:
         if not os.path.isabs(value):
             value = os.path.join(standarddir.config(), value)
             not_isfile_message = ("must be a valid path relative to the "
                                   "config directory!")
         else:
             not_isfile_message = "must be a valid file!"
         if self.required and not os.path.isfile(value):
             raise configexc.ValidationError(value, not_isfile_message)
     except UnicodeEncodeError as e:
         raise configexc.ValidationError(value, e)
Пример #31
0
 def test_config_explicit(self, monkeypatch, tmpdir):
     """Test config dir with XDG_CONFIG_HOME explicitly set."""
     monkeypatch.setenv('XDG_CONFIG_HOME', str(tmpdir))
     standarddir.init(None)
     assert standarddir.config() == str(tmpdir / 'qutebrowser_test')
Пример #32
0
 def __init__(self):
     self._filename = os.path.join(standarddir.config(auto=True),
                                   'autoconfig.yml')
     self.values = {}
Пример #33
0
def _get_init_context() -> InitContext:
    """Get an InitContext object."""
    return InitContext(data_dir=pathlib.Path(standarddir.data()),
                       config_dir=pathlib.Path(standarddir.config()),
                       args=objreg.get('args'))
Пример #34
0
 def __init__(self, conf: config.Config, keyconfig: config.KeyConfig):
     self._config = conf
     self._keyconfig = keyconfig
     self.errors = []  # type: typing.List[configexc.ConfigErrorDesc]
     self.configdir = pathlib.Path(standarddir.config())
     self.datadir = pathlib.Path(standarddir.data())
Пример #35
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self._filename = os.path.join(standarddir.config(auto=True),
                                   'autoconfig.yml')
     self._values = {}
     self._dirty = None
Пример #36
0
def run_async(tab,
              cmd,
              *args,
              win_id,
              env,
              verbose=False,
              output_messages=False):
    """Run a userscript after dumping page html/source.

    Raises:
        UnsupportedError if userscripts are not supported on the current
        platform.
        NotFoundError if the command could not be found.

    Args:
        tab: The WebKitTab/WebEngineTab to get the source from.
        cmd: The userscript binary to run.
        *args: The arguments to pass to the userscript.
        win_id: The window id the userscript is executed in.
        env: A dictionary of variables to add to the process environment.
        verbose: Show notifications when the command started/exited.
        output_messages: Show the output as messages.
    """
    tb = objreg.get('tabbed-browser', scope='window', window=win_id)
    commandrunner = runners.CommandRunner(win_id, parent=tb)

    if utils.is_posix:
        runner: _BaseUserscriptRunner = _POSIXUserscriptRunner(tb)
    elif utils.is_windows:  # pragma: no cover
        runner = _WindowsUserscriptRunner(tb)
    else:  # pragma: no cover
        raise UnsupportedError

    runner.got_cmd.connect(lambda cmd: log.commands.debug(
        "Got userscript command: {}".format(cmd)))
    runner.got_cmd.connect(commandrunner.run_safely)

    env['QUTE_USER_AGENT'] = websettings.user_agent()
    env['QUTE_CONFIG_DIR'] = standarddir.config()
    env['QUTE_DATA_DIR'] = standarddir.data()
    env['QUTE_DOWNLOAD_DIR'] = downloads.download_dir()
    env['QUTE_COMMANDLINE_TEXT'] = objreg.get('status-command',
                                              scope='window',
                                              window=win_id).text()
    env['QUTE_VERSION'] = qutebrowser.__version__

    cmd_path = os.path.expanduser(cmd)

    # if cmd is not given as an absolute path, look it up
    # ~/.local/share/qutebrowser/userscripts (or $XDG_DATA_HOME)
    if not os.path.isabs(cmd_path):
        log.misc.debug("{} is no absolute path".format(cmd_path))
        cmd_path = _lookup_path(cmd)
    elif not os.path.exists(cmd_path):
        raise NotFoundError(cmd_path)
    log.misc.debug("Userscript to run: {}".format(cmd_path))

    runner.finished.connect(commandrunner.deleteLater)
    runner.finished.connect(runner.deleteLater)

    runner.prepare_run(cmd_path,
                       *args,
                       env=env,
                       verbose=verbose,
                       output_messages=output_messages)
    tab.dump_async(runner.store_html)
    tab.dump_async(runner.store_text, plain=True)
    return runner
Пример #37
0
def _scripts_dirs():
    """Get the directory of the scripts."""
    return [
        os.path.join(standarddir.data(), 'greasemonkey'),
        os.path.join(standarddir.config(), 'greasemonkey'),
    ]
Пример #38
0
 def __init__(self, conf, keyconfig):
     self._config = conf
     self._keyconfig = keyconfig
     self.errors = []
     self.configdir = pathlib.Path(standarddir.config())
     self.datadir = pathlib.Path(standarddir.data())
Пример #39
0
class TestStandardDir:
    """Tests for standarddir."""
    @pytest.mark.parametrize('func, varname', [
        (standarddir.data, 'XDG_DATA_HOME'),
        (standarddir.config, 'XDG_CONFIG_HOME'),
        (lambda: standarddir.config(auto=True), 'XDG_CONFIG_HOME'),
        (standarddir.cache, 'XDG_CACHE_HOME'),
        (standarddir.runtime, 'XDG_RUNTIME_DIR'),
    ])
    @pytest.mark.linux
    def test_linux_explicit(self, monkeypatch, tmpdir, func, varname):
        """Test dirs with XDG environment variables explicitly set.

        Args:
            func: The function to test.
            varname: The environment variable which should be set.
        """
        monkeypatch.setenv(varname, str(tmpdir))
        standarddir._init_dirs()
        assert func() == str(tmpdir / APPNAME)

    @pytest.mark.parametrize('func, subdirs', [
        (standarddir.data, ['.local', 'share', APPNAME]),
        (standarddir.config, ['.config', APPNAME]),
        (lambda: standarddir.config(auto=True), ['.config', APPNAME]),
        (standarddir.cache, ['.cache', APPNAME]),
        (standarddir.download, ['Downloads']),
    ])
    @pytest.mark.linux
    def test_linux_normal(self, monkeypatch, tmpdir, func, subdirs):
        """Test dirs with XDG_*_HOME not set."""
        monkeypatch.setenv('HOME', str(tmpdir))
        for var in ['DATA', 'CONFIG', 'CACHE']:
            monkeypatch.delenv('XDG_{}_HOME'.format(var), raising=False)
        standarddir._init_dirs()
        assert func() == str(tmpdir.join(*subdirs))

    @pytest.mark.linux
    @pytest.mark.qt_log_ignore(r'^QStandardPaths: ')
    def test_linux_invalid_runtimedir(self, monkeypatch, tmpdir):
        """With invalid XDG_RUNTIME_DIR, fall back to TempLocation."""
        monkeypatch.setenv('XDG_RUNTIME_DIR', str(tmpdir / 'does-not-exist'))
        monkeypatch.setenv('TMPDIR', str(tmpdir / 'temp'))
        standarddir._init_dirs()
        assert standarddir.runtime() == str(tmpdir / 'temp' / APPNAME)

    @pytest.mark.fake_os('windows')
    def test_runtimedir_empty_tempdir(self, monkeypatch, tmpdir):
        """With an empty tempdir on non-Linux, we should raise."""
        monkeypatch.setattr(standarddir.QStandardPaths, 'writableLocation',
                            lambda typ: '')
        with pytest.raises(standarddir.EmptyValueError):
            standarddir._init_runtime(args=None)

    @pytest.mark.parametrize('func, elems, expected', [
        (standarddir.data, 2, [APPNAME, 'data']),
        (standarddir.config, 2, [APPNAME, 'config']),
        (lambda: standarddir.config(auto=True), 2, [APPNAME, 'config']),
        (standarddir.cache, 2, [APPNAME, 'cache']),
        (standarddir.download, 1, ['Downloads']),
    ])
    @pytest.mark.windows
    def test_windows(self, func, elems, expected):
        standarddir._init_dirs()
        assert func().split(os.sep)[-elems:] == expected

    @pytest.mark.parametrize('func, elems, expected', [
        (standarddir.data, 2, ['Application Support', APPNAME]),
        (lambda: standarddir.config(auto=True), 1, [APPNAME]),
        (standarddir.config, 0,
         os.path.expanduser('~').split(os.sep) + ['.qute_test']),
        (standarddir.cache, 2, ['Caches', APPNAME]),
        (standarddir.download, 1, ['Downloads']),
    ])
    @pytest.mark.mac
    def test_mac(self, func, elems, expected):
        standarddir._init_dirs()
        assert func().split(os.sep)[-elems:] == expected
Пример #40
0
def test_fake_mac_config(tmpdir, monkeypatch):
    """Test standardir.config on a fake Mac."""
    monkeypatch.setenv('HOME', str(tmpdir))
    expected = str(tmpdir) + '/.qute_test'  # always with /
    standarddir._init_config(args=None)
    assert standarddir.config() == expected
Пример #41
0
class TestStandardDir:
    @pytest.mark.parametrize('func, init_func, varname', [
        (standarddir.data, standarddir._init_data, 'XDG_DATA_HOME'),
        (standarddir.config, standarddir._init_config, 'XDG_CONFIG_HOME'),
        (lambda: standarddir.config(auto=True), standarddir._init_config,
         'XDG_CONFIG_HOME'),
        (standarddir.cache, standarddir._init_cache, 'XDG_CACHE_HOME'),
        pytest.param(
            standarddir.runtime,
            standarddir._init_runtime,
            'XDG_RUNTIME_DIR',
            marks=pytest.mark.not_flatpak,
        ),
    ])
    @pytest.mark.linux
    def test_linux_explicit(self, monkeypatch, tmpdir, func, init_func,
                            varname):
        """Test dirs with XDG environment variables explicitly set.

        Args:
            func: The function to test.
            init_func: The initialization function to call.
            varname: The environment variable which should be set.
        """
        monkeypatch.setenv(varname, str(tmpdir))
        if varname == 'XDG_RUNTIME_DIR':
            tmpdir.chmod(0o0700)

        init_func(args=None)
        assert func() == str(tmpdir / APPNAME)

    @pytest.mark.parametrize('func, subdirs', [
        (standarddir.data, ['.local', 'share', APPNAME]),
        (standarddir.config, ['.config', APPNAME]),
        (lambda: standarddir.config(auto=True), ['.config', APPNAME]),
        (standarddir.cache, ['.cache', APPNAME]),
        (standarddir.download, ['Downloads']),
    ])
    @pytest.mark.linux
    def test_linux_normal(self, fake_home_envvar, tmp_path, func, subdirs):
        """Test dirs with XDG_*_HOME not set."""
        standarddir._init_dirs()
        assert func() == str(tmp_path.joinpath(*subdirs))

    @pytest.mark.linux
    @pytest.mark.qt_log_ignore(r'^QStandardPaths: ')
    @pytest.mark.skipif(
        qtutils.version_check('5.14', compiled=False),
        reason="Qt 5.14 automatically creates missing runtime dirs")
    def test_linux_invalid_runtimedir(self, monkeypatch, tmpdir):
        """With invalid XDG_RUNTIME_DIR, fall back to TempLocation."""
        tmpdir_env = tmpdir / 'temp'
        tmpdir_env.ensure(dir=True)
        monkeypatch.setenv('XDG_RUNTIME_DIR', str(tmpdir / 'does-not-exist'))
        monkeypatch.setenv('TMPDIR', str(tmpdir_env))

        standarddir._init_runtime(args=None)
        assert standarddir.runtime() == str(tmpdir_env / APPNAME)

    @pytest.mark.linux
    @pytest.mark.parametrize('args_basedir', [True, False])
    def test_flatpak_runtimedir(self, fake_flatpak, monkeypatch, tmp_path,
                                args_basedir):
        runtime_path = tmp_path / 'runtime'
        runtime_path.mkdir()
        runtime_path.chmod(0o0700)
        monkeypatch.setenv('XDG_RUNTIME_DIR', str(runtime_path))

        if args_basedir:
            init_args = types.SimpleNamespace(basedir=str(tmp_path))
            expected = tmp_path / 'runtime'
        else:
            init_args = None
            expected = runtime_path / 'app' / 'org.qutebrowser.qutebrowser'

        standarddir._init_runtime(args=init_args)
        assert standarddir.runtime() == str(expected)

    @pytest.mark.fake_os('windows')
    def test_runtimedir_empty_tempdir(self, monkeypatch, tmpdir):
        """With an empty tempdir on non-Linux, we should raise."""
        monkeypatch.setattr(standarddir.QStandardPaths, 'writableLocation',
                            lambda typ: '')
        with pytest.raises(standarddir.EmptyValueError):
            standarddir._init_runtime(args=None)

    @pytest.mark.parametrize('func, elems, expected', [
        (standarddir.data, 2, [APPNAME, 'data']),
        (standarddir.config, 2, [APPNAME, 'config']),
        (lambda: standarddir.config(auto=True), 2, [APPNAME, 'config']),
        (standarddir.cache, 2, [APPNAME, 'cache']),
        (standarddir.download, 1, ['Downloads']),
    ])
    @pytest.mark.windows
    def test_windows(self, func, elems, expected):
        standarddir._init_dirs()
        assert func().split(os.sep)[-elems:] == expected

    @pytest.mark.parametrize('func, elems, expected', [
        (standarddir.data, 2, ['Application Support', APPNAME]),
        (lambda: standarddir.config(auto=True), 1, [APPNAME]),
        (standarddir.config, 0,
         os.path.expanduser('~').split(os.sep) + ['.qute_test']),
        (standarddir.cache, 2, ['Caches', APPNAME]),
        (standarddir.download, 1, ['Downloads']),
    ])
    @pytest.mark.mac
    def test_mac(self, func, elems, expected):
        standarddir._init_dirs()
        assert func().split(os.sep)[-elems:] == expected
Пример #42
0
def test_fake_mac_config(tmp_path, fake_home_envvar):
    """Test standardir.config on a fake Mac."""
    expected = str(tmp_path) + '/.qute_test'  # always with /
    standarddir._init_config(args=None)
    assert standarddir.config() == expected
Пример #43
0
 def test_config(self):
     """Test config dir."""
     assert standarddir.config().split(os.sep)[-1] == 'qutebrowser_test'
Пример #44
0
def _open_special_pages(args):
    """Open special notification pages which are only shown once.

    Args:
        args: The argparse namespace.
    """
    if args.basedir is not None:
        # With --basedir given, don't open anything.
        return

    general_sect = configfiles.state['general']
    tabbed_browser = objreg.get('tabbed-browser',
                                scope='window',
                                window='last-focused')

    pages = [
        # state, condition, URL
        ('quickstart-done', True, 'https://www.qutebrowser.org/quickstart.html'
         ),
        ('config-migration-shown',
         os.path.exists(os.path.join(standarddir.config(),
                                     'qutebrowser.conf')),
         'qute://help/configuring.html'),
        ('webkit-warning-shown', objects.backend == usertypes.Backend.QtWebKit,
         'qute://warning/webkit'),
        ('session-warning-shown', qtutils.version_check('5.15',
                                                        compiled=False),
         'qute://warning/sessions'),
    ]

    if 'quickstart-done' not in general_sect:
        # New users aren't going to be affected by the Qt 5.15 session change much, as
        # they aren't used to qutebrowser saving the full back/forward history in
        # sessions.
        general_sect['session-warning-shown'] = '1'

    for state, condition, url in pages:
        if general_sect.get(state) != '1' and condition:
            tabbed_browser.tabopen(QUrl(url), background=False)
            general_sect[state] = '1'

    # Show changelog on new releases
    change = configfiles.state.qutebrowser_version_changed
    if change == configfiles.VersionChange.equal:
        return

    setting = config.val.changelog_after_upgrade
    if not change.matches_filter(setting):
        log.init.debug(
            f"Showing changelog is disabled (setting {setting}, change {change})"
        )
        return

    try:
        changelog = resources.read_file('html/doc/changelog.html')
    except OSError as e:
        log.init.warning(f"Not showing changelog due to {e}")
        return

    qbversion = qutebrowser.__version__
    if f'id="v{qbversion}"' not in changelog:
        log.init.warning("Not showing changelog (anchor not found)")
        return

    message.info(
        f"Showing changelog after upgrade to qutebrowser v{qbversion}.")
    changelog_url = f'qute://help/changelog.html#v{qbversion}'
    tabbed_browser.tabopen(QUrl(changelog_url), background=False)
Пример #45
0
 def _init_lineparser(self):
     self._lineparser = lineparser.LineParser(
         standarddir.config(), 'quickmarks', parent=self)
Пример #46
0
 def test_confdir_none(self):
     """Test --confdir with None given."""
     args = types.SimpleNamespace(confdir=None, cachedir=None, datadir=None)
     standarddir.init(args)
     assert standarddir.config().split(os.sep)[-1] == 'qute_test'
Пример #47
0
 def _init_savemanager(self, save_manager):
     filename = os.path.join(standarddir.config(), 'quickmarks')
     save_manager.add_saveable('quickmark-manager', self.save, self.changed,
                               filename=filename)
Пример #48
0
 def test_confdir(self, testcase):
     """Test --confdir."""
     args = types.SimpleNamespace(confdir=testcase.arg, cachedir=None,
                                  datadir=None, basedir=None)
     standarddir.init(args)
     assert standarddir.config() == testcase.expected