summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2021-01-20 13:57:09 +0100
committerFlorian Bruhin <me@the-compiler.org>2021-01-20 14:12:39 +0100
commit2c382a761de5c72071bfc952e11c608016139c1f (patch)
treea346745e4b16f5c8344ea57ef773872dc3fdf4be /tests
parent729e098baeabd301e983b8dd50c00293ba757975 (diff)
downloadqutebrowser-2c382a761de5c72071bfc952e11c608016139c1f.tar.gz
qutebrowser-2c382a761de5c72071bfc952e11c608016139c1f.zip
config: Improve error handling for missing sections
When the user does something like this with the new adblocking config: c.content.host_blocking.lists = ... Then we didn't notify her about the setting being renamed. Instead, she got: While getting 'content.host_blocking': No option 'content.host_blocking' Unhandled exception: 'NoneType' object has no attribute 'lists' Traceback (most recent call last): File ".../qutebrowser/config/configfiles.py", line 805, in read_config_py exec(code, module.__dict__) File "/tmp/config.py", line 1, in <module> c.content.host_blocking.lists = [] AttributeError: 'NoneType' object has no attribute 'lists' This happens because we did something like (simplified): with self._handle_error(...): return self._config.get(...) # End of method Thus, if there was an error, nothing is returned and the method ends, therefore returning an implicit None. When then trying to access .lists on that None, we get the AttributeError. Instead, we now permit this kind of wrong usage in config.py files. If this is a qutebrowser-internal ConfigContainer, we would've already raised in _handle_error() anyways. What we now do instead is returning a new ConfigContainer, i.e. allowing further access (while still capturing the error message). Thus, this now leads to: While getting 'content.host_blocking': No option 'content.host_blocking' While setting 'content.host_blocking.lists': No option 'content.host_blocking.lists' (this option was renamed to 'content.blocking.hosts.lists') This still isn't optimal, but the best we can do without more magic: At the point the first failure happens, we can't tell whether the user wants to get an option or is just getting a prefix. Fixes #5991
Diffstat (limited to 'tests')
-rw-r--r--tests/unit/config/test_config.py17
1 files changed, 17 insertions, 0 deletions
diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
index b30ab4bee..03eb61c8b 100644
--- a/tests/unit/config/test_config.py
+++ b/tests/unit/config/test_config.py
@@ -761,6 +761,23 @@ class TestContainer:
assert error.text == "While getting 'tabs.foobar'"
assert str(error.exception) == "No option 'tabs.foobar'"
+ def test_confapi_missing_prefix(self, container):
+ configapi = types.SimpleNamespace(errors=[])
+ container._configapi = configapi
+ container.content.host_blocking.lists = []
+
+ assert len(configapi.errors) == 2
+
+ error1 = configapi.errors[0]
+ assert error1.text == "While getting 'content.host_blocking'"
+ assert str(error1.exception) == "No option 'content.host_blocking'"
+
+ error2 = configapi.errors[1]
+ assert error2.text == "While setting 'content.host_blocking.lists'"
+ assert str(error2.exception) == (
+ "No option 'content.host_blocking.lists' (this option was renamed to "
+ "'content.blocking.hosts.lists')")
+
def test_pattern_no_configapi(self, config_stub):
pattern = urlmatch.UrlPattern('https://example.com/')
with pytest.raises(TypeError,