Merge remote-tracking branch 'origin/pr/4283'

This commit is contained in:
Florian Bruhin 2018-10-07 17:00:12 +02:00
commit 7cea4e3262
3 changed files with 180 additions and 7 deletions

View File

@ -27,12 +27,7 @@ from qutebrowser.keyinput import keyutils
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()
if not opt.no_autoconfig)
model.add_category(listcategory.ListCategory("Options", options))
return model
return _option(info, "Options", lambda opt: not opt.no_autoconfig)
def customized_option(*, info):
@ -47,6 +42,35 @@ def customized_option(*, info):
return model
def list_option(*, info):
"""A CompletionModel filled with settings whose values are lists."""
predicate = lambda opt: isinstance(info.config.get_obj(opt.name), list)
return _option(info, "List options", predicate)
def dict_option(*, info):
"""A CompletionModel filled with settings whose values are dicts."""
predicate = lambda opt: isinstance(info.config.get_obj(opt.name), dict)
return _option(info, "Dict options", predicate)
def _option(info, title, predicate):
"""A CompletionModel that is generified for several option sets.
Args:
info: The config info that can be passed through.
title: The title of the options.
predicate: The function for filtering out the options. Takes a single
argument.
"""
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()
if predicate(opt))
model.add_category(listcategory.ListCategory(title, options))
return model
def value(optname, *values, info):
"""A CompletionModel filled with setting values.

View File

@ -245,11 +245,63 @@ class ConfigCommands:
Args:
option: The name of the option.
temp: Don't touch autoconfig.yml.
temp: Set value temporarily until qutebrowser is closed.
"""
with self._handle_config_error():
self._config.unset(option, save_yaml=not temp)
@cmdutils.register(instance='config-commands')
@cmdutils.argument('option', completion=configmodel.list_option)
def config_add_list(self, option, value, temp=False):
"""Append a value to a config option that is a list.
Args:
option: The name of the option.
value: The value to append to the end of the list.
temp: Set value temporarily until qutebrowser is closed.
"""
opt = self._config.get_opt(option)
valid_list_types = (configtypes.List, configtypes.ListOrValue)
if not isinstance(opt.typ, valid_list_types):
raise cmdexc.CommandError(":config-add-list can only be used for "
"lists")
with self._handle_config_error():
option_value = self._config.get_mutable_obj(option)
option_value.append(value)
self._config.update_mutables(save_yaml=not temp)
@cmdutils.register(instance='config-commands')
@cmdutils.argument('option', completion=configmodel.dict_option)
def config_add_dict(self, option, key, value, temp=False, replace=False):
"""Add a value at the key within the option specified.
This adds an element to a dictionary. --replace is needed to override
existing values.
Args:
option: The name of the option.
key: The key to use.
value: The value to place in the dictionary.
temp: Set value temporarily until qutebrowser is closed.
replace: Whether or not we should replace, default is not.
"""
opt = self._config.get_opt(option)
if not isinstance(opt.typ, configtypes.Dict):
raise cmdexc.CommandError(":config-add-dict can only be used for "
"dicts")
with self._handle_config_error():
option_value = self._config.get_mutable_obj(option)
if key in option_value and not replace:
raise cmdexc.CommandError("{} already exists in {} - use "
"--replace to overwrite!"
.format(key, option))
option_value[key] = value
self._config.update_mutables(save_yaml=not temp)
@cmdutils.register(instance='config-commands')
def config_clear(self, save=False):
"""Set all settings back to their default.

View File

@ -282,6 +282,103 @@ class TestCycle:
assert msg.text == 'auto_save.session = true'
class TestAdd:
"""Test :config-add-list and :config-add-dict."""
@pytest.mark.parametrize('temp', [True, False])
@pytest.mark.parametrize('value', ['test1', 'test2'])
def test_add_list(self, commands, config_stub, yaml_value, temp, value):
name = 'content.host_blocking.whitelist'
commands.config_add_list(name, value, temp=temp)
assert str(config_stub.get(name)[-1]) == value
if temp:
assert yaml_value(name) == configutils.UNSET
else:
assert yaml_value(name)[-1] == value
def test_add_list_non_list(self, commands):
name = 'history_gap_interval'
value = 'value'
with pytest.raises(
cmdexc.CommandError,
match=":config-add-list can only be used for lists"):
commands.config_add_list(name, value)
def test_add_list_empty_value(self, commands):
name = 'content.host_blocking.whitelist'
value = ''
with pytest.raises(
cmdexc.CommandError,
match="Invalid value '{}' - may not be empty!".format(value)):
commands.config_add_list(name, value)
def test_add_list_none_value(self, commands):
name = 'content.host_blocking.whitelist'
value = None
with pytest.raises(
cmdexc.CommandError,
match="Invalid value 'None' - may not be null!"):
commands.config_add_list(name, value)
@pytest.mark.parametrize('value', ['test1', 'test2'])
@pytest.mark.parametrize('temp', [True, False])
def test_add_dict(self, commands, config_stub, yaml_value, value, temp):
name = 'aliases'
key = 'missingkey'
commands.config_add_dict(name, key, value, temp=temp)
assert str(config_stub.get(name)[key]) == value
if temp:
assert yaml_value(name) == configutils.UNSET
else:
assert yaml_value(name)[key] == value
@pytest.mark.parametrize('replace', [True, False])
def test_add_dict_replace(self, commands, config_stub, replace):
name = 'aliases'
key = 'w'
value = 'anything'
if replace:
commands.config_add_dict(name, key, value, replace=True)
assert str(config_stub.get(name)[key]) == value
else:
with pytest.raises(
cmdexc.CommandError,
match="w already exists in aliases - use --replace to "
"overwrite!"):
commands.config_add_dict(name, key, value, replace=False)
def test_add_dict_non_dict(self, commands):
name = 'history_gap_interval'
key = 'value'
value = 'value'
with pytest.raises(
cmdexc.CommandError,
match=":config-add-dict can only be used for dicts"):
commands.config_add_dict(name, key, value)
def test_add_dict_empty_value(self, commands):
name = 'aliases'
key = 'missingkey'
value = ''
with pytest.raises(cmdexc.CommandError,
match="Invalid value '' - may not be empty!"):
commands.config_add_dict(name, key, value)
def test_add_dict_none_value(self, commands):
name = 'aliases'
key = 'missingkey'
value = None
with pytest.raises(cmdexc.CommandError,
match="Invalid value 'None' - may not be null!"):
commands.config_add_dict(name, key, value)
class TestUnsetAndClear:
"""Test :config-unset and :config-clear."""