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 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 utils.is_posix: runner = _POSIXUserscriptRunner(tabbed_browser) elif utils.is_windows: # 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.val.content.headers.user_agent if user_agent is not None: env['QUTE_USER_AGENT'] = 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() cmd_path = os.path.expanduser(cmd) # if cmd is not given as an absolute path, look it up # ~/.local/share/glimpsebrowser/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) tab.dump_async(runner.store_html) tab.dump_async(runner.store_text, plain=True) return runner
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.glimpsebrowser.org/quickstart.html'), ('config-migration-shown', os.path.exists( os.path.join(standarddir.config(), 'glimpsebrowser.conf')), 'glimpse://help/configuring.html'), ('webkit-warning-shown', objects.backend == usertypes.Backend.QtWebKit, 'glimpse://warning/webkit'), ('old-qt-warning-shown', not qtutils.version_check('5.9'), 'glimpse://warning/old-qt'), ] 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'
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 [('glimpsebrowser.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 _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 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_dirs(args) assert standarddir.config() == str(basedir / 'config')
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() -> None: """Initialize config storage not related to the main config.""" global state state = StateConfig() # Set the QSettings path to something like # ~/.config/glimpsebrowser/qsettings/glimpsebrowser/glimpsebrowser.conf so it # doesn't overwrite our config. # # This fixes one of the corruption issues here: # https://github.com/glimpsebrowser/glimpsebrowser/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 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 = standarddir.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 config_source(self, filename: str = None, clear: bool = False) -> None: """Read a config.py file. Args: filename: The file to load. If not given, loads the default config.py. clear: Clear current settings first. """ if filename is None: filename = standarddir.config_py() else: filename = os.path.expanduser(filename) if not os.path.isabs(filename): filename = os.path.join(standarddir.config(), filename) if clear: self.config_clear() try: configfiles.read_config_py(filename) except configexc.ConfigFileErrors as e: raise cmdutils.CommandError(e)
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_savemanager(self, save_manager): filename = os.path.join(standarddir.config(), 'bookmarks', 'urls') save_manager.add_saveable('bookmark-manager', self.save, self.changed, filename=filename)
def _init_lineparser(self): self._lineparser = lineparser.LineParser(standarddir.config(), 'quickmarks', parent=self)
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 test_fake_mac_config(tmpdir, monkeypatch): """Test standardir.config on a fake Mac.""" monkeypatch.setenv('HOME', str(tmpdir)) expected = str(tmpdir) + '/.glimpse_test' # always with / standarddir._init_config(args=None) assert standarddir.config() == expected
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.""" 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_dirs() assert standarddir.runtime() == str(tmpdir_env / 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) + ['.glimpse_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