Allow fallback=False with config.get/get_obj

This commit is contained in:
Florian Bruhin 2018-09-28 13:33:42 +02:00
parent 5527d27ba7
commit f780974d07
4 changed files with 114 additions and 34 deletions

View File

@ -312,10 +312,14 @@ class Config(QObject):
name, deleted=deleted, renamed=renamed)
raise exception from None
def get(self, name, url=None):
"""Get the given setting converted for Python code."""
def get(self, name, url=None, *, fallback=True):
"""Get the given setting converted for Python code.
Args:
fallback: Use the global value if there's no URL-specific one.
"""
opt = self.get_opt(name)
obj = self.get_obj(name, url=url)
obj = self.get_obj(name, url=url, fallback=fallback)
return opt.typ.to_py(obj)
def _maybe_copy(self, value):
@ -329,14 +333,14 @@ class Config(QObject):
assert value.__hash__ is not None, value
return value
def get_obj(self, name, *, url=None):
def get_obj(self, name, *, url=None, fallback=True):
"""Get the given setting as object (for YAML/config.py).
Note that the returned values are not watched for mutation.
If a URL is given, return the value which should be used for that URL.
"""
self.get_opt(name) # To make sure it exists
value = self._values[name].get_for_url(url)
value = self._values[name].get_for_url(url, fallback=fallback)
return self._maybe_copy(value)
def get_obj_for_pattern(self, name, *, pattern):

View File

@ -60,7 +60,7 @@ from PyQt5.QtGui import QColor, QFont
from PyQt5.QtWidgets import QTabWidget, QTabBar
from qutebrowser.commands import cmdutils
from qutebrowser.config import configexc
from qutebrowser.config import configexc, configutils
from qutebrowser.utils import standarddir, utils, qtutils, urlutils, urlmatch
from qutebrowser.keyinput import keyutils
@ -149,6 +149,9 @@ class BaseType:
value: The value to check.
pytype: A Python type to check the value against.
"""
if value is configutils.UNSET:
return
if (value is None or (pytype == list and value == []) or
(pytype == dict and value == {})):
if not self.none_ok:
@ -309,7 +312,9 @@ class MappingType(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
self._validate_valid_values(value.lower())
return self.MAPPING[value.lower()]
@ -367,7 +372,9 @@ class String(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
self._validate_encoding(value)
@ -399,7 +406,9 @@ class UniqueCharString(String):
def to_py(self, value):
value = super().to_py(value)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
# Check for duplicate values
@ -455,7 +464,9 @@ class List(BaseType):
def to_py(self, value):
self._basic_py_validation(value, list)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return []
for val in value:
@ -534,6 +545,9 @@ class ListOrValue(BaseType):
return value
def to_py(self, value):
if value is configutils.UNSET:
return value
try:
return [self.valtype.to_py(value)]
except configexc.ValidationError:
@ -577,7 +591,8 @@ class FlagList(List):
def to_py(self, value):
vals = super().to_py(value)
self._check_duplicates(vals)
if vals is not configutils.UNSET:
self._check_duplicates(vals)
return vals
def complete(self):
@ -764,7 +779,9 @@ class Perc(_Numeric):
def to_py(self, value):
self._basic_py_validation(value, (float, int, str))
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
if isinstance(value, str):
@ -907,7 +924,9 @@ class QtColor(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
color = QColor(value)
@ -936,7 +955,9 @@ class QssColor(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
functions = ['rgb', 'rgba', 'hsv', 'hsva', 'qlineargradient',
@ -981,7 +1002,9 @@ class Font(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
if not self.font_regex.fullmatch(value): # pragma: no cover
@ -1000,7 +1023,9 @@ class FontFamily(Font):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
match = self.font_regex.fullmatch(value)
@ -1024,7 +1049,9 @@ class QtFont(Font):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
style_map = {
@ -1136,7 +1163,9 @@ class Regex(BaseType):
def to_py(self, value):
"""Get a compiled regex from either a string or a regex object."""
self._basic_py_validation(value, (str, self._regex_type))
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
elif isinstance(value, str):
return self._compile_regex(value)
@ -1214,7 +1243,9 @@ class Dict(BaseType):
def to_py(self, value):
self._basic_py_validation(value, dict)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return self._fill_fixed_keys({})
self._validate_keys(value)
@ -1256,7 +1287,9 @@ class File(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
value = os.path.expanduser(value)
@ -1282,7 +1315,9 @@ class Directory(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
value = os.path.expandvars(value)
value = os.path.expanduser(value)
@ -1309,7 +1344,9 @@ class FormatString(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
@ -1341,7 +1378,9 @@ class ShellCommand(List):
def to_py(self, value):
value = super().to_py(value)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return value
if (self.placeholder and
@ -1365,7 +1404,9 @@ class Proxy(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
@ -1401,7 +1442,9 @@ class SearchEngineUrl(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
if not ('{}' in value or '{0}' in value):
@ -1429,7 +1472,9 @@ class FuzzyUrl(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
@ -1463,6 +1508,9 @@ class Padding(Dict):
def to_py(self, value):
d = super().to_py(value)
if d is configutils.UNSET:
return d
return PaddingValues(**d)
@ -1472,7 +1520,9 @@ class Encoding(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
codecs.lookup(value)
@ -1529,7 +1579,9 @@ class Url(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
qurl = QUrl.fromUserInput(value)
@ -1545,7 +1597,9 @@ class SessionName(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
if value.startswith('_'):
raise configexc.ValidationError(value, "may not start with '_'!")
@ -1593,7 +1647,7 @@ class ConfirmQuit(FlagList):
def to_py(self, value):
values = super().to_py(value)
if not values:
if not values or values is configutils.UNSET:
return values
# Never can't be set with other options
@ -1630,7 +1684,9 @@ class TimestampTemplate(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
@ -1654,7 +1710,9 @@ class Key(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:
@ -1673,7 +1731,9 @@ class UrlPattern(BaseType):
def to_py(self, value):
self._basic_py_validation(value, str)
if not value:
if value is configutils.UNSET:
return value
elif not value:
return None
try:

View File

@ -480,6 +480,17 @@ class TestConfig:
conf.set_obj(name, False, pattern=pattern)
assert conf.get(name, url=QUrl('https://example.com/')) is False
@pytest.mark.parametrize('fallback, expected', [
(True, True),
(False, configutils.UNSET)
])
def test_get_for_url_fallback(self, conf, fallback, expected):
"""Test conf.get() with an URL and fallback."""
value = conf.get('content.javascript.enabled',
url=QUrl('https://example.com/'),
fallback=fallback)
assert value is expected
@pytest.mark.parametrize('value', [{}, {'normal': {'a': 'nop'}}])
def test_get_bindings(self, config_stub, conf, value):
"""Test conf.get() with bindings which have missing keys."""

View File

@ -34,7 +34,7 @@ from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtNetwork import QNetworkProxy
from qutebrowser.config import configtypes, configexc
from qutebrowser.config import configtypes, configexc, configutils
from qutebrowser.utils import debug, utils, qtutils, urlmatch
from qutebrowser.browser.network import pac
from qutebrowser.keyinput import keyutils
@ -274,6 +274,11 @@ class TestAll:
with pytest.raises(configexc.ValidationError):
meth(value)
@pytest.mark.parametrize('none_ok', [True, False])
def test_unset(self, klass, none_ok):
typ = klass(none_ok=none_ok)
assert typ.to_py(configutils.UNSET) is configutils.UNSET
def test_to_str_none(self, klass):
assert klass().to_str(None) == ''