Add basic pattern support for config.py

This commit is contained in:
Florian Bruhin 2018-02-20 18:43:42 +01:00
parent a3dfec20c1
commit 3ade923edb
2 changed files with 77 additions and 9 deletions

View File

@ -33,7 +33,7 @@ from PyQt5.QtCore import pyqtSignal, QObject, QSettings
import qutebrowser import qutebrowser
from qutebrowser.config import configexc, config, configdata, configutils from qutebrowser.config import configexc, config, configdata, configutils
from qutebrowser.utils import standarddir, utils, qtutils, log from qutebrowser.utils import standarddir, utils, qtutils, log, urlmatch
# The StateConfig instance # The StateConfig instance
@ -308,6 +308,9 @@ class ConfigAPI:
except configexc.Error as e: except configexc.Error as e:
text = "While {} '{}'".format(action, name) text = "While {} '{}'".format(action, name)
self.errors.append(configexc.ConfigErrorDesc(text, e)) self.errors.append(configexc.ConfigErrorDesc(text, e))
except urlmatch.ParseError as e:
text = "While {} '{}' and parsing pattern".format(action, name)
self.errors.append(configexc.ConfigErrorDesc(text, e))
def finalize(self): def finalize(self):
"""Do work which needs to be done after reading config.py.""" """Do work which needs to be done after reading config.py."""
@ -317,13 +320,15 @@ class ConfigAPI:
with self._handle_error('reading', 'autoconfig.yml'): with self._handle_error('reading', 'autoconfig.yml'):
read_autoconfig() read_autoconfig()
def get(self, name): def get(self, name, pattern=None):
with self._handle_error('getting', name): with self._handle_error('getting', name):
return self._config.get_mutable_obj(name) urlpattern = urlmatch.UrlPattern(pattern) if pattern else None
return self._config.get_mutable_obj(name, pattern=urlpattern)
def set(self, name, value): def set(self, name, value, pattern=None):
with self._handle_error('setting', name): with self._handle_error('setting', name):
self._config.set_obj(name, value) urlpattern = urlmatch.UrlPattern(pattern) if pattern else None
self._config.set_obj(name, value, pattern=urlpattern)
def bind(self, key, command, mode='normal'): def bind(self, key, command, mode='normal'):
with self._handle_error('binding', key): with self._handle_error('binding', key):
@ -401,8 +406,7 @@ class ConfigPyWriter:
def _gen_options(self): def _gen_options(self):
"""Generate the options part of the config.""" """Generate the options part of the config."""
# FIXME:conf handle _pattern for pattern, opt, value in self._options:
for _pattern, opt, value in self._options:
if opt.name in ['bindings.commands', 'bindings.default']: if opt.name in ['bindings.commands', 'bindings.default']:
continue continue
@ -421,7 +425,11 @@ class ConfigPyWriter:
except KeyError: except KeyError:
yield self._line("# - {}".format(val)) yield self._line("# - {}".format(val))
yield self._line('c.{} = {!r}'.format(opt.name, value)) if pattern is None:
yield self._line('c.{} = {!r}'.format(opt.name, value))
else:
yield self._line('config.set({!r}, {!r}, {!r})'.format(
opt.name, value, str(pattern)))
yield '' yield ''
def _gen_bindings(self): def _gen_bindings(self):

View File

