diff options
-rw-r--r-- | doc/changelog.asciidoc | 29 | ||||
-rw-r--r-- | qutebrowser/browser/commands.py | 3 | ||||
-rw-r--r-- | qutebrowser/misc/guiprocess.py | 11 | ||||
-rw-r--r-- | qutebrowser/utils/version.py | 2 | ||||
-rw-r--r-- | scripts/dev/misc_checks.py | 4 | ||||
-rw-r--r-- | tests/unit/misc/test_guiprocess.py | 18 | ||||
-rw-r--r-- | tests/unit/utils/test_version.py | 1 |
7 files changed, 55 insertions, 13 deletions
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 58fbecb6f..a939de539 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -21,6 +21,20 @@ v2.0.0 (unreleased) Major changes ~~~~~~~~~~~~~ +- Quick checklist for packagers: + * Ensure you're providing at least Python 3.6.1 + * Ensure you're providing at least Qt 5.12 and PyQt 5.12 + * Add a new optional dependency on the Python `adblock` library (if packaged - + if not, consider packaging it, albeit optional it's very useful for users) + * Remove the `cssutils` optional dependency (if present) + * Remove the `attrs` (`attr`) dependency + * Move the `pygments` dependency from required to optional + * TODO: Move the `setuptools` dependency from runtime (for `pkg_resources`) to + build-time. + * For Python 3.6, 3.7 or 3.8, add a dependency on the `importlib_resources` + backport. + * For Python 3.6 only, add a dependency on the `dataclasses` backport. + * TODO complete? - At least Python 3.6.1 is now required to run qutebrowser, support for Python 3.5 (and 3.6.0) is dropped. Note that Python 3.5 is https://www.python.org/downloads/release/python-3510/[no longer supported @@ -37,7 +51,8 @@ Major changes with a newer version of Qt/PyQt. - New optional dependency on the Python `adblock` library, which is now used to integrate Brave's Rust adblocker library, if the `adblock` module is available. -- Windows 7 is not supported anymore by the Windows binaries. + If it is unavailable, qutebrowser falls back to host-blocking, i.e. the same + blocking technique it used before this release. - The (formerly optional) `cssutils` dependency is now removed. It was only needed for improved behavior in corner cases when using `:download --mhtml` with the (non-default) QtWebKit backend, and as such it's unlikely anyone is @@ -56,6 +71,8 @@ Major changes thus requiring the backports for those versions as well. - The former dependency on the `attrs`/`attr` package is now dropped. - On Python 3.6, a new dependency on the `dataclasses` backport is now required. +- Windows 7 is not supported anymore by the Windows binaries. +- TODO: The Windows and macOS binaries are now updated to Python 3.9. Removed ~~~~~~~ @@ -87,10 +104,10 @@ Added the desktop filename passed to Qt (which is used to set the `app_id` on Wayland). - New userscripts: - - `kodi` to play videos in Kodi - - `qr` to generate a QR code of the current URL - - `add-nextcloud-bookmarks` to create bookmarks in Nextcloud's Bookmarks app - - `add-nextcloud-cookbook` to add recipes to Nextcloud's Cookbook app + * `kodi` to play videos in Kodi + * `qr` to generate a QR code of the current URL + * `add-nextcloud-bookmarks` to create bookmarks in Nextcloud's Bookmarks app + * `add-nextcloud-cookbook` to add recipes to Nextcloud's Cookbook app Changed ~~~~~~~ @@ -156,6 +173,8 @@ Fixed contains a proper extension. Before this fix, qutebrowser would use the URL's data contents as filename with QtWebEngine; or "binary blob" with the Qt network stack. +- When `:tab-only` is run before a tab is available, an error is now shown + instead of crashing. - TODO: Due to a long-standing bug in the `pkg_resources` dependency, it caused qutebrowser's startup to slow down by around 150ms-1s (heavily depending on the system). Since the dependency is now removed, qutebrowser's startup time diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index ec43a3210..936af5402 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -764,7 +764,8 @@ class CommandDispatcher: """ cmdutils.check_exclusive((prev, next_), 'pn') cur_idx = self._tabbed_browser.widget.currentIndex() - assert cur_idx != -1 + if cur_idx == -1: + raise cmdutils.CommandError("Failed to get current tab for :tab-only") def _to_close(i): """Helper method to check if a tab should be closed or not.""" diff --git a/qutebrowser/misc/guiprocess.py b/qutebrowser/misc/guiprocess.py index 872a594f3..4b0727793 100644 --- a/qutebrowser/misc/guiprocess.py +++ b/qutebrowser/misc/guiprocess.py @@ -25,7 +25,7 @@ import shlex from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QProcess, QProcessEnvironment) -from qutebrowser.utils import message, log +from qutebrowser.utils import message, log, utils from qutebrowser.browser import qutescheme @@ -75,9 +75,12 @@ class GUIProcess(QObject): procenv.insert(k, v) self._proc.setProcessEnvironment(procenv) - @pyqtSlot() - def _on_error(self): + @pyqtSlot(QProcess.ProcessError) + def _on_error(self, error): """Show a message if there was an error while spawning.""" + if error == QProcess.Crashed and not utils.is_windows: + # Already handled via ExitStatus in _on_finished + return msg = self._proc.errorString() message.error("Error while spawning {}: {}".format(self._what, msg)) @@ -101,7 +104,7 @@ class GUIProcess(QObject): message.error(stderr.strip()) if status == QProcess.CrashExit: - exitinfo = "{} crashed!".format(self._what.capitalize()) + exitinfo = "{} crashed.".format(self._what.capitalize()) message.error(exitinfo) elif status == QProcess.NormalExit and code == 0: exitinfo = "{} exited successfully.".format( diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 74ad73833..94c835357 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -365,8 +365,6 @@ MODULE_INFO: Mapping[str, ModuleInfo] = collections.OrderedDict([ ('pygments', ['__version__']), ('yaml', ['__version__']), ('adblock', ['__version__'], "0.3.2"), - ('dataclasses', []), - ('importlib_resources', []), ('PyQt5.QtWebEngineWidgets', []), ('PyQt5.QtWebEngine', ['PYQT_WEBENGINE_VERSION_STR']), ('PyQt5.QtWebKitWidgets', []), diff --git a/scripts/dev/misc_checks.py b/scripts/dev/misc_checks.py index 5c654235c..afbb5e791 100644 --- a/scripts/dev/misc_checks.py +++ b/scripts/dev/misc_checks.py @@ -214,6 +214,10 @@ def check_spelling(args: argparse.Namespace) -> Optional[bool]: re.compile(r'Q_(ENUM|FLAG)'), "Q_ENUM and Q_FLAG are removed in PyQt 6", ), + ( + re.compile(r'attr\.(s|ib)($|\()'), + "attrs have been replaced by dataclasses in qutebrowser.", + ), ] # Files which should be ignored, e.g. because they come from another diff --git a/tests/unit/misc/test_guiprocess.py b/tests/unit/misc/test_guiprocess.py index 4ed19f64e..9b2e1e7b3 100644 --- a/tests/unit/misc/test_guiprocess.py +++ b/tests/unit/misc/test_guiprocess.py @@ -25,7 +25,7 @@ import pytest from PyQt5.QtCore import QProcess from qutebrowser.misc import guiprocess -from qutebrowser.utils import usertypes +from qutebrowser.utils import usertypes, utils from qutebrowser.browser import qutescheme @@ -237,6 +237,22 @@ def test_exit_unsuccessful(qtbot, proc, message_mock, py_proc, caplog): assert msg.text == expected +def test_exit_crash(qtbot, proc, message_mock, py_proc, caplog): + with caplog.at_level(logging.ERROR): + with qtbot.waitSignal(proc.finished, timeout=10000): + proc.start(*py_proc(""" + import os, signal + os.kill(os.getpid(), signal.SIGSEGV) + """)) + + expected = ( + "Testprocess exited with status 11, see :messages for details." + if utils.is_windows else "Testprocess crashed." + ) + msg = message_mock.getmsg(usertypes.MessageLevel.error) + assert msg.text == expected + + @pytest.mark.parametrize('stream', ['stdout', 'stderr']) def test_exit_unsuccessful_output(qtbot, proc, caplog, py_proc, stream): """When a process fails, its output should be logged.""" diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 912be3bec..6d94fc72c 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -715,6 +715,7 @@ class TestModuleVersions: ('yaml', True), ('adblock', True), ('dataclasses', False), + ('importlib_resources', False), ]) def test_existing_attributes(self, name, has_version): """Check if all dependencies have an expected __version__ attribute. |