summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <git@the-compiler.org>2018-03-07 18:30:44 +0100
committerFlorian Bruhin <git@the-compiler.org>2018-03-07 18:30:44 +0100
commit34815f5cf815db7909252ec59e090f4dba57ee47 (patch)
treee66037acb64f5935206b8b0cc369d9d9dfc32973
parent8a60855b88b582b3ace9c107a5869ea64aaea6bd (diff)
downloadqutebrowser-34815f5cf815db7909252ec59e090f4dba57ee47.tar.gz
qutebrowser-34815f5cf815db7909252ec59e090f4dba57ee47.zip
Make bindings.default only settable in autoconfig.yml
Fixes #3131
-rw-r--r--doc/changelog.asciidoc2
-rw-r--r--doc/help/settings.asciidoc2
-rw-r--r--qutebrowser/completion/models/configmodel.py3
-rw-r--r--qutebrowser/config/config.py13
-rw-r--r--qutebrowser/config/configdata.py4
-rw-r--r--qutebrowser/config/configdata.yml1
-rw-r--r--qutebrowser/config/configexc.py9
-rw-r--r--qutebrowser/config/configfiles.py6
-rw-r--r--qutebrowser/html/settings.html2
-rwxr-xr-xscripts/dev/src2asciidoc.py2
-rw-r--r--tests/unit/completion/test_models.py5
-rw-r--r--tests/unit/config/test_config.py28
-rw-r--r--tests/unit/config/test_configexc.py6
-rw-r--r--tests/unit/config/test_configfiles.py10
14 files changed, 85 insertions, 8 deletions
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index dfc11fd59..c526e4430 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -71,6 +71,8 @@ Changed
* Yes/no prompts don't use keybindings from the `prompt` section anymore, they
have their own `yesno` section instead.
* Trying to bind invalid keys now shows an error.
+ * The `bindings.default` setting can now only be set in a `config.py`, and
+ existing values in `autoconfig.yml` are ignored.
- Improvements for GreaseMonkey support:
* `@include` and `@exclude` now support regex matches. With QtWebEngine and Qt
5.8 and newer, Qt handles the matching, but similar functionality will be
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index 0c2d09d5f..bfbb8672e 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -376,6 +376,8 @@ Default keybindings. If you want to add bindings, modify `bindings.commands` ins
The main purpose of this setting is that you can set it to an empty dictionary if you want to load no default keybindings at all.
If you want to preserve default bindings (and get new bindings when there is an update), use `config.bind()` in `config.py` or the `:bind` command, and leave this setting alone.
+This setting can only be set in config.py.
+
Type: <<types,Dict>>
Default:
diff --git a/qutebrowser/completion/models/configmodel.py b/qutebrowser/completion/models/configmodel.py
index 877de62b7..b462442a0 100644
--- a/qutebrowser/completion/models/configmodel.py
+++ b/qutebrowser/completion/models/configmodel.py
@@ -29,7 +29,8 @@ def option(*, info):
"""A CompletionModel filled with settings and their descriptions."""
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
options = ((opt.name, opt.description, info.config.get_str(opt.name))
- for opt in configdata.DATA.values())
+ for opt in configdata.DATA.values()
+ if not opt.no_autoconfig)
model.add_category(listcategory.ListCategory("Options", options))
return model
diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py
index eb2a81594..de8cc7042 100644
--- a/qutebrowser/config/config.py
+++ b/qutebrowser/config/config.py
@@ -286,6 +286,11 @@ class Config(QObject):
log.config.debug("Config option changed: {} = {}".format(
opt.name, value))
+ def _check_yaml(self, opt, save_yaml):
+ """Make sure the given option may be set in autoconfig.yml."""
+ if save_yaml and opt.no_autoconfig:
+ raise configexc.NoAutoconfigError(opt.name)
+
def read_yaml(self):
"""Read the YAML settings from self._yaml."""
self._yaml.load()
@@ -383,7 +388,9 @@ class Config(QObject):
If save_yaml=True is given, store the new value to YAML.
"""
- self._set_value(self.get_opt(name), value, pattern=pattern)
+ opt = self.get_opt(name)
+ self._check_yaml(opt, save_yaml)
+ self._set_value(opt, value, pattern=pattern)
if save_yaml:
self._yaml.set_obj(name, value, pattern=pattern)
@@ -393,6 +400,7 @@ class Config(QObject):
If save_yaml=True is given, store the new value to YAML.
"""
opt = self.get_opt(name)
+ self._check_yaml(opt, save_yaml)
converted = opt.typ.from_str(value)
log.config.debug("Setting {} (type {}) to {!r} (converted from {!r})"
.format(name, opt.typ.__class__.__name__, converted,
@@ -403,7 +411,8 @@ class Config(QObject):
def unset(self, name, *, save_yaml=False, pattern=None):
"""Set the given setting back to its default."""
- self.get_opt(name) # To check whether it exists
+ opt = self.get_opt(name)
+ self._check_yaml(opt, save_yaml)
changed = self._values[name].remove(pattern)
if changed:
self.changed.emit(name)
diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py
index 52ad123e1..c617fca14 100644
--- a/qutebrowser/config/configdata.py
+++ b/qutebrowser/config/configdata.py
@@ -50,6 +50,7 @@ class Option:
description = attr.ib()
supports_pattern = attr.ib(default=False)
restart = attr.ib(default=False)
+ no_autoconfig = attr.ib(default=False)
@attr.s
@@ -199,7 +200,7 @@ def _read_yaml(yaml_data):
data = utils.yaml_load(yaml_data)
keys = {'type', 'default', 'desc', 'backend', 'restart',
- 'supports_pattern'}
+ 'supports_pattern', 'no_autoconfig'}
for name, option in data.items():
if set(option.keys()) == {'renamed'}:
@@ -227,6 +228,7 @@ def _read_yaml(yaml_data):
description=option['desc'],
restart=option.get('restart', False),
supports_pattern=option.get('supports_pattern', False),
+ no_autoconfig=option.get('no_autoconfig', False),
)
# Make sure no key shadows another.
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 28c3a5d87..92d100744 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -2177,6 +2177,7 @@ bindings.key_mappings:
`bindings.commands`), the mapping is ignored.
bindings.default:
+ no_autoconfig: true
default:
normal:
<Escape>: clear-keychain ;; search ;; fullscreen --leave
diff --git a/qutebrowser/config/configexc.py b/qutebrowser/config/configexc.py
index e08bec913..4d1ab5d7f 100644
--- a/qutebrowser/config/configexc.py
+++ b/qutebrowser/config/configexc.py
@@ -31,6 +31,15 @@ class Error(Exception):
pass
+class NoAutoconfigError(Error):
+
+ """Raised when this option can't be set in autoconfig.yml."""
+
+ def __init__(self, name):
+ super().__init__("The {} setting can only be set in config.py!"
+ .format(name))
+
+
class BackendError(Error):
"""Raised when this setting is unavailable with the current backend."""
diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py
index 05ed23e60..fdb1583e0 100644
--- a/qutebrowser/config/configfiles.py
+++ b/qutebrowser/config/configfiles.py
@@ -262,6 +262,12 @@ class YamlConfig(QObject):
del settings[old]
self._mark_changed()
+ # bindings.default can't be set in autoconfig.yml anymore, so ignore
+ # old values.
+ if 'bindings.default' in settings:
+ del settings['bindings.default']
+ self._mark_changed()
+
return settings
def _validate(self, settings):
diff --git a/qutebrowser/html/settings.html b/qutebrowser/html/settings.html
index b370c0d91..62b424a59 100644
--- a/qutebrowser/html/settings.html
+++ b/qutebrowser/html/settings.html
@@ -33,7 +33,7 @@ input { width: 98%; }
<th>Setting</th>
<th>Value</th>
</tr>
- {% for option in configdata.DATA.values() %}
+ {% for option in configdata.DATA.values() if not option.no_autoconfig %}
<tr>
<!-- FIXME: convert to string properly -->
<td class="setting">{{ option.name }} (Current: {{ confget(option.name) | string |truncate(100) }})
diff --git a/scripts/dev/src2asciidoc.py b/scripts/dev/src2asciidoc.py
index 5fab901fc..cc00c3757 100755
--- a/scripts/dev/src2asciidoc.py
+++ b/scripts/dev/src2asciidoc.py
@@ -421,6 +421,8 @@ def _generate_setting_option(f, opt):
f.write("This setting requires a restart.\n")
if opt.supports_pattern:
f.write("\nThis setting supports URL patterns.\n")
+ if opt.no_autoconfig:
+ f.write("\nThis setting can only be set in config.py.\n")
f.write("\n")
typ = opt.typ.get_name().replace(',', '&#44;')
f.write('Type: <<types,{typ}>>\n'.format(typ=typ))
diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py
index 5240f2813..e14c5a466 100644
--- a/tests/unit/completion/test_models.py
+++ b/tests/unit/completion/test_models.py
@@ -111,7 +111,8 @@ def configdata_stub(config_stub, monkeypatch, configdata_init):
])
},
backends=[],
- raw_backends=None)),
+ raw_backends=None,
+ no_autoconfig=True)),
('bindings.commands', configdata.Option(
name='bindings.commands',
description='Default keybindings',
@@ -655,8 +656,6 @@ def test_setting_option_completion(qtmodeltester, config_stub,
('bindings.commands', 'Default keybindings', (
'{"normal": {"<Ctrl+q>": "quit", "ZQ": "quit", '
'"I": "invalid", "d": "scroll down"}}')),
- ('bindings.default', 'Default keybindings',
- '{"normal": {"<Ctrl+q>": "quit", "d": "tab-close"}}'),
('content.javascript.enabled', 'Enable/Disable JavaScript',
'true'),
]
diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
index 40e82ba4b..d51d79370 100644
--- a/tests/unit/config/test_config.py
+++ b/tests/unit/config/test_config.py
@@ -621,6 +621,34 @@ class TestConfig:
meth('content.cookies.accept', 'all')
assert not conf._values['content.cookies.accept']
+ @pytest.mark.parametrize('method, value', [
+ ('set_obj', {}),
+ ('set_str', '{}'),
+ ])
+ def test_set_no_autoconfig_save(self, conf, qtbot, yaml_value,
+ method, value):
+ meth = getattr(conf, method)
+ option = 'bindings.default'
+ with pytest.raises(configexc.NoAutoconfigError):
+ with qtbot.assert_not_emitted(conf.changed):
+ meth(option, value, save_yaml=True)
+
+ assert not conf._values[option]
+ assert yaml_value(option) is configutils.UNSET
+
+ @pytest.mark.parametrize('method, value', [
+ ('set_obj', {}),
+ ('set_str', '{}'),
+ ])
+ def test_set_no_autoconfig_no_save(self, conf, qtbot, yaml_value,
+ method, value):
+ meth = getattr(conf, method)
+ option = 'bindings.default'
+ with qtbot.wait_signal(conf.changed):
+ meth(option, value)
+
+ assert conf._values[option]
+
@pytest.mark.parametrize('method', ['set_obj', 'set_str'])
def test_set_no_pattern(self, conf, method, qtbot):
meth = getattr(conf, method)
diff --git a/tests/unit/config/test_configexc.py b/tests/unit/config/test_configexc.py
index c41e02b4c..c11850a15 100644
--- a/tests/unit/config/test_configexc.py
+++ b/tests/unit/config/test_configexc.py
@@ -48,6 +48,12 @@ def test_no_option_error_clash():
configexc.NoOptionError('opt', deleted=True, renamed='foo')
+def test_no_autoconfig_error():
+ e = configexc.NoAutoconfigError('opt')
+ expected = "The opt setting can only be set in config.py!"
+ assert str(e) == expected
+
+
def test_backend_error():
e = configexc.BackendError('foo', usertypes.Backend.QtWebKit)
expected = "The foo setting is not available with the QtWebKit backend!"
diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py
index d3b3f5726..96f5d4976 100644
--- a/tests/unit/config/test_configfiles.py
+++ b/tests/unit/config/test_configfiles.py
@@ -223,6 +223,16 @@ class TestYaml:
mode = 'persist' if persist else 'normal'
assert data['tabs.mode_on_change']['global'] == mode
+ def test_bindings_default(self, yaml, autoconfig):
+ """Make sure bindings.default gets removed from autoconfig.yml."""
+ autoconfig.write({'bindings.default': {'global': '{}'}})
+
+ yaml.load()
+ yaml._save()
+
+ data = autoconfig.read()
+ assert 'bindings.default' not in data
+
def test_renamed_key_unknown_target(self, monkeypatch, yaml,
autoconfig):
"""A key marked as renamed with invalid name should raise an error."""