Allow fallback=False with config.get/get_obj
This commit is contained in:
parent
5527d27ba7
commit
f780974d07
@ -312,10 +312,14 @@ class Config(QObject):
|
|||||||
name, deleted=deleted, renamed=renamed)
|
name, deleted=deleted, renamed=renamed)
|
||||||
raise exception from None
|
raise exception from None
|
||||||
|
|
||||||
def get(self, name, url=None):
|
def get(self, name, url=None, *, fallback=True):
|
||||||
"""Get the given setting converted for Python code."""
|
"""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)
|
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)
|
return opt.typ.to_py(obj)
|
||||||
|
|
||||||
def _maybe_copy(self, value):
|
def _maybe_copy(self, value):
|
||||||
@ -329,14 +333,14 @@ class Config(QObject):
|
|||||||
assert value.__hash__ is not None, value
|
assert value.__hash__ is not None, value
|
||||||
return 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).
|
"""Get the given setting as object (for YAML/config.py).
|
||||||
|
|
||||||
Note that the returned values are not watched for mutation.
|
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.
|
If a URL is given, return the value which should be used for that URL.
|
||||||
"""
|
"""
|
||||||
self.get_opt(name) # To make sure it exists
|
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)
|
return self._maybe_copy(value)
|
||||||
|
|
||||||
def get_obj_for_pattern(self, name, *, pattern):
|
def get_obj_for_pattern(self, name, *, pattern):
|
||||||
|
@ -60,7 +60,7 @@ from PyQt5.QtGui import QColor, QFont
|
|||||||
from PyQt5.QtWidgets import QTabWidget, QTabBar
|
from PyQt5.QtWidgets import QTabWidget, QTabBar
|
||||||
|
|
||||||
from qutebrowser.commands import cmdutils
|
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.utils import standarddir, utils, qtutils, urlutils, urlmatch
|
||||||
from qutebrowser.keyinput import keyutils
|
from qutebrowser.keyinput import keyutils
|
||||||
|
|
||||||
@ -149,6 +149,9 @@ class BaseType:
|
|||||||
value: The value to check.
|
value: The value to check.
|
||||||
pytype: A Python type to check the value against.
|
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
|
if (value is None or (pytype == list and value == []) or
|
||||||
(pytype == dict and value == {})):
|
(pytype == dict and value == {})):
|
||||||
if not self.none_ok:
|
if not self.none_ok:
|
||||||
@ -309,7 +312,9 @@ class MappingType(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
self._validate_valid_values(value.lower())
|
self._validate_valid_values(value.lower())
|
||||||
return self.MAPPING[value.lower()]
|
return self.MAPPING[value.lower()]
|
||||||
@ -367,7 +372,9 @@ class String(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self._validate_encoding(value)
|
self._validate_encoding(value)
|
||||||
@ -399,7 +406,9 @@ class UniqueCharString(String):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
value = super().to_py(value)
|
value = super().to_py(value)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Check for duplicate values
|
# Check for duplicate values
|
||||||
@ -455,7 +464,9 @@ class List(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, list)
|
self._basic_py_validation(value, list)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for val in value:
|
for val in value:
|
||||||
@ -534,6 +545,9 @@ class ListOrValue(BaseType):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return [self.valtype.to_py(value)]
|
return [self.valtype.to_py(value)]
|
||||||
except configexc.ValidationError:
|
except configexc.ValidationError:
|
||||||
@ -577,7 +591,8 @@ class FlagList(List):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
vals = super().to_py(value)
|
vals = super().to_py(value)
|
||||||
self._check_duplicates(vals)
|
if vals is not configutils.UNSET:
|
||||||
|
self._check_duplicates(vals)
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
def complete(self):
|
def complete(self):
|
||||||
@ -764,7 +779,9 @@ class Perc(_Numeric):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, (float, int, str))
|
self._basic_py_validation(value, (float, int, str))
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
@ -907,7 +924,9 @@ class QtColor(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
color = QColor(value)
|
color = QColor(value)
|
||||||
@ -936,7 +955,9 @@ class QssColor(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
functions = ['rgb', 'rgba', 'hsv', 'hsva', 'qlineargradient',
|
functions = ['rgb', 'rgba', 'hsv', 'hsva', 'qlineargradient',
|
||||||
@ -981,7 +1002,9 @@ class Font(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not self.font_regex.fullmatch(value): # pragma: no cover
|
if not self.font_regex.fullmatch(value): # pragma: no cover
|
||||||
@ -1000,7 +1023,9 @@ class FontFamily(Font):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
match = self.font_regex.fullmatch(value)
|
match = self.font_regex.fullmatch(value)
|
||||||
@ -1024,7 +1049,9 @@ class QtFont(Font):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
style_map = {
|
style_map = {
|
||||||
@ -1136,7 +1163,9 @@ class Regex(BaseType):
|
|||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
"""Get a compiled regex from either a string or a regex object."""
|
"""Get a compiled regex from either a string or a regex object."""
|
||||||
self._basic_py_validation(value, (str, self._regex_type))
|
self._basic_py_validation(value, (str, self._regex_type))
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
return self._compile_regex(value)
|
return self._compile_regex(value)
|
||||||
@ -1214,7 +1243,9 @@ class Dict(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, dict)
|
self._basic_py_validation(value, dict)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return self._fill_fixed_keys({})
|
return self._fill_fixed_keys({})
|
||||||
|
|
||||||
self._validate_keys(value)
|
self._validate_keys(value)
|
||||||
@ -1256,7 +1287,9 @@ class File(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
value = os.path.expanduser(value)
|
value = os.path.expanduser(value)
|
||||||
@ -1282,7 +1315,9 @@ class Directory(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
value = os.path.expandvars(value)
|
value = os.path.expandvars(value)
|
||||||
value = os.path.expanduser(value)
|
value = os.path.expanduser(value)
|
||||||
@ -1309,7 +1344,9 @@ class FormatString(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1341,7 +1378,9 @@ class ShellCommand(List):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
value = super().to_py(value)
|
value = super().to_py(value)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
if (self.placeholder and
|
if (self.placeholder and
|
||||||
@ -1365,7 +1404,9 @@ class Proxy(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1401,7 +1442,9 @@ class SearchEngineUrl(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not ('{}' in value or '{0}' in value):
|
if not ('{}' in value or '{0}' in value):
|
||||||
@ -1429,7 +1472,9 @@ class FuzzyUrl(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1463,6 +1508,9 @@ class Padding(Dict):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
d = super().to_py(value)
|
d = super().to_py(value)
|
||||||
|
if d is configutils.UNSET:
|
||||||
|
return d
|
||||||
|
|
||||||
return PaddingValues(**d)
|
return PaddingValues(**d)
|
||||||
|
|
||||||
|
|
||||||
@ -1472,7 +1520,9 @@ class Encoding(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
codecs.lookup(value)
|
codecs.lookup(value)
|
||||||
@ -1529,7 +1579,9 @@ class Url(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
qurl = QUrl.fromUserInput(value)
|
qurl = QUrl.fromUserInput(value)
|
||||||
@ -1545,7 +1597,9 @@ class SessionName(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
if value.startswith('_'):
|
if value.startswith('_'):
|
||||||
raise configexc.ValidationError(value, "may not start with '_'!")
|
raise configexc.ValidationError(value, "may not start with '_'!")
|
||||||
@ -1593,7 +1647,7 @@ class ConfirmQuit(FlagList):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
values = super().to_py(value)
|
values = super().to_py(value)
|
||||||
if not values:
|
if not values or values is configutils.UNSET:
|
||||||
return values
|
return values
|
||||||
|
|
||||||
# Never can't be set with other options
|
# Never can't be set with other options
|
||||||
@ -1630,7 +1684,9 @@ class TimestampTemplate(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1654,7 +1710,9 @@ class Key(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1673,7 +1731,9 @@ class UrlPattern(BaseType):
|
|||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, str)
|
self._basic_py_validation(value, str)
|
||||||
if not value:
|
if value is configutils.UNSET:
|
||||||
|
return value
|
||||||
|
elif not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -480,6 +480,17 @@ class TestConfig:
|
|||||||
conf.set_obj(name, False, pattern=pattern)
|
conf.set_obj(name, False, pattern=pattern)
|
||||||
assert conf.get(name, url=QUrl('https://example.com/')) is False
|
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'}}])
|
@pytest.mark.parametrize('value', [{}, {'normal': {'a': 'nop'}}])
|
||||||
def test_get_bindings(self, config_stub, conf, value):
|
def test_get_bindings(self, config_stub, conf, value):
|
||||||
"""Test conf.get() with bindings which have missing keys."""
|
"""Test conf.get() with bindings which have missing keys."""
|
||||||
|
@ -34,7 +34,7 @@ from PyQt5.QtCore import QUrl
|
|||||||
from PyQt5.QtGui import QColor, QFont
|
from PyQt5.QtGui import QColor, QFont
|
||||||
from PyQt5.QtNetwork import QNetworkProxy
|
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.utils import debug, utils, qtutils, urlmatch
|
||||||
from qutebrowser.browser.network import pac
|
from qutebrowser.browser.network import pac
|
||||||
from qutebrowser.keyinput import keyutils
|
from qutebrowser.keyinput import keyutils
|
||||||
@ -274,6 +274,11 @@ class TestAll:
|
|||||||
with pytest.raises(configexc.ValidationError):
|
with pytest.raises(configexc.ValidationError):
|
||||||
meth(value)
|
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):
|
def test_to_str_none(self, klass):
|
||||||
assert klass().to_str(None) == ''
|
assert klass().to_str(None) == ''
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user