Allow direct values for url.start_pages and content.user_stylesheets
This commit is contained in:
parent
2dfcf9c506
commit
c694bff902
@ -1944,7 +1944,7 @@ Default: +pass:[ask]+
|
|||||||
=== content.user_stylesheets
|
=== content.user_stylesheets
|
||||||
A list of user stylesheet filenames to use.
|
A list of user stylesheet filenames to use.
|
||||||
|
|
||||||
Type: <<types,List>>
|
Type: <<types,ListOrValue>>
|
||||||
|
|
||||||
Default: empty
|
Default: empty
|
||||||
|
|
||||||
@ -3056,11 +3056,9 @@ Default:
|
|||||||
=== url.start_pages
|
=== url.start_pages
|
||||||
The page(s) to open at the start.
|
The page(s) to open at the start.
|
||||||
|
|
||||||
Type: <<types,List>>
|
Type: <<types,ListOrValue>>
|
||||||
|
|
||||||
Default:
|
Default: +pass:[https://start.duckduckgo.com]+
|
||||||
|
|
||||||
- +pass:[https://start.duckduckgo.com]+
|
|
||||||
|
|
||||||
[[url.yank_ignored_parameters]]
|
[[url.yank_ignored_parameters]]
|
||||||
=== url.yank_ignored_parameters
|
=== url.yank_ignored_parameters
|
||||||
@ -3199,6 +3197,7 @@ Lists with duplicate flags are invalid. Each item is checked against the valid v
|
|||||||
|List|A list of values.
|
|List|A list of values.
|
||||||
|
|
||||||
When setting from a string, pass a json-like list, e.g. `["one", "two"]`.
|
When setting from a string, pass a json-like list, e.g. `["one", "two"]`.
|
||||||
|
|ListOrValue|A list of values, or a single value.
|
||||||
|NewTabPosition|How new tabs are positioned.
|
|NewTabPosition|How new tabs are positioned.
|
||||||
|Padding|Setting for paddings around elements.
|
|Padding|Setting for paddings around elements.
|
||||||
|Perc|A percentage.
|
|Perc|A percentage.
|
||||||
|
@ -93,7 +93,7 @@ def _parse_yaml_type(name, node):
|
|||||||
if typ is configtypes.Dict:
|
if typ is configtypes.Dict:
|
||||||
kwargs['keytype'] = _parse_yaml_type(name, kwargs['keytype'])
|
kwargs['keytype'] = _parse_yaml_type(name, kwargs['keytype'])
|
||||||
kwargs['valtype'] = _parse_yaml_type(name, kwargs['valtype'])
|
kwargs['valtype'] = _parse_yaml_type(name, kwargs['valtype'])
|
||||||
elif typ is configtypes.List:
|
elif typ is configtypes.List or typ is configtypes.ListOrValue:
|
||||||
kwargs['valtype'] = _parse_yaml_type(name, kwargs['valtype'])
|
kwargs['valtype'] = _parse_yaml_type(name, kwargs['valtype'])
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
_raise_invalid_node(name, str(e), node)
|
_raise_invalid_node(name, str(e), node)
|
||||||
|
@ -545,7 +545,7 @@ content.ssl_strict:
|
|||||||
|
|
||||||
content.user_stylesheets:
|
content.user_stylesheets:
|
||||||
type:
|
type:
|
||||||
name: List
|
name: ListOrValue
|
||||||
valtype: File
|
valtype: File
|
||||||
none_ok: True
|
none_ok: True
|
||||||
default: null
|
default: null
|
||||||
@ -1240,9 +1240,9 @@ url.searchengines:
|
|||||||
|
|
||||||
url.start_pages:
|
url.start_pages:
|
||||||
type:
|
type:
|
||||||
name: List
|
name: ListOrValue
|
||||||
valtype: FuzzyUrl
|
valtype: FuzzyUrl
|
||||||
default: ["https://start.duckduckgo.com"]
|
default: "https://start.duckduckgo.com"
|
||||||
desc: The page(s) to open at the start.
|
desc: The page(s) to open at the start.
|
||||||
|
|
||||||
url.yank_ignored_parameters:
|
url.yank_ignored_parameters:
|
||||||
|
@ -476,6 +476,67 @@ class List(BaseType):
|
|||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
class ListOrValue(BaseType):
|
||||||
|
|
||||||
|
"""A list of values, or a single value.
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
Internally, the value is stored as either a value (of valtype), or a list.
|
||||||
|
to_py() then ensures that it's always a list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_show_valtype = True
|
||||||
|
|
||||||
|
def __init__(self, valtype, none_ok=False, *args, **kwargs):
|
||||||
|
super().__init__(none_ok)
|
||||||
|
assert not isinstance(valtype, (List, ListOrValue)), valtype
|
||||||
|
self.listtype = List(valtype, none_ok=none_ok, *args, **kwargs)
|
||||||
|
self.valtype = valtype
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return self.listtype.get_name() + ' or ' + self.valtype.get_name()
|
||||||
|
|
||||||
|
def get_valid_values(self):
|
||||||
|
return self.valtype.get_valid_values()
|
||||||
|
|
||||||
|
def from_str(self, value):
|
||||||
|
try:
|
||||||
|
return self.listtype.from_str(value)
|
||||||
|
except configexc.ValidationError:
|
||||||
|
return self.valtype.from_str(value)
|
||||||
|
|
||||||
|
def to_py(self, value):
|
||||||
|
try:
|
||||||
|
return [self.valtype.to_py(value)]
|
||||||
|
except configexc.ValidationError:
|
||||||
|
return self.listtype.to_py(value)
|
||||||
|
|
||||||
|
def to_str(self, value):
|
||||||
|
if value is None:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
if isinstance(value, list):
|
||||||
|
if len(value) == 1:
|
||||||
|
return self.valtype.to_str(value[0])
|
||||||
|
else:
|
||||||
|
return self.listtype.to_str(value)
|
||||||
|
else:
|
||||||
|
return self.valtype.to_str(value)
|
||||||
|
|
||||||
|
def to_doc(self, value):
|
||||||
|
if value is None:
|
||||||
|
return 'empty'
|
||||||
|
|
||||||
|
if isinstance(value, list):
|
||||||
|
if len(value) == 1:
|
||||||
|
return self.valtype.to_doc(value[0])
|
||||||
|
else:
|
||||||
|
return self.listtype.to_doc(value)
|
||||||
|
else:
|
||||||
|
return self.valtype.to_doc(value)
|
||||||
|
|
||||||
|
|
||||||
class FlagList(List):
|
class FlagList(List):
|
||||||
|
|
||||||
"""A list of flags.
|
"""A list of flags.
|
||||||
|
@ -193,7 +193,8 @@ class TestAll:
|
|||||||
if member in [configtypes.BaseType, configtypes.MappingType,
|
if member in [configtypes.BaseType, configtypes.MappingType,
|
||||||
configtypes._Numeric]:
|
configtypes._Numeric]:
|
||||||
pass
|
pass
|
||||||
elif member is configtypes.List:
|
elif (member is configtypes.List or
|
||||||
|
member is configtypes.ListOrValue):
|
||||||
yield functools.partial(member, valtype=configtypes.Int())
|
yield functools.partial(member, valtype=configtypes.Int())
|
||||||
yield functools.partial(member, valtype=configtypes.Url())
|
yield functools.partial(member, valtype=configtypes.Url())
|
||||||
elif member is configtypes.Dict:
|
elif member is configtypes.Dict:
|
||||||
@ -240,6 +241,9 @@ class TestAll:
|
|||||||
configtypes.PercOrInt, # ditto
|
configtypes.PercOrInt, # ditto
|
||||||
]:
|
]:
|
||||||
return
|
return
|
||||||
|
if (isinstance(typ, configtypes.ListOrValue) and
|
||||||
|
isinstance(typ.valtype, configtypes.Int)):
|
||||||
|
return
|
||||||
|
|
||||||
assert converted == s
|
assert converted == s
|
||||||
|
|
||||||
@ -250,7 +254,7 @@ class TestAll:
|
|||||||
to_py_expected = configtypes.PaddingValues(None, None, None, None)
|
to_py_expected = configtypes.PaddingValues(None, None, None, None)
|
||||||
elif isinstance(typ, configtypes.Dict):
|
elif isinstance(typ, configtypes.Dict):
|
||||||
to_py_expected = {}
|
to_py_expected = {}
|
||||||
elif isinstance(typ, configtypes.List):
|
elif isinstance(typ, (configtypes.List, configtypes.ListOrValue)):
|
||||||
to_py_expected = []
|
to_py_expected = []
|
||||||
else:
|
else:
|
||||||
to_py_expected = None
|
to_py_expected = None
|
||||||
@ -670,6 +674,99 @@ class TestFlagList:
|
|||||||
assert klass().complete() is None
|
assert klass().complete() is None
|
||||||
|
|
||||||
|
|
||||||
|
class TestListOrValue:
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def klass(self):
|
||||||
|
return configtypes.ListOrValue
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def strtype(self):
|
||||||
|
return configtypes.String()
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val, expected', [
|
||||||
|
('["foo"]', ['foo']),
|
||||||
|
('["foo", "bar"]', ['foo', 'bar']),
|
||||||
|
('foo', 'foo'),
|
||||||
|
])
|
||||||
|
def test_from_str(self, klass, strtype, val, expected):
|
||||||
|
assert klass(strtype).from_str(val) == expected
|
||||||
|
|
||||||
|
def test_from_str_invalid(self, klass):
|
||||||
|
valtype = configtypes.String(minlen=10)
|
||||||
|
with pytest.raises(configexc.ValidationError):
|
||||||
|
klass(valtype).from_str('123')
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val, expected', [
|
||||||
|
(['foo'], ['foo']),
|
||||||
|
('foo', ['foo']),
|
||||||
|
])
|
||||||
|
def test_to_py_valid(self, klass, strtype, val, expected):
|
||||||
|
assert klass(strtype).to_py(val) == expected
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val', [[42], ['\U00010000']])
|
||||||
|
def test_to_py_invalid(self, klass, strtype, val):
|
||||||
|
with pytest.raises(configexc.ValidationError):
|
||||||
|
klass(strtype).to_py(val)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val', [None, ['foo', 'bar'], 'abcd'])
|
||||||
|
def test_to_py_length(self, strtype, klass, val):
|
||||||
|
klass(strtype, none_ok=True, length=2).to_py(val)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val', [['a'], ['a', 'b'], ['a', 'b', 'c', 'd']])
|
||||||
|
def test_wrong_length(self, strtype, klass, val):
|
||||||
|
with pytest.raises(configexc.ValidationError,
|
||||||
|
match='Exactly 3 values need to be set!'):
|
||||||
|
klass(strtype, length=3).to_py(val)
|
||||||
|
|
||||||
|
def test_get_name(self, strtype, klass):
|
||||||
|
assert klass(strtype).get_name() == 'List of String or String'
|
||||||
|
|
||||||
|
def test_get_valid_values(self, klass):
|
||||||
|
valid_values = configtypes.ValidValues('foo', 'bar', 'baz')
|
||||||
|
valtype = configtypes.String(valid_values=valid_values)
|
||||||
|
assert klass(valtype).get_valid_values() == valid_values
|
||||||
|
|
||||||
|
def test_to_str(self, strtype, klass):
|
||||||
|
assert klass(strtype).to_str(["a", True]) == '["a", true]'
|
||||||
|
|
||||||
|
@hypothesis.given(val=strategies.lists(strategies.just('foo')))
|
||||||
|
def test_hypothesis(self, strtype, klass, val):
|
||||||
|
typ = klass(strtype, none_ok=True)
|
||||||
|
try:
|
||||||
|
converted = typ.to_py(val)
|
||||||
|
except configexc.ValidationError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
expected = converted if converted else []
|
||||||
|
assert typ.to_py(typ.from_str(typ.to_str(converted))) == expected
|
||||||
|
|
||||||
|
@hypothesis.given(val=strategies.lists(strategies.just('foo')))
|
||||||
|
def test_hypothesis_text(self, strtype, klass, val):
|
||||||
|
typ = klass(strtype)
|
||||||
|
text = json.dumps(val)
|
||||||
|
try:
|
||||||
|
typ.to_str(typ.from_str(text))
|
||||||
|
except configexc.ValidationError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('val, expected', [
|
||||||
|
# simple list
|
||||||
|
(['foo', 'bar'], '\n\n- +pass:[foo]+\n- +pass:[bar]+'),
|
||||||
|
# only one value
|
||||||
|
(['foo'], '+pass:[foo]+'),
|
||||||
|
# value without list
|
||||||
|
('foo', '+pass:[foo]+'),
|
||||||
|
# empty
|
||||||
|
([], 'empty'),
|
||||||
|
(None, 'empty'),
|
||||||
|
])
|
||||||
|
def test_to_doc(self, klass, strtype, val, expected):
|
||||||
|
doc = klass(strtype).to_doc(val)
|
||||||
|
print(doc)
|
||||||
|
assert doc == expected
|
||||||
|
|
||||||
|
|
||||||
class TestBool:
|
class TestBool:
|
||||||
|
|
||||||
TESTS = {
|
TESTS = {
|
||||||
|
Loading…
Reference in New Issue
Block a user