parent
0b491f6caf
commit
e5e1a0d95c
@ -48,6 +48,7 @@ Fixed
|
|||||||
- Fixed crash when downloading a file without any path information (e.g a
|
- Fixed crash when downloading a file without any path information (e.g a
|
||||||
magnet link).
|
magnet link).
|
||||||
- Fixed crashes when opening an empty URL (e.g. via pasting).
|
- Fixed crashes when opening an empty URL (e.g. via pasting).
|
||||||
|
- Fixed validation of duplicate values in `hints -> chars`.
|
||||||
|
|
||||||
v0.5.1
|
v0.5.1
|
||||||
------
|
------
|
||||||
|
@ -870,7 +870,7 @@ def data(readonly=False):
|
|||||||
"Mode to use for hints."),
|
"Mode to use for hints."),
|
||||||
|
|
||||||
('chars',
|
('chars',
|
||||||
SettingValue(typ.String(minlen=2, completions=[
|
SettingValue(typ.UniqueCharString(minlen=2, completions=[
|
||||||
('asdfghjkl', "Home row"),
|
('asdfghjkl', "Home row"),
|
||||||
('dhtnaoeu', "Home row (Dvorak)"),
|
('dhtnaoeu', "Home row (Dvorak)"),
|
||||||
('abcdefghijklmnopqrstuvwxyz', "All letters"),
|
('abcdefghijklmnopqrstuvwxyz', "All letters"),
|
||||||
|
@ -283,6 +283,21 @@ class String(BaseType):
|
|||||||
return super().complete()
|
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):
|
class List(BaseType):
|
||||||
|
|
||||||
"""Base class for a (string-)list setting."""
|
"""Base class for a (string-)list setting."""
|
||||||
|
@ -278,9 +278,9 @@ class TestString:
|
|||||||
|
|
||||||
"""Test String."""
|
"""Test String."""
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture(params=[configtypes.String, configtypes.UniqueCharString])
|
||||||
def klass(self):
|
def klass(self, request):
|
||||||
return configtypes.String
|
return request.param
|
||||||
|
|
||||||
@pytest.mark.parametrize('minlen, maxlen', [(1, None), (None, 1)])
|
@pytest.mark.parametrize('minlen, maxlen', [(1, None), (None, 1)])
|
||||||
def test_lengths_valid(self, klass, minlen, maxlen):
|
def test_lengths_valid(self, klass, minlen, maxlen):
|
||||||
@ -297,16 +297,16 @@ class TestString:
|
|||||||
|
|
||||||
@pytest.mark.parametrize('kwargs, val', [
|
@pytest.mark.parametrize('kwargs, val', [
|
||||||
({'none_ok': True}, ''), # Empty with none_ok
|
({'none_ok': True}, ''), # Empty with none_ok
|
||||||
({}, "Hello World! :-)"),
|
({}, "Test! :-)"),
|
||||||
# Forbidden chars
|
# Forbidden chars
|
||||||
({'forbidden': 'xyz'}, 'foobar'),
|
({'forbidden': 'xyz'}, 'fobar'),
|
||||||
({'forbidden': 'xyz'}, 'foXbar'),
|
({'forbidden': 'xyz'}, 'foXbar'),
|
||||||
# Lengths
|
# Lengths
|
||||||
({'minlen': 2}, 'fo'),
|
({'minlen': 2}, 'fo'),
|
||||||
({'minlen': 2, 'maxlen': 3}, 'fo'),
|
({'minlen': 2, 'maxlen': 3}, 'fo'),
|
||||||
({'minlen': 2, 'maxlen': 3}, 'foo'),
|
({'minlen': 2, 'maxlen': 3}, 'abc'),
|
||||||
# valid_values
|
# valid_values
|
||||||
({'valid_values': configtypes.ValidValues('fooo')}, 'fooo'),
|
({'valid_values': configtypes.ValidValues('abcd')}, 'abcd'),
|
||||||
])
|
])
|
||||||
def test_validate_valid(self, klass, kwargs, val):
|
def test_validate_valid(self, klass, kwargs, val):
|
||||||
klass(**kwargs).validate(val)
|
klass(**kwargs).validate(val)
|
||||||
@ -320,16 +320,21 @@ class TestString:
|
|||||||
({'minlen': 2}, 'f'),
|
({'minlen': 2}, 'f'),
|
||||||
({'maxlen': 2}, 'fob'),
|
({'maxlen': 2}, 'fob'),
|
||||||
({'minlen': 2, 'maxlen': 3}, 'f'),
|
({'minlen': 2, 'maxlen': 3}, 'f'),
|
||||||
({'minlen': 2, 'maxlen': 3}, 'fooo'),
|
({'minlen': 2, 'maxlen': 3}, 'abcd'),
|
||||||
# valid_values
|
# valid_values
|
||||||
({'valid_values': configtypes.ValidValues('blah')}, 'fooo'),
|
({'valid_values': configtypes.ValidValues('blah')}, 'abcd'),
|
||||||
])
|
])
|
||||||
def test_validate_invalid(self, klass, kwargs, val):
|
def test_validate_invalid(self, klass, kwargs, val):
|
||||||
with pytest.raises(configexc.ValidationError):
|
with pytest.raises(configexc.ValidationError):
|
||||||
klass(**kwargs).validate(val)
|
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):
|
def test_transform(self, klass):
|
||||||
assert klass().transform('foobar') == 'foobar'
|
assert klass().transform('fobar') == 'fobar'
|
||||||
|
|
||||||
@pytest.mark.parametrize('value', [
|
@pytest.mark.parametrize('value', [
|
||||||
None,
|
None,
|
||||||
|
Loading…
Reference in New Issue
Block a user