@ -28,7 +28,7 @@ from PyQt5.QtCore import QSettings
from qutebrowser.config import (config, configfiles, configexc, configdata, from qutebrowser.config import (config, configfiles, configexc, configdata,
configtypes) configtypes)
from qutebrowser.utils import utils, usertypes from qutebrowser.utils import utils, usertypes, urlmatch
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -500,16 +500,29 @@ class TestConfigPy:
@pytest.mark.parametrize('line', [ @pytest.mark.parametrize('line', [
'c.colors.hints.bg = "red"', 'c.colors.hints.bg = "red"',
'config.set("colors.hints.bg", "red")', 'config.set("colors.hints.bg", "red")',
'config.set("colors.hints.bg", "red", pattern=None)',
]) ])
def test_set(self, confpy, line): def test_set(self, confpy, line):
confpy.write(line) confpy.write(line)
confpy.read() confpy.read()
assert config.instance.get_obj('colors.hints.bg') == 'red' assert config.instance.get_obj('colors.hints.bg') == 'red'
def test_set_with_pattern(self, confpy):
option = 'content.javascript.enabled'
pattern = 'https://www.example.com/'
confpy.write('config.set({!r}, False, {!r})'.format(option, pattern))
confpy.read()
assert config.instance.get_obj(option)
assert not config.instance.get_obj_for_pattern(
option, pattern=urlmatch.UrlPattern(pattern))
@pytest.mark.parametrize('set_first', [True, False]) @pytest.mark.parametrize('set_first', [True, False])
@pytest.mark.parametrize('get_line', [ @pytest.mark.parametrize('get_line', [
'c.colors.hints.fg', 'c.colors.hints.fg',
'config.get("colors.hints.fg")', 'config.get("colors.hints.fg")',
'config.get("colors.hints.fg", pattern=None)',
]) ])
def test_get(self, confpy, set_first, get_line): def test_get(self, confpy, set_first, get_line):
"""Test whether getting options works correctly.""" """Test whether getting options works correctly."""
@ -523,6 +536,24 @@ class TestConfigPy:
confpy.write('assert {} == "green"'.format(get_line)) confpy.write('assert {} == "green"'.format(get_line))
confpy.read() confpy.read()
def test_get_with_pattern(self, confpy):
"""Test whether we get a matching value with a pattern."""
option = 'content.javascript.enabled'
pattern = 'https://www.example.com/'
config.instance.set_obj(option, False,
pattern=urlmatch.UrlPattern(pattern))
confpy.write('assert config.get({!r})'.format(option),
'assert not config.get({!r}, pattern={!r})'
.format(option, pattern))
confpy.read()
def test_get_with_pattern_no_match(self, confpy):
confpy.write(
'val = config.get("content.images", "https://www.example.com")',
'assert val is True',
)
confpy.read()
@pytest.mark.parametrize('line, mode', [ @pytest.mark.parametrize('line, mode', [
('config.bind(",a", "message-info foo")', 'normal'), ('config.bind(",a", "message-info foo")', 'normal'),
('config.bind(",a", "message-info foo", "prompt")', 'prompt'), ('config.bind(",a", "message-info foo", "prompt")', 'prompt'),
@ -672,6 +703,21 @@ class TestConfigPy:
"'qt.args')") "'qt.args')")
assert str(error.exception) == expected assert str(error.exception) == expected
@pytest.mark.parametrize('line, action', [
('config.get("content.images", "://")', 'getting'),
('config.set("content.images", False, "://")', 'setting'),
])
def test_invalid_pattern(self, confpy, line, action):
confpy.write(line)
error = confpy.read(error=True)
assert error.text == ("While {} 'content.images' and parsing pattern"
.format(action))
assert isinstance(error.exception, urlmatch.ParseError)
assert str(error.exception) == "No scheme given"
assert error.traceback is None
def test_multiple_errors(self, confpy): def test_multiple_errors(self, confpy):
confpy.write("c.foo = 42", "config.set('foo', 42)", "1/0") confpy.write("c.foo = 42", "config.set('foo', 42)", "1/0")
@ -862,6 +908,20 @@ class TestConfigPyWriter:
""").lstrip() """).lstrip()
assert text == expected assert text == expected
def test_pattern(self):
opt = configdata.Option(
name='opt', typ=configtypes.BoolAsk(), default='ask',
backends=[usertypes.Backend.QtWebEngine], raw_backends=None,
description='Hello World')
options = [
(urlmatch.UrlPattern('https://www.example.com/'), opt, 'ask'),
]
writer = configfiles.ConfigPyWriter(options=options, bindings={},
commented=False)
text = '\n'.join(writer._gen_lines())
expected = "config.set('opt', 'ask', 'https://www.example.com/')"
assert expected in text
def test_write(self, tmpdir): def test_write(self, tmpdir):
pyfile = tmpdir / 'config.py' pyfile = tmpdir / 'config.py'
writer = configfiles.ConfigPyWriter(options=[], bindings={}, writer = configfiles.ConfigPyWriter(options=[], bindings={},