From f4ed31b2952d6c01969998e3dacd18762886100e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 15 Dec 2017 16:12:31 +0100 Subject: [PATCH] Add an utils.Unreachable exception --- .coveragerc | 1 + qutebrowser/browser/browsertab.py | 4 ++-- qutebrowser/browser/shared.py | 4 ++-- qutebrowser/completion/completer.py | 3 +-- qutebrowser/completion/completionwidget.py | 5 +++++ qutebrowser/config/configdata.py | 1 + qutebrowser/keyinput/basekeyparser.py | 2 +- qutebrowser/mainwindow/statusbar/command.py | 6 +++--- qutebrowser/misc/backendproblem.py | 11 ++++------- qutebrowser/misc/miscwidgets.py | 4 ++-- qutebrowser/misc/split.py | 5 +++-- qutebrowser/utils/utils.py | 5 +++++ tests/end2end/fixtures/testprocess.py | 2 ++ tests/unit/browser/test_tab.py | 5 +++-- tests/unit/commands/test_userscripts.py | 1 + tests/unit/utils/test_version.py | 2 +- 16 files changed, 37 insertions(+), 24 deletions(-) diff --git a/.coveragerc b/.coveragerc index 18fb85ba4..9ba8e8a5e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -12,6 +12,7 @@ exclude_lines = def __repr__ raise AssertionError raise NotImplementedError + raise utils\.Unreachable if __name__ == ["']__main__["']: [xml] diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 57a3f6ba7..eb0e55c4b 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -706,8 +706,8 @@ class AbstractTab(QWidget): # This only gives us some mild protection against re-using events, but # it's certainly better than a segfault. if getattr(evt, 'posted', False): - raise AssertionError("Can't re-use an event which was already " - "posted!") + raise utils.Unreachable("Can't re-use an event which was already " + "posted!") recipient = self.event_target() evt.posted = True QApplication.postEvent(recipient, evt) diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index ab1b6ad9f..b6bfefe7b 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -22,7 +22,7 @@ import html from qutebrowser.config import config -from qutebrowser.utils import usertypes, message, log, objreg, jinja +from qutebrowser.utils import usertypes, message, log, objreg, jinja, utils from qutebrowser.mainwindow import mainwindow @@ -182,7 +182,7 @@ def ignore_certificate_errors(url, errors, abort_on): return False else: raise ValueError("Invalid ssl_strict value {!r}".format(ssl_strict)) - raise AssertionError("Not reached") + raise utils.Unreachable def feature_permission(url, option, msg, yes_action, no_action, abort_on): diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py index 6eb8b51c4..2e5b75f2d 100644 --- a/qutebrowser/completion/completer.py +++ b/qutebrowser/completion/completer.py @@ -153,8 +153,7 @@ class Completer(QObject): "partitioned: {} '{}' {}".format(prefix, center, postfix)) return prefix, center, postfix - # We should always return above - assert False, parts + raise utils.Unreachable("Not all parts consumed: {}".format(parts)) @pyqtSlot(str) def on_selection_changed(self, text): diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py index f1be785e1..29f4f6653 100644 --- a/qutebrowser/completion/completionwidget.py +++ b/qutebrowser/completion/completionwidget.py @@ -180,6 +180,7 @@ class CompletionView(QTreeView): return self.model().last_item() else: return self.model().first_item() + while True: idx = self.indexAbove(idx) if upwards else self.indexBelow(idx) # wrap around if we arrived at beginning/end @@ -193,6 +194,8 @@ class CompletionView(QTreeView): # Item is a real item, not a category header -> success return idx + raise utils.Unreachable + def _next_category_idx(self, upwards): """Get the index of the previous/next category. @@ -222,6 +225,8 @@ class CompletionView(QTreeView): self.scrollTo(idx) return idx.child(0, 0) + raise utils.Unreachable + @cmdutils.register(instance='completion', modes=[usertypes.KeyMode.command], scope='window') @cmdutils.argument('which', choices=['next', 'prev', 'next-category', diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 143cbd49a..b265ab8fc 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -174,6 +174,7 @@ def _parse_yaml_backends(name, node): elif isinstance(node, dict): return _parse_yaml_backends_dict(name, node) _raise_invalid_node(name, 'backends', node) + raise utils.Unreachable def _read_yaml(yaml_data): diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 658b52d2d..b435ac52c 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -214,7 +214,7 @@ class BaseKeyParser(QObject): elif match == self.Match.other: pass else: - raise AssertionError("Invalid match value {!r}".format(match)) + raise utils.Unreachable("Invalid match value {!r}".format(match)) return match def _match_key(self, cmd_input): diff --git a/qutebrowser/mainwindow/statusbar/command.py b/qutebrowser/mainwindow/statusbar/command.py index 3e0a339a3..ab8ac7b5d 100644 --- a/qutebrowser/mainwindow/statusbar/command.py +++ b/qutebrowser/mainwindow/statusbar/command.py @@ -26,7 +26,7 @@ from qutebrowser.keyinput import modeman, modeparsers from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.misc import cmdhistory, editor from qutebrowser.misc import miscwidgets as misc -from qutebrowser.utils import usertypes, log, objreg, message +from qutebrowser.utils import usertypes, log, objreg, message, utils from qutebrowser.config import config @@ -221,8 +221,8 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): elif text[0] in modeparsers.STARTCHARS: super().set_prompt(text[0]) else: - raise AssertionError("setText got called with invalid text " - "'{}'!".format(text)) + raise utils.Unreachable("setText got called with invalid text " + "'{}'!".format(text)) super().setText(text) def keyPressEvent(self, e): diff --git a/qutebrowser/misc/backendproblem.py b/qutebrowser/misc/backendproblem.py index 8a51d50ce..8cc5b71b2 100644 --- a/qutebrowser/misc/backendproblem.py +++ b/qutebrowser/misc/backendproblem.py @@ -152,7 +152,7 @@ def _show_dialog(*args, **kwargs): elif status == _Result.restart: quitter.restart() else: - assert False, status + raise utils.Unreachable(status) sys.exit(usertypes.Exit.err_init) @@ -199,8 +199,7 @@ def _handle_nouveau_graphics(): buttons=[button], ) - # Should never be reached - assert False + raise utils.Unreachable def _handle_wayland(): @@ -239,8 +238,7 @@ def _handle_wayland(): "(based on Chromium). " ) - # Should never be reached - assert False + raise utils.Unreachable @attr.s @@ -359,8 +357,7 @@ def _check_backend_modules(): html.escape(imports.webengine_error)) ) - # Should never be reached - assert False + raise utils.Unreachable def init(): diff --git a/qutebrowser/misc/miscwidgets.py b/qutebrowser/misc/miscwidgets.py index f398feb4c..5d3e9b5ca 100644 --- a/qutebrowser/misc/miscwidgets.py +++ b/qutebrowser/misc/miscwidgets.py @@ -241,7 +241,7 @@ class WrapperLayout(QLayout): self._widget = None def addItem(self, _widget): - raise AssertionError("Should never be called!") + raise utils.Unreachable def sizeHint(self): return self._widget.sizeHint() @@ -250,7 +250,7 @@ class WrapperLayout(QLayout): return None def takeAt(self, _index): - raise AssertionError("Should never be called!") + raise utils.Unreachable def setGeometry(self, rect): self._widget.setGeometry(rect) diff --git a/qutebrowser/misc/split.py b/qutebrowser/misc/split.py index bdde2b7ee..2ae8b3792 100644 --- a/qutebrowser/misc/split.py +++ b/qutebrowser/misc/split.py @@ -21,7 +21,7 @@ import re -from qutebrowser.utils import log +from qutebrowser.utils import log, utils class ShellLexer: @@ -117,7 +117,8 @@ class ShellLexer: else: self.token += nextchar else: - raise AssertionError("Invalid state {!r}!".format(self.state)) + raise utils.Unreachable( + "Invalid state {!r}!".format(self.state)) if self.state in self.escape and not self.keep: self.token += self.state if self.token or self.quoted: diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index 8333c4132..b277ccb77 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -60,6 +60,11 @@ is_windows = sys.platform.startswith('win') is_posix = os.name == 'posix' +class Unreachable(Exception): + + """Raised when there was unreachable code.""" + + class ClipboardError(Exception): """Raised if the clipboard contents are unavailable for some reason.""" diff --git a/tests/end2end/fixtures/testprocess.py b/tests/end2end/fixtures/testprocess.py index 7836ab79a..ac220af58 100644 --- a/tests/end2end/fixtures/testprocess.py +++ b/tests/end2end/fixtures/testprocess.py @@ -404,6 +404,8 @@ class Process(QObject): self._log("----> found it") return match + raise quteutils.Unreachable + def _wait_for_match(self, spy, kwargs): """Try matching the kwargs with the given QSignalSpy.""" for args in spy: diff --git a/tests/unit/browser/test_tab.py b/tests/unit/browser/test_tab.py index a2a34d9ce..d67ee4c8f 100644 --- a/tests/unit/browser/test_tab.py +++ b/tests/unit/browser/test_tab.py @@ -20,6 +20,7 @@ import pytest from qutebrowser.browser import browsertab +from qutebrowser.utils import utils pytestmark = pytest.mark.usefixtures('redirect_webengine_data') @@ -54,7 +55,7 @@ def tab(request, qtbot, tab_registry, cookiejar_and_cache, mode_manager): 'qutebrowser.browser.webengine.webenginetab') tab_class = webenginetab.WebEngineTab else: - assert False + raise utils.Unreachable t = tab_class(win_id=0, mode_manager=mode_manager) qtbot.add_widget(t) @@ -67,7 +68,7 @@ class Zoom(browsertab.AbstractZoom): pass def factor(self): - assert False + raise utils.Unreachable class Tab(browsertab.AbstractTab): diff --git a/tests/unit/commands/test_userscripts.py b/tests/unit/commands/test_userscripts.py index 32f9a1bb9..3b6a69710 100644 --- a/tests/unit/commands/test_userscripts.py +++ b/tests/unit/commands/test_userscripts.py @@ -64,6 +64,7 @@ def runner(request, runtime_tmpdir): if (not utils.is_posix and request.param is userscripts._POSIXUserscriptRunner): pytest.skip("Requires a POSIX os") + raise utils.Unreachable else: return request.param() diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 3d01fcfb5..620e0688a 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -795,7 +795,7 @@ class FakeQSslSocket: def sslLibraryVersionString(self): """Fake for QSslSocket::sslLibraryVersionString().""" if self._version is None: - raise AssertionError("Got called with version None!") + raise utils.Unreachable("Got called with version None!") return self._version