conftypes: Various bugfixes/cleanups/tests.

This commit is contained in:
Florian Bruhin 2014-08-05 14:14:16 +02:00
parent 7c54c20808
commit 963fb40961
3 changed files with 237 additions and 70 deletions

View File

@ -126,9 +126,10 @@ class BaseType:
Return:
The transformed value.
"""
if self.none_ok and not value:
if not value:
return None
return value
else:
return value
def validate(self, value):
"""Validate value against possible values.
@ -259,7 +260,8 @@ class Bool(BaseType):
def transform(self, value):
if not value:
return None
return Bool._BOOLEAN_STATES[value.lower()]
else:
return Bool._BOOLEAN_STATES[value.lower()]
def validate(self, value):
if not value:
@ -294,9 +296,10 @@ class Int(BaseType):
self.maxval = maxval
def transform(self, value):
if self.none_ok and not value:
if not value:
return None
return int(value)
else:
return int(value)
def validate(self, value):
if not value:
@ -328,9 +331,12 @@ class IntList(List):
def validate(self, value):
try:
self.transform(value)
vals = self.transform(value)
except ValueError:
raise ValidationError(value, "must be a list of integers!")
for v in vals:
if v is None and not self.none_ok:
raise ValidationError(value, "items may not be empty!")
class Float(BaseType):
@ -353,9 +359,10 @@ class Float(BaseType):
self.maxval = maxval
def transform(self, value):
if self.none_ok and not value:
if not value:
return None
return float(value)
else:
return float(value)
def validate(self, value):
if not value:
@ -395,9 +402,10 @@ class Perc(BaseType):
self.maxval = maxval
def transform(self, value):
if self.none_ok and not value:
if not value:
return
return int(value[:-1])
else:
return int(value[:-1])
def validate(self, value):
if not value:
@ -440,7 +448,7 @@ class PercList(List):
def transform(self, value):
vals = super().transform(value)
return [int(val[:-1]) for val in vals]
return [int(v[:-1]) if v is not None else None for v in vals]
def validate(self, value):
vals = super().transform(value)
@ -556,12 +564,13 @@ class ColorSystem(BaseType):
def transform(self, value):
if not value:
return None
mapping = {
'rgb': QColor.Rgb,
'hsv': QColor.Hsv,
'hsl': QColor.Hsl,
}
return mapping[value.lower()]
else:
mapping = {
'rgb': QColor.Rgb,
'hsv': QColor.Hsv,
'hsl': QColor.Hsl,
}
return mapping[value.lower()]
class QtColor(BaseType):
@ -582,7 +591,10 @@ class QtColor(BaseType):
raise ValidationError(value, "must be a valid color")
def transform(self, value):
return QColor(value)
if not value:
return None
else:
return QColor(value)
class CssColor(BaseType):
@ -654,6 +666,8 @@ class QtFont(Font):
"""A Font which gets converted to q QFont."""
def transform(self, value):
if not value:
return None
style_map = {
'normal': QFont.StyleNormal,
'italic': QFont.StyleItalic,
@ -708,7 +722,10 @@ class Regex(BaseType):
raise ValidationError(value, "must be a valid regex - " + str(e))
def transform(self, value):
return re.compile(value, self.flags)
if not value:
return None
else:
return re.compile(value, self.flags)
class RegexList(List):
@ -723,7 +740,8 @@ class RegexList(List):
def transform(self, value):
vals = super().transform(value)
return [re.compile(pattern, self.flags) for pattern in vals]
return [re.compile(v, self.flags) if v is not None else None
for v in vals]
def validate(self, value):
try:
@ -752,6 +770,8 @@ class File(BaseType):
raise ValidationError(value, "must be an absolute path!")
def transform(self, value):
if not value:
return None
return os.path.expanduser(value)
@ -824,7 +844,7 @@ class WebKitBytes(BaseType):
def transform(self, value):
if not value:
return None
if any(value.lower().endswith(c) for c in self.SUFFIXES):
elif any(value.lower().endswith(c) for c in self.SUFFIXES):
suffix = value[-1].lower()
val = value[:-1]
multiplicator = self.SUFFIXES[suffix]
@ -853,8 +873,9 @@ class WebKitBytesList(List):
def transform(self, value):
if value == '':
return None
vals = super().transform(value)
return [self.bytestype.transform(val) for val in vals]
else:
vals = super().transform(value)
return [self.bytestype.transform(val) for val in vals]
def validate(self, value):
if not value:
@ -894,7 +915,10 @@ class ShellCommand(String):
raise ValidationError(value, "needs to contain a {}-placeholder.")
def transform(self, value):
return shlex.split(value)
if not value:
return None
else:
return shlex.split(value)
class ZoomPerc(Perc):
@ -962,7 +986,9 @@ class Proxy(BaseType):
return out
def transform(self, value):
if value == 'system':
if not value:
return None
elif value == 'system':
return None
elif value == 'none':
return QNetworkProxy(QNetworkProxy.NoProxy)
@ -1011,7 +1037,11 @@ class KeyBindingName(BaseType):
"""The name (keys) of a keybinding."""
def validate(self, value):
pass
if not value:
if self.none_ok:
return
else:
raise ValidationError(value, "may not be empty!")
class KeyBinding(Command):
@ -1046,13 +1076,20 @@ class AutoSearch(BaseType):
('false', "Never search automatically."))
def validate(self, value):
if not value:
if self.none_ok:
return
else:
raise ValidationError(value, "may not be empty!")
if value.lower() in ('naive', 'dns'):
pass
else:
Bool.validate(self, value)
def transform(self, value):
if value.lower() in ('naive', 'dns'):
if not value:
return None
elif value.lower() in ('naive', 'dns'):
return value.lower()
elif super().transform(value):
# boolean true is an alias for naive matching

