Reject hints -> chars containing duplicate chars

Fixes #1286.
This commit is contained in:
Florian Bruhin 2016-02-03 21:05:35 +01:00
parent 0b491f6caf
commit e5e1a0d95c
4 changed files with 32 additions and 11 deletions

View File

@ -48,6 +48,7 @@ Fixed
- Fixed crash when downloading a file without any path information (e.g a
magnet link).
- Fixed crashes when opening an empty URL (e.g. via pasting).
- Fixed validation of duplicate values in `hints -> chars`.
v0.5.1
------

View File

@ -870,7 +870,7 @@ def data(readonly=False):
"Mode to use for hints."),
('chars',
SettingValue(typ.String(minlen=2, completions=[
SettingValue(typ.UniqueCharString(minlen=2, completions=[
('asdfghjkl', "Home row"),
('dhtnaoeu', "Home row (Dvorak)"),
('abcdefghijklmnopqrstuvwxyz', "All letters"),

View File

@ -283,6 +283,21 @@ class String(BaseType):
return super().complete()
class UniqueCharString(String):
"""A string which may not contain duplicate chars."""
def validate(self, value):
super().validate(value)
if not value:
return
# Check for duplicate values
if len(set(value)) != len(value):
raise configexc.ValidationError(
value, "String contains duplicate values!")
class List(BaseType):
"""Base class for a (string-)list setting."""

View File

@ -278,9 +278,9 @@ class TestString:
"""Test String."""
@pytest.fixture
def klass(self):
return configtypes.String
@pytest.fixture(params=[configtypes.String, configtypes.UniqueCharString])
def klass(self, request):
return request.param
@pytest.mark.parametrize('minlen, maxlen', [(1, None), (None, 1)])
def test_lengths_valid(self, klass, minlen, maxlen):
@ -297,16 +297,16 @@ class TestString:
@pytest.mark.parametrize('kwargs, val', [
({'none_ok': True}, ''), # Empty with none_ok
({}, "Hello World! :-)"),
({}, "Test! :-)"),
# Forbidden chars
({'forbidden': 'xyz'}, 'foobar'),
({'forbidden': 'xyz'}, 'fobar'),
({'forbidden': 'xyz'}, 'foXbar'),
# Lengths
({'minlen': 2}, 'fo'),
({'minlen': 2, 'maxlen': 3}, 'fo'),
({'minlen': 2, 'maxlen': 3}, 'foo'),
({'minlen': 2, 'maxlen': 3}, 'abc'),
# valid_values
({'valid_values': configtypes.ValidValues('fooo')}, 'fooo'),
({'valid_values': configtypes.ValidValues('abcd')}, 'abcd'),
])
def test_validate_valid(self, klass, kwargs, val):
klass(**kwargs).validate(val)
@ -320,16 +320,21 @@ class TestString:
({'minlen': 2}, 'f'),
({'maxlen': 2}, 'fob'),
({'minlen': 2, 'maxlen': 3}, 'f'),
({'minlen': 2, 'maxlen': 3}, 'fooo'),
({'minlen': 2, 'maxlen': 3}, 'abcd'),
# valid_values
({'valid_values': configtypes.ValidValues('blah')}, 'fooo'),
({'valid_values': configtypes.ValidValues('blah')}, 'abcd'),
])
def test_validate_invalid(self, klass, kwargs, val):
with pytest.raises(configexc.ValidationError):
klass(**kwargs).validate(val)
def test_validate_duplicate_invalid(self):
typ = configtypes.UniqueCharString()
with pytest.raises(configexc.ValidationError):
typ.validate('foobar')
def test_transform(self, klass):
assert klass().transform('foobar') == 'foobar'
assert klass().transform('fobar') == 'fobar'
@pytest.mark.parametrize('value', [
None,