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)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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'
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')
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
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
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)
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)
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
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
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))
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)
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(), }
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)
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)
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)
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
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)
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))
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'))
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)
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')
def __init__(self): self._filename = os.path.join(standarddir.config(auto=True), 'autoconfig.yml') self.values = {}
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'))
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())
def __init__(self, parent=None): super().__init__(parent) self._filename = os.path.join(standarddir.config(auto=True), 'autoconfig.yml') self._values = {} self._dirty = None
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
def _scripts_dirs(): """Get the directory of the scripts.""" return [ os.path.join(standarddir.data(), 'greasemonkey'), os.path.join(standarddir.config(), 'greasemonkey'), ]
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())
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
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
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
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
def test_config(self): """Test config dir.""" assert standarddir.config().split(os.sep)[-1] == 'qutebrowser_test'
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)
def _init_lineparser(self): self._lineparser = lineparser.LineParser( standarddir.config(), 'quickmarks', parent=self)
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'
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)
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