summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2019-10-11 12:36:28 +0200
committerFlorian Bruhin <me@the-compiler.org>2019-11-22 15:24:54 +0100
commit25e6f103457f89544f99bfcd62bbd78f8a4ce7f3 (patch)
treeac25cdebd4a08793f99c20bd8deda05559e6270d
parent9d9c404d4fbc527a75c7c71669a366d6225c4081 (diff)
downloadqutebrowser-25e6f103457f89544f99bfcd62bbd78f8a4ce7f3.tar.gz
qutebrowser-25e6f103457f89544f99bfcd62bbd78f8a4ce7f3.zip
Handle errors while reading state config
-rw-r--r--doc/changelog.asciidoc10
-rw-r--r--qutebrowser/config/configexc.py4
-rw-r--r--qutebrowser/config/configfiles.py9
-rw-r--r--qutebrowser/config/configinit.py11
-rw-r--r--tests/unit/config/test_configexc.py6
-rw-r--r--tests/unit/config/test_configinit.py18
6 files changed, 52 insertions, 6 deletions
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index dd183a29c..a56a04694 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -27,6 +27,16 @@ Fixed
deprecated and shows an error. Note that `:config-py-write` did write
such invalid lines before v1.8.0, so existing config files might need
adjustments.
+- The `readability-js` userscript now handles encodings correctly (which it
+ didn't before for some websites).
+- New `tabs.tooltips` setting which can be used to disable hover tooltips for
+ tabs.
+- <Shift-Insert> can now be used to paste text starting with a hyphen.
+- Following hints via the number keypad now works properly again.
+- The logic for `:restart` has been revisited which should fix issues with
+ relative basedirs.
+- Errors while reading the state file are now displayed instead of causing a
+ crash.
v1.8.1 (2019-09-27)
-------------------
diff --git a/qutebrowser/config/configexc.py b/qutebrowser/config/configexc.py
index df171c365..d83ca403b 100644
--- a/qutebrowser/config/configexc.py
+++ b/qutebrowser/config/configexc.py
@@ -141,11 +141,13 @@ class ConfigFileErrors(Error):
def __init__(self,
basename: str,
- errors: typing.Sequence[ConfigErrorDesc]) -> None:
+ errors: typing.Sequence[ConfigErrorDesc], *,
+ fatal: bool = False) -> None:
super().__init__("Errors occurred while reading {}:\n{}".format(
basename, '\n'.join(' {}'.format(e) for e in errors)))
self.basename = basename
self.errors = errors
+ self.fatal = fatal
for err in errors:
if err.traceback:
log.config.debug("Config error stack:")
diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py
index f220d2ca4..df7fdaae1 100644
--- a/qutebrowser/config/configfiles.py
+++ b/qutebrowser/config/configfiles.py
@@ -55,7 +55,6 @@ class StateConfig(configparser.ConfigParser):
super().__init__()
self._filename = os.path.join(standarddir.data(), 'state')
self.read(self._filename, encoding='utf-8')
-
qt_version = qVersion()
# We handle this here, so we can avoid setting qt_version_changed if
# the config is brand new, but can still set it when qt_version wasn't
@@ -690,7 +689,13 @@ def saved_sys_properties() -> typing.Iterator[None]:
def init() -> None:
"""Initialize config storage not related to the main config."""
global state
- state = StateConfig()
+
+ try:
+ state = StateConfig()
+ except configparser.Error as e:
+ msg = "While loading state file from {}".format(standarddir.data())
+ desc = configexc.ConfigErrorDesc(msg, e)
+ raise configexc.ConfigFileErrors('state', [desc], fatal=True)
# Set the QSettings path to something like
# ~/.config/qutebrowser/qsettings/qutebrowser/qutebrowser.conf so it
diff --git a/qutebrowser/config/configinit.py b/qutebrowser/config/configinit.py
index 74c07e3ab..3a39e1bc3 100644
--- a/qutebrowser/config/configinit.py
+++ b/qutebrowser/config/configinit.py
@@ -60,6 +60,7 @@ def early_init(args: argparse.Namespace) -> None:
objreg.register('config-commands', config_commands)
config_file = standarddir.config_py()
+ global _init_errors
try:
if os.path.exists(config_file):
@@ -68,10 +69,12 @@ def early_init(args: argparse.Namespace) -> None:
configfiles.read_autoconfig()
except configexc.ConfigFileErrors as e:
log.config.exception("Error while loading {}".format(e.basename))
- global _init_errors
_init_errors = e
- configfiles.init()
+ try:
+ configfiles.init()
+ except configexc.ConfigFileErrors as e:
+ _init_errors = e
for opt, val in args.temp_settings:
try:
@@ -149,6 +152,10 @@ def late_init(save_manager: savemanager.SaveManager) -> None:
icon=QMessageBox.Warning,
plain_text=False)
errbox.exec_()
+
+ if _init_errors.fatal:
+ sys.exit(usertypes.Exit.err_init)
+
_init_errors = None
config.instance.init_save_manager(save_manager)
diff --git a/tests/unit/config/test_configexc.py b/tests/unit/config/test_configexc.py
index f3f86a6dd..0335d0cee 100644
--- a/tests/unit/config/test_configexc.py
+++ b/tests/unit/config/test_configexc.py
@@ -126,3 +126,9 @@ Fake traceback
""")
# Make sure the traceback is not indented
assert '<pre>\nFake traceback\n' in html
+
+
+def test_config_file_errors_fatal():
+ err = configexc.ConfigErrorDesc("Text", Exception("Text"))
+ errors = configexc.ConfigFileErrors("state", [err], fatal=True)
+ assert errors.fatal
diff --git a/tests/unit/config/test_configinit.py b/tests/unit/config/test_configinit.py
index 93ca334ef..273c13d43 100644
--- a/tests/unit/config/test_configinit.py
+++ b/tests/unit/config/test_configinit.py
@@ -205,6 +205,12 @@ class TestEarlyInit:
assert dump == '\n'.join(expected)
+ def test_state_init_errors(self, init_patch, args, data_tmpdir):
+ state_file = data_tmpdir / 'state'
+ state_file.write_binary(b'\x00')
+ configinit.early_init(args)
+ assert configinit._init_errors.errors
+
def test_invalid_change_filter(self, init_patch, args):
config.change_filter('foobar')
with pytest.raises(configexc.NoOptionError):
@@ -325,16 +331,23 @@ class TestEarlyInit:
configinit._init_envvars()
-@pytest.mark.parametrize('errors', [True, False])
+@pytest.mark.parametrize('errors', [True, 'fatal', False])
def test_late_init(init_patch, monkeypatch, fake_save_manager, args,
mocker, errors):
configinit.early_init(args)
+
if errors:
err = configexc.ConfigErrorDesc("Error text", Exception("Exception"))
errs = configexc.ConfigFileErrors("config.py", [err])
+ if errors == 'fatal':
+ errs.fatal = True
+
monkeypatch.setattr(configinit, '_init_errors', errs)
+
msgbox_mock = mocker.patch('qutebrowser.config.configinit.msgbox.msgbox',
autospec=True)
+ exit_mock = mocker.patch('qutebrowser.config.configinit.sys.exit',
+ autospec=True)
configinit.late_init(fake_save_manager)
@@ -342,12 +355,15 @@ def test_late_init(init_patch, monkeypatch, fake_save_manager, args,
'state-config', unittest.mock.ANY)
fake_save_manager.add_saveable.assert_any_call(
'yaml-config', unittest.mock.ANY, unittest.mock.ANY)
+
if errors:
assert len(msgbox_mock.call_args_list) == 1
_call_posargs, call_kwargs = msgbox_mock.call_args_list[0]
text = call_kwargs['text'].strip()
assert text.startswith('Errors occurred while reading config.py:')
assert '<b>Error text</b>: Exception' in text
+
+ assert exit_mock.called == (errors == 'fatal')
else:
assert not msgbox_mock.called