View File

@ -20,6 +20,9 @@
import unittest
import qutebrowser.config.conftypes as conftypes
from qutebrowser.test.stubs import FakeCmdUtils, FakeCommand
from PyQt5.QtGui import QColor, QFont
class ValidValuesTest(unittest.TestCase):
@ -87,13 +90,8 @@ class BaseTypeTests(unittest.TestCase):
self.assertEqual(self.t.transform("foobar"), "foobar")
def test_transform_empty(self):
"""Test transform with none_ok = False and an empty value."""
self.assertEqual(self.t.transform(''), '')
def test_transform_empty_none_ok(self):
"""Test transform with none_ok = True and an empty value."""
t = conftypes.BaseType(none_ok=True)
self.assertIsNone(t.transform(''))
"""Test transform with an empty value."""
self.assertIsNone(self.t.transform(''))
def test_validate_not_implemented(self):
"""Test validate without valid_values set."""
@ -166,7 +164,8 @@ class StringTests(unittest.TestCase):
def test_validate_empty(self):
"""Test validate with empty string and none_ok = False."""
t = conftypes.String()
t.validate("")
with self.assertRaises(conftypes.ValidationError):
t.validate("")
def test_validate_empty_none_ok(self):
"""Test validate with empty string and none_ok = True."""
@ -249,7 +248,7 @@ class ListTests(unittest.TestCase):
def test_transform_empty(self):
"""Test transform with an empty value."""
self.assertEqual(self.t.transform('foo,,baz'),
['foo', '', 'baz'])
['foo', None, 'baz'])
def test_transform_empty_none_ok(self):
"""Test transform with an empty value and none_ok = True."""
@ -271,7 +270,11 @@ class BoolTests(unittest.TestCase):
"""Test transform with all values."""
for out, inputs in self.TESTS.items():
for inp in inputs:
self.assertEqual(self.t.transform(inp), out)
self.assertEqual(self.t.transform(inp), out, inp)
def test_transform_empty(self):
"""Test transform with none_ok = False and an empty value."""
self.assertIsNone(self.t.transform(''))
def test_validate_valid(self):
"""Test validate with valid values."""
@ -285,6 +288,18 @@ class BoolTests(unittest.TestCase):
with self.assertRaises(conftypes.ValidationError):
self.t.validate(val)
def test_validate_empty(self):
"""Test validate with empty string and none_ok = False."""
t = conftypes.Bool()
with self.assertRaises(conftypes.ValidationError):
t.validate('')
def test_validate_empty_none_ok(self):
"""Test validate with empty string and none_ok = True."""
t = conftypes.Int(none_ok=True)
t.validate('')
class IntTests(unittest.TestCase):
@ -397,10 +412,9 @@ class IntListTests(unittest.TestCase):
self.assertEqual(self.t.transform('23,42,1337'),
[23, 42, 1337])
def test_transform_empty_none_ok(self):
"""Test transform with an empty value and none_ok = True."""
t = conftypes.IntList(none_ok=True)
self.assertEqual(t.transform('23,,42'), [23, None, 42])
def test_transform_empty(self):
"""Test transform with an empty value."""
self.assertEqual(self.t.transform('23,,42'), [23, None, 42])
class FloatTests(unittest.TestCase):
@ -481,9 +495,9 @@ class FloatTests(unittest.TestCase):
with self.assertRaises(conftypes.ValidationError):
t.validate('3.01')
def test_transform_none(self):
def test_transform_empty(self):
"""Test transform with an empty value."""
t = conftypes.Float(none_ok=True)
t = conftypes.Float()
self.assertIsNone(t.transform(''))
def test_transform_float(self):
@ -501,6 +515,9 @@ class PercTests(unittest.TestCase):
"""Test Perc."""
def setUp(self):
self.t = conftypes.Perc()
def test_minval_gt_maxval(self):
"""Test __init__ with a minval bigger than the maxval."""
with self.assertRaises(ValueError):
@ -508,26 +525,22 @@ class PercTests(unittest.TestCase):
def test_validate_int(self):
"""Test validate with a normal int (not a percentage)."""
t = conftypes.Perc()
with self.assertRaises(ValueError):
t.validate('1337')
self.t.validate('1337')
def test_validate_string(self):
"""Test validate with something which isn't a percentage."""
t = conftypes.Perc()
with self.assertRaises(conftypes.ValidationError):
t.validate('1337%%')
self.t.validate('1337%%')
def test_validate_perc(self):
"""Test validate with a percentage."""
t = conftypes.Perc()
t.validate('1337%')
self.t.validate('1337%')
def test_validate_empty(self):
"""Test validate with empty string and none_ok = False."""
t = conftypes.Perc()
with self.assertRaises(conftypes.ValidationError):
t.validate('')
self.t.validate('')
def test_validate_empty_none_ok(self):
"""Test validate with empty string and none_ok = True."""
@ -570,15 +583,13 @@ class PercTests(unittest.TestCase):
with self.assertRaises(conftypes.ValidationError):
t.validate('4%')
def test_transform_none(self):
def test_transform_empty(self):
"""Test transform with an empty value."""
t = conftypes.Perc(none_ok=True)
self.assertIsNone(t.transform(''))
self.assertIsNone(self.t.transform(''))
def test_transform_perc(self):
"""Test transform with a percentage."""
t = conftypes.Perc()
self.assertEqual(t.transform('1337%'), 1337)
self.assertEqual(self.t.transform('1337%'), 1337)
class PercListTests(unittest.TestCase):
@ -663,6 +674,9 @@ class PercOrIntTests(unittest.TestCase):
"""Test PercOrInt."""
def setUp(self):
self.t = conftypes.PercOrInt()
def test_minint_gt_maxint(self):
"""Test __init__ with a minint bigger than the maxint."""
with self.assertRaises(ValueError):
@ -675,25 +689,21 @@ class PercOrIntTests(unittest.TestCase):
def test_validate_string(self):
"""Test validate with something which isn't a percentage."""
t = conftypes.PercOrInt()
with self.assertRaises(conftypes.ValidationError):
t.validate('1337%%')
self.t.validate('1337%%')
def test_validate_perc(self):
"""Test validate with a percentage."""
t = conftypes.PercOrInt()
t.validate('1337%')
self.t.validate('1337%')
def test_validate_int(self):
"""Test validate with a normal int."""
t = conftypes.PercOrInt()
t.validate('1337')
self.t.validate('1337')
def test_validate_empty(self):
"""Test validate with empty string and none_ok = False."""
t = conftypes.PercOrInt()
with self.assertRaises(conftypes.ValidationError):
t.validate('')
self.t.validate('')
def test_validate_empty_none_ok(self):
"""Test validate with empty string and none_ok = True."""
@ -786,21 +796,125 @@ class PercOrIntTests(unittest.TestCase):
def test_transform_none(self):
"""Test transform with an empty value."""
t = conftypes.PercOrInt(none_ok=True)
self.assertIsNone(t.transform(''))
self.assertIsNone(self.t.transform(''))
def test_transform_perc(self):
"""Test transform with a percentage."""
t = conftypes.PercOrInt()
self.assertEqual(t.transform('1337%'), '1337%')
self.assertEqual(self.t.transform('1337%'), '1337%')
def test_transform_int(self):
"""Test transform with an int."""
t = conftypes.PercOrInt()
self.assertEqual(t.transform('1337'), '1337')
self.assertEqual(self.t.transform('1337'), '1337')
class CommandTests(unittest.TestCase):
"""Test Command."""
def setUp(self):
self.old_cmdutils = conftypes.cmdutils
commands = {
'cmd1': FakeCommand("desc 1"),
'cmd2': FakeCommand("desc 2"),
}
conftypes.cmdutils = FakeCmdUtils(commands)
self.t = conftypes.Command()
def tearDown(self):
conftypes.cmdutils = self.old_cmdutils
def test_validate_empty(self):
"""Test validate with an empty string."""
with self.assertRaises(conftypes.ValidationError):
self.t.validate('')
def test_validate_empty_none_ok(self):
"""Test validate with an empty string and none_ok=True."""
t = conftypes.Command(none_ok=True)
t.validate('')
def test_validate_command(self):
"""Test validate with a command."""
self.t.validate('cmd1')
self.t.validate('cmd2')
def test_validate_command_args(self):
"""Test validate with a command and arguments."""
self.t.validate('cmd1 foo bar')
self.t.validate('cmd2 baz fish')
def test_validate_invalid_command(self):
"""Test validate with an invalid command."""
with self.assertRaises(conftypes.ValidationError):
self.t.validate('cmd3')
def test_validate_invalid_command_args(self):
"""Test validate with an invalid command and arguments."""
with self.assertRaises(conftypes.ValidationError):
self.t.validate('cmd3 foo bar')
def test_transform(self):
"""Make sure transform doesn't alter values."""
self.assertEqual(self.t.transform('foo bar'), 'foo bar')
def test_transform_empty(self):
"""Test transform with an empty value."""
self.assertIsNone(self.t.transform(''))
def test_complete(self):
"""Test complete."""
items = self.t.complete()
self.assertEqual(len(items), 2)
self.assertIn(('cmd1', "desc 1"), items)
self.assertIn(('cmd2', "desc 2"), items)
class ColorSystemTests(unittest.TestCase):
"""Test ColorSystem."""
TESTS = {
'RGB': QColor.Rgb,
'rgb': QColor.Rgb,
'HSV': QColor.Hsv,
'hsv': QColor.Hsv,
'HSL': QColor.Hsl,
'hsl': QColor.Hsl,
}
INVALID = ['RRGB', 'HSV ']
def setUp(self):
self.t = conftypes.ColorSystem()
def test_validate_empty(self):
"""Test validate with an empty string."""
with self.assertRaises(conftypes.ValidationError):
self.t.validate('')
def test_validate_empty_none_ok(self):
"""Test validate with an empty string and none_ok=True."""
t = conftypes.ColorSystem(none_ok=True)
t.validate('')
def test_validate_valid(self):
"""Test validate with valid values."""
for val in self.TESTS:
self.t.validate(val)
def test_validate_invalid(self):
"""Test validate with invalid values."""
for val in self.INVALID:
with self.assertRaises(conftypes.ValidationError, msg=val):
self.t.validate(val)
def test_transform(self):
"""Test transform."""
for k, v in self.TESTS.items():
self.assertEqual(self.t.transform(k), v, k)
def test_transform_empty(self):
"""Test transform with an empty value."""
self.assertIsNone(self.t.transform(''))
if __name__ == '__main__':
unittest.main()

View File

@ -279,3 +279,19 @@ class FakeSignal:
def __init__(self, name='fake'):
self.signal = '2{}(int, int)'.format(name)
class FakeCmdUtils:
"""Stub for cmdutils which provides a cmd_dict."""
def __init__(self, commands):
self.cmd_dict = commands
class FakeCommand:
"""A simple command stub which has a description."""
def __init__(self, desc):
self.desc = desc