Make sure :bind/unbind works properly when bindings.commands is None
To make this work, we should never return None when trying to get bindings to modify. Fixes #3026
This commit is contained in:
parent
0fbd914432
commit
a273baf8a0
@ -384,7 +384,7 @@ class Config(QObject):
|
||||
raise configexc.BackendError(objects.backend)
|
||||
|
||||
opt.typ.to_py(value) # for validation
|
||||
self._values[opt.name] = value
|
||||
self._values[opt.name] = opt.typ.from_obj(value)
|
||||
|
||||
self.changed.emit(opt.name)
|
||||
log.config.debug("Config option changed: {} = {}".format(
|
||||
|
@ -227,6 +227,10 @@ class BaseType:
|
||||
return None
|
||||
return value
|
||||
|
||||
def from_obj(self, value):
|
||||
"""Get the setting value from a config.py/YAML object."""
|
||||
return value
|
||||
|
||||
def to_py(self, value):
|
||||
"""Get the setting value from a Python value.
|
||||
|
||||
@ -441,6 +445,11 @@ class List(BaseType):
|
||||
self.to_py(yaml_val)
|
||||
return yaml_val
|
||||
|
||||
def from_obj(self, value):
|
||||
if value is None:
|
||||
return []
|
||||
return value
|
||||
|
||||
def to_py(self, value):
|
||||
self._basic_py_validation(value, list)
|
||||
if not value:
|
||||
@ -506,6 +515,11 @@ class ListOrValue(BaseType):
|
||||
except configexc.ValidationError:
|
||||
return self.valtype.from_str(value)
|
||||
|
||||
def from_obj(self, value):
|
||||
if value is None:
|
||||
return []
|
||||
return value
|
||||
|
||||
def to_py(self, value):
|
||||
try:
|
||||
return [self.valtype.to_py(value)]
|
||||
@ -1176,6 +1190,11 @@ class Dict(BaseType):
|
||||
self.to_py(yaml_val)
|
||||
return yaml_val
|
||||
|
||||
def from_obj(self, value):
|
||||
if value is None:
|
||||
return {}
|
||||
return value
|
||||
|
||||
def _fill_fixed_keys(self, value):
|
||||
"""Fill missing fixed keys with a None-value."""
|
||||
if self.fixed_keys is None:
|
||||
|
@ -547,6 +547,14 @@ class TestBindConfigCommand:
|
||||
commands.bind(key, 'message-info foo', mode='normal')
|
||||
assert keyconf.get_command(key, 'normal') == 'nop'
|
||||
|
||||
def test_bind_none(self, commands, config_stub):
|
||||
config_stub.val.bindings.commands = None
|
||||
commands.bind(',x', 'nop')
|
||||
|
||||
def test_unbind_none(self, commands, config_stub):
|
||||
config_stub.val.bindings.commands = None
|
||||
commands.unbind('H')
|
||||
|
||||
@pytest.mark.parametrize('key, normalized', [
|
||||
('a', 'a'), # default bindings
|
||||
('b', 'b'), # custom bindings
|
||||
|
@ -378,6 +378,13 @@ class TestConfigPy:
|
||||
expected = "Duplicate key H - use force=True to override!"
|
||||
assert str(error.exception) == expected
|
||||
|
||||
def test_bind_none(self, confpy):
|
||||
confpy.write("c.bindings.commands = None",
|
||||
"config.bind(',x', 'nop')")
|
||||
confpy.read()
|
||||
expected = {'normal': {',x': 'nop'}}
|
||||
assert config.instance._values['bindings.commands'] == expected
|
||||
|
||||
@pytest.mark.parametrize('line, key, mode', [
|
||||
('config.unbind("o")', 'o', 'normal'),
|
||||
('config.unbind("y", mode="prompt")', 'y', 'prompt'),
|
||||
|
@ -370,6 +370,10 @@ class TestBaseType:
|
||||
def test_to_doc(self, klass, value, expected):
|
||||
assert klass().to_doc(value) == expected
|
||||
|
||||
@pytest.mark.parametrize('obj', [42, '', None, 'foo'])
|
||||
def test_from_obj(self, klass, obj):
|
||||
assert klass(none_ok=True).from_obj(obj) == obj
|
||||
|
||||
|
||||
class MappingSubclass(configtypes.MappingType):
|
||||
|
||||
@ -550,6 +554,14 @@ class TestList:
|
||||
with pytest.raises(configexc.ValidationError):
|
||||
klass().from_str(val)
|
||||
|
||||
@pytest.mark.parametrize('obj, expected', [
|
||||
([1], [1]),
|
||||
([], []),
|
||||
(None, []),
|
||||
])
|
||||
def test_from_obj(self, klass, obj, expected):
|
||||
assert klass(none_ok_outer=True).from_obj(obj) == expected
|
||||
|
||||
@pytest.mark.parametrize('val', [['foo'], ['foo', 'bar']])
|
||||
def test_to_py_valid(self, klass, val):
|
||||
assert klass().to_py(val) == val
|
||||
@ -713,6 +725,15 @@ class TestListOrValue:
|
||||
def test_to_py_length(self, strtype, klass, val):
|
||||
klass(strtype, none_ok=True, length=2).to_py(val)
|
||||
|
||||
@pytest.mark.parametrize('obj, expected', [
|
||||
(['a'], ['a']),
|
||||
([], []),
|
||||
(None, []),
|
||||
])
|
||||
def test_from_obj(self, klass, obj, expected):
|
||||
typ = klass(none_ok=True, valtype=configtypes.String())
|
||||
assert typ.from_obj(obj) == expected
|
||||
|
||||
@pytest.mark.parametrize('val', [['a'], ['a', 'b'], ['a', 'b', 'c', 'd']])
|
||||
def test_wrong_length(self, strtype, klass, val):
|
||||
with pytest.raises(configexc.ValidationError,
|
||||
@ -1533,6 +1554,16 @@ class TestDict:
|
||||
valtype=configtypes.Int())
|
||||
assert typ.from_str('{"answer": 42}') == {"answer": 42}
|
||||
|
||||
@pytest.mark.parametrize('obj, expected', [
|
||||
({'a': 'b'}, {'a': 'b'}),
|
||||
({}, {}),
|
||||
(None, {}),
|
||||
])
|
||||
def test_from_obj(self, klass, obj, expected):
|
||||
d = klass(keytype=configtypes.String(), valtype=configtypes.String(),
|
||||
none_ok=True)
|
||||
assert d.from_obj(obj) == expected
|
||||
|
||||
@pytest.mark.parametrize('keytype, valtype, val', [
|
||||
(configtypes.String(), configtypes.String(), {'hello': 'world'}),
|
||||
(configtypes.String(), configtypes.Int(), {'hello': 42}),
|
||||
|
Loading…
Reference in New Issue
Block a user