Allow missing fixed_keys for configtypes.Dict
We just fill them up with a None value for the value type, so we can e.g. only specify a subset of modes for bindings and the rest is {}.
This commit is contained in:
parent
9d8b76e497
commit
441b3a4df4
@ -2095,6 +2095,7 @@ bindings.commands:
|
|||||||
'prompt', 'caret', 'register']
|
'prompt', 'caret', 'register']
|
||||||
valtype:
|
valtype:
|
||||||
name: Dict
|
name: Dict
|
||||||
|
none_ok: true
|
||||||
keytype: Key
|
keytype: Key
|
||||||
valtype:
|
valtype:
|
||||||
name: Command
|
name: Command
|
||||||
|
@ -1031,10 +1031,11 @@ class Dict(BaseType):
|
|||||||
self.required_keys = required_keys
|
self.required_keys = required_keys
|
||||||
|
|
||||||
def _validate_keys(self, value):
|
def _validate_keys(self, value):
|
||||||
if (self.fixed_keys is not None and
|
if (self.fixed_keys is not None and not
|
||||||
value.keys() != set(self.fixed_keys)):
|
set(value.keys()).issubset(self.fixed_keys)):
|
||||||
raise configexc.ValidationError(
|
raise configexc.ValidationError(
|
||||||
value, "Expected keys {}".format(self.fixed_keys))
|
value, "Expected keys {}".format(self.fixed_keys))
|
||||||
|
|
||||||
if (self.required_keys is not None and not
|
if (self.required_keys is not None and not
|
||||||
set(self.required_keys).issubset(value.keys())):
|
set(self.required_keys).issubset(value.keys())):
|
||||||
raise configexc.ValidationError(
|
raise configexc.ValidationError(
|
||||||
@ -1055,19 +1056,25 @@ class Dict(BaseType):
|
|||||||
self.to_py(yaml_val)
|
self.to_py(yaml_val)
|
||||||
return yaml_val
|
return yaml_val
|
||||||
|
|
||||||
|
def _fill_fixed_keys(self, value):
|
||||||
|
"""Fill missing fixed keys with a None-value."""
|
||||||
|
if self.fixed_keys is None:
|
||||||
|
return value
|
||||||
|
for key in self.fixed_keys:
|
||||||
|
if key not in value:
|
||||||
|
value[key] = self.valtype.to_py(None)
|
||||||
|
return value
|
||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, dict)
|
self._basic_py_validation(value, dict)
|
||||||
if not value:
|
if not value:
|
||||||
if self.fixed_keys is None:
|
return self._fill_fixed_keys({})
|
||||||
return {}
|
|
||||||
else:
|
|
||||||
return {key: self.valtype.to_py(None)
|
|
||||||
for key in self.fixed_keys}
|
|
||||||
|
|
||||||
self._validate_keys(value)
|
self._validate_keys(value)
|
||||||
|
|
||||||
return {self.keytype.to_py(key): self.valtype.to_py(val)
|
d = {self.keytype.to_py(key): self.valtype.to_py(val)
|
||||||
for key, val in value.items()}
|
for key, val in value.items()}
|
||||||
|
return self._fill_fixed_keys(d)
|
||||||
|
|
||||||
def to_str(self, value):
|
def to_str(self, value):
|
||||||
if not value:
|
if not value:
|
||||||
|
@ -1398,7 +1398,7 @@ class TestDict:
|
|||||||
assert typ.from_str('{"answer": 42}') == {"answer": 42}
|
assert typ.from_str('{"answer": 42}') == {"answer": 42}
|
||||||
|
|
||||||
@pytest.mark.parametrize('kind, val, ok', [
|
@pytest.mark.parametrize('kind, val, ok', [
|
||||||
('fixed', {"one": "1"}, False), # missing key
|
('fixed', {"one": "1"}, True), # missing key (gets filled with None)
|
||||||
('fixed', {"one": "1", "two": "2", "three": "3"}, False), # extra key
|
('fixed', {"one": "1", "two": "2", "three": "3"}, False), # extra key
|
||||||
('fixed', {"one": "1", "two": "2"}, True),
|
('fixed', {"one": "1", "two": "2"}, True),
|
||||||
|
|
||||||
@ -1410,7 +1410,7 @@ class TestDict:
|
|||||||
def test_keys(self, klass, kind, val, ok, from_str):
|
def test_keys(self, klass, kind, val, ok, from_str):
|
||||||
if kind == 'fixed':
|
if kind == 'fixed':
|
||||||
d = klass(keytype=configtypes.String(),
|
d = klass(keytype=configtypes.String(),
|
||||||
valtype=configtypes.String(),
|
valtype=configtypes.String(none_ok=True),
|
||||||
fixed_keys=['one', 'two'])
|
fixed_keys=['one', 'two'])
|
||||||
message = 'Expected keys .*'
|
message = 'Expected keys .*'
|
||||||
elif kind == 'required':
|
elif kind == 'required':
|
||||||
|
Loading…
Reference in New Issue
Block a user