parent
d33fae455d
commit
c5999443a1
@ -20,6 +20,7 @@
|
||||
"""Setting options used for qutebrowser."""
|
||||
|
||||
import re
|
||||
import json
|
||||
import shlex
|
||||
import base64
|
||||
import codecs
|
||||
@ -1423,6 +1424,61 @@ class UrlList(List):
|
||||
"{}".format(val.errorString()))
|
||||
|
||||
|
||||
class HeaderDict(BaseType):
|
||||
|
||||
"""A JSON-like dictionary for custom HTTP headers."""
|
||||
|
||||
def validate(self, value):
|
||||
self._basic_validation(value)
|
||||
if not value:
|
||||
return
|
||||
|
||||
try:
|
||||
json_val = json.loads(value)
|
||||
except ValueError as e:
|
||||
raise configexc.ValidationError(value, str(e))
|
||||
|
||||
if not isinstance(json_val, dict):
|
||||
raise configexc.ValidationError(value, "Expected json dict, but "
|
||||
"got {}".format(type(json_val)))
|
||||
|
||||
if not json_val:
|
||||
if self.none_ok:
|
||||
return
|
||||
else:
|
||||
raise configexc.ValidationError(value, "may not be empty!")
|
||||
|
||||
for key, val in json_val.items():
|
||||
if not isinstance(key, str):
|
||||
msg = "Expected string for key {!r} but got {}".format(
|
||||
key, type(key))
|
||||
raise configexc.ValidationError(value, msg)
|
||||
|
||||
if not isinstance(val, str):
|
||||
msg = "Expected string for value {!r} but got {}".format(
|
||||
key, type(key))
|
||||
raise configexc.ValidationError(value, msg)
|
||||
|
||||
try:
|
||||
key.encode('ascii')
|
||||
except UnicodeEncodeError as e:
|
||||
msg = "Key {!r} contains non-ascii characters: {}".format(
|
||||
key, e)
|
||||
raise configexc.ValidationError(value, msg)
|
||||
|
||||
try:
|
||||
val.encode('ascii')
|
||||
except UnicodeEncodeError as e:
|
||||
msg = "Value {!r} contains non-ascii characters: {}".format(
|
||||
val, e)
|
||||
raise configexc.ValidationError(value, msg)
|
||||
|
||||
|
||||
def transform(self, value):
|
||||
val = json.loads(value)
|
||||
return val or None
|
||||
|
||||
|
||||
class SessionName(BaseType):
|
||||
|
||||
"""The name of a session."""
|
||||
|
@ -1715,6 +1715,41 @@ class TestSearchEngineName:
|
||||
assert klass().transform(val) == expected
|
||||
|
||||
|
||||
class TestHeaderDict:
|
||||
|
||||
@pytest.fixture
|
||||
def klass(self):
|
||||
return configtypes.HeaderDict
|
||||
|
||||
@pytest.mark.parametrize('val', [
|
||||
'{"foo": "bar"}',
|
||||
'{"foo": "bar", "baz": "fish"}',
|
||||
'', # empty value with none_ok=true
|
||||
'{}', # ditto
|
||||
])
|
||||
def test_validate_valid(self, klass, val):
|
||||
klass(none_ok=True).validate(val)
|
||||
|
||||
@pytest.mark.parametrize('val', [
|
||||
'["foo"]', # valid json but not a dict
|
||||
'{"hello": 23}', # non-string as value
|
||||
'{"hällo": "world"}', # non-ascii data in key
|
||||
'{"hello": "wörld"}', # non-ascii data in value
|
||||
'', # empty value with none_ok=False
|
||||
'{}', # ditto
|
||||
])
|
||||
def test_validate_invalid(self, klass, val):
|
||||
with pytest.raises(configexc.ValidationError):
|
||||
klass().validate(val)
|
||||
|
||||
@pytest.mark.parametrize('val, expected', [
|
||||
('{"foo": "bar"}', {"foo": "bar"}),
|
||||
('{}', None),
|
||||
])
|
||||
def test_transform(self, klass, val, expected):
|
||||
assert klass(none_ok=True).transform(val) == expected
|
||||
|
||||
|
||||
class TestSearchEngineUrl:
|
||||
|
||||
"""Test SearchEngineUrl."""
|
||||
|
Loading…
Reference in New Issue
Block a user