diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 1ff491037..f1e6a5038 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -365,7 +365,7 @@ class Config(QObject): Those contain the type, default value, etc. _values: A dict mapping setting names to their values. _mutables: A list of mutable objects to be checked for changes. - _yaml: A YamlConfig object. + _yaml: A YamlConfig object or None. Signals: changed: Emitted with the option name when an option changed. @@ -373,12 +373,12 @@ class Config(QObject): changed = pyqtSignal(str) - def __init__(self, parent=None): + def __init__(self, yaml_config, parent=None): super().__init__(parent) self.options = {} self._values = {} self._mutables = [] - self._yaml = configfiles.YamlConfig() + self._yaml = yaml_config def _changed(self, name, value): """Emit changed signal and log change.""" @@ -605,7 +605,8 @@ def init(parent=None): """ configdata.init() - config = Config(parent) + yaml_config = configfiles.YamlConfig() + config = Config(yaml_config=yaml_config, parent=parent) config.read_configdata() objreg.register('config', config) diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index c4062ac62..f1b446a81 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -2070,6 +2070,7 @@ bindings.default: 'prompt', 'caret', 'register'] valtype: name: Dict + none_ok: true keytype: Key valtype: Command desc: >- diff --git a/tests/helpers/fixtures.py b/tests/helpers/fixtures.py index 935b71709..c59fb233c 100644 --- a/tests/helpers/fixtures.py +++ b/tests/helpers/fixtures.py @@ -38,7 +38,7 @@ import pytest import py.path # pylint: disable=no-name-in-module import helpers.stubs as stubsmod -from qutebrowser.config import config +from qutebrowser.config import config, configdata from qutebrowser.utils import objreg, standarddir from qutebrowser.browser.webkit import cookies from qutebrowser.misc import savemanager @@ -205,13 +205,15 @@ def cmdline_test(request): @pytest.fixture def config_stub(stubs, monkeypatch): """Fixture which provides a fake config object.""" - conf = stubs.ConfigStub() + configdata.init() + conf = config.Config(yaml_config=None) + conf.read_configdata() monkeypatch.setattr(config, 'instance', conf) container = config.ConfigContainer(conf) monkeypatch.setattr(config, 'val', container) - conf.val = container + conf.val = container # For easier use in tests return conf diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index 20354f9cb..51a5a1058 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -412,43 +412,6 @@ class StatusBarCommandStub(QLineEdit): return self.text()[0] -class ConfigStub(QObject): - - """Stub for the config module. - - Attributes: - data: The config data to return. - val: A ConfigContainer - """ - - changed = pyqtSignal(str) - - def __init__(self, parent=None): - super().__init__(parent) - if configdata.DATA is None: - configdata.init() - self.data = {} - self.val = None - - def __getitem__(self, name): - return self.section(name) - - def get(self, name): - """Get a value from the config.""" - try: - return self.data[name] - except KeyError: - raise configexc.NoOptionError(name) - - def set_obj(self, name, value): - """Set a value in the config.""" - try: - self.data[name] = value - except KeyError: - raise configexc.NoOptionError(name) - self.changed.emit(name) - - class UrlMarkManagerStub(QObject): """Stub for the quickmark-manager or bookmark-manager object.""" diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index ebb579e00..89e130345 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -23,6 +23,7 @@ import copy import pytest from PyQt5.QtCore import QObject +import qutebrowser.app # To register commands from qutebrowser.config import config, configdata, configexc @@ -85,18 +86,28 @@ class TestKeyConfig: @pytest.fixture def keyconf(self, config_stub): + config_stub.val.aliases = {} return config.KeyConfig(config_stub) @pytest.mark.parametrize('commands, expected', [ # Unbinding default key - ({'a': None}, {'b': 'bar'}), + ({'a': None}, {'b': 'message-info bar'}), # Additional binding - ({'c': 'baz'}, {'a': 'foo', 'b': 'bar', 'c': 'baz'}), + ({'c': 'message-info baz'}, + {'a': 'message-info foo', 'b': 'message-info bar', 'c': 'message-info baz'}), # Unbinding unknown key - ({'x': None}, {'a': 'foo', 'b': 'bar'}), + ({'x': None}, {'a': 'message-info foo', 'b': 'message-info bar'}), ]) def test_get_bindings_for(self, keyconf, config_stub, commands, expected): - orig_default_bindings = {'normal': {'a': 'foo', 'b': 'bar'}} + orig_default_bindings = {'normal': {'a': 'message-info foo', + 'b': 'message-info bar'}, + 'insert': {}, + 'hint': {}, + 'passthrough': {}, + 'command': {}, + 'prompt': {}, + 'caret': {}, + 'register': {}} config_stub.val.bindings.default = copy.deepcopy(orig_default_bindings) config_stub.val.bindings.commands = {'normal': commands} bindings = keyconf.get_bindings_for('normal') @@ -107,13 +118,17 @@ class TestKeyConfig: @pytest.mark.parametrize('bindings, expected', [ # Simple - ({'a': 'foo', 'b': 'bar'}, {'foo': ['a'], 'bar': ['b']}), + ({'a': 'message-info foo', 'b': 'message-info bar'}, + {'message-info foo': ['a'], 'message-info bar': ['b']}), # Multiple bindings - ({'a': 'foo', 'b': 'foo'}, {'foo': ['b', 'a']}), - # With special keys (should be listed last) - ({'a': 'foo', '': 'foo'}, {'foo': ['a', '']}), + ({'a': 'message-info foo', 'b': 'message-info foo'}, + {'message-info foo': ['b', 'a']}), + # With special keys (should be listed last and normalized) + ({'a': 'message-info foo', '': 'message-info foo'}, + {'message-info foo': ['a', '']}), # Chained command - ({'a': 'foo ;; bar'}, {'foo': ['a'], 'bar': ['a']}), + ({'a': 'message-info foo ;; message-info bar'}, + {'message-info foo': ['a'], 'message-info bar': ['a']}), ]) def test_get_reverse_bindings_for(self, keyconf, config_stub, bindings, expected): @@ -148,9 +163,9 @@ class StyleObj(QObject): def test_get_stylesheet(config_stub): - config_stub.val.colors.completion.bg = 'magenta' + config_stub.val.colors.hints.fg = 'magenta' observer = config.StyleSheetObserver( - StyleObj(), stylesheet="{{ conf.colors.completion.bg }}") + StyleObj(), stylesheet="{{ conf.colors.hints.fg }}") assert observer._get_stylesheet() == 'magenta' @@ -159,8 +174,8 @@ def test_get_stylesheet(config_stub): @pytest.mark.parametrize('update', [True, False]) def test_set_register_stylesheet(delete, stylesheet_param, update, qtbot, config_stub, caplog): - config_stub.val.colors.completion.fg = 'magenta' - stylesheet = "{{ conf.colors.completion.fg }}" + config_stub.val.colors.hints.fg = 'magenta' + stylesheet = "{{ conf.colors.hints.fg }}" with caplog.at_level(9): # VDEBUG if stylesheet_param: @@ -171,8 +186,7 @@ def test_set_register_stylesheet(delete, stylesheet_param, update, qtbot, obj = StyleObj(stylesheet) config.set_register_stylesheet(obj, update=update) - assert len(caplog.records) == 1 - assert caplog.records[0].message == 'stylesheet for StyleObj: magenta' + assert caplog.records[-1].message == 'stylesheet for StyleObj: magenta' assert obj.rendered_stylesheet == 'magenta' @@ -180,7 +194,7 @@ def test_set_register_stylesheet(delete, stylesheet_param, update, qtbot, with qtbot.waitSignal(obj.destroyed): obj.deleteLater() - config_stub.val.colors.completion.fg = 'yellow' + config_stub.val.colors.hints.fg = 'yellow' if delete or not update: expected = 'magenta' diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index 3e83da403..7101f7b9f 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -1036,7 +1036,9 @@ class TestCommand: def patch_aliases(self, config_stub): """Patch the aliases setting.""" # FIXME:conf use the real config so we can test the RecursionError + configtypes.Command.unvalidated = True config_stub.val.aliases = {'alias': 'cmd1'} + configtypes.Command.unvalidated = False @pytest.fixture def klass(self):