diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 195c06192..696e1f4c4 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -29,6 +29,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl from qutebrowser.config import configdata, configexc, configtypes, configfiles from qutebrowser.utils import (utils, objreg, message, standarddir, log, usertypes, jinja) +from qutebrowser.misc import objects from qutebrowser.commands import cmdexc, cmdutils, runners @@ -303,11 +304,8 @@ class ConfigCommands: """Catch errors in set_command and raise CommandError.""" try: yield - except (configexc.NoOptionError, configexc.ValidationError) as e: - raise cmdexc.CommandError("set: {}".format(e)) except configexc.Error as e: - raise cmdexc.CommandError("set: {} - {}".format( - e.__class__.__name__, e)) + raise cmdexc.CommandError("set: {}".format(e)) @cmdutils.register(instance='config-commands', maxsplit=1, no_cmd_split=True, no_replace_variables=True) @@ -380,18 +378,25 @@ class Config(QObject): self._mutables = [] self._yaml = yaml_config - def _changed(self, name, value): - """Emit changed signal and log change.""" - self.changed.emit(name) - log.config.debug("Config option changed: {} = {}".format(name, value)) + def _set_value(self, opt, value): + """Set the given option to the given value.""" + if objects.backend is not None: + # FIXME:conf Validate all backends after init + if objects.backend not in opt.backends: + raise configexc.BackendError(objects.backend) + + opt.typ.to_py(value) # for validation + self._values[opt.name] = value + + self.changed.emit(opt.name) + log.config.debug("Config option changed: {} = {}".format( + opt.name, value)) def read_yaml(self): """Read the YAML settings from self._yaml.""" self._yaml.load() for name, value in self._yaml.values.items(): - opt = self.get_opt(name) - opt.typ.to_py(value) # for validation - self._values[name] = value + self._set_value(self.get_opt(name), value) # FIXME:conf when to emit changed() here? def get_opt(self, name): @@ -436,10 +441,7 @@ class Config(QObject): If save_yaml=True is given, store the new value to YAML. """ - opt = self.get_opt(name) - opt.typ.to_py(value) # for validation - self._values[name] = value - self._changed(name, value) + self._set_value(self.get_opt(name), value) if save_yaml: self._yaml.values[name] = value @@ -450,8 +452,7 @@ class Config(QObject): """ opt = self.get_opt(name) converted = opt.typ.from_str(value) - self._values[name] = converted - self._changed(name, converted) + self._set_value(opt, converted) if save_yaml: self._yaml.values[name] = converted diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index e1a114652..e471068e9 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -29,6 +29,7 @@ import qutebrowser.app # To register commands from qutebrowser.commands import cmdexc from qutebrowser.config import config, configdata, configexc, configfiles from qutebrowser.utils import objreg, usertypes +from qutebrowser.misc import objects @pytest.fixture(autouse=True) @@ -292,12 +293,14 @@ class TestSetConfigCommand: assert msg.text == 'url.auto_search = never' @pytest.mark.parametrize('temp', [True, False]) - def test_set_simple(self, commands, config_stub, temp): + def test_set_simple(self, monkeypatch, commands, config_stub, temp): """:set [-t] url.auto_search dns Should set the setting accordingly. """ + monkeypatch.setattr(objects, 'backend', usertypes.Backend.QtWebKit) assert config_stub.val.url.auto_search == 'naive' + commands.set(0, 'url.auto_search', 'dns', temp=temp) assert config_stub.val.url.auto_search == 'dns' @@ -383,6 +386,13 @@ class TestSetConfigCommand: "boolean!"): commands.set(0, 'auto_save.config', 'blah') + def test_set_wrong_backend(self, commands, monkeypatch): + monkeypatch.setattr(objects, 'backend', usertypes.Backend.QtWebEngine) + with pytest.raises(cmdexc.CommandError, + match="set: This setting is not available with the " + "QtWebEngine backend!"): + commands.set(0, 'content.cookies.accept', 'all') + @pytest.mark.parametrize('option', ['?', '!', 'url.auto_search']) def test_empty(self, commands, option): """:set ? / :set ! / :set url.auto_search @@ -572,12 +582,15 @@ class TestConfig: yaml_config = stubs.FakeYamlConfig() return config.Config(yaml_config) - def test_changed(self, qtbot, conf, caplog): + def test_set_value(self, qtbot, conf, caplog): + opt = conf.get_opt('tabs.show') with qtbot.wait_signal(conf.changed) as blocker: - conf._changed('foo', '42') - assert blocker.args == ['foo'] + conf._set_value(opt, 'never') + + assert blocker.args == ['tabs.show'] assert len(caplog.records) == 1 - assert caplog.records[0].message == 'Config option changed: foo = 42' + expected_message = 'Config option changed: tabs.show = never' + assert caplog.records[0].message == expected_message def test_read_yaml(self, conf): # FIXME:conf what about wrong values? @@ -700,6 +713,15 @@ class TestConfig: meth('content.plugins', '42') assert 'content.plugins' not in conf._values + @pytest.mark.parametrize('method', ['set_obj', 'set_str']) + def test_set_wrong_backend(self, conf, qtbot, monkeypatch, method): + monkeypatch.setattr(objects, 'backend', usertypes.Backend.QtWebEngine) + meth = getattr(conf, method) + with pytest.raises(configexc.BackendError): + with qtbot.assert_not_emitted(conf.changed): + meth('content.cookies.accept', 'all') + assert 'content.cookies.accept' not in conf._values + def test_dump_userconfig(self, conf): conf.set_obj('content.plugins', True) conf.set_obj('content.headers.custom', {'X-Foo': 'bar'})