Add config.pattern()
This commit is contained in:
parent
de38566c11
commit
439d51875f
@ -185,6 +185,15 @@ https://developer.chrome.com/apps/match_patterns[URL pattern]:
|
|||||||
config.set('content.images', False, '*://example.com/')
|
config.set('content.images', False, '*://example.com/')
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Alternatively, you can use `with config.pattern(...) as p:` to get a shortcut
|
||||||
|
similar to `c.` which is scoped to the given domain:
|
||||||
|
|
||||||
|
[source,python]
|
||||||
|
----
|
||||||
|
with config.pattern('*://example.com/') as p:
|
||||||
|
p.content.images = False
|
||||||
|
----
|
||||||
|
|
||||||
Binding keys
|
Binding keys
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -466,16 +466,21 @@ class ConfigContainer:
|
|||||||
_prefix: The __getattr__ chain leading up to this object.
|
_prefix: The __getattr__ chain leading up to this object.
|
||||||
_configapi: If given, get values suitable for config.py and
|
_configapi: If given, get values suitable for config.py and
|
||||||
add errors to the given ConfigAPI object.
|
add errors to the given ConfigAPI object.
|
||||||
|
_pattern: The URL pattern to be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, config, configapi=None, prefix=''):
|
def __init__(self, config, configapi=None, prefix='', pattern=None):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._prefix = prefix
|
self._prefix = prefix
|
||||||
self._configapi = configapi
|
self._configapi = configapi
|
||||||
|
self._pattern = pattern
|
||||||
|
if configapi is None and pattern is not None:
|
||||||
|
raise TypeError("Can't use pattern without configapi!")
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return utils.get_repr(self, constructor=True, config=self._config,
|
return utils.get_repr(self, constructor=True, config=self._config,
|
||||||
configapi=self._configapi, prefix=self._prefix)
|
configapi=self._configapi, prefix=self._prefix,
|
||||||
|
pattern=self._pattern)
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _handle_error(self, action, name):
|
def _handle_error(self, action, name):
|
||||||
@ -503,7 +508,7 @@ class ConfigContainer:
|
|||||||
if configdata.is_valid_prefix(name):
|
if configdata.is_valid_prefix(name):
|
||||||
return ConfigContainer(config=self._config,
|
return ConfigContainer(config=self._config,
|
||||||
configapi=self._configapi,
|
configapi=self._configapi,
|
||||||
prefix=name)
|
prefix=name, pattern=self._pattern)
|
||||||
|
|
||||||
with self._handle_error('getting', name):
|
with self._handle_error('getting', name):
|
||||||
if self._configapi is None:
|
if self._configapi is None:
|
||||||
@ -511,7 +516,8 @@ class ConfigContainer:
|
|||||||
return self._config.get(name)
|
return self._config.get(name)
|
||||||
else:
|
else:
|
||||||
# access from config.py
|
# access from config.py
|
||||||
return self._config.get_mutable_obj(name)
|
return self._config.get_mutable_obj(
|
||||||
|
name, pattern=self._pattern)
|
||||||
|
|
||||||
def __setattr__(self, attr, value):
|
def __setattr__(self, attr, value):
|
||||||
"""Set the given option in the config."""
|
"""Set the given option in the config."""
|
||||||
@ -521,7 +527,7 @@ class ConfigContainer:
|
|||||||
|
|
||||||
name = self._join(attr)
|
name = self._join(attr)
|
||||||
with self._handle_error('setting', name):
|
with self._handle_error('setting', name):
|
||||||
self._config.set_obj(name, value)
|
self._config.set_obj(name, value, pattern=self._pattern)
|
||||||
|
|
||||||
def _join(self, attr):
|
def _join(self, attr):
|
||||||
"""Get the prefix joined with the given attribute."""
|
"""Get the prefix joined with the given attribute."""
|
||||||
|
@ -348,6 +348,16 @@ class ConfigAPI:
|
|||||||
except configexc.ConfigFileErrors as e:
|
except configexc.ConfigFileErrors as e:
|
||||||
self.errors += e.errors
|
self.errors += e.errors
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def pattern(self, pattern):
|
||||||
|
"""Get a ConfigContainer for the given pattern."""
|
||||||
|
# We need to propagate the exception so we don't need to return
|
||||||
|
# something.
|
||||||
|
urlpattern = urlmatch.UrlPattern(pattern)
|
||||||
|
container = config.ConfigContainer(config=self._config, configapi=self,
|
||||||
|
pattern=urlpattern)
|
||||||
|
yield container
|
||||||
|
|
||||||
|
|
||||||
class ConfigPyWriter:
|
class ConfigPyWriter:
|
||||||
|
|
||||||
|
@ -637,6 +637,12 @@ class TestContainer:
|
|||||||
assert error.text == "While getting 'tabs.foobar'"
|
assert error.text == "While getting 'tabs.foobar'"
|
||||||
assert str(error.exception) == "No option 'tabs.foobar'"
|
assert str(error.exception) == "No option 'tabs.foobar'"
|
||||||
|
|
||||||
|
def test_pattern_no_configapi(self, config_stub):
|
||||||
|
pattern = urlmatch.UrlPattern('https://example.com/')
|
||||||
|
with pytest.raises(TypeError,
|
||||||
|
match="Can't use pattern without configapi!"):
|
||||||
|
config.ConfigContainer(config_stub, pattern=pattern)
|
||||||
|
|
||||||
|
|
||||||
class StyleObj(QObject):
|
class StyleObj(QObject):
|
||||||
|
|
||||||
|
@ -507,17 +507,29 @@ class TestConfigPy:
|
|||||||
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):
|
@pytest.mark.parametrize('template', [
|
||||||
|
"config.set({opt!r}, False, {pattern!r})",
|
||||||
|
"with config.pattern({pattern!r}) as p: p.{opt} = False",
|
||||||
|
])
|
||||||
|
def test_set_with_pattern(self, confpy, template):
|
||||||
option = 'content.javascript.enabled'
|
option = 'content.javascript.enabled'
|
||||||
pattern = 'https://www.example.com/'
|
pattern = 'https://www.example.com/'
|
||||||
|
|
||||||
confpy.write('config.set({!r}, False, {!r})'.format(option, pattern))
|
confpy.write(template.format(opt=option, pattern=pattern))
|
||||||
confpy.read()
|
confpy.read()
|
||||||
|
|
||||||
assert config.instance.get_obj(option)
|
assert config.instance.get_obj(option)
|
||||||
assert not config.instance.get_obj_for_pattern(
|
assert not config.instance.get_obj_for_pattern(
|
||||||
option, pattern=urlmatch.UrlPattern(pattern))
|
option, pattern=urlmatch.UrlPattern(pattern))
|
||||||
|
|
||||||
|
def test_set_context_manager_global(self, confpy):
|
||||||
|
"""When "with config.pattern" is used, "c." should still be global."""
|
||||||
|
option = 'content.javascript.enabled'
|
||||||
|
confpy.write('with config.pattern("https://www.example.com/") as p:'
|
||||||
|
' c.{} = False'.format(option))
|
||||||
|
confpy.read()
|
||||||
|
assert not config.instance.get_obj(option)
|
||||||
|
|
||||||
@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',
|
||||||
@ -703,20 +715,21 @@ class TestConfigPy:
|
|||||||
"'qt.args')")
|
"'qt.args')")
|
||||||
assert str(error.exception) == expected
|
assert str(error.exception) == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('line, action', [
|
@pytest.mark.parametrize('line, text', [
|
||||||
('config.get("content.images", "://")', 'getting'),
|
('config.get("content.images", "://")',
|
||||||
('config.set("content.images", False, "://")', 'setting'),
|
"While getting 'content.images' and parsing pattern"),
|
||||||
|
('config.set("content.images", False, "://")',
|
||||||
|
"While setting 'content.images' and parsing pattern"),
|
||||||
|
('with config.pattern("://"): pass',
|
||||||
|
"Unhandled exception"),
|
||||||
])
|
])
|
||||||
def test_invalid_pattern(self, confpy, line, action):
|
def test_invalid_pattern(self, confpy, line, text):
|
||||||
confpy.write(line)
|
confpy.write(line)
|
||||||
|
|
||||||
error = confpy.read(error=True)
|
error = confpy.read(error=True)
|
||||||
|
|
||||||
assert error.text == ("While {} 'content.images' and parsing pattern"
|
assert error.text == text
|
||||||
.format(action))
|
|
||||||
assert isinstance(error.exception, urlmatch.ParseError)
|
assert isinstance(error.exception, urlmatch.ParseError)
|
||||||
assert str(error.exception) == "No scheme given"
|
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")
|
||||||
|
Loading…
Reference in New Issue
Block a user