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/')
|
||||
----
|
||||
|
||||
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
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
@ -466,16 +466,21 @@ class ConfigContainer:
|
||||
_prefix: The __getattr__ chain leading up to this object.
|
||||
_configapi: If given, get values suitable for config.py and
|
||||
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._prefix = prefix
|
||||
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):
|
||||
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
|
||||
def _handle_error(self, action, name):
|
||||
@ -503,7 +508,7 @@ class ConfigContainer:
|
||||
if configdata.is_valid_prefix(name):
|
||||
return ConfigContainer(config=self._config,
|
||||
configapi=self._configapi,
|
||||
prefix=name)
|
||||
prefix=name, pattern=self._pattern)
|
||||
|
||||
with self._handle_error('getting', name):
|
||||
if self._configapi is None:
|
||||
@ -511,7 +516,8 @@ class ConfigContainer:
|
||||
return self._config.get(name)
|
||||
else:
|
||||
# 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):
|
||||
"""Set the given option in the config."""
|
||||
@ -521,7 +527,7 @@ class ConfigContainer:
|
||||
|
||||
name = self._join(attr)
|
||||
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):
|
||||
"""Get the prefix joined with the given attribute."""
|
||||
|
@ -348,6 +348,16 @@ class ConfigAPI:
|
||||
except configexc.ConfigFileErrors as e:
|
||||
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:
|
||||
|
||||
|
@ -637,6 +637,12 @@ class TestContainer:
|
||||
assert error.text == "While getting '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):
|
||||
|
||||
|
@ -507,17 +507,29 @@ class TestConfigPy:
|
||||
confpy.read()
|
||||
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'
|
||||
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()
|
||||
|
||||
assert config.instance.get_obj(option)
|
||||
assert not config.instance.get_obj_for_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('get_line', [
|
||||
'c.colors.hints.fg',
|
||||
@ -703,20 +715,21 @@ class TestConfigPy:
|
||||
"'qt.args')")
|
||||
assert str(error.exception) == expected
|
||||
|
||||
@pytest.mark.parametrize('line, action', [
|
||||
('config.get("content.images", "://")', 'getting'),
|
||||
('config.set("content.images", False, "://")', 'setting'),
|
||||
@pytest.mark.parametrize('line, text', [
|
||||
('config.get("content.images", "://")',
|
||||
"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)
|
||||
|
||||
error = confpy.read(error=True)
|
||||
|
||||
assert error.text == ("While {} 'content.images' and parsing pattern"
|
||||
.format(action))
|
||||
assert error.text == text
|
||||
assert isinstance(error.exception, urlmatch.ParseError)
|
||||
assert str(error.exception) == "No scheme given"
|
||||
assert error.traceback is None
|
||||
|
||||
def test_multiple_errors(self, confpy):
|
||||
confpy.write("c.foo = 42", "config.set('foo', 42)", "1/0")
|
||||
|
Loading…
Reference in New Issue
Block a user