From a3c7ed51d4b935683d99b87aa2063cfb2f721db5 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Tue, 26 Jul 2016 23:59:55 -0400 Subject: [PATCH] Create LengthList to remove WebKitBytesList and refactor Padding --- qutebrowser/config/configdata.py | 4 +- qutebrowser/config/configtypes.py | 61 +++++--------- tests/unit/config/test_configtypes.py | 84 +++++++++---------- .../config/test_configtypes_hypothesis.py | 2 +- 4 files changed, 64 insertions(+), 87 deletions(-) diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 84c670c60..59998c090 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -684,8 +684,8 @@ def data(readonly=False): ('object-cache-capacities', SettingValue( - typ.WebKitBytesList(length=3, maxsize=MAXVALS['int'], - none_ok=True), ''), + typ.LengthList(typ.WebKitBytes(maxsize=MAXVALS['int'], + none_ok=True), none_ok=True, length=3), ''), "The capacities for the global memory cache for dead objects " "such as stylesheets or scripts. Syntax: cacheMinDeadCapacity, " "cacheMaxDead, totalCapacity.\n\n" diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index 05fa6a15d..0ed6ddb5e 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -337,6 +337,23 @@ class BaseList(List): self._basic_validation(value) +class LengthList(List): + + """Base class for a list with length checking.""" + + def __init__(self, inner_type, length=None, none_ok=False): + super().__init__(inner_type, none_ok) + self.length = length + + def validate(self, value): + super().validate(value) + if not value: + return + if self.length is not None and value.count(',')+1 != self.length: + raise configexc.ValidationError(value, "Exactly {} values need to " + "be set!".format(self.length)) + + class FlagList(BaseList): """Base class for a list setting that contains one or more flags. @@ -969,29 +986,6 @@ class WebKitBytes(BaseType): return int(val) * multiplicator -class WebKitBytesList(List): - - """A size with an optional suffix. - - Attributes: - length: The length of the list. - bytestype: The webkit bytes type. - """ - - def __init__(self, maxsize=None, length=None, none_ok=False): - super().__init__(WebKitBytes(maxsize, none_ok), none_ok=none_ok) - self.length = length - - def validate(self, value): - super().validate(value) - if not value: - return - vals = super().transform(value) - if self.length is not None and len(vals) != self.length: - raise configexc.ValidationError(value, "exactly {} values need to " - "be set!".format(self.length)) - - class ShellCommand(BaseType): """A shellcommand which is split via shlex. @@ -1141,30 +1135,15 @@ PaddingValues = collections.namedtuple('PaddingValues', ['top', 'bottom', 'left', 'right']) -class Padding(List): +class Padding(LengthList): """Setting for paddings around elements.""" def __init__(self, none_ok=False, valid_values=None): - super().__init__(Int(none_ok=none_ok), none_ok=none_ok) + super().__init__(Int(minval=0, none_ok=none_ok), + none_ok=none_ok, length=4) self.inner_type.valid_values = valid_values - def validate(self, value): - self._basic_validation(value) - if not value: - return - try: - vals = self.transform(value) - except (ValueError, TypeError): - raise configexc.ValidationError(value, "must be a list of 4 " - "integers!") - if None in vals and not self.none_ok: - raise configexc.ValidationError(value, "items may not be empty!") - elems = self.transform(value) - if any(e is not None and e < 0 for e in elems): - raise configexc.ValidationError(value, "Values need to be " - "positive!") - def transform(self, value): elems = super().transform(value) if elems is None: diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index 5537d45ea..32600e026 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -400,6 +400,47 @@ class TestList: assert klass().transform(val) == expected +class LengthListSubclass(configtypes.LengthList): + + """A subclass of LengthList which we use in tests.""" + + def __init__(self, length=None, none_ok_inner=False, none_ok_outer=False): + super().__init__(configtypes.Int(none_ok=none_ok_inner), + length=length, none_ok=none_ok_outer) + + +class TestLengthList: + + """Test List with length.""" + + @pytest.fixture + def klass(self): + return LengthListSubclass + + @pytest.mark.parametrize('val', ['', '0,1,2', '-5,4,2']) + def test_validate_valid(self, klass, val): + klass(none_ok_outer=True, length=3).validate(val) + + @pytest.mark.parametrize('val', ['', '1,,4']) + def test_validate_invalid(self, klass, val): + with pytest.raises(configexc.ValidationError): + klass().validate(val) + + def test_invalid_empty_value_none_ok(self, klass): + with pytest.raises(configexc.ValidationError): + klass(none_ok_outer=True).validate('1,,4') + klass(none_ok_inner=True).validate('') + + @pytest.mark.parametrize('val', ['-8', '0,-1', '1,2,3,4,5']) + def test_no_length_given(self, klass, val): + klass().validate(val) + + @pytest.mark.parametrize('val', ['-8', '0,-1', '1,2,3,4,5']) + def test_wrong_length(self, klass, val): + with pytest.raises(configexc.ValidationError): + klass(length=3).validate(val) + + class FlagListSubclass(configtypes.FlagList): """A subclass of FlagList which we use in tests. @@ -1437,49 +1478,6 @@ class TestWebKitByte: assert klass().transform(val) == expected -class TestWebKitBytesList: - - """Test WebKitBytesList.""" - - @pytest.fixture - def klass(self): - return configtypes.WebKitBytesList - - @pytest.mark.parametrize('kwargs, val', [ - ({}, '23,56k,1337'), - ({'maxsize': 2}, '2'), - ({'maxsize': 2048}, '2k'), - ({'length': 3}, '1,2,3'), - ({'none_ok': True}, '23,,42'), - ({'none_ok': True}, ''), - ]) - def test_validate_valid(self, klass, kwargs, val): - klass(**kwargs).validate(val) - - @pytest.mark.parametrize('kwargs, val', [ - ({}, '23,56kk,1337'), - ({'maxsize': 2}, '3'), - ({'maxsize': 2}, '3k'), - ({}, '23,,42'), - ({'length': 3}, '1,2'), - ({'length': 3}, '1,2,3,4'), - ({}, '23,,42'), - ({}, ''), - ]) - def test_validate_invalid(self, klass, kwargs, val): - with pytest.raises(configexc.ValidationError): - klass(**kwargs).validate(val) - - @pytest.mark.parametrize('val, expected', [ - ('1k', [1024]), - ('23,2k,1337', [23, 2048, 1337]), - ('23,,42', [23, None, 42]), - ('', None), - ]) - def test_transform_single(self, klass, val, expected): - assert klass().transform(val) == expected - - class TestShellCommand: """Test ShellCommand.""" diff --git a/tests/unit/config/test_configtypes_hypothesis.py b/tests/unit/config/test_configtypes_hypothesis.py index a5b40c417..a575cae3a 100644 --- a/tests/unit/config/test_configtypes_hypothesis.py +++ b/tests/unit/config/test_configtypes_hypothesis.py @@ -36,7 +36,7 @@ def gen_classes(): pass elif member is configtypes.MappingType: pass - elif member is configtypes.List: + elif member in [configtypes.List, configtypes.LengthList]: pass elif member is configtypes.FormatString: yield functools.partial(member, fields=['a', 'b'])