Initial configexc refactoring
This commit is contained in:
parent
5ab2c89a37
commit
3e3685b68b
@ -1541,6 +1541,7 @@ class CommandDispatcher:
|
||||
command))
|
||||
path = 'commands.html#{}'.format(command)
|
||||
elif '->' in topic:
|
||||
# FIXME:conf refactor
|
||||
parts = topic.split('->')
|
||||
if len(parts) != 2:
|
||||
raise cmdexc.CommandError("Invalid help topic {}!".format(
|
||||
|
@ -110,8 +110,8 @@ class CommandRunner(QObject):
|
||||
return default
|
||||
parts = text.strip().split(maxsplit=1)
|
||||
try:
|
||||
alias = config.get('aliases', parts[0])
|
||||
except (configexc.NoOptionError, configexc.NoSectionError):
|
||||
alias = config.val.aliases[parts[0]]
|
||||
except KeyError:
|
||||
return default
|
||||
try:
|
||||
new_cmd = '{} {}'.format(alias, parts[1])
|
||||
|
@ -147,16 +147,15 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
||||
# We can't use drawContents because then the color would be ignored.
|
||||
clip = QRectF(0, 0, rect.width(), rect.height())
|
||||
self._painter.save()
|
||||
|
||||
if self._opt.state & QStyle.State_Selected:
|
||||
option = 'completion.item.selected.fg'
|
||||
color = config.val.completion.item.selected.fg
|
||||
elif not self._opt.state & QStyle.State_Enabled:
|
||||
option = 'completion.category.fg'
|
||||
color = config.val.completion.category.fg
|
||||
else:
|
||||
option = 'completion.fg'
|
||||
try:
|
||||
self._painter.setPen(config.get('colors', option))
|
||||
except configexc.NoOptionError:
|
||||
self._painter.setPen(config.val.colors.completion.fg)
|
||||
color = config.val.completion.fg
|
||||
self._painter.setPen(color)
|
||||
|
||||
ctx = QAbstractTextDocumentLayout.PaintContext()
|
||||
ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
|
||||
if clip.isValid():
|
||||
|
@ -46,6 +46,9 @@ from qutebrowser.utils import (message, objreg, utils, standarddir, log,
|
||||
from qutebrowser.misc import objects
|
||||
from qutebrowser.utils.usertypes import Completion
|
||||
|
||||
# FIXME:conf compat
|
||||
from qutebrowser.config.newconfig import change_filter
|
||||
|
||||
|
||||
UNSET = object()
|
||||
|
||||
@ -54,74 +57,6 @@ UNSET = object()
|
||||
val = None
|
||||
|
||||
|
||||
class change_filter: # pylint: disable=invalid-name
|
||||
|
||||
"""Decorator to filter calls based on a config section/option matching.
|
||||
|
||||
This could also be a function, but as a class (with a "wrong" name) it's
|
||||
much cleaner to implement.
|
||||
|
||||
Attributes:
|
||||
_option: An option or prefix to be filtered
|
||||
_function: Whether a function rather than a method is decorated.
|
||||
"""
|
||||
|
||||
def __init__(self, option, function=False):
|
||||
"""Save decorator arguments.
|
||||
|
||||
Gets called on parse-time with the decorator arguments.
|
||||
|
||||
Args:
|
||||
option: The option to be filtered.
|
||||
function: Whether a function rather than a method is decorated.
|
||||
"""
|
||||
if (option not in configdata.DATA and
|
||||
not configdata.is_valid_prefix(option)):
|
||||
raise configexc.NoOptionError(option)
|
||||
self._option = option
|
||||
self._function = function
|
||||
|
||||
def _check_match(self, option):
|
||||
"""Check if the given option matches the filter."""
|
||||
if option is None:
|
||||
# Called directly, not from a config change event.
|
||||
return True
|
||||
elif option == self._option:
|
||||
return True
|
||||
elif option.startswith(self._option + '.'):
|
||||
# prefix match
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __call__(self, func):
|
||||
"""Filter calls to the decorated function.
|
||||
|
||||
Gets called when a function should be decorated.
|
||||
|
||||
Adds a filter which returns if we're not interested in the change-event
|
||||
and calls the wrapped function if we are.
|
||||
|
||||
We assume the function passed doesn't take any parameters.
|
||||
|
||||
Args:
|
||||
func: The function to be decorated.
|
||||
|
||||
Return:
|
||||
The decorated function.
|
||||
"""
|
||||
if self._function:
|
||||
@functools.wraps(func)
|
||||
def wrapper(option=None):
|
||||
if self._check_match(option):
|
||||
return func()
|
||||
else:
|
||||
@functools.wraps(func)
|
||||
def wrapper(wrapper_self, option=None):
|
||||
if self._check_match(option):
|
||||
return func(wrapper_self)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def get(*args, **kwargs):
|
||||
|
@ -52,35 +52,10 @@ class ValidationError(Error):
|
||||
self.option = None
|
||||
|
||||
|
||||
class NoSectionError(Error):
|
||||
|
||||
"""Raised when no section matches a requested option."""
|
||||
|
||||
def __init__(self, section):
|
||||
super().__init__("Section {!r} does not exist!".format(section))
|
||||
self.section = section
|
||||
|
||||
|
||||
class NoOptionError(Error):
|
||||
|
||||
"""Raised when an option was not found."""
|
||||
|
||||
def __init__(self, option, section):
|
||||
super().__init__("No option {!r} in section {!r}".format(
|
||||
option, section))
|
||||
def __init__(self, option):
|
||||
super().__init__("No option {!r}".format(option))
|
||||
self.option = option
|
||||
self.section = section
|
||||
|
||||
|
||||
class InterpolationSyntaxError(Error):
|
||||
|
||||
"""Raised when the source text contains invalid syntax.
|
||||
|
||||
Current implementation raises this exception when the source text into
|
||||
which substitutions are made does not conform to the required syntax.
|
||||
"""
|
||||
|
||||
def __init__(self, option, section, msg):
|
||||
super().__init__(msg)
|
||||
self.option = option
|
||||
self.section = section
|
||||
|
@ -19,20 +19,17 @@
|
||||
|
||||
"""New qutebrowser configuration code."""
|
||||
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
|
||||
from qutebrowser.config import configdata
|
||||
from qutebrowser.config import configdata, configexc
|
||||
from qutebrowser.utils import utils, objreg
|
||||
|
||||
# An easy way to access the config from other code via config.val.foo
|
||||
val = None
|
||||
|
||||
|
||||
class UnknownOptionError(Exception):
|
||||
|
||||
"""Raised by NewConfigManager when an option is unknown."""
|
||||
_change_filters = []
|
||||
|
||||
|
||||
class SectionStub:
|
||||
@ -47,6 +44,83 @@ class SectionStub:
|
||||
return self._conf.get(self._name, item)
|
||||
|
||||
|
||||
class change_filter: # pylint: disable=invalid-name
|
||||
|
||||
"""Decorator to filter calls based on a config section/option matching.
|
||||
|
||||
This could also be a function, but as a class (with a "wrong" name) it's
|
||||
much cleaner to implement.
|
||||
|
||||
Attributes:
|
||||
_option: An option or prefix to be filtered
|
||||
_function: Whether a function rather than a method is decorated.
|
||||
"""
|
||||
|
||||
def __init__(self, option, function=False):
|
||||
"""Save decorator arguments.
|
||||
|
||||
Gets called on parse-time with the decorator arguments.
|
||||
|
||||
Args:
|
||||
option: The option to be filtered.
|
||||
function: Whether a function rather than a method is decorated.
|
||||
"""
|
||||
self._option = option
|
||||
self._function = function
|
||||
_change_filters.append(self)
|
||||
|
||||
def validate(self):
|
||||
"""Make sure the configured option or prefix exists.
|
||||
|
||||
We can't do this in __init__ as configdata isn't ready yet.
|
||||
"""
|
||||
if (self._option not in configdata.DATA and
|
||||
not configdata.is_valid_prefix(self._option)):
|
||||
raise configexc.NoOptionError(self._option)
|
||||
|
||||
def _check_match(self, option):
|
||||
"""Check if the given option matches the filter."""
|
||||
if option is None:
|
||||
# Called directly, not from a config change event.
|
||||
return True
|
||||
elif option == self._option:
|
||||
return True
|
||||
elif option.startswith(self._option + '.'):
|
||||
# prefix match
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __call__(self, func):
|
||||
"""Filter calls to the decorated function.
|
||||
|
||||
Gets called when a function should be decorated.
|
||||
|
||||
Adds a filter which returns if we're not interested in the change-event
|
||||
and calls the wrapped function if we are.
|
||||
|
||||
We assume the function passed doesn't take any parameters.
|
||||
|
||||
Args:
|
||||
func: The function to be decorated.
|
||||
|
||||
Return:
|
||||
The decorated function.
|
||||
"""
|
||||
if self._function:
|
||||
@functools.wraps(func)
|
||||
def wrapper(option=None):
|
||||
if self._check_match(option):
|
||||
return func()
|
||||
else:
|
||||
@functools.wraps(func)
|
||||
def wrapper(wrapper_self, option=None):
|
||||
if self._check_match(option):
|
||||
return func(wrapper_self)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class NewConfigManager(QObject):
|
||||
|
||||
# FIXME:conf QObject?
|
||||
@ -65,7 +139,7 @@ class NewConfigManager(QObject):
|
||||
try:
|
||||
val = self._values[option]
|
||||
except KeyError as e:
|
||||
raise UnknownOptionError(e)
|
||||
raise configexc.NoOptionError(e)
|
||||
return val.typ.from_py(val.default)
|
||||
|
||||
|
||||
@ -117,5 +191,9 @@ def init(parent):
|
||||
new_config = NewConfigManager(parent)
|
||||
new_config.read_defaults()
|
||||
objreg.register('config', new_config)
|
||||
|
||||
global val
|
||||
val = ConfigContainer(new_config)
|
||||
|
||||
for cf in _change_filters:
|
||||
cf.validate()
|
||||
|
@ -29,7 +29,7 @@ import urllib.parse
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtNetwork import QHostInfo, QHostAddress, QNetworkProxy
|
||||
|
||||
from qutebrowser.config import config, configexc
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import log, qtutils, message, utils
|
||||
from qutebrowser.commands import cmdexc
|
||||
from qutebrowser.browser.network import pac
|
||||
@ -70,8 +70,8 @@ def _parse_search_term(s):
|
||||
if len(split) == 2:
|
||||
engine = split[0]
|
||||
try:
|
||||
config.get('searchengines', engine)
|
||||
except configexc.NoOptionError:
|
||||
config.val.searchengines[engine]
|
||||
except KeyError:
|
||||
engine = None
|
||||
term = s
|
||||
else:
|
||||
|
@ -419,6 +419,8 @@ class ConfigStub(QObject):
|
||||
data: The config data to return.
|
||||
"""
|
||||
|
||||
# FIXME:conf refactor...
|
||||
|
||||
changed = pyqtSignal(str, str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
|
@ -29,24 +29,10 @@ def test_validation_error():
|
||||
assert str(e) == "Invalid value 'val' - msg"
|
||||
|
||||
|
||||
def test_no_section_error():
|
||||
e = configexc.NoSectionError('sect')
|
||||
assert e.section == 'sect'
|
||||
assert str(e) == "Section 'sect' does not exist!"
|
||||
|
||||
|
||||
def test_no_option_error():
|
||||
e = configexc.NoOptionError('opt', 'sect')
|
||||
assert e.section == 'sect'
|
||||
e = configexc.NoOptionError('opt')
|
||||
assert e.option == 'opt'
|
||||
assert str(e) == "No option 'opt' in section 'sect'"
|
||||
|
||||
|
||||
def test_interpolation_syntax_error():
|
||||
e = configexc.InterpolationSyntaxError('opt', 'sect', 'msg')
|
||||
assert e.section == 'sect'
|
||||
assert e.option == 'opt'
|
||||
assert str(e) == 'msg'
|
||||
assert str(e) == "No option 'opt'"
|
||||
|
||||
|
||||
def test_backend_error():
|
||||
|
Loading…
Reference in New Issue
Block a user