diff options
author | Jimmy <jimmy@spalge.com> | 2022-04-30 14:14:17 +1200 |
---|---|---|
committer | Jimmy <jimmy@spalge.com> | 2022-04-30 19:30:49 +1200 |
commit | 477941fa9bdab278a4d459b8b9f2d819a8ffb1ca (patch) | |
tree | 715c85fcd0d3d39f4ffd4d26e2e93934a16d3a9d | |
parent | 2341a00fe48afee3fb42ef720c8a786767d8ba31 (diff) | |
download | qutebrowser-477941fa9bdab278a4d459b8b9f2d819a8ffb1ca.tar.gz qutebrowser-477941fa9bdab278a4d459b8b9f2d819a8ffb1ca.zip |
Run darker over pyqt reference rewrite
Looks like there is still a few places like:
thing = {
really.hecking.long.name = foo,
}
where black is unable to reformat them to be under 88 chars. Possibly
adding backslashes would help, I might manually edit them to have part
of the right hand side referred to via a shorter local variable.
ran like:
$ cat pyproject.toml
[tool.black]
skip-string-normalization = true
target-version = 'py37'
darker diff -W 8 -r 488dc175e069 qutebrowser tests/
133 files changed, 2937 insertions, 1780 deletions
diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 54b19a44f..cf76a04e8 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -168,8 +168,7 @@ def init(*, args: argparse.Namespace) -> None: _process_args(args) for scheme in ['http', 'https', 'qute']: - QtGui.QDesktopServices.setUrlHandler( - scheme, open_desktopservices_url) + QtGui.QDesktopServices.setUrlHandler(scheme, open_desktopservices_url) log.init.debug("Init done!") crashsignal.crash_handler.raise_crashdlg() diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 3a484a8ec..dc6b9e454 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -46,9 +46,9 @@ if TYPE_CHECKING: tab_id_gen = itertools.count(0) -def create(win_id: int, - private: bool, - parent: QtWidgets.QWidget = None) -> 'AbstractTab': +def create( + win_id: int, private: bool, parent: QtWidgets.QWidget = None +) -> 'AbstractTab': """Get a QtWebKit/QtWebEngine tab object. Args: @@ -143,8 +143,15 @@ class AbstractAction: """Attribute ``action`` of AbstractTab for Qt WebActions.""" - action_class: Type[Union['QtWebKitWidgets.QWebPage', 'QtWebEngineWidgets.QWebEnginePage']] - action_base: Type[Union['QtWebKitWidgets.QWebPage.WebAction', 'QtWebEngineWidgets.QWebEnginePage.WebAction']] + action_class: Type[ + Union['QtWebKitWidgets.QWebPage', 'QtWebEngineWidgets.QWebEnginePage'] + ] + action_base: Type[ + Union[ + 'QtWebKitWidgets.QWebPage.WebAction', + 'QtWebEngineWidgets.QWebEnginePage.WebAction', + ] + ] def __init__(self, tab: 'AbstractTab') -> None: self._widget = cast(QtWidgets.QWidget, None) @@ -243,8 +250,9 @@ class AbstractPrinting: """Print the tab to a PDF with the given filename.""" raise NotImplementedError - def to_printer(self, printer: QtPrintSupport.QPrinter, - callback: Callable[[bool], None] = None) -> None: + def to_printer( + self, printer: QtPrintSupport.QPrinter, callback: Callable[[bool], None] = None + ) -> None: """Print the tab. Args: @@ -452,10 +460,12 @@ class AbstractCaret(QtCore.QObject): #: Emitted when a ``follow_selection`` action is done. follow_selected_done = QtCore.pyqtSignal() - def __init__(self, - tab: 'AbstractTab', - mode_manager: modeman.ModeManager, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + tab: 'AbstractTab', + mode_manager: modeman.ModeManager, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(parent) self._widget = cast(QtWidgets.QWidget, None) self._mode_manager = mode_manager @@ -529,7 +539,9 @@ class AbstractCaret(QtCore.QObject): def _follow_enter(self, tab: bool) -> None: """Follow a link by faking an enter press.""" if tab: - self._tab.fake_key_press(QtCore.Qt.Key_Enter, modifier=QtCore.Qt.ControlModifier) + self._tab.fake_key_press( + QtCore.Qt.Key_Enter, modifier=QtCore.Qt.ControlModifier + ) else: self._tab.fake_key_press(QtCore.Qt.Key_Enter) @@ -637,13 +649,19 @@ class AbstractHistory: def __init__(self, tab: 'AbstractTab') -> None: self._tab = tab - self._history = cast(Union['QtWebKit.QWebHistory', 'QtWebEngineWidgets.QWebEngineHistory'], None) + self._history = cast( + Union['QtWebKit.QWebHistory', 'QtWebEngineWidgets.QWebEngineHistory'], None + ) self.private_api = AbstractHistoryPrivate() def __len__(self) -> int: raise NotImplementedError - def __iter__(self) -> Iterable[Union['QtWebKit.QWebHistoryItem', 'QtWebEngineWidgets.QWebEngineHistoryItem']]: + def __iter__( + self, + ) -> Iterable[ + Union['QtWebKit.QWebHistoryItem', 'QtWebEngineWidgets.QWebEngineHistoryItem'] + ]: raise NotImplementedError def _check_count(self, count: int) -> None: @@ -871,9 +889,12 @@ class AbstractTabPrivate: tabdata.inspector.inspect(self._widget.page()) tabdata.inspector.set_position(position) - def _init_inspector(self, splitter: 'miscwidgets.InspectorSplitter', - win_id: int, - parent: QtWidgets.QWidget = None) -> 'AbstractWebInspector': + def _init_inspector( + self, + splitter: 'miscwidgets.InspectorSplitter', + win_id: int, + parent: QtWidgets.QWidget = None, + ) -> 'AbstractWebInspector': """Get a WebKitInspector/WebEngineInspector. Args: @@ -935,10 +956,14 @@ class AbstractTab(QtWidgets.QWidget): # for a given hostname anyways. _insecure_hosts: Set[str] = set() - def __init__(self, *, win_id: int, - mode_manager: 'modeman.ModeManager', - private: bool, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + *, + win_id: int, + mode_manager: 'modeman.ModeManager', + private: bool, + parent: QtWidgets.QWidget = None + ) -> None: utils.unused(mode_manager) # needed for mypy self.is_private = private self.win_id = win_id @@ -1144,13 +1169,14 @@ class AbstractTab(QtWidgets.QWidget): def stop(self) -> None: raise NotImplementedError - def fake_key_press(self, - key: QtCore.Qt.Key, - modifier: QtCore.Qt.KeyboardModifier = QtCore.Qt.NoModifier) -> None: + def fake_key_press( + self, + key: QtCore.Qt.Key, + modifier: QtCore.Qt.KeyboardModifier = QtCore.Qt.NoModifier, + ) -> None: """Send a fake key event to this tab.""" press_evt = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, key, modifier, 0, 0, 0) - release_evt = QtGui.QKeyEvent(QtCore.QEvent.KeyRelease, key, modifier, - 0, 0, 0) + release_evt = QtGui.QKeyEvent(QtCore.QEvent.KeyRelease, key, modifier, 0, 0, 0) self.send_event(press_evt) self.send_event(release_evt) @@ -1224,7 +1250,8 @@ class AbstractTab(QtWidgets.QWidget): try: qurl = self.url() url = qurl.toDisplayString( - QtCore.QUrl.EncodeUnicode) # type: ignore[arg-type] + QtCore.QUrl.EncodeUnicode + ) # type: ignore[arg-type] except (AttributeError, RuntimeError) as exc: url = '<{}>'.format(exc.__class__.__name__) else: diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index af5cc2223..c52f3923c 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1292,8 +1292,9 @@ class CommandDispatcher: current page's url. """ if url is None: - url = self._current_url().toString(QtCore.QUrl.RemovePassword | - QtCore.QUrl.FullyEncoded) + url = self._current_url().toString( + QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded + ) try: objreg.get('bookmark-manager').delete(url) except KeyError: @@ -1868,5 +1869,8 @@ class CommandDispatcher: else: window.setWindowState(window.windowState() ^ QtCore.Qt.WindowFullScreen) - log.misc.debug('state before fullscreen: {}'.format( - debug.qflags_key(QtCore.Qt, window.state_before_fullscreen))) + log.misc.debug( + 'state before fullscreen: {}'.format( + debug.qflags_key(QtCore.Qt, window.state_before_fullscreen) + ) + ) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index b4dd859d8..f78d63af5 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -939,7 +939,8 @@ class AbstractDownloadManager(QtCore.QObject): delay = config.val.downloads.remove_finished if delay > -1: download.finished.connect( - lambda: QtCore.QTimer.singleShot(delay, download.remove)) + lambda: QtCore.QTimer.singleShot(delay, download.remove) + ) elif auto_remove: download.finished.connect(download.remove) @@ -1265,8 +1266,11 @@ class DownloadModel(QtCore.QAbstractListModel): def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): """Simple constant header.""" - if (section == 0 and orientation == QtCore.Qt.Horizontal and - role == QtCore.Qt.DisplayRole): + if ( + section == 0 + and orientation == QtCore.Qt.Horizontal + and role == QtCore.Qt.DisplayRole + ): return "Downloads" else: return "" diff --git a/qutebrowser/browser/downloadview.py b/qutebrowser/browser/downloadview.py index 5edead500..ec188deb3 100644 --- a/qutebrowser/browser/downloadview.py +++ b/qutebrowser/browser/downloadview.py @@ -62,7 +62,9 @@ class DownloadView(QtWidgets.QListView): stylesheet.set_register(self) self.setResizeMode(QtWidgets.QListView.Adjust) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) + self.setSizePolicy( + QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed + ) self.setFocusPolicy(QtCore.Qt.NoFocus) self.setFlow(QtWidgets.QListView.LeftToRight) self.setSpacing(1) diff --git a/qutebrowser/browser/eventfilter.py b/qutebrowser/browser/eventfilter.py index 0af93482a..ca057e0ac 100644 --- a/qutebrowser/browser/eventfilter.py +++ b/qutebrowser/browser/eventfilter.py @@ -97,8 +97,10 @@ class TabEventFilter(QtCore.QObject): Return: True if the event should be filtered, False otherwise. """ - is_rocker_gesture = (config.val.input.mouse.rocker_gestures and - e.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.RightButton) + is_rocker_gesture = ( + config.val.input.mouse.rocker_gestures + and e.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.RightButton + ) if e.button() in [QtCore.Qt.XButton1, QtCore.Qt.XButton2] or is_rocker_gesture: self._mousepress_backforward(e) @@ -238,8 +240,10 @@ class TabEventFilter(QtCore.QObject): Return: True if the event should be filtered, False otherwise. """ - if (not config.val.input.mouse.back_forward_buttons and - e.button() in [QtCore.Qt.XButton1, QtCore.Qt.XButton2]): + if not config.val.input.mouse.back_forward_buttons and e.button() in [ + QtCore.Qt.XButton1, + QtCore.Qt.XButton2, + ]: # Back and forward on mice are disabled return diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py index 61594b329..be5e40bb0 100644 --- a/qutebrowser/browser/greasemonkey.py +++ b/qutebrowser/browser/greasemonkey.py @@ -409,10 +409,10 @@ class GreasemonkeyManager(QtCore.QObject): download_manager = objreg.get('qtnetwork-download-manager') for url, target_path in required_dls: - target = downloads.FileDownloadTarget(target_path, - force_overwrite=True) - download = download_manager.get(QtCore.QUrl(url), target=target, - auto_remove=True) + target = downloads.FileDownloadTarget(target_path, force_overwrite=True) + download = download_manager.get( + QtCore.QUrl(url), target=target, auto_remove=True + ) download.requested_url = url self._in_progress_dls.append(download) if download.successful: diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 4e5157cf0..027c9cb56 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -357,7 +357,8 @@ class HintActions: context: The HintContext to use. """ urlstr = url.toString( - QtCore.QUrl.FullyEncoded | QtCore.QUrl.RemovePassword) # type: ignore[arg-type] + QtCore.QUrl.FullyEncoded | QtCore.QUrl.RemovePassword + ) # type: ignore[arg-type] args = context.get_args(urlstr) commandrunner = runners.CommandRunner(self._win_id) commandrunner.run_safely('spawn ' + ' '.join(args)) diff --git a/qutebrowser/browser/history.py b/qutebrowser/browser/history.py index ab39bed04..43d81ade8 100644 --- a/qutebrowser/browser/history.py +++ b/qutebrowser/browser/history.py @@ -90,8 +90,9 @@ class CompletionMetaInfo(sql.SqlTable): 'force_rebuild': False, } - def __init__(self, database: sql.Database, - parent: Optional[QtCore.QObject] = None) -> None: + def __init__( + self, database: sql.Database, parent: Optional[QtCore.QObject] = None + ) -> None: self._fields = ['key', 'value'] self._constraints = {'key': 'PRIMARY KEY'} super().__init__(database, "CompletionMetaInfo", self._fields, @@ -138,13 +139,20 @@ class CompletionHistory(sql.SqlTable): """History which only has the newest entry for each URL.""" - def __init__(self, database: sql.Database, - parent: Optional[QtCore.QObject] = None) -> None: - super().__init__(database, "CompletionHistory", ['url', 'title', 'last_atime'], - constraints={'url': 'PRIMARY KEY', - 'title': 'NOT NULL', - 'last_atime': 'NOT NULL'}, - parent=parent) + def __init__( + self, database: sql.Database, parent: Optional[QtCore.QObject] = None + ) -> None: + super().__init__( + database, + "CompletionHistory", + ['url', 'title', 'last_atime'], + constraints={ + 'url': 'PRIMARY KEY', + 'title': 'NOT NULL', + 'last_atime': 'NOT NULL', + }, + parent=parent, + ) self.create_index('CompletionHistoryAtimeIndex', 'last_atime') @@ -163,14 +171,24 @@ class WebHistory(sql.SqlTable): # one url cleared url_cleared = QtCore.pyqtSignal(QtCore.QUrl) - def __init__(self, database: sql.Database, progress: HistoryProgress, - parent: Optional[QtCore.QObject] = None) -> None: - super().__init__(database, "History", ['url', 'title', 'atime', 'redirect'], - constraints={'url': 'NOT NULL', - 'title': 'NOT NULL', - 'atime': 'NOT NULL', - 'redirect': 'NOT NULL'}, - parent=parent) + def __init__( + self, + database: sql.Database, + progress: HistoryProgress, + parent: Optional[QtCore.QObject] = None, + ) -> None: + super().__init__( + database, + "History", + ['url', 'title', 'atime', 'redirect'], + constraints={ + 'url': 'NOT NULL', + 'title': 'NOT NULL', + 'atime': 'NOT NULL', + 'redirect': 'NOT NULL', + }, + parent=parent, + ) self._progress = progress # Store the last saved url to avoid duplicate immediate saves. self._last_url = None diff --git a/qutebrowser/browser/inspector.py b/qutebrowser/browser/inspector.py index b2c6d91b1..daf3c820e 100644 --- a/qutebrowser/browser/inspector.py +++ b/qutebrowser/browser/inspector.py @@ -89,9 +89,12 @@ class AbstractWebInspector(QtWidgets.QWidget): recreate = QtCore.pyqtSignal() - def __init__(self, splitter: 'miscwidgets.InspectorSplitter', - win_id: int, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + splitter: 'miscwidgets.InspectorSplitter', + win_id: int, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(parent) self._widget = cast(QtWidgets.QWidget, None) self._layout = miscwidgets.WrapperLayout(self) diff --git a/qutebrowser/browser/navigate.py b/qutebrowser/browser/navigate.py index efc36899d..9a4f588bb 100644 --- a/qutebrowser/browser/navigate.py +++ b/qutebrowser/browser/navigate.py @@ -41,25 +41,31 @@ class Error(Exception): # Note that the getters must not use FullyDecoded decoded mode to prevent loss # of information. (host and path use FullyDecoded by default) _URL_SEGMENTS = [ - ('host', - lambda url: url.host(QtCore.QUrl.FullyEncoded), - lambda url, host: url.setHost(host, QtCore.QUrl.StrictMode)), - - ('port', - lambda url: str(url.port()) if url.port() > 0 else '', - lambda url, x: url.setPort(int(x))), - - ('path', - lambda url: url.path(QtCore.QUrl.FullyEncoded), - lambda url, path: url.setPath(path, QtCore.QUrl.StrictMode)), - - ('query', - lambda url: url.query(QtCore.QUrl.FullyEncoded), - lambda url, query: url.setQuery(query, QtCore.QUrl.StrictMode)), - - ('anchor', - lambda url: url.fragment(QtCore.QUrl.FullyEncoded), - lambda url, fragment: url.setFragment(fragment, QtCore.QUrl.StrictMode)), + ( + 'host', + lambda url: url.host(QtCore.QUrl.FullyEncoded), + lambda url, host: url.setHost(host, QtCore.QUrl.StrictMode), + ), + ( + 'port', + lambda url: str(url.port()) if url.port() > 0 else '', + lambda url, x: url.setPort(int(x)), + ), + ( + 'path', + lambda url: url.path(QtCore.QUrl.FullyEncoded), + lambda url, path: url.setPath(path, QtCore.QUrl.StrictMode), + ), + ( + 'query', + lambda url: url.query(QtCore.QUrl.FullyEncoded), + lambda url, query: url.setQuery(query, QtCore.QUrl.StrictMode), + ), + ( + 'anchor', + lambda url: url.fragment(QtCore.QUrl.FullyEncoded), + lambda url, fragment: url.setFragment(fragment, QtCore.QUrl.StrictMode), + ), ] diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py index c21e4f982..c6cea79ca 100644 --- a/qutebrowser/browser/network/pac.py +++ b/qutebrowser/browser/network/pac.py @@ -150,12 +150,16 @@ class PACResolver: if len(config) != 2: raise ParseProxyError("Invalid number of parameters for PROXY") host, port = PACResolver._parse_proxy_host(config[1]) - return QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.HttpProxy, host, port) + return QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.HttpProxy, host, port + ) elif config[0] in ["SOCKS", "SOCKS5"]: if len(config) != 2: raise ParseProxyError("Invalid number of parameters for SOCKS") host, port = PACResolver._parse_proxy_host(config[1]) - return QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, host, port) + return QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, host, port + ) else: err = "Unknown proxy type: {}" raise ParseProxyError(err.format(config[0])) @@ -249,7 +253,9 @@ class PACFetcher(QtCore.QObject): with log.disable_qt_msghandler(): # WORKAROUND for a hang when messages are printed, see our # NetworkAccessManager subclass for details. - self._manager: Optional[QtNetwork.QNetworkAccessManager] = QtNetwork.QNetworkAccessManager() + self._manager: Optional[ + QtNetwork.QNetworkAccessManager + ] = QtNetwork.QNetworkAccessManager() self._manager.setProxy(QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.NoProxy)) self._pac = None self._error_message = None @@ -330,4 +336,8 @@ class PACFetcher(QtCore.QObject): # Later NetworkManager.createRequest will detect this and display # an error message. error_host = "pac-resolve-error.qutebrowser.invalid" - return [QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.HttpProxy, error_host, 9)] + return [ + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.HttpProxy, error_host, 9 + ) + ] diff --git a/qutebrowser/browser/pdfjs.py b/qutebrowser/browser/pdfjs.py index 0942c78c3..1551aa8b9 100644 --- a/qutebrowser/browser/pdfjs.py +++ b/qutebrowser/browser/pdfjs.py @@ -95,7 +95,8 @@ def _generate_pdfjs_script(filename): url.setQuery(url_query) js_url = javascript.to_js( - url.toString(QtCore.QUrl.FullyEncoded)) # type: ignore[arg-type] + url.toString(QtCore.QUrl.FullyEncoded) + ) # type: ignore[arg-type] return jinja.js_environment.from_string(""" document.addEventListener("DOMContentLoaded", function() { @@ -223,8 +224,9 @@ def is_available(): def should_use_pdfjs(mimetype, url): """Check whether PDF.js should be used.""" # e.g. 'blob:qute%3A///b45250b3-787e-44d1-a8d8-c2c90f81f981' - is_download_url = (url.scheme() == 'blob' and - QtCore.QUrl(url.path()).scheme() == 'qute') + is_download_url = ( + url.scheme() == 'blob' and QtCore.QUrl(url.path()).scheme() == 'qute' + ) is_pdf = mimetype in ['application/pdf', 'application/x-pdf'] config_enabled = config.instance.get('content.pdfjs', url=url) return is_pdf and not is_download_url and config_enabled diff --git a/qutebrowser/browser/qtnetworkdownloads.py b/qutebrowser/browser/qtnetworkdownloads.py index d8f1e645f..161fedef1 100644 --- a/qutebrowser/browser/qtnetworkdownloads.py +++ b/qutebrowser/browser/qtnetworkdownloads.py @@ -337,7 +337,8 @@ class DownloadItem(downloads.AbstractDownloadItem): if self._reply is None: error = "Unknown error: {}".format( - debug.qenum_key(QtNetwork.QNetworkReply, code)) + debug.qenum_key(QtNetwork.QNetworkReply, code) + ) else: error = self._reply.errorString() @@ -370,7 +371,8 @@ class DownloadItem(downloads.AbstractDownloadItem): """ assert self._reply is not None redirect = self._reply.attribute( - QtNetwork.QNetworkRequest.RedirectionTargetAttribute) + QtNetwork.QNetworkRequest.RedirectionTargetAttribute + ) if redirect is None or redirect.isEmpty(): return False new_url = self._reply.url().resolved(redirect) @@ -509,8 +511,10 @@ class DownloadManager(downloads.AbstractDownloadManager): """ # WORKAROUND for Qt corrupting data loaded from cache: # https://bugreports.qt.io/browse/QTBUG-42757 - request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, - QtNetwork.QNetworkRequest.AlwaysNetwork) + request.setAttribute( + QtNetwork.QNetworkRequest.CacheLoadControlAttribute, + QtNetwork.QNetworkRequest.AlwaysNetwork, + ) if suggested_fn is None: suggested_fn = self._get_suggested_filename(request) diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index c2fc257fc..fb9bc7c55 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -127,8 +127,9 @@ def data_for_url(url: QtCore.QUrl) -> Tuple[str, bytes]: A (mimetype, data) tuple. """ norm_url = url.adjusted( - QtCore.QUrl.NormalizePathSegments | # type: ignore[arg-type] - QtCore.QUrl.StripTrailingSlash) + QtCore.QUrl.NormalizePathSegments + | QtCore.QUrl.StripTrailingSlash # type: ignore[arg-type] + ) if norm_url != url: raise Redirect(norm_url) @@ -200,7 +201,10 @@ def qute_tabs(_url: QtCore.QUrl) -> _HandlerRet: scope='window', window=win_id) for tab in tabbed_browser.widgets(): - if tab.url() not in [QtCore.QUrl("qute://tabs/"), QtCore.QUrl("qute://tabs")]: + if tab.url() not in [ + QtCore.QUrl("qute://tabs/"), + QtCore.QUrl("qute://tabs"), + ]: urlstr = tab.url().toDisplayString() tabs[str(win_id)].append((tab.title(), urlstr)) diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index 1b1f1e3d3..d4fd379d3 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -158,11 +158,11 @@ def javascript_log_message(level, source, line, msg): def ignore_certificate_error( - *, - request_url: QtCore.QUrl, - first_party_url: QtCore.QUrl, - error: usertypes.AbstractCertificateErrorWrapper, - abort_on: Iterable[QtCore.pyqtBoundSignal], + *, + request_url: QtCore.QUrl, + first_party_url: QtCore.QUrl, + error: usertypes.AbstractCertificateErrorWrapper, + abort_on: Iterable[QtCore.pyqtBoundSignal], ) -> bool: """Display a certificate error question. @@ -182,11 +182,9 @@ def ignore_certificate_error( # We get the first party URL with a heuristic - with HTTP -> HTTPS redirects, the # scheme might not match. - is_resource = ( - first_party_url.isValid() and - not request_url.matches( - first_party_url, - QtCore.QUrl.RemoveScheme)) # type: ignore[arg-type] + is_resource = first_party_url.isValid() and not request_url.matches( + first_party_url, QtCore.QUrl.RemoveScheme + ) # type: ignore[arg-type] if conf == 'ask' or conf == 'ask-block-thirdparty' and not is_resource: err_template = jinja.environment.from_string(""" @@ -217,10 +215,16 @@ def ignore_certificate_error( ) urlstr = request_url.toString( - QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded) # type: ignore[arg-type] - ignore = message.ask(title="Certificate error", text=msg, - mode=usertypes.PromptMode.yesno, default=False, - abort_on=abort_on, url=urlstr) + QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded + ) # type: ignore[arg-type] + ignore = message.ask( + title="Certificate error", + text=msg, + mode=usertypes.PromptMode.yesno, + default=False, + abort_on=abort_on, + url=urlstr, + ) if ignore is None: # prompt aborted ignore = False diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index a79af7c02..d47e84c02 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -143,8 +143,9 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a """Insert the given text into the element.""" raise NotImplementedError - def rect_on_view(self, *, elem_geometry: QtCore.QRect = None, - no_js: bool = False) -> QtCore.QRect: + def rect_on_view( + self, *, elem_geometry: QtCore.QRect = None, no_js: bool = False + ) -> QtCore.QRect: """Get the geometry of the element relative to the webview. Args: @@ -336,8 +337,11 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a """Move cursor to end after clicking.""" raise NotImplementedError - def _click_fake_event(self, click_target: usertypes.ClickTarget, - button: QtCore.Qt.MouseButton = QtCore.Qt.LeftButton) -> None: + def _click_fake_event( + self, + click_target: usertypes.ClickTarget, + button: QtCore.Qt.MouseButton = QtCore.Qt.LeftButton, + ) -> None: """Send a fake click event to the element.""" pos = self._mouse_pos() @@ -346,7 +350,8 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a target_modifiers = { usertypes.ClickTarget.normal: QtCore.Qt.NoModifier, - usertypes.ClickTarget.window: QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, + usertypes.ClickTarget.window: QtCore.Qt.AltModifier + | QtCore.Qt.ShiftModifier, usertypes.ClickTarget.tab: QtCore.Qt.ControlModifier, usertypes.ClickTarget.tab_bg: QtCore.Qt.ControlModifier, } @@ -358,9 +363,23 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a modifiers = cast(QtCore.Qt.KeyboardModifiers, target_modifiers[click_target]) events = [ - QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier), - QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, pos, button, button, modifiers), - QtGui.QMouseEvent(QtCore.QEvent.MouseButtonRelease, pos, button, QtCore.Qt.NoButton, modifiers), + QtGui.QMouseEvent( + QtCore.QEvent.MouseMove, + pos, + QtCore.Qt.NoButton, + QtCore.Qt.NoButton, + QtCore.Qt.NoModifier, + ), + QtGui.QMouseEvent( + QtCore.QEvent.MouseButtonPress, pos, button, button, modifiers + ), + QtGui.QMouseEvent( + QtCore.QEvent.MouseButtonRelease, + pos, + button, + QtCore.Qt.NoButton, + modifiers, + ), ] for evt in events: @@ -444,11 +463,17 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a def hover(self) -> None: """Simulate a mouse hover over the element.""" pos = self._mouse_pos() - event = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, QtCore.Qt.NoButton, - QtCore.Qt.NoModifier) + event = QtGui.QMouseEvent( + QtCore.QEvent.MouseMove, + pos, + QtCore.Qt.NoButton, + QtCore.Qt.NoButton, + QtCore.Qt.NoModifier, + ) self._tab.send_event(event) def right_click(self) -> None: """Simulate a right-click on the element.""" - self._click_fake_event(usertypes.ClickTarget.normal, - button=QtCore.Qt.RightButton) + self._click_fake_event( + usertypes.ClickTarget.normal, button=QtCore.Qt.RightButton + ) diff --git a/qutebrowser/browser/webengine/certificateerror.py b/qutebrowser/browser/webengine/certificateerror.py index d057c47f3..e6427163b 100644 --- a/qutebrowser/browser/webengine/certificateerror.py +++ b/qutebrowser/browser/webengine/certificateerror.py @@ -38,8 +38,11 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): def __repr__(self) -> str: return utils.get_repr( self, - error=debug.qenum_key(QtWebEngineWidgets.QWebEngineCertificateError, self._error.error()), - string=str(self)) + error=debug.qenum_key( + QtWebEngineWidgets.QWebEngineCertificateError, self._error.error() + ), + string=str(self), + ) def url(self) -> QtCore.QUrl: return self._error.url() diff --git a/qutebrowser/browser/webengine/interceptor.py b/qutebrowser/browser/webengine/interceptor.py index 91557f4df..7f24eebd4 100644 --- a/qutebrowser/browser/webengine/interceptor.py +++ b/qutebrowser/browser/webengine/interceptor.py @@ -31,7 +31,10 @@ class WebEngineRequest(interceptors.Request): """QtWebEngine-specific request interceptor functionality.""" - _WHITELISTED_REQUEST_METHODS = {QtCore.QByteArray(b'GET'), QtCore.QByteArray(b'HEAD')} + _WHITELISTED_REQUEST_METHODS = { + QtCore.QByteArray(b'GET'), + QtCore.QByteArray(b'HEAD'), + } def __init__(self, *args, webengine_info, **kwargs): super().__init__(*args, **kwargs) @@ -68,51 +71,34 @@ class RequestInterceptor(QtWebEngineCore.QWebEngineUrlRequestInterceptor): # extension ResourceTypes. If a ResourceType is added to Qt, this table # should be updated too. self._resource_types = { - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeMainFrame: - interceptors.ResourceType.main_frame, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSubFrame: - interceptors.ResourceType.sub_frame, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeStylesheet: - interceptors.ResourceType.stylesheet, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeScript: - interceptors.ResourceType.script, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeImage: - interceptors.ResourceType.image, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeFontResource: - interceptors.ResourceType.font_resource, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSubResource: - interceptors.ResourceType.sub_resource, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeObject: - interceptors.ResourceType.object, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeMedia: - interceptors.ResourceType.media, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeWorker: - interceptors.ResourceType.worker, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSharedWorker: - interceptors.ResourceType.shared_worker, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePrefetch: - interceptors.ResourceType.prefetch, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeFavicon: - interceptors.ResourceType.favicon, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeXhr: - interceptors.ResourceType.xhr, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePing: - interceptors.ResourceType.ping, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeServiceWorker: - interceptors.ResourceType.service_worker, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeCspReport: - interceptors.ResourceType.csp_report, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePluginResource: - interceptors.ResourceType.plugin_resource, - QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeUnknown: - interceptors.ResourceType.unknown, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeMainFrame: interceptors.ResourceType.main_frame, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSubFrame: interceptors.ResourceType.sub_frame, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeStylesheet: interceptors.ResourceType.stylesheet, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeScript: interceptors.ResourceType.script, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeImage: interceptors.ResourceType.image, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeFontResource: interceptors.ResourceType.font_resource, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSubResource: interceptors.ResourceType.sub_resource, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeObject: interceptors.ResourceType.object, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeMedia: interceptors.ResourceType.media, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeWorker: interceptors.ResourceType.worker, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeSharedWorker: interceptors.ResourceType.shared_worker, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePrefetch: interceptors.ResourceType.prefetch, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeFavicon: interceptors.ResourceType.favicon, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeXhr: interceptors.ResourceType.xhr, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePing: interceptors.ResourceType.ping, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeServiceWorker: interceptors.ResourceType.service_worker, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeCspReport: interceptors.ResourceType.csp_report, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypePluginResource: interceptors.ResourceType.plugin_resource, + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeUnknown: interceptors.ResourceType.unknown, } try: - preload_main_frame = (QtWebEngineCore.QWebEngineUrlRequestInfo. - ResourceTypeNavigationPreloadMainFrame) - preload_sub_frame = (QtWebEngineCore.QWebEngineUrlRequestInfo. - ResourceTypeNavigationPreloadSubFrame) + preload_main_frame = ( + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeNavigationPreloadMainFrame + ) + preload_sub_frame = ( + QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeNavigationPreloadSubFrame + ) except AttributeError: # Added in Qt 5.14 pass @@ -149,16 +135,22 @@ class RequestInterceptor(QtWebEngineCore.QWebEngineUrlRequestInterceptor): info: QWebEngineUrlRequestInfo &info """ if 'log-requests' in objects.debug_flags: - resource_type_str = debug.qenum_key(QtWebEngineCore.QWebEngineUrlRequestInfo, - info.resourceType()) - navigation_type_str = debug.qenum_key(QtWebEngineCore.QWebEngineUrlRequestInfo, - info.navigationType()) - log.network.debug("{} {}, first-party {}, resource {}, " - "navigation {}".format( - bytes(info.requestMethod()).decode('ascii'), - info.requestUrl().toDisplayString(), - info.firstPartyUrl().toDisplayString(), - resource_type_str, navigation_type_str)) + resource_type_str = debug.qenum_key( + QtWebEngineCore.QWebEngineUrlRequestInfo, info.resourceType() + ) + navigation_type_str = debug.qenum_key( + QtWebEngineCore.QWebEngineUrlRequestInfo, info.navigationType() + ) + log.network.debug( + "{} {}, first-party {}, resource {}, " + "navigation {}".format( + bytes(info.requestMethod()).decode('ascii'), + info.requestUrl().toDisplayString(), + info.firstPartyUrl().toDisplayString(), + resource_type_str, + navigation_type_str, + ) + ) url = info.requestUrl() first_party = info.firstPartyUrl() @@ -173,12 +165,18 @@ class RequestInterceptor(QtWebEngineCore.QWebEngineUrlRequestInterceptor): resource_type = self._resource_types[info.resourceType()] except KeyError: log.network.warning( - "Resource type {} not found in RequestInterceptor dict." - .format(debug.qenum_key(QtWebEngineCore.QWebEngineUrlRequestInfo, - info.resourceType()))) + "Resource type {} not found in RequestInterceptor dict.".format( + debug.qenum_key( + QtWebEngineCore.QWebEngineUrlRequestInfo, info.resourceType() + ) + ) + ) resource_type = interceptors.ResourceType.unknown - is_xhr = info.resourceType() == QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeXhr + is_xhr = ( + info.resourceType() + == QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceTypeXhr + ) if ((url.scheme(), url.host(), url.path()) == ('qute', 'settings', '/set')): diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py index a5ba56b62..8a30e70ba 100644 --- a/qutebrowser/browser/webengine/notification.py +++ b/qutebrowser/browser/webengine/notification.py @@ -167,7 +167,9 @@ class NotificationBridgePresenter(QtCore.QObject): super().__init__(parent) assert _notifications_supported() - self._active_notifications: Dict[int, 'QtWebEngineCore.QWebEngineNotification'] = {} + self._active_notifications: Dict[ + int, 'QtWebEngineCore.QWebEngineNotification' + ] = {} self._adapter: Optional[AbstractNotificationAdapter] = None config.instance.changed.connect(self._init_adapter) @@ -233,14 +235,18 @@ class NotificationBridgePresenter(QtCore.QObject): # its refcount to prevent it from getting GC'd. Otherwise, random # methods start getting called with the notification as `self`, or # segfaults happen, or other badness. - def _present_and_reset(qt_notification: "QtWebEngineCore.QWebEngineNotification") -> None: + def _present_and_reset( + qt_notification: "QtWebEngineCore.QWebEngineNotification", + ) -> None: profile.setNotificationPresenter(_present_and_reset) self.present(qt_notification) profile.setNotificationPresenter(_present_and_reset) else: profile.setNotificationPresenter(self.present) - def present(self, qt_notification: "QtWebEngineCore.QWebEngineNotification") -> None: + def present( + self, qt_notification: "QtWebEngineCore.QWebEngineNotification" + ) -> None: """Show a notification using the configured adapter. Lazily initializes a suitable adapter if none exists yet. @@ -359,7 +365,9 @@ class NotificationBridgePresenter(QtCore.QObject): return self._focus_first_matching_tab(notification) - def _focus_first_matching_tab(self, notification: "QtWebEngineCore.QWebEngineNotification") -> None: + def _focus_first_matching_tab( + self, notification: "QtWebEngineCore.QWebEngineNotification" + ) -> None: for win_id in objreg.window_registry: tabbedbrowser = objreg.get("tabbed-browser", window=win_id, scope="window") for idx, tab in enumerate(tabbedbrowser.widgets()): @@ -520,7 +528,9 @@ class MessagesNotificationAdapter(AbstractNotificationAdapter): def on_web_closed(self, _notification_id: int) -> None: """We can't close messages.""" - def _format_message(self, qt_notification: "QtWebEngineCore.QWebEngineNotification") -> str: + def _format_message( + self, qt_notification: "QtWebEngineCore.QWebEngineNotification" + ) -> str: title = html.escape(qt_notification.title()) body = html.escape(qt_notification.message()) hint = "" if qt_notification.icon().isNull() else " (image not shown)" @@ -596,7 +606,9 @@ class HerbeNotificationAdapter(AbstractNotificationAdapter): if not qt_notification.icon().isNull(): yield "(icon not shown)" - def _on_finished(self, pid: int, code: int, status: QtCore.QProcess.ExitStatus) -> None: + def _on_finished( + self, pid: int, code: int, status: QtCore.QProcess.ExitStatus + ) -> None: """Handle a closing herbe process. From the GitHub page: @@ -919,7 +931,9 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): typ = msg.type() if typ != expected_type: type_str = debug.qenum_key(QtDBus.QDBusMessage.MessageType, typ) - expected_type_str = debug.qenum_key(QtDBus.QDBusMessage.MessageType, expected_type) + expected_type_str = debug.qenum_key( + QtDBus.QDBusMessage.MessageType, expected_type + ) raise Error( f"Got a message of type {type_str} but expected {expected_type_str}" f"(args: {msg.arguments()})") diff --git a/qutebrowser/browser/webengine/webenginedownloads.py b/qutebrowser/browser/webengine/webenginedownloads.py index 2bae19952..a2df805d4 100644 --- a/qutebrowser/browser/webengine/webenginedownloads.py +++ b/qutebrowser/browser/webengine/webenginedownloads.py @@ -38,9 +38,12 @@ class DownloadItem(downloads.AbstractDownloadItem): _qt_item: The wrapped item. """ - def __init__(self, qt_item: QtWebEngineWidgets.QWebEngineDownloadItem, - manager: downloads.AbstractDownloadManager, - parent: QtCore.QObject = None) -> None: + def __init__( + self, + qt_item: QtWebEngineWidgets.QWebEngineDownloadItem, + manager: downloads.AbstractDownloadManager, + parent: QtCore.QObject = None, + ) -> None: super().__init__(manager=manager, parent=manager) self._qt_item = qt_item qt_item.downloadProgress.connect( # type: ignore[attr-defined] @@ -54,8 +57,10 @@ class DownloadItem(downloads.AbstractDownloadItem): def _is_page_download(self): """Check if this item is a page (i.e. mhtml) download.""" - return (self._qt_item.savePageFormat() != - QtWebEngineWidgets.QWebEngineDownloadItem.UnknownSaveFormat) + return ( + self._qt_item.savePageFormat() + != QtWebEngineWidgets.QWebEngineDownloadItem.UnknownSaveFormat + ) @QtCore.pyqtSlot(QtWebEngineWidgets.QWebEngineDownloadItem.DownloadState) def _on_state_changed(self, state): @@ -92,14 +97,19 @@ class DownloadItem(downloads.AbstractDownloadItem): def _do_die(self): progress_signal = self._qt_item.downloadProgress progress_signal.disconnect() # type: ignore[attr-defined] - if self._qt_item.state() != QtWebEngineWidgets.QWebEngineDownloadItem.DownloadInterrupted: + if ( + self._qt_item.state() + != QtWebEngineWidgets.QWebEngineDownloadItem.DownloadInterrupted + ): self._qt_item.cancel() def _do_cancel(self): state = self._qt_item.state() state_name = debug.qenum_key(QtWebEngineWidgets.QWebEngineDownloadItem, state) - assert state not in [QtWebEngineWidgets.QWebEngineDownloadItem.DownloadCompleted, - QtWebEngineWidgets.QWebEngineDownloadItem.DownloadCancelled], state_name + assert state not in [ + QtWebEngineWidgets.QWebEngineDownloadItem.DownloadCompleted, + QtWebEngineWidgets.QWebEngineDownloadItem.DownloadCancelled, + ], state_name self._qt_item.cancel() def retry(self): @@ -107,7 +117,9 @@ class DownloadItem(downloads.AbstractDownloadItem): if state != QtWebEngineWidgets.QWebEngineDownloadItem.DownloadInterrupted: log.downloads.warning( "Refusing to retry download in state {}".format( - debug.qenum_key(QtWebEngineWidgets.QWebEngineDownloadItem, state))) + debug.qenum_key(QtWebEngineWidgets.QWebEngineDownloadItem, state) + ) + ) return self._qt_item.resume() @@ -133,10 +145,13 @@ class DownloadItem(downloads.AbstractDownloadItem): def _ensure_can_set_filename(self, filename): state = self._qt_item.state() if state != QtWebEngineWidgets.QWebEngineDownloadItem.DownloadRequested: - state_name = debug.qenum_key(QtWebEngineWidgets.QWebEngineDownloadItem, state) - raise ValueError("Trying to set filename {} on {!r} which is " - "state {} (not in requested state)!".format( - filename, self, state_name)) + state_name = debug.qenum_key( + QtWebEngineWidgets.QWebEngineDownloadItem, state + ) + raise ValueError( + "Trying to set filename {} on {!r} which is " + "state {} (not in requested state)!".format(filename, self, state_name) + ) def _ask_confirm_question(self, title, msg, *, custom_yes_action=None): yes_action = custom_yes_action or self._after_set_filename @@ -245,8 +260,9 @@ class DownloadManager(downloads.AbstractDownloadManager): def install(self, profile): """Set up the download manager on a QWebEngineProfile.""" - profile.downloadRequested.connect(self.handle_download, - QtCore.Qt.DirectConnection) + profile.downloadRequested.connect( + self.handle_download, QtCore.Qt.DirectConnection + ) @QtCore.pyqtSlot(QtWebEngineWidgets.QWebEngineDownloadItem) def handle_download(self, qt_item): diff --git a/qutebrowser/browser/webengine/webengineelem.py b/qutebrowser/browser/webengine/webengineelem.py index 8068e2278..b195551e6 100644 --- a/qutebrowser/browser/webengine/webengineelem.py +++ b/qutebrowser/browser/webengine/webengineelem.py @@ -162,8 +162,9 @@ class WebEngineElement(webelem.AbstractWebElement): log.webelem.debug("Inserting text into element {!r}".format(self)) self._js_call('insert_text', text) - def rect_on_view(self, *, elem_geometry: QtCore.QRect = None, - no_js: bool = False) -> QtCore.QRect: + def rect_on_view( + self, *, elem_geometry: QtCore.QRect = None, no_js: bool = False + ) -> QtCore.QRect: """Get the geometry of the element relative to the webview. Skipping of small rectangles is due to <a> elements containing other @@ -192,8 +193,12 @@ class WebEngineElement(webelem.AbstractWebElement): # We're not checking for zoom.text_only here as that doesn't # exist for QtWebEngine. zoom = self._tab.zoom.factor() - rect = QtCore.QRect(int(left * zoom), int(top * zoom), - int(width * zoom), int(height * zoom)) + rect = QtCore.QRect( + int(left * zoom), + int(top * zoom), + int(width * zoom), + int(height * zoom), + ) # FIXME:qtwebengine # frame = self._elem.webFrame() # while frame is not None: @@ -248,8 +253,9 @@ class WebEngineElement(webelem.AbstractWebElement): # This is also used in Qt's tests: # https://github.com/qt/qtwebengine/commit/5e572e88efa7ba7c2b9138ec19e606d3e345ac90 QtWidgets.QApplication.processEvents( # type: ignore[call-overload] - QtCore.QEventLoop.ExcludeSocketNotifiers | - QtCore.QEventLoop.ExcludeUserInputEvents) + QtCore.QEventLoop.ExcludeSocketNotifiers + | QtCore.QEventLoop.ExcludeUserInputEvents + ) def reset_setting(_arg: Any) -> None: """Set the JavascriptCanOpenWindows setting to its old value.""" diff --git a/qutebrowser/browser/webengine/webengineinspector.py b/qutebrowser/browser/webengine/webengineinspector.py index a7384913a..4cdd564d8 100644 --- a/qutebrowser/browser/webengine/webengineinspector.py +++ b/qutebrowser/browser/webengine/webengineinspector.py @@ -38,8 +38,9 @@ class WebEngineInspectorView(QtWebEngineWidgets.QWebEngineView): customization which doesn't apply to the inspector. """ - def createWindow(self, - wintype: QtWebEngineWidgets.QWebEnginePage.WebWindowType) -> QtWebEngineWidgets.QWebEngineView: + def createWindow( + self, wintype: QtWebEngineWidgets.QWebEnginePage.WebWindowType + ) -> QtWebEngineWidgets.QWebEngineView: """Called by Qt when a page wants to create a new tab or window. In case the user wants to open a resource in a new tab, we use the @@ -54,9 +55,12 @@ class WebEngineInspector(inspector.AbstractWebInspector): """A web inspector for QtWebEngine with Qt API support.""" - def __init__(self, splitter: miscwidgets.InspectorSplitter, - win_id: int, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + splitter: miscwidgets.InspectorSplitter, + win_id: int, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(splitter, win_id, parent) self._check_devtools_resources() @@ -87,7 +91,9 @@ class WebEngineInspector(inspector.AbstractWebInspector): if dist is None or dist.parsed != version.Distribution.fedora: return - data_path = pathlib.Path(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.DataPath)) + data_path = pathlib.Path( + QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.DataPath) + ) pak = data_path / 'resources' / 'qtwebengine_devtools_resources.pak' if not pak.exists(): raise inspector.Error("QtWebEngine devtools resources not found, " diff --git a/qutebrowser/browser/webengine/webenginequtescheme.py b/qutebrowser/browser/webengine/webenginequtescheme.py index 0a21d967f..8e15dd1ad 100644 --- a/qutebrowser/browser/webengine/webenginequtescheme.py +++ b/qutebrowser/browser/webengine/webenginequtescheme.py @@ -93,16 +93,11 @@ class QuteSchemeHandler(QtWebEngineCore.QWebEngineUrlSchemeHandler): mimetype, data = qutescheme.data_for_url(url) except qutescheme.Error as e: errors = { - qutescheme.NotFoundError: - QtWebEngineCore.QWebEngineUrlRequestJob.UrlNotFound, - qutescheme.UrlInvalidError: - QtWebEngineCore.QWebEngineUrlRequestJob.UrlInvalid, - qutescheme.RequestDeniedError: - QtWebEngineCore.QWebEngineUrlRequestJob.RequestDenied, - qutescheme.SchemeOSError: - QtWebEngineCore.QWebEngineUrlRequestJob.UrlNotFound, - qutescheme.Error: - QtWebEngineCore.QWebEngineUrlRequestJob.RequestFailed, + qutescheme.NotFoundError: QtWebEngineCore.QWebEngineUrlRequestJob.UrlNotFound, + qutescheme.UrlInvalidError: QtWebEngineCore.QWebEngineUrlRequestJob.UrlInvalid, + qutescheme.RequestDeniedError: QtWebEngineCore.QWebEngineUrlRequestJob.RequestDenied, + qutescheme.SchemeOSError: QtWebEngineCore.QWebEngineUrlRequestJob.UrlNotFound, + qutescheme.Error: QtWebEngineCore.QWebEngineUrlRequestJob.RequestFailed, } exctype = type(e) log.network.error(f"{exctype.__name__} while handling qute://* URL: {e}") @@ -134,6 +129,7 @@ def init(): assert not QtWebEngineCore.QWebEngineUrlScheme.schemeByName(b'qute').name() scheme = QtWebEngineCore.QWebEngineUrlScheme(b'qute') scheme.setFlags( - QtWebEngineCore.QWebEngineUrlScheme.LocalScheme | # type: ignore[arg-type] - QtWebEngineCore.QWebEngineUrlScheme.LocalAccessAllowed) + QtWebEngineCore.QWebEngineUrlScheme.LocalScheme + | QtWebEngineCore.QWebEngineUrlScheme.LocalAccessAllowed # type: ignore[arg-type] + ) QtWebEngineCore.QWebEngineUrlScheme.registerScheme(scheme) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 55cbd3f08..ca544a67e 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -107,65 +107,68 @@ class WebEngineSettings(websettings.AbstractSettings): """A wrapper for the config for QWebEngineSettings.""" _ATTRIBUTES = { - 'content.xss_auditing': - Attr(QtWebEngineWidgets.QWebEngineSettings.XSSAuditingEnabled), - 'content.images': - Attr(QtWebEngineWidgets.QWebEngineSettings.AutoLoadImages), - 'content.javascript.enabled': - Attr(QtWebEngineWidgets.QWebEngineSettings.JavascriptEnabled), - 'content.javascript.can_open_tabs_automatically': - Attr(QtWebEngineWidgets.QWebEngineSettings.JavascriptCanOpenWindows), - 'content.javascript.can_access_clipboard': - Attr(QtWebEngineWidgets.QWebEngineSettings.JavascriptCanAccessClipboard), - 'content.plugins': - Attr(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled), - 'content.hyperlink_auditing': - Attr(QtWebEngineWidgets.QWebEngineSettings.HyperlinkAuditingEnabled), - 'content.local_content_can_access_remote_urls': - Attr(QtWebEngineWidgets.QWebEngineSettings.LocalContentCanAccessRemoteUrls), - 'content.local_content_can_access_file_urls': - Attr(QtWebEngineWidgets.QWebEngineSettings.LocalContentCanAccessFileUrls), - 'content.webgl': - Attr(QtWebEngineWidgets.QWebEngineSettings.WebGLEnabled), - 'content.local_storage': - Attr(QtWebEngineWidgets.QWebEngineSettings.LocalStorageEnabled), - 'content.desktop_capture': - Attr(QtWebEngineWidgets.QWebEngineSettings.ScreenCaptureEnabled, - converter=lambda val: True if val == 'ask' else val), + 'content.xss_auditing': Attr( + QtWebEngineWidgets.QWebEngineSettings.XSSAuditingEnabled + ), + 'content.images': Attr(QtWebEngineWidgets.QWebEngineSettings.AutoLoadImages), + 'content.javascript.enabled': Attr( + QtWebEngineWidgets.QWebEngineSettings.JavascriptEnabled + ), + 'content.javascript.can_open_tabs_automatically': Attr( + QtWebEngineWidgets.QWebEngineSettings.JavascriptCanOpenWindows + ), + 'content.javascript.can_access_clipboard': Attr( + QtWebEngineWidgets.QWebEngineSettings.JavascriptCanAccessClipboard + ), + 'content.plugins': Attr(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled), + 'content.hyperlink_auditing': Attr( + QtWebEngineWidgets.QWebEngineSettings.HyperlinkAuditingEnabled + ), + 'content.local_content_can_access_remote_urls': Attr( + QtWebEngineWidgets.QWebEngineSettings.LocalContentCanAccessRemoteUrls + ), + 'content.local_content_can_access_file_urls': Attr( + QtWebEngineWidgets.QWebEngineSettings.LocalContentCanAccessFileUrls + ), + 'content.webgl': Attr(QtWebEngineWidgets.QWebEngineSettings.WebGLEnabled), + 'content.local_storage': Attr( + QtWebEngineWidgets.QWebEngineSettings.LocalStorageEnabled + ), + 'content.desktop_capture': Attr( + QtWebEngineWidgets.QWebEngineSettings.ScreenCaptureEnabled, + converter=lambda val: True if val == 'ask' else val, + ), # 'ask' is handled via the permission system - - 'input.spatial_navigation': - Attr(QtWebEngineWidgets.QWebEngineSettings.SpatialNavigationEnabled), - 'input.links_included_in_focus_chain': - Attr(QtWebEngineWidgets.QWebEngineSettings.LinksIncludedInFocusChain), - - 'scrolling.smooth': - Attr(QtWebEngineWidgets.QWebEngineSettings.ScrollAnimatorEnabled), - - 'content.print_element_backgrounds': - Attr(QtWebEngineWidgets.QWebEngineSettings.PrintElementBackgrounds), - - 'content.autoplay': - Attr(QtWebEngineWidgets.QWebEngineSettings.PlaybackRequiresUserGesture, - converter=operator.not_), - - 'content.dns_prefetch': - Attr(QtWebEngineWidgets.QWebEngineSettings.DnsPrefetchEnabled), - - 'tabs.favicons.show': - Attr(QtWebEngineWidgets.QWebEngineSettings.AutoLoadIconsForPage, - converter=lambda val: val != 'never'), + 'input.spatial_navigation': Attr( + QtWebEngineWidgets.QWebEngineSettings.SpatialNavigationEnabled + ), + 'input.links_included_in_focus_chain': Attr( + QtWebEngineWidgets.QWebEngineSettings.LinksIncludedInFocusChain + ), + 'scrolling.smooth': Attr( + QtWebEngineWidgets.QWebEngineSettings.ScrollAnimatorEnabled + ), + 'content.print_element_backgrounds': Attr( + QtWebEngineWidgets.QWebEngineSettings.PrintElementBackgrounds + ), + 'content.autoplay': Attr( + QtWebEngineWidgets.QWebEngineSettings.PlaybackRequiresUserGesture, + converter=operator.not_, + ), + 'content.dns_prefetch': Attr( + QtWebEngineWidgets.QWebEngineSettings.DnsPrefetchEnabled + ), + 'tabs.favicons.show': Attr( + QtWebEngineWidgets.QWebEngineSettings.AutoLoadIconsForPage, + converter=lambda val: val != 'never', + ), } _FONT_SIZES = { - 'fonts.web.size.minimum': - QtWebEngineWidgets.QWebEngineSettings.MinimumFontSize, - 'fonts.web.size.minimum_logical': - QtWebEngineWidgets.QWebEngineSettings.MinimumLogicalFontSize, - 'fonts.web.size.default': - QtWebEngineWidgets.QWebEngineSettings.DefaultFontSize, - 'fonts.web.size.default_fixed': - QtWebEngineWidgets.QWebEngineSettings.DefaultFixedFontSize, + 'fonts.web.size.minimum': QtWebEngineWidgets.QWebEngineSettings.MinimumFontSize, + 'fonts.web.size.minimum_logical': QtWebEngineWidgets.QWebEngineSettings.MinimumLogicalFontSize, + 'fonts.web.size.default': QtWebEngineWidgets.QWebEngineSettings.DefaultFontSize, + 'fonts.web.size.default_fixed': QtWebEngineWidgets.QWebEngineSettings.DefaultFixedFontSize, } _FONT_FAMILIES = { @@ -178,12 +181,9 @@ class WebEngineSettings(websettings.AbstractSettings): } _UNKNOWN_URL_SCHEME_POLICY = { - 'disallow': - QtWebEngineWidgets.QWebEngineSettings.DisallowUnknownUrlSchemes, - 'allow-from-user-interaction': - QtWebEngineWidgets.QWebEngineSettings.AllowUnknownUrlSchemesFromUserInteraction, - 'allow-all': - QtWebEngineWidgets.QWebEngineSettings.AllowAllUnknownUrlSchemes, + 'disallow': QtWebEngineWidgets.QWebEngineSettings.DisallowUnknownUrlSchemes, + 'allow-from-user-interaction': QtWebEngineWidgets.QWebEngineSettings.AllowUnknownUrlSchemesFromUserInteraction, + 'allow-all': QtWebEngineWidgets.QWebEngineSettings.AllowAllUnknownUrlSchemes, } # Mapping from WebEngineSettings::initDefaults in @@ -263,12 +263,16 @@ class ProfileSetter: settings = self._profile.settings() settings.setAttribute( - QtWebEngineWidgets.QWebEngineSettings.FullScreenSupportEnabled, True) + QtWebEngineWidgets.QWebEngineSettings.FullScreenSupportEnabled, True + ) settings.setAttribute( - QtWebEngineWidgets.QWebEngineSettings.FocusOnNavigationEnabled, False) + QtWebEngineWidgets.QWebEngineSettings.FocusOnNavigationEnabled, False + ) try: - settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, False) + settings.setAttribute( + QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, False + ) except AttributeError: # Added in Qt 5.13 pass @@ -341,7 +345,9 @@ def _init_user_agent_str(ua): def init_user_agent(): - _init_user_agent_str(QtWebEngineWidgets.QWebEngineProfile.defaultProfile().httpUserAgent()) + _init_user_agent_str( + QtWebEngineWidgets.QWebEngineProfile.defaultProfile().httpUserAgent() + ) def _init_profile(profile: QtWebEngineWidgets.QWebEngineProfile) -> None: diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 38d8b5e7b..fa8d9288f 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -229,8 +229,13 @@ class WebEngineSearch(browsertab.AbstractSearch): found_text = 'found' if found else "didn't find" if flags: - flag_text = 'with flags {}'.format(debug.qflags_key( - QtWebEngineWidgets.QWebEnginePage, flags, klass=QtWebEngineWidgets.QWebEnginePage.FindFlag)) + flag_text = 'with flags {}'.format( + debug.qflags_key( + QtWebEngineWidgets.QWebEnginePage, + flags, + klass=QtWebEngineWidgets.QWebEnginePage.FindFlag, + ) + ) else: flag_text = '' log.webview.debug(' '.join([caller, found_text, text, flag_text]) @@ -659,8 +664,10 @@ class WebEngineHistoryPrivate(browsertab.AbstractHistoryPrivate): if cur_data is not None: if 'zoom' in cur_data: self._tab.zoom.set_factor(cur_data['zoom']) - if ('scroll-pos' in cur_data and - self._tab.scroller.pos_px() == QtCore.QPoint(0, 0)): + if ( + 'scroll-pos' in cur_data + and self._tab.scroller.pos_px() == QtCore.QPoint(0, 0) + ): self._tab.load_finished.connect(_on_load_finished) @@ -924,21 +931,27 @@ class _WebEnginePermissions(QtCore.QObject): """Ask the user for approval for geolocation/media/etc..""" page = self._widget.page() grant_permission = functools.partial( - page.setFeaturePermission, url, feature, - QtWebEngineWidgets.QWebEnginePage.PermissionGrantedByUser) + page.setFeaturePermission, + url, + feature, + QtWebEngineWidgets.QWebEnginePage.PermissionGrantedByUser, + ) deny_permission = functools.partial( - page.setFeaturePermission, url, feature, - QtWebEngineWidgets.QWebEnginePage.PermissionDeniedByUser) + page.setFeaturePermission, + url, + feature, + QtWebEngineWidgets.QWebEnginePage.PermissionDeniedByUser, + ) permission_str = debug.qenum_key(QtWebEngineWidgets.QWebEnginePage, feature) if not url.isValid(): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-85116 - is_qtbug = (qtutils.version_check('5.15.0', - compiled=False, - exact=True) and - self._tab.is_private and - feature == QtWebEngineWidgets.QWebEnginePage.Notifications) + is_qtbug = ( + qtutils.version_check('5.15.0', compiled=False, exact=True) + and self._tab.is_private + and feature == QtWebEngineWidgets.QWebEnginePage.Notifications + ) logger = log.webview.debug if is_qtbug else log.webview.warning logger("Ignoring feature permission {} for invalid URL {}".format( permission_str, url)) @@ -952,10 +965,13 @@ class _WebEnginePermissions(QtCore.QObject): return if ( - feature in [QtWebEngineWidgets.QWebEnginePage.DesktopVideoCapture, - QtWebEngineWidgets.QWebEnginePage.DesktopAudioVideoCapture] and - qtutils.version_check('5.13', compiled=False) and - not qtutils.version_check('5.13.2', compiled=False) + feature + in [ + QtWebEngineWidgets.QWebEnginePage.DesktopVideoCapture, + QtWebEngineWidgets.QWebEnginePage.DesktopAudioVideoCapture, + ] + and qtutils.version_check('5.13', compiled=False) + and not qtutils.version_check('5.13.2', compiled=False) ): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-78016 log.webview.warning("Ignoring desktop sharing request due to " @@ -1013,8 +1029,11 @@ class _Quirk: filename: str injection_point: QtWebEngineWidgets.QWebEngineScript.InjectionPoint = ( - QtWebEngineWidgets.QWebEngineScript.DocumentCreation) - world: QtWebEngineWidgets.QWebEngineScript.ScriptWorldId = QtWebEngineWidgets.QWebEngineScript.MainWorld + QtWebEngineWidgets.QWebEngineScript.DocumentCreation + ) + world: QtWebEngineWidgets.QWebEngineScript.ScriptWorldId = ( + QtWebEngineWidgets.QWebEngineScript.MainWorld + ) predicate: bool = True name: Optional[str] = None @@ -1052,10 +1071,15 @@ class _WebEngineScripts(QtCore.QObject): code = javascript.assemble('stylesheet', 'set_css', css) self._tab.run_js_async(code) - def _inject_js(self, name, js_code, *, - world=QtWebEngineWidgets.QWebEngineScript.ApplicationWorld, - injection_point=QtWebEngineWidgets.QWebEngineScript.DocumentCreation, - subframes=False): + def _inject_js( + self, + name, + js_code, + *, + world=QtWebEngineWidgets.QWebEngineScript.ApplicationWorld, + injection_point=QtWebEngineWidgets.QWebEngineScript.DocumentCreation, + subframes=False, + ): """Inject the given script to run early on a page load.""" script = QtWebEngineWidgets.QWebEngineScript() script.setInjectionPoint(injection_point) @@ -1169,7 +1193,9 @@ class _WebEngineScripts(QtCore.QObject): # NOTE that this needs to be done before setSourceCode, so that # QtWebEngine's parsing of GreaseMonkey tags will override it if there is a # @run-at comment. - new_script.setInjectionPoint(QtWebEngineWidgets.QWebEngineScript.DocumentReady) + new_script.setInjectionPoint( + QtWebEngineWidgets.QWebEngineScript.DocumentReady + ) new_script.setSourceCode(script.code()) new_script.setName(script.full_name()) @@ -1177,8 +1203,11 @@ class _WebEngineScripts(QtCore.QObject): if script.needs_document_end_workaround(): log.greasemonkey.debug( - f"Forcing @run-at document-end for {script.name}") - new_script.setInjectionPoint(QtWebEngineWidgets.QWebEngineScript.DocumentReady) + f"Forcing @run-at document-end for {script.name}" + ) + new_script.setInjectionPoint( + QtWebEngineWidgets.QWebEngineScript.DocumentReady + ) log.greasemonkey.debug(f'adding script: {new_script.name()}') page_scripts.insert(new_script) @@ -1353,7 +1382,9 @@ class WebEngineTab(browsertab.AbstractTab): def run_js_async(self, code, callback=None, *, world=None): world_id_type = Union[QtWebEngineWidgets.QWebEngineScript.ScriptWorldId, int] if world is None: - world_id: world_id_type = QtWebEngineWidgets.QWebEngineScript.ApplicationWorld + world_id: world_id_type = ( + QtWebEngineWidgets.QWebEngineScript.ApplicationWorld + ) elif isinstance(world, int): world_id = world if not 0 <= world_id <= qtutils.MAX_WORLD_ID: @@ -1429,7 +1460,8 @@ class WebEngineTab(browsertab.AbstractTab): title_url = QtCore.QUrl(url) title_url.setScheme('') title_url_str = title_url.toDisplayString( - QtCore.QUrl.RemoveScheme) # type: ignore[arg-type] + QtCore.QUrl.RemoveScheme + ) # type: ignore[arg-type] if title == title_url_str.strip('/'): title = "" @@ -1492,25 +1524,24 @@ class WebEngineTab(browsertab.AbstractTab): log.webview.debug("Renderer process PID for tab {}: {}" .format(self.tab_id, pid)) - @QtCore.pyqtSlot(QtWebEngineWidgets.QWebEnginePage.RenderProcessTerminationStatus, int) + @QtCore.pyqtSlot( + QtWebEngineWidgets.QWebEnginePage.RenderProcessTerminationStatus, int + ) def _on_render_process_terminated(self, status, exitcode): """Show an error when the renderer process terminated.""" - if (status == QtWebEngineWidgets.QWebEnginePage.AbnormalTerminationStatus and - exitcode == 256): + if ( + status == QtWebEngineWidgets.QWebEnginePage.AbnormalTerminationStatus + and exitcode == 256 + ): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-58697 status = QtWebEngineWidgets.QWebEnginePage.CrashedTerminationStatus status_map = { - QtWebEngineWidgets.QWebEnginePage.NormalTerminationStatus: - browsertab.TerminationStatus.normal, - QtWebEngineWidgets.QWebEnginePage.AbnormalTerminationStatus: - browsertab.TerminationStatus.abnormal, - QtWebEngineWidgets.QWebEnginePage.CrashedTerminationStatus: - browsertab.TerminationStatus.crashed, - QtWebEngineWidgets.QWebEnginePage.KilledTerminationStatus: - browsertab.TerminationStatus.killed, - -1: - browsertab.TerminationStatus.unknown, + QtWebEngineWidgets.QWebEnginePage.NormalTerminationStatus: browsertab.TerminationStatus.normal, + QtWebEngineWidgets.QWebEnginePage.AbnormalTerminationStatus: browsertab.TerminationStatus.abnormal, + QtWebEngineWidgets.QWebEnginePage.CrashedTerminationStatus: browsertab.TerminationStatus.crashed, + QtWebEngineWidgets.QWebEnginePage.KilledTerminationStatus: browsertab.TerminationStatus.killed, + -1: browsertab.TerminationStatus.unknown, } self.renderer_process_terminated.emit(status_map[status], exitcode) @@ -1603,9 +1634,9 @@ class WebEngineTab(browsertab.AbstractTab): # We can't really know when to show an error page, as the error might # have happened when loading some resource. - is_resource = ( - first_party_url.isValid() and - url.matches(first_party_url, QtCore.QUrl.RemoveScheme)) + is_resource = first_party_url.isValid() and url.matches( + first_party_url, QtCore.QUrl.RemoveScheme + ) if show_non_overr_cert_error and is_resource: self._show_error_page(url, str(error)) diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index bf9440c22..f6e266523 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -39,7 +39,9 @@ _QB_FILESELECTION_MODES = { # the public QWebEnginePage::FileSelectionMode enum). # However, QWebEnginePage::chooseFiles is still called with the matching value # (2) when a file input with "webkitdirectory" is used. - QtWebEngineWidgets.QWebEnginePage.FileSelectionMode(2): shared.FileSelectionMode.folder, + QtWebEngineWidgets.QWebEnginePage.FileSelectionMode( + 2 + ): shared.FileSelectionMode.folder, } @@ -218,28 +220,25 @@ class WebEnginePage(QtWebEngineWidgets.QWebEnginePage): } shared.javascript_log_message(level_map[level], source, line, msg) - def acceptNavigationRequest(self, - url: QtCore.QUrl, - typ: QtWebEngineWidgets.QWebEnginePage.NavigationType, - is_main_frame: bool) -> bool: + def acceptNavigationRequest( + self, + url: QtCore.QUrl, + typ: QtWebEngineWidgets.QWebEnginePage.NavigationType, + is_main_frame: bool, + ) -> bool: """Override acceptNavigationRequest to forward it to the tab API.""" type_map = { - QtWebEngineWidgets.QWebEnginePage.NavigationTypeLinkClicked: - usertypes.NavigationRequest.Type.link_clicked, - QtWebEngineWidgets.QWebEnginePage.NavigationTypeTyped: - usertypes.NavigationRequest.Type.typed, - QtWebEngineWidgets.QWebEnginePage.NavigationTypeFormSubmitted: - usertypes.NavigationRequest.Type.form_submitted, - QtWebEngineWidgets.QWebEnginePage.NavigationTypeBackForward: - usertypes.NavigationRequest.Type.back_forward, - QtWebEngineWidgets.QWebEnginePage.NavigationTypeReload: - usertypes.NavigationRequest.Type.reloaded, - QtWebEngineWidgets.QWebEnginePage.NavigationTypeOther: - usertypes.NavigationRequest.Type.other, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeLinkClicked: usertypes.NavigationRequest.Type.link_clicked, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeTyped: usertypes.NavigationRequest.Type.typed, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeFormSubmitted: usertypes.NavigationRequest.Type.form_submitted, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeBackForward: usertypes.NavigationRequest.Type.back_forward, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeReload: usertypes.NavigationRequest.Type.reloaded, + QtWebEngineWidgets.QWebEnginePage.NavigationTypeOther: usertypes.NavigationRequest.Type.other, } try: - type_map[QtWebEngineWidgets.QWebEnginePage.NavigationTypeRedirect] = ( - usertypes.NavigationRequest.Type.redirect) + type_map[ + QtWebEngineWidgets.QWebEnginePage.NavigationTypeRedirect + ] = usertypes.NavigationRequest.Type.redirect except AttributeError: # Added in Qt 5.14 pass diff --git a/qutebrowser/browser/webkit/certificateerror.py b/qutebrowser/browser/webkit/certificateerror.py index 569df3988..1099093af 100644 --- a/qutebrowser/browser/webkit/certificateerror.py +++ b/qutebrowser/browser/webkit/certificateerror.py @@ -39,8 +39,12 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): def __repr__(self) -> str: return utils.get_repr( self, - errors=[debug.qenum_key(QtNetwork.QSslError, err.error()) for err in self._errors], - string=str(self)) + errors=[ + debug.qenum_key(QtNetwork.QSslError, err.error()) + for err in self._errors + ], + string=str(self), + ) def __hash__(self) -> int: return hash(self._errors) diff --git a/qutebrowser/browser/webkit/network/networkmanager.py b/qutebrowser/browser/webkit/network/networkmanager.py index b5aaee394..5b95e3091 100644 --- a/qutebrowser/browser/webkit/network/networkmanager.py +++ b/qutebrowser/browser/webkit/network/networkmanager.py @@ -403,15 +403,18 @@ class NetworkManager(QtNetwork.QNetworkAccessManager): proxy_error = proxymod.application_factory.get_error() if proxy_error is not None: return networkreply.ErrorNetworkReply( - req, proxy_error, QtNetwork.QNetworkReply.UnknownProxyError, - self) + req, proxy_error, QtNetwork.QNetworkReply.UnknownProxyError, self + ) if not req.url().isValid(): log.network.debug("Ignoring invalid requested URL: {}".format( req.url().errorString())) return networkreply.ErrorNetworkReply( - req, "Invalid request URL", QtNetwork.QNetworkReply.HostNotFoundError, - self) + req, + "Invalid request URL", + QtNetwork.QNetworkReply.HostNotFoundError, + self, + ) for header, value in shared.custom_headers(url=req.url()): req.setRawHeader(header, value) @@ -430,8 +433,11 @@ class NetworkManager(QtNetwork.QNetworkAccessManager): interceptors.run(request) if request.is_blocked: return networkreply.ErrorNetworkReply( - req, HOSTBLOCK_ERROR_STRING, QtNetwork.QNetworkReply.ContentAccessDenied, - self) + req, + HOSTBLOCK_ERROR_STRING, + QtNetwork.QNetworkReply.ContentAccessDenied, + self, + ) if 'log-requests' in objects.debug_flags: operation = debug.qenum_key(QtNetwork.QNetworkAccessManager, op) diff --git a/qutebrowser/browser/webkit/network/networkreply.py b/qutebrowser/browser/webkit/network/networkreply.py index b29c6e5f2..3cb40ee53 100644 --- a/qutebrowser/browser/webkit/network/networkreply.py +++ b/qutebrowser/browser/webkit/network/networkreply.py @@ -50,8 +50,10 @@ class FixedDataNetworkReply(QtNetwork.QNetworkReply): self.setOpenMode(QtCore.QIODevice.ReadOnly) self.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, mimeType) - self.setHeader(QtNetwork.QNetworkRequest.ContentLengthHeader, - QtCore.QByteArray.number(len(fileData))) + self.setHeader( + QtNetwork.QNetworkRequest.ContentLengthHeader, + QtCore.QByteArray.number(len(fileData)), + ) self.setAttribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute, 200) self.setAttribute(QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute, 'OK') # For some reason, a segfault will be triggered if these lambdas aren't @@ -120,10 +122,12 @@ class ErrorNetworkReply(QtNetwork.QNetworkReply): # the device to avoid getting a warning. self.setOpenMode(QtCore.QIODevice.ReadOnly) self.setError(error, errorstring) - QtCore.QTimer.singleShot(0, lambda: - self.error.emit(error)) # type: ignore[attr-defined] - QtCore.QTimer.singleShot(0, lambda: - self.finished.emit()) # type: ignore[attr-defined] + QtCore.QTimer.singleShot( + 0, lambda: self.error.emit(error) + ) # type: ignore[attr-defined] + QtCore.QTimer.singleShot( + 0, lambda: self.finished.emit() + ) # type: ignore[attr-defined] def abort(self): """Do nothing since it's a fake reply.""" @@ -150,8 +154,9 @@ class RedirectNetworkReply(QtNetwork.QNetworkReply): def __init__(self, new_url, parent=None): super().__init__(parent) self.setAttribute(QtNetwork.QNetworkRequest.RedirectionTargetAttribute, new_url) - QtCore.QTimer.singleShot(0, lambda: - self.finished.emit()) # type: ignore[attr-defined] + QtCore.QTimer.singleShot( + 0, lambda: self.finished.emit() + ) # type: ignore[attr-defined] def abort(self): """Called when there's e.g. a redirection limit.""" diff --git a/qutebrowser/browser/webkit/network/webkitqutescheme.py b/qutebrowser/browser/webkit/network/webkitqutescheme.py index 0fdc3b772..cbd0baa18 100644 --- a/qutebrowser/browser/webkit/network/webkitqutescheme.py +++ b/qutebrowser/browser/webkit/network/webkitqutescheme.py @@ -39,8 +39,10 @@ def handler(request, operation, current_url): """ if operation != QtNetwork.QNetworkAccessManager.GetOperation: return networkreply.ErrorNetworkReply( - request, "Unsupported request type", - QtNetwork.QNetworkReply.ContentOperationNotPermittedError) + request, + "Unsupported request type", + QtNetwork.QNetworkReply.ContentOperationNotPermittedError, + ) url = request.url() @@ -51,23 +53,20 @@ def handler(request, operation, current_url): .format(current_url.toDisplayString(), url.toDisplayString())) return networkreply.ErrorNetworkReply( - request, "Invalid qute://settings request", - QtNetwork.QNetworkReply.ContentAccessDenied) + request, + "Invalid qute://settings request", + QtNetwork.QNetworkReply.ContentAccessDenied, + ) try: mimetype, data = qutescheme.data_for_url(url) except qutescheme.Error as e: errors = { - qutescheme.NotFoundError: - QtNetwork.QNetworkReply.ContentNotFoundError, - qutescheme.UrlInvalidError: - QtNetwork.QNetworkReply.ContentOperationNotPermittedError, - qutescheme.RequestDeniedError: - QtNetwork.QNetworkReply.ContentAccessDenied, - qutescheme.SchemeOSError: - QtNetwork.QNetworkReply.ContentNotFoundError, - qutescheme.Error: - QtNetwork.QNetworkReply.InternalServerError, + qutescheme.NotFoundError: QtNetwork.QNetworkReply.ContentNotFoundError, + qutescheme.UrlInvalidError: QtNetwork.QNetworkReply.ContentOperationNotPermittedError, + qutescheme.RequestDeniedError: QtNetwork.QNetworkReply.ContentAccessDenied, + qutescheme.SchemeOSError: QtNetwork.QNetworkReply.ContentNotFoundError, + qutescheme.Error: QtNetwork.QNetworkReply.InternalServerError, } exctype = type(e) log.misc.error("{} while handling qute://* URL".format( diff --git a/qutebrowser/browser/webkit/webkitelem.py b/qutebrowser/browser/webkit/webkitelem.py index 5b771f045..f78189c3d 100644 --- a/qutebrowser/browser/webkit/webkitelem.py +++ b/qutebrowser/browser/webkit/webkitelem.py @@ -210,8 +210,9 @@ class WebKitElement(webelem.AbstractWebElement): rect["top"] *= zoom width *= zoom height *= zoom - rect = QtCore.QRect(int(rect["left"]), int(rect["top"]), - int(width), int(height)) + rect = QtCore.QRect( + int(rect["left"]), int(rect["top"]), int(width), int(height) + ) frame = cast(Optional[QtWebKitWidgets.QWebFrame], self._elem.webFrame()) while frame is not None: @@ -224,7 +225,9 @@ class WebKitElement(webelem.AbstractWebElement): return None - def _rect_on_view_python(self, elem_geometry: Optional[QtCore.QRect]) -> QtCore.QRect: + def _rect_on_view_python( + self, elem_geometry: Optional[QtCore.QRect] + ) -> QtCore.QRect: """Python implementation for rect_on_view.""" if elem_geometry is None: geometry = self._elem.geometry() @@ -240,8 +243,9 @@ class WebKitElement(webelem.AbstractWebElement): return rect - def rect_on_view(self, *, elem_geometry: QtCore.QRect = None, - no_js: bool = False) -> QtCore.QRect: + def rect_on_view( + self, *, elem_geometry: QtCore.QRect = None, no_js: bool = False + ) -> QtCore.QRect: """Get the geometry of the element relative to the webview. Uses the getClientRects() JavaScript method to obtain the collection of @@ -369,13 +373,18 @@ class WebKitElement(webelem.AbstractWebElement): log.webelem.debug("Failed to click via JS, falling back to event") self._click_fake_event(click_target) - def _click_fake_event(self, click_target: usertypes.ClickTarget, - button: QtCore.Qt.MouseButton = QtCore.Qt.LeftButton) -> None: + def _click_fake_event( + self, + click_target: usertypes.ClickTarget, + button: QtCore.Qt.MouseButton = QtCore.Qt.LeftButton, + ) -> None: self._tab.data.override_target = click_target super()._click_fake_event(click_target) -def get_child_frames(startframe: QtWebKitWidgets.QWebFrame) -> List[QtWebKitWidgets.QWebFrame]: +def get_child_frames( + startframe: QtWebKitWidgets.QWebFrame, +) -> List[QtWebKitWidgets.QWebFrame]: """Get all children recursively of a given QWebFrame. Loosely based on https://blog.nextgenetics.net/?e=64 diff --git a/qutebrowser/browser/webkit/webkitinspector.py b/qutebrowser/browser/webkit/webkitinspector.py index a90673b2b..1e287e57b 100644 --- a/qutebrowser/browser/webkit/webkitinspector.py +++ b/qutebrowser/browser/webkit/webkitinspector.py @@ -29,9 +29,12 @@ class WebKitInspector(inspector.AbstractWebInspector): """A web inspector for QtWebKit.""" - def __init__(self, splitter: miscwidgets.InspectorSplitter, - win_id: int, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + splitter: miscwidgets.InspectorSplitter, + win_id: int, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(splitter, win_id, parent) qwebinspector = QtWebKitWidgets.QWebInspector() self._set_widget(qwebinspector) diff --git a/qutebrowser/browser/webkit/webkitsettings.py b/qutebrowser/browser/webkit/webkitsettings.py index 083dd7aeb..3747cbade 100644 --- a/qutebrowser/browser/webkit/webkitsettings.py +++ b/qutebrowser/browser/webkit/webkitsettings.py @@ -46,62 +46,59 @@ class WebKitSettings(websettings.AbstractSettings): """A wrapper for the config for QWebSettings.""" _ATTRIBUTES = { - 'content.images': - Attr(QtWebKit.QWebSettings.AutoLoadImages), - 'content.javascript.enabled': - Attr(QtWebKit.QWebSettings.JavascriptEnabled), - 'content.javascript.can_open_tabs_automatically': - Attr(QtWebKit.QWebSettings.JavascriptCanOpenWindows), - 'content.javascript.can_close_tabs': - Attr(QtWebKit.QWebSettings.JavascriptCanCloseWindows), - 'content.javascript.can_access_clipboard': - Attr(QtWebKit.QWebSettings.JavascriptCanAccessClipboard), - 'content.plugins': - Attr(QtWebKit.QWebSettings.PluginsEnabled), - 'content.webgl': - Attr(QtWebKit.QWebSettings.WebGLEnabled), - 'content.hyperlink_auditing': - Attr(QtWebKit.QWebSettings.HyperlinkAuditingEnabled), - 'content.local_content_can_access_remote_urls': - Attr(QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls), - 'content.local_content_can_access_file_urls': - Attr(QtWebKit.QWebSettings.LocalContentCanAccessFileUrls), - 'content.dns_prefetch': - Attr(QtWebKit.QWebSettings.DnsPrefetchEnabled), - 'content.frame_flattening': - Attr(QtWebKit.QWebSettings.FrameFlatteningEnabled), - 'content.cache.appcache': - Attr(QtWebKit.QWebSettings.OfflineWebApplicationCacheEnabled), - 'content.local_storage': - Attr(QtWebKit.QWebSettings.LocalStorageEnabled, - QtWebKit.QWebSettings.OfflineStorageDatabaseEnabled), - 'content.print_element_backgrounds': - Attr(QtWebKit.QWebSettings.PrintElementBackgrounds), - 'content.xss_auditing': - Attr(QtWebKit.QWebSettings.XSSAuditingEnabled), - 'content.site_specific_quirks.enabled': - Attr(QtWebKit.QWebSettings.SiteSpecificQuirksEnabled), - - 'input.spatial_navigation': - Attr(QtWebKit.QWebSettings.SpatialNavigationEnabled), - 'input.links_included_in_focus_chain': - Attr(QtWebKit.QWebSettings.LinksIncludedInFocusChain), - - 'zoom.text_only': - Attr(QtWebKit.QWebSettings.ZoomTextOnly), - 'scrolling.smooth': - Attr(QtWebKit.QWebSettings.ScrollAnimatorEnabled), + 'content.images': Attr(QtWebKit.QWebSettings.AutoLoadImages), + 'content.javascript.enabled': Attr(QtWebKit.QWebSettings.JavascriptEnabled), + 'content.javascript.can_open_tabs_automatically': Attr( + QtWebKit.QWebSettings.JavascriptCanOpenWindows + ), + 'content.javascript.can_close_tabs': Attr( + QtWebKit.QWebSettings.JavascriptCanCloseWindows + ), + 'content.javascript.can_access_clipboard': Attr( + QtWebKit.QWebSettings.JavascriptCanAccessClipboard + ), + 'content.plugins': Attr(QtWebKit.QWebSettings.PluginsEnabled), + 'content.webgl': Attr(QtWebKit.QWebSettings.WebGLEnabled), + 'content.hyperlink_auditing': Attr( + QtWebKit.QWebSettings.HyperlinkAuditingEnabled + ), + 'content.local_content_can_access_remote_urls': Attr( + QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls + ), + 'content.local_content_can_access_file_urls': Attr( + QtWebKit.QWebSettings.LocalContentCanAccessFileUrls + ), + 'content.dns_prefetch': Attr(QtWebKit.QWebSettings.DnsPrefetchEnabled), + 'content.frame_flattening': Attr(QtWebKit.QWebSettings.FrameFlatteningEnabled), + 'content.cache.appcache': Attr( + QtWebKit.QWebSettings.OfflineWebApplicationCacheEnabled + ), + 'content.local_storage': Attr( + QtWebKit.QWebSettings.LocalStorageEnabled, + QtWebKit.QWebSettings.OfflineStorageDatabaseEnabled, + ), + 'content.print_element_backgrounds': Attr( + QtWebKit.QWebSettings.PrintElementBackgrounds + ), + 'content.xss_auditing': Attr(QtWebKit.QWebSettings.XSSAuditingEnabled), + 'content.site_specific_quirks.enabled': Attr( + QtWebKit.QWebSettings.SiteSpecificQuirksEnabled + ), + 'input.spatial_navigation': Attr( + QtWebKit.QWebSettings.SpatialNavigationEnabled + ), + 'input.links_included_in_focus_chain': Attr( + QtWebKit.QWebSettings.LinksIncludedInFocusChain + ), + 'zoom.text_only': Attr(QtWebKit.QWebSettings.ZoomTextOnly), + 'scrolling.smooth': Attr(QtWebKit.QWebSettings.ScrollAnimatorEnabled), } _FONT_SIZES = { - 'fonts.web.size.minimum': - QtWebKit.QWebSettings.MinimumFontSize, - 'fonts.web.size.minimum_logical': - QtWebKit.QWebSettings.MinimumLogicalFontSize, - 'fonts.web.size.default': - QtWebKit.QWebSettings.DefaultFontSize, - 'fonts.web.size.default_fixed': - QtWebKit.QWebSettings.DefaultFixedFontSize, + 'fonts.web.size.minimum': QtWebKit.QWebSettings.MinimumFontSize, + 'fonts.web.size.minimum_logical': QtWebKit.QWebSettings.MinimumLogicalFontSize, + 'fonts.web.size.default': QtWebKit.QWebSettings.DefaultFontSize, + 'fonts.web.size.default_fixed': QtWebKit.QWebSettings.DefaultFixedFontSize, } _FONT_FAMILIES = { diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index 5839ccfb8..6734ea974 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -128,8 +128,10 @@ class WebKitSearch(browsertab.AbstractSearch): # Removing FindWrapsAroundDocument to get the same logging as with # QtWebEngine debug_flags = debug.qflags_key( - QtWebKitWidgets.QWebPage, flags & ~QtWebKitWidgets.QWebPage.FindWrapsAroundDocument, - klass=QtWebKitWidgets.QWebPage.FindFlag) + QtWebKitWidgets.QWebPage, + flags & ~QtWebKitWidgets.QWebPage.FindWrapsAroundDocument, + klass=QtWebKitWidgets.QWebPage.FindFlag, + ) if debug_flags != '0x0000': flag_text = 'with flags {}'.format(debug_flags) else: @@ -167,8 +169,9 @@ class WebKitSearch(browsertab.AbstractSearch): # We actually search *twice* - once to highlight everything, then again # to get a mark so we can navigate. found = self._widget.findText(text, self._flags) - self._widget.findText(text, - self._flags | QtWebKitWidgets.QWebPage.HighlightAllOccurrences) + self._widget.findText( + text, self._flags | QtWebKitWidgets.QWebPage.HighlightAllOccurrences + ) self._call_cb(result_cb, found, text, self._flags, 'search') def next_result(self, *, result_cb=None): @@ -193,10 +196,12 @@ class WebKitCaret(browsertab.AbstractCaret): """QtWebKit implementations related to moving the cursor/selection.""" - def __init__(self, - tab: 'WebKitTab', - mode_manager: modeman.ModeManager, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + tab: 'WebKitTab', + mode_manager: modeman.ModeManager, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(tab, mode_manager, parent) self._selection_state = browsertab.SelectionState.none @@ -339,11 +344,15 @@ class WebKitCaret(browsertab.AbstractCaret): def move_to_start_of_next_block(self, count=1): if self._selection_state is not browsertab.SelectionState.none: - act = [QtWebKitWidgets.QWebPage.SelectNextLine, - QtWebKitWidgets.QWebPage.SelectStartOfBlock] + act = [ + QtWebKitWidgets.QWebPage.SelectNextLine, + QtWebKitWidgets.QWebPage.SelectStartOfBlock, + ] else: - act = [QtWebKitWidgets.QWebPage.MoveToNextLine, - QtWebKitWidgets.QWebPage.MoveToStartOfBlock] + act = [ + QtWebKitWidgets.QWebPage.MoveToNextLine, + QtWebKitWidgets.QWebPage.MoveToStartOfBlock, + ] for _ in range(count): for a in act: self._widget.triggerPageAction(a) @@ -352,11 +361,15 @@ class WebKitCaret(browsertab.AbstractCaret): def move_to_start_of_prev_block(self, count=1): if self._selection_state is not browsertab.SelectionState.none: - act = [QtWebKitWidgets.QWebPage.SelectPreviousLine, - QtWebKitWidgets.QWebPage.SelectStartOfBlock] + act = [ + QtWebKitWidgets.QWebPage.SelectPreviousLine, + QtWebKitWidgets.QWebPage.SelectStartOfBlock, + ] else: - act = [QtWebKitWidgets.QWebPage.MoveToPreviousLine, - QtWebKitWidgets.QWebPage.MoveToStartOfBlock] + act = [ + QtWebKitWidgets.QWebPage.MoveToPreviousLine, + QtWebKitWidgets.QWebPage.MoveToStartOfBlock, + ] for _ in range(count): for a in act: self._widget.triggerPageAction(a) @@ -365,11 +378,15 @@ class WebKitCaret(browsertab.AbstractCaret): def move_to_end_of_next_block(self, count=1): if self._selection_state is not browsertab.SelectionState.none: - act = [QtWebKitWidgets.QWebPage.SelectNextLine, - QtWebKitWidgets.QWebPage.SelectEndOfBlock] + act = [ + QtWebKitWidgets.QWebPage.SelectNextLine, + QtWebKitWidgets.QWebPage.SelectEndOfBlock, + ] else: - act = [QtWebKitWidgets.QWebPage.MoveToNextLine, - QtWebKitWidgets.QWebPage.MoveToEndOfBlock] + act = [ + QtWebKitWidgets.QWebPage.MoveToNextLine, + QtWebKitWidgets.QWebPage.MoveToEndOfBlock, + ] for _ in range(count): for a in act: self._widget.triggerPageAction(a) @@ -378,9 +395,15 @@ class WebKitCaret(browsertab.AbstractCaret): def move_to_end_of_prev_block(self, count=1): if self._selection_state is not browsertab.SelectionState.none: - act = [QtWebKitWidgets.QWebPage.SelectPreviousLine, QtWebKitWidgets.QWebPage.SelectEndOfBlock] + act = [ + QtWebKitWidgets.QWebPage.SelectPreviousLine, + QtWebKitWidgets.QWebPage.SelectEndOfBlock, + ] else: - act = [QtWebKitWidgets.QWebPage.MoveToPreviousLine, QtWebKitWidgets.QWebPage.MoveToEndOfBlock] + act = [ + QtWebKitWidgets.QWebPage.MoveToPreviousLine, + QtWebKitWidgets.QWebPage.MoveToEndOfBlock, + ] for _ in range(count): for a in act: self._widget.triggerPageAction(a) @@ -459,7 +482,8 @@ class WebKitCaret(browsertab.AbstractCaret): def _follow_selected(self, *, tab=False): if QtWebKit.QWebSettings.globalSettings().testAttribute( - QtWebKit.QWebSettings.JavascriptEnabled): + QtWebKit.QWebSettings.JavascriptEnabled + ): if tab: self._tab.data.override_target = usertypes.ClickTarget.tab self._tab.run_js_async(""" @@ -557,7 +581,10 @@ class WebKitScroller(browsertab.AbstractScroller): elif x is None and y == 100: self.bottom() else: - for val, orientation in [(x, QtCore.Qt.Horizontal), (y, QtCore.Qt.Vertical)]: + for val, orientation in [ + (x, QtCore.Qt.Horizontal), + (y, QtCore.Qt.Vertical), + ]: if val is not None: frame = self._widget.page().mainFrame() maximum = frame.scrollBarMaximum(orientation) @@ -585,13 +612,19 @@ class WebKitScroller(browsertab.AbstractScroller): self._key_press(QtCore.Qt.Key_Up, count, 'scrollBarMinimum', QtCore.Qt.Vertical) def down(self, count=1): - self._key_press(QtCore.Qt.Key_Down, count, 'scrollBarMaximum', QtCore.Qt.Vertical) + self._key_press( + QtCore.Qt.Key_Down, count, 'scrollBarMaximum', QtCore.Qt.Vertical + ) def left(self, count=1): - self._key_press(QtCore.Qt.Key_Left, count, 'scrollBarMinimum', QtCore.Qt.Horizontal) + self._key_press( + QtCore.Qt.Key_Left, count, 'scrollBarMinimum', QtCore.Qt.Horizontal + ) def right(self, count=1): - self._key_press(QtCore.Qt.Key_Right, count, 'scrollBarMaximum', QtCore.Qt.Horizontal) + self._key_press( + QtCore.Qt.Key_Right, count, 'scrollBarMaximum', QtCore.Qt.Horizontal + ) def top(self): self._key_press(QtCore.Qt.Key_Home) @@ -600,11 +633,14 @@ class WebKitScroller(browsertab.AbstractScroller): self._key_press(QtCore.Qt.Key_End) def page_up(self, count=1): - self._key_press(QtCore.Qt.Key_PageUp, count, 'scrollBarMinimum', QtCore.Qt.Vertical) + self._key_press( + QtCore.Qt.Key_PageUp, count, 'scrollBarMinimum', QtCore.Qt.Vertical + ) def page_down(self, count=1): - self._key_press(QtCore.Qt.Key_PageDown, count, 'scrollBarMaximum', - QtCore.Qt.Vertical) + self._key_press( + QtCore.Qt.Key_PageDown, count, 'scrollBarMaximum', QtCore.Qt.Vertical + ) def at_top(self): return self.pos_px().y() == 0 @@ -641,10 +677,16 @@ class WebKitHistoryPrivate(browsertab.AbstractHistoryPrivate): if cur_data is not None: if 'zoom' in cur_data: self._tab.zoom.set_factor(cur_data['zoom']) - if ('scroll-pos' in cur_data and - self._tab.scroller.pos_px() == QtCore.QPoint(0, 0)): - QtCore.QTimer.singleShot(0, functools.partial( - self._tab.scroller.to_point, cur_data['scroll-pos'])) + if ( + 'scroll-pos' in cur_data + and self._tab.scroller.pos_px() == QtCore.QPoint(0, 0) + ): + QtCore.QTimer.singleShot( + 0, + functools.partial( + self._tab.scroller.to_point, cur_data['scroll-pos'] + ), + ) class WebKitHistory(browsertab.AbstractHistory): @@ -699,7 +741,9 @@ class WebKitElements(browsertab.AbstractElements): elems = [] frames = webkitelem.get_child_frames(mainframe) for f in frames: - frame_elems = cast(Iterable[QtWebKit.QWebElement], f.findAllElements(selector)) + frame_elems = cast( + Iterable[QtWebKit.QWebElement], f.findAllElements(selector) + ) for elem in frame_elems: elems.append(webkitelem.WebKitElement(elem, tab=self._tab)) diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py index 90e30cb12..3c732a2dd 100644 --- a/qutebrowser/browser/webkit/webpage.py +++ b/qutebrowser/browser/webkit/webpage.py @@ -129,7 +129,10 @@ class BrowserPage(QtWebKitWidgets.QWebPage): False if no error page should be displayed, True otherwise. """ ignored_errors = [ - (QtWebKitWidgets.QWebPage.QtNetwork, QtNetwork.QNetworkReply.OperationCanceledError), + ( + QtWebKitWidgets.QWebPage.QtNetwork, + QtNetwork.QNetworkReply.OperationCanceledError, + ), # "Loading is handled by the media engine" (QtWebKitWidgets.QWebPage.WebKit, 203), # "Frame load interrupted by policy change" @@ -137,8 +140,10 @@ class BrowserPage(QtWebKitWidgets.QWebPage): ] errpage.baseUrl = info.url urlstr = info.url.toDisplayString() - if (info.domain, info.error) == (QtWebKitWidgets.QWebPage.QtNetwork, - QtNetwork.QNetworkReply.ProtocolUnknownError): + if (info.domain, info.error) == ( + QtWebKitWidgets.QWebPage.QtNetwork, + QtNetwork.QNetworkReply.ProtocolUnknownError, + ): # For some reason, we get a segfault when we use # QDesktopServices::openUrl with info.url directly - however it # works when we construct a copy of it. @@ -149,7 +154,10 @@ class BrowserPage(QtWebKitWidgets.QWebPage): text="URL: <b>{}</b>".format( html.escape(url.toDisplayString())), yes_action=functools.partial(QtGui.QDesktopServices.openUrl, url), - url=info.url.toString(QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded)) + url=info.url.toString( + QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded + ), + ) return True elif (info.domain, info.error) in ignored_errors: log.webview.debug("Ignored error on {}: {} (error domain: {}, " @@ -186,7 +194,9 @@ class BrowserPage(QtWebKitWidgets.QWebPage): errpage.encoding = 'utf-8' return True - def chooseFile(self, parent_frame: QtWebKitWidgets.QWebFrame, suggested_file: str) -> str: + def chooseFile( + self, parent_frame: QtWebKitWidgets.QWebFrame, suggested_file: str + ) -> str: """Override chooseFile to (optionally) invoke custom file uploader.""" handler = config.val.fileselect.handler if handler == "default": @@ -359,17 +369,27 @@ class BrowserPage(QtWebKitWidgets.QWebPage): QtWebKitWidgets.QWebPage.Geolocation: 'access your location', } yes_action = functools.partial( - self.setFeaturePermission, frame, feature, - QtWebKitWidgets.QWebPage.PermissionGrantedByUser) + self.setFeaturePermission, + frame, + feature, + QtWebKitWidgets.QWebPage.PermissionGrantedByUser, + ) no_action = functools.partial( - self.setFeaturePermission, frame, feature, - QtWebKitWidgets.QWebPage.PermissionDeniedByUser) - - url = frame.url().adjusted(cast(QtCore.QUrl.FormattingOptions, - QtCore.QUrl.RemoveUserInfo | - QtCore.QUrl.RemovePath | - QtCore.QUrl.RemoveQuery | - QtCore.QUrl.RemoveFragment)) + self.setFeaturePermission, + frame, + feature, + QtWebKitWidgets.QWebPage.PermissionDeniedByUser, + ) + + url = frame.url().adjusted( + cast( + QtCore.QUrl.FormattingOptions, + QtCore.QUrl.RemoveUserInfo + | QtCore.QUrl.RemovePath + | QtCore.QUrl.RemoveQuery + | QtCore.QUrl.RemoveFragment, + ) + ) question = shared.feature_permission( url=url, option=options[feature], msg=messages[feature], @@ -488,10 +508,12 @@ class BrowserPage(QtWebKitWidgets.QWebPage): shared.javascript_log_message(usertypes.JsLogLevel.unknown, source, line, msg) - def acceptNavigationRequest(self, - frame: QtWebKitWidgets.QWebFrame, - request: QtNetwork.QNetworkRequest, - typ: QtWebKitWidgets.QWebPage.NavigationType) -> bool: + def acceptNavigationRequest( + self, + frame: QtWebKitWidgets.QWebFrame, + request: QtNetwork.QNetworkRequest, + typ: QtWebKitWidgets.QWebPage.NavigationType, + ) -> bool: """Override acceptNavigationRequest to handle clicked links. Setting linkDelegationPolicy to DelegateAllLinks and using a slot bound @@ -502,18 +524,12 @@ class BrowserPage(QtWebKitWidgets.QWebPage): and then conditionally opens the URL here or in another tab/window. """ type_map = { - QtWebKitWidgets.QWebPage.NavigationTypeLinkClicked: - usertypes.NavigationRequest.Type.link_clicked, - QtWebKitWidgets.QWebPage.NavigationTypeFormSubmitted: - usertypes.NavigationRequest.Type.form_submitted, - QtWebKitWidgets.QWebPage.NavigationTypeFormResubmitted: - usertypes.NavigationRequest.Type.form_resubmitted, - QtWebKitWidgets.QWebPage.NavigationTypeBackOrForward: - usertypes.NavigationRequest.Type.back_forward, - QtWebKitWidgets.QWebPage.NavigationTypeReload: - usertypes.NavigationRequest.Type.reloaded, - QtWebKitWidgets.QWebPage.NavigationTypeOther: - usertypes.NavigationRequest.Type.other, + QtWebKitWidgets.QWebPage.NavigationTypeLinkClicked: usertypes.NavigationRequest.Type.link_clicked, + QtWebKitWidgets.QWebPage.NavigationTypeFormSubmitted: usertypes.NavigationRequest.Type.form_submitted, + QtWebKitWidgets.QWebPage.NavigationTypeFormResubmitted: usertypes.NavigationRequest.Type.form_resubmitted, + QtWebKitWidgets.QWebPage.NavigationTypeBackOrForward: usertypes.NavigationRequest.Type.back_forward, + QtWebKitWidgets.QWebPage.NavigationTypeReload: usertypes.NavigationRequest.Type.reloaded, + QtWebKitWidgets.QWebPage.NavigationTypeOther: usertypes.NavigationRequest.Type.other, } is_main_frame = frame is self.mainFrame() navigation = usertypes.NavigationRequest(url=request.url(), diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py index ab1c15dd0..5a6acfbc1 100644 --- a/qutebrowser/browser/webkit/webview.py +++ b/qutebrowser/browser/webkit/webview.py @@ -72,8 +72,10 @@ class WebView(QtWebKitWidgets.QWebView): tabdata=tab.data, private=private, parent=self) page.setVisibilityState( - QtWebKitWidgets.QWebPage.VisibilityStateVisible if self.isVisible() - else QtWebKitWidgets.QWebPage.VisibilityStateHidden) + QtWebKitWidgets.QWebPage.VisibilityStateVisible + if self.isVisible() + else QtWebKitWidgets.QWebPage.VisibilityStateHidden + ) self.setPage(page) @@ -152,14 +154,20 @@ class WebView(QtWebKitWidgets.QWebView): e: The QPaintEvent. """ frame = self.page().mainFrame() - new_pos = (frame.scrollBarValue(QtCore.Qt.Horizontal), - frame.scrollBarValue(QtCore.Qt.Vertical)) + new_pos = ( + frame.scrollBarValue(QtCore.Qt.Horizontal), + frame.scrollBarValue(QtCore.Qt.Vertical), + ) if self._old_scroll_pos != new_pos: self._old_scroll_pos = new_pos - m = (frame.scrollBarMaximum(QtCore.Qt.Horizontal), - frame.scrollBarMaximum(QtCore.Qt.Vertical)) - perc = (round(100 * new_pos[0] / m[0]) if m[0] != 0 else 0, - round(100 * new_pos[1] / m[1]) if m[1] != 0 else 0) + m = ( + frame.scrollBarMaximum(QtCore.Qt.Horizontal), + frame.scrollBarMaximum(QtCore.Qt.Vertical), + ) + perc = ( + round(100 * new_pos[0] / m[0]) if m[0] != 0 else 0, + round(100 * new_pos[1] / m[1]) if m[1] != 0 else 0, + ) self.scroll_pos = perc self.scroll_pos_changed.emit(*perc) # Let superclass handle the event @@ -199,7 +207,10 @@ class WebView(QtWebKitWidgets.QWebView): This is implemented here as we don't need it for QtWebEngine. """ - if e.button() == QtCore.Qt.MidButton or e.modifiers() & QtCore.Qt.ControlModifier: + if ( + e.button() == QtCore.Qt.MidButton + or e.modifiers() & QtCore.Qt.ControlModifier + ): background = config.val.tabs.background if e.modifiers() & QtCore.Qt.ShiftModifier: background = not background diff --git a/qutebrowser/commands/argparser.py b/qutebrowser/commands/argparser.py index 137e8216f..910d2194b 100644 --- a/qutebrowser/commands/argparser.py +++ b/qutebrowser/commands/argparser.py @@ -60,7 +60,8 @@ class HelpAction(argparse.Action): tabbed_browser = objreg.get('tabbed-browser', scope='window', window='last-focused') tabbed_browser.tabopen( - QtCore.QUrl('qute://help/commands.html#{}'.format(parser.name))) + QtCore.QUrl('qute://help/commands.html#{}'.format(parser.name)) + ) parser.exit() diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py index 9a548a22e..e5d5d2617 100644 --- a/qutebrowser/commands/runners.py +++ b/qutebrowser/commands/runners.py @@ -54,9 +54,11 @@ def _init_variable_replacements() -> Mapping[str, _ReplacementFunction]: """Return a dict from variable replacements to fns processing them.""" replacements: Dict[str, _ReplacementFunction] = { 'url': lambda tb: _url(tb).toString( - QtCore.QUrl.FullyEncoded | QtCore.QUrl.RemovePassword), + QtCore.QUrl.FullyEncoded | QtCore.QUrl.RemovePassword + ), 'url:pretty': lambda tb: _url(tb).toString( - QtCore.QUrl.DecodeReserved | QtCore.QUrl.RemovePassword), + QtCore.QUrl.DecodeReserved | QtCore.QUrl.RemovePassword + ), 'url:domain': lambda tb: "{}://{}{}".format( _url(tb).scheme(), _url(tb).host(), ":" + str(_url(tb).port()) if _url(tb).port() != -1 else ""), diff --git a/qutebrowser/commands/userscripts.py b/qutebrowser/commands/userscripts.py index dc0783dab..c47bead34 100644 --- a/qutebrowser/commands/userscripts.py +++ b/qutebrowser/commands/userscripts.py @@ -59,10 +59,10 @@ class _QtFIFOReader(QtCore.QObject): fd = os.open(filepath, os.O_RDWR | os.O_NONBLOCK) # pylint: enable=no-member,useless-suppression self._fifo = os.fdopen(fd, 'r') - self._notifier = QtCore.QSocketNotifier(cast(sip.voidptr, fd), - QtCore.QSocketNotifier.Read, self) - self._notifier.activated.connect( # type: ignore[attr-defined] - self.read_line) + self._notifier = QtCore.QSocketNotifier( + cast(sip.voidptr, fd), QtCore.QSocketNotifier.Read, self + ) + self._notifier.activated.connect(self.read_line) # type: ignore[attr-defined] @QtCore.pyqtSlot() def read_line(self): diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py index d5d85c60d..d3c635bbf 100644 --- a/qutebrowser/completion/completiondelegate.py +++ b/qutebrowser/completion/completiondelegate.py @@ -109,9 +109,14 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): mode = QtGui.QIcon.Disabled elif self._opt.state & QtWidgets.QStyle.State_Selected: mode = QtGui.QIcon.Selected - state = QtGui.QIcon.On if self._opt.state & QtWidgets.QStyle.State_Open else QtGui.QIcon.Off - self._opt.icon.paint(self._painter, icon_rect, - self._opt.decorationAlignment, mode, state) + state = ( + QtGui.QIcon.On + if self._opt.state & QtWidgets.QStyle.State_Open + else QtGui.QIcon.Off + ) + self._opt.icon.paint( + self._painter, icon_rect, self._opt.decorationAlignment, mode, state + ) def _draw_text(self, index): """Draw the text of an ItemViewItem. @@ -131,8 +136,12 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): text_rect_ = self._style.subElementRect( self._style.SE_ItemViewItemText, self._opt, self._opt.widget) qtutils.ensure_valid(text_rect_) - margin = self._style.pixelMetric(QtWidgets.QStyle.PM_FocusFrameHMargin, - self._opt, self._opt.widget) + 1 + margin = ( + self._style.pixelMetric( + QtWidgets.QStyle.PM_FocusFrameHMargin, self._opt, self._opt.widget + ) + + 1 + ) # remove width padding text_rect = text_rect_.adjusted(margin, 0, -margin, 0) qtutils.ensure_valid(text_rect) @@ -143,7 +152,10 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): text_rect.adjust(0, -2, 0, -2) self._painter.save() state = self._opt.state - if state & QtWidgets.QStyle.State_Enabled and state & QtWidgets.QStyle.State_Active: + if ( + state & QtWidgets.QStyle.State_Enabled + and state & QtWidgets.QStyle.State_Active + ): cg = QtGui.QPalette.Normal elif state & QtWidgets.QStyle.State_Enabled: cg = QtGui.QPalette.Inactive @@ -151,8 +163,9 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): cg = QtGui.QPalette.Disabled if state & QtWidgets.QStyle.State_Selected: - self._painter.setPen(self._opt.palette.color( - cg, QtGui.QPalette.HighlightedText)) + self._painter.setPen( + self._opt.palette.color(cg, QtGui.QPalette.HighlightedText) + ) # This is a dirty fix for the text jumping by one pixel for # whatever reason. text_rect.adjust(0, -1, 0, 0) @@ -216,8 +229,11 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): else: text_option.setWrapMode(QtGui.QTextOption.ManualWrap) text_option.setTextDirection(self._opt.direction) - text_option.setAlignment(QtWidgets.QStyle.visualAlignment( - self._opt.direction, self._opt.displayAlignment)) + text_option.setAlignment( + QtWidgets.QStyle.visualAlignment( + self._opt.direction, self._opt.displayAlignment + ) + ) if self._doc is not None: self._doc.deleteLater() @@ -252,8 +268,11 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): return o = self._opt o.rect = self._style.subElementRect( - self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget) - o.state |= int(QtWidgets.QStyle.State_KeyboardFocusChange | QtWidgets.QStyle.State_Item) + self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget + ) + o.state |= int( + QtWidgets.QStyle.State_KeyboardFocusChange | QtWidgets.QStyle.State_Item + ) qtutils.ensure_valid(o.rect) if state & QtWidgets.QStyle.State_Enabled: cg = QtGui.QPalette.Normal @@ -264,8 +283,9 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): else: role = QtGui.QPalette.Window o.backgroundColor = self._opt.palette.color(cg, role) - self._style.drawPrimitive(QtWidgets.QStyle.PE_FrameFocusRect, o, self._painter, - self._opt.widget) + self._style.drawPrimitive( + QtWidgets.QStyle.PE_FrameFocusRect, o, self._painter, self._opt.widget + ) def sizeHint(self, option, index): """Override sizeHint of QStyledItemDelegate. @@ -291,8 +311,9 @@ class CompletionItemDelegate(QtWidgets.QStyledItemDelegate): assert self._doc is not None docsize = self._doc.size().toSize() - size = self._style.sizeFromContents(QtWidgets.QStyle.CT_ItemViewItem, self._opt, - docsize, self._opt.widget) + size = self._style.sizeFromContents( + QtWidgets.QStyle.CT_ItemViewItem, self._opt, docsize, self._opt.widget + ) qtutils.ensure_valid(size) return size + QtCore.QSize(10, 3) # type: ignore[operator] diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py index dd13122cf..d523241fb 100644 --- a/qutebrowser/completion/completionwidget.py +++ b/qutebrowser/completion/completionwidget.py @@ -109,10 +109,9 @@ class CompletionView(QtWidgets.QTreeView): update_geometry = QtCore.pyqtSignal() selection_changed = QtCore.pyqtSignal(str) - def __init__(self, *, - cmd: 'command.Command', - win_id: int, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, *, cmd: 'command.Command', win_id: int, parent: QtWidgets.QWidget = None + ) -> None: super().__init__(parent) self.pattern: Optional[str] = None self._win_id = win_id @@ -326,8 +325,9 @@ class CompletionView(QtWidgets.QTreeView): selmodel.setCurrentIndex( idx, - QtCore.QItemSelectionModel.ClearAndSelect | # type: ignore[arg-type] - QtCore.QItemSelectionModel.Rows) + QtCore.QItemSelectionModel.ClearAndSelect + | QtCore.QItemSelectionModel.Rows, # type: ignore[arg-type] + ) # if the last item is focused, try to fetch more next_idx = self.indexBelow(idx) diff --git a/qutebrowser/completion/models/completionmodel.py b/qutebrowser/completion/models/completionmodel.py index 5b4d19ba3..b08b7fc92 100644 --- a/qutebrowser/completion/models/completionmodel.py +++ b/qutebrowser/completion/models/completionmodel.py @@ -99,8 +99,11 @@ class CompletionModel(QtCore.QAbstractItemModel): return QtCore.Qt.NoItemFlags if index.parent().isValid(): # item - return (QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | - QtCore.Qt.ItemNeverHasChildren) + return ( + QtCore.Qt.ItemIsEnabled + | QtCore.Qt.ItemIsSelectable + | QtCore.Qt.ItemNeverHasChildren + ) else: # category return QtCore.Qt.NoItemFlags diff --git a/qutebrowser/completion/models/filepathcategory.py b/qutebrowser/completion/models/filepathcategory.py index c1dea4c01..412bf06d0 100644 --- a/qutebrowser/completion/models/filepathcategory.py +++ b/qutebrowser/completion/models/filepathcategory.py @@ -99,7 +99,9 @@ class FilePathCategory(QtCore.QAbstractListModel): paths = self._glob(expanded) self._paths = sorted(self._contract_user(val, path) for path in paths) - def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole) -> Optional[str]: + def data( + self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole + ) -> Optional[str]: """Implement abstract method in QAbstractListModel.""" if role == QtCore.Qt.DisplayRole and index.column() == 0: return self._paths[index.row()] diff --git a/qutebrowser/completion/models/histcategory.py b/qutebrowser/completion/models/histcategory.py index aa7edb59f..662753dfc 100644 --- a/qutebrowser/completion/models/histcategory.py +++ b/qutebrowser/completion/models/histcategory.py @@ -33,9 +33,13 @@ class HistoryCategory(QtSql.QSqlQueryModel): """A completion category that queries the SQL history store.""" - def __init__(self, *, database: sql.Database, - delete_func: util.DeleteFuncType = None, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + *, + database: sql.Database, + delete_func: util.DeleteFuncType = None, + parent: QtWidgets.QWidget = None + ) -> None: """Create a new History completion category.""" super().__init__(parent=parent) self._database = database diff --git a/qutebrowser/completion/models/listcategory.py b/qutebrowser/completion/models/listcategory.py index 9d07bd13e..727222b88 100644 --- a/qutebrowser/completion/models/listcategory.py +++ b/qutebrowser/completion/models/listcategory.py @@ -32,12 +32,14 @@ class ListCategory(QtCore.QSortFilterProxyModel): """Expose a list of items as a category for the CompletionModel.""" - def __init__(self, - name: str, - items: Iterable[Tuple[str, ...]], - sort: bool = True, - delete_func: util.DeleteFuncType = None, - parent: QtWidgets.QWidget = None): + def __init__( + self, + name: str, + items: Iterable[Tuple[str, ...]], + sort: bool = True, + delete_func: util.DeleteFuncType = None, + parent: QtWidgets.QWidget = None, + ): super().__init__(parent) self.name = name self.srcmodel = QtGui.QStandardItemModel(parent=self) @@ -64,7 +66,9 @@ class ListCategory(QtCore.QSortFilterProxyModel): val = re.sub(r' +', r' ', val) # See #1919 val = re.escape(val) val = val.replace(r'\ ', '.*') - rx = QtCore.QRegularExpression(val, QtCore.QRegularExpression.CaseInsensitiveOption) + rx = QtCore.QRegularExpression( + val, QtCore.QRegularExpression.CaseInsensitiveOption + ) qtutils.ensure_valid(rx) self.setFilterRegularExpression(rx) self.invalidate() diff --git a/qutebrowser/components/hostblock.py b/qutebrowser/components/hostblock.py index 0d3c5193e..f3f2682c7 100644 --- a/qutebrowser/components/hostblock.py +++ b/qutebrowser/components/hostblock.py @@ -115,7 +115,9 @@ class HostBlocker: self._config_hosts_file = str(config_dir / "blocked-hosts") - def _is_blocked(self, request_url: QtCore.QUrl, first_party_url: QtCore.QUrl = None) -> bool: + def _is_blocked( + self, request_url: QtCore.QUrl, first_party_url: QtCore.QUrl = None + ) -> bool: """Check whether the given request is blocked.""" if not self.enabled: return False diff --git a/qutebrowser/components/misccommands.py b/qutebrowser/components/misccommands.py index 95c5c078a..543d80254 100644 --- a/qutebrowser/components/misccommands.py +++ b/qutebrowser/components/misccommands.py @@ -82,11 +82,13 @@ def _print_preview(tab: apitypes.Tab) -> None: diag = QtPrintSupport.QPrintPreviewDialog(tab) diag.setAttribute(QtCore.Qt.WA_DeleteOnClose) diag.setWindowFlags( - diag.windowFlags() | # type: ignore[operator, arg-type] - QtCore.Qt.WindowMaximizeButtonHint | - QtCore.Qt.WindowMinimizeButtonHint) - diag.paintRequested.connect(functools.partial( - tab.printing.to_printer, callback=print_callback)) + diag.windowFlags() + | QtCore.Qt.WindowMaximizeButtonHint # type: ignore[operator, arg-type] + | QtCore.Qt.WindowMinimizeButtonHint + ) + diag.paintRequested.connect( + functools.partial(tab.printing.to_printer, callback=print_callback) + ) diag.exec() diff --git a/qutebrowser/components/utils/blockutils.py b/qutebrowser/components/utils/blockutils.py index 799ee862a..08bf5b95a 100644 --- a/qutebrowser/components/utils/blockutils.py +++ b/qutebrowser/components/utils/blockutils.py @@ -62,7 +62,9 @@ class BlocklistDownloads(QtCore.QObject): single_download_finished = QtCore.pyqtSignal(object) # arg: the file object all_downloads_finished = QtCore.pyqtSignal(int) # arg: download count - def __init__(self, urls: List[QtCore.QUrl], parent: Optional[QtCore.QObject] = None) -> None: + def __init__( + self, urls: List[QtCore.QUrl], parent: Optional[QtCore.QObject] = None + ) -> None: super().__init__(parent) self._urls = urls diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 320579ac7..23d5e1a31 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -301,9 +301,9 @@ class Config(QtCore.QObject): MUTABLE_TYPES = (dict, list) changed = QtCore.pyqtSignal(str) - def __init__(self, - yaml_config: 'configfiles.YamlConfig', - parent: QtCore.QObject = None) -> None: + def __init__( + self, yaml_config: 'configfiles.YamlConfig', parent: QtCore.QObject = None + ) -> None: super().__init__(parent) self._mutables: MutableMapping[str, Tuple[Any, Any]] = {} self._yaml = yaml_config @@ -379,10 +379,7 @@ class Config(QtCore.QObject): """Raise NoOptionError if the given setting does not exist.""" self.get_opt(name) - def get(self, - name: str, - url: QtCore.QUrl = None, *, - fallback: bool = True) -> Any: + def get(self, name: str, url: QtCore.QUrl = None, *, fallback: bool = True) -> Any: """Get the given setting converted for Python code. Args: @@ -405,10 +402,9 @@ class Config(QtCore.QObject): assert value.__hash__ is not None, value return value - def get_obj(self, - name: str, *, - url: QtCore.QUrl = None, - fallback: bool = True) -> Any: + def get_obj( + self, name: str, *, url: QtCore.QUrl = None, fallback: bool = True + ) -> Any: """Get the given setting as object (for YAML/config.py). Note that the returned values are not watched for mutation. diff --git a/qutebrowser/config/configinit.py b/qutebrowser/config/configinit.py index a0ad40cf2..e88a4cd30 100644 --- a/qutebrowser/config/configinit.py +++ b/qutebrowser/config/configinit.py @@ -132,11 +132,13 @@ def late_init(save_manager: savemanager.SaveManager) -> None: """Initialize the rest of the config after the QApplication is created.""" global _init_errors if _init_errors is not None: - errbox = msgbox.msgbox(parent=None, - title="Error while reading config", - text=_init_errors.to_html(), - icon=QtWidgets.QMessageBox.Warning, - plain_text=False) + errbox = msgbox.msgbox( + parent=None, + title="Error while reading config", + text=_init_errors.to_html(), + icon=QtWidgets.QMessageBox.Warning, + plain_text=False, + ) errbox.exec() if _init_errors.fatal: diff --git a/qutebrowser/config/configutils.py b/qutebrowser/config/configutils.py index 49933c89f..c58898d62 100644 --- a/qutebrowser/config/configutils.py +++ b/qutebrowser/config/configutils.py @@ -144,7 +144,8 @@ class Values: return bool(self._vmap) def _check_pattern_support( - self, arg: Union[urlmatch.UrlPattern, QtCore.QUrl, None]) -> None: + self, arg: Union[urlmatch.UrlPattern, QtCore.QUrl, None] + ) -> None: """Make sure patterns are supported if one was given.""" if arg is not None and not self.opt.supports_pattern: raise configexc.NoPatternError(self.opt.name) @@ -291,8 +292,8 @@ class FontFamilies: @classmethod def from_system_default( - cls, - font_type: QtGui.QFontDatabase.SystemFont = QtGui.QFontDatabase.FixedFont, + cls, + font_type: QtGui.QFontDatabase.SystemFont = QtGui.QFontDatabase.FixedFont, ) -> 'FontFamilies': """Get a FontFamilies object for the default system font. diff --git a/qutebrowser/config/qtargs.py b/qutebrowser/config/qtargs.py index 01a5c1d97..dd93e6689 100644 --- a/qutebrowser/config/qtargs.py +++ b/qutebrowser/config/qtargs.py @@ -195,7 +195,9 @@ def _webengine_locales_path() -> pathlib.Path: # not QtWebEngine. base = pathlib.Path('/app/translations') else: - base = pathlib.Path(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)) + base = pathlib.Path( + QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath) + ) return base / 'qtwebengine_locales' diff --git a/qutebrowser/config/stylesheet.py b/qutebrowser/config/stylesheet.py index 9c893e0b1..b23e51ef0 100644 --- a/qutebrowser/config/stylesheet.py +++ b/qutebrowser/config/stylesheet.py @@ -28,9 +28,9 @@ from qutebrowser.utils import jinja, log from qutebrowser.qt import QtCore -def set_register(obj: QtCore.QObject, - stylesheet: str = None, *, - update: bool = True) -> None: +def set_register( + obj: QtCore.QObject, stylesheet: str = None, *, update: bool = True +) -> None: """Set the stylesheet for an object. Also, register an update when the config is changed. @@ -70,8 +70,9 @@ class _StyleSheetObserver(QtCore.QObject): None. """ - def __init__(self, obj: QtCore.QObject, - stylesheet: Optional[str], update: bool) -> None: + def __init__( + self, obj: QtCore.QObject, stylesheet: Optional[str], update: bool + ) -> None: super().__init__() self._obj = obj self._update = update diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index f9ed3e04d..08cb2b3bc 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -129,22 +129,28 @@ class BindingTrie: try: node = node.children[key] except KeyError: - return MatchResult(match_type=QtGui.QKeySequence.NoMatch, - command=None, - sequence=sequence) + return MatchResult( + match_type=QtGui.QKeySequence.NoMatch, + command=None, + sequence=sequence, + ) if node.command is not None: - return MatchResult(match_type=QtGui.QKeySequence.ExactMatch, - command=node.command, - sequence=sequence) + return MatchResult( + match_type=QtGui.QKeySequence.ExactMatch, + command=node.command, + sequence=sequence, + ) elif node.children: - return MatchResult(match_type=QtGui.QKeySequence.PartialMatch, - command=None, - sequence=sequence) + return MatchResult( + match_type=QtGui.QKeySequence.PartialMatch, + command=None, + sequence=sequence, + ) else: # This can only happen when there are no bindings at all. - return MatchResult(match_type=QtGui.QKeySequence.NoMatch, - command=None, - sequence=sequence) + return MatchResult( + match_type=QtGui.QKeySequence.NoMatch, command=None, sequence=sequence + ) class BaseKeyParser(QtCore.QObject): @@ -177,12 +183,16 @@ class BaseKeyParser(QtCore.QObject): keystring_updated = QtCore.pyqtSignal(str) request_leave = QtCore.pyqtSignal(usertypes.KeyMode, str, bool) - def __init__(self, *, mode: usertypes.KeyMode, - win_id: int, - parent: QtCore.QObject = None, - do_log: bool = True, - passthrough: bool = False, - supports_count: bool = True) -> None: + def __init__( + self, + *, + mode: usertypes.KeyMode, + win_id: int, + parent: QtCore.QObject = None, + do_log: bool = True, + passthrough: bool = False, + supports_count: bool = True + ) -> None: super().__init__(parent) self._win_id = win_id self._sequence = keyutils.KeySequence() @@ -245,9 +255,9 @@ class BaseKeyParser(QtCore.QObject): self._debug_log("Mapped {} -> {}".format( sequence, mapped)) return self._match_key(mapped) - return MatchResult(match_type=QtGui.QKeySequence.NoMatch, - command=None, - sequence=sequence) + return MatchResult( + match_type=QtGui.QKeySequence.NoMatch, command=None, sequence=sequence + ) def _match_count(self, sequence: keyutils.KeySequence, dry_run: bool) -> bool: @@ -266,8 +276,9 @@ class BaseKeyParser(QtCore.QObject): return True return False - def handle(self, e: QtGui.QKeyEvent, *, - dry_run: bool = False) -> QtGui.QKeySequence.SequenceMatch: + def handle( + self, e: QtGui.QKeyEvent, *, dry_run: bool = False + ) -> QtGui.QKeySequence.SequenceMatch: """Handle a new keypress. Separate the keypress into count/command, then check if it matches diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py index f1c0e8837..e6ed74314 100644 --- a/qutebrowser/keyinput/keyutils.py +++ b/qutebrowser/keyinput/keyutils.py @@ -159,15 +159,17 @@ def _assert_plain_modifier(key: _ModifierType) -> None: def _is_printable(key: QtCore.Qt.Key) -> bool: _assert_plain_key(key) - return key <= 0xff and key not in [QtCore.Qt.Key_Space, _NIL_KEY] + return key <= 0xFF and key not in [QtCore.Qt.Key_Space, _NIL_KEY] def is_special(key: QtCore.Qt.Key, modifiers: _ModifierType) -> bool: """Check whether this key requires special key syntax.""" _assert_plain_key(key) _assert_plain_modifier(modifiers) - return not (_is_printable(key) and - modifiers in [QtCore.Qt.ShiftModifier, QtCore.Qt.NoModifier]) + return not ( + _is_printable(key) + and modifiers in [QtCore.Qt.ShiftModifier, QtCore.Qt.NoModifier] + ) def is_modifier_key(key: QtCore.Qt.Key) -> bool: @@ -418,7 +420,9 @@ class KeyInfo: text = text.lower() return text - def to_event(self, typ: QtCore.QEvent.Type = QtCore.QEvent.KeyPress) -> QtGui.QKeyEvent: + def to_event( + self, typ: QtCore.QEvent.Type = QtCore.QEvent.KeyPress + ) -> QtGui.QKeyEvent: """Get a QKeyEvent from this KeyInfo.""" return QtGui.QKeyEvent(typ, self.key, self.modifiers, self.text()) @@ -470,9 +474,12 @@ class KeySequence: def __iter__(self) -> Iterator[KeyInfo]: """Iterate over KeyInfo objects.""" for key_and_modifiers in self._iter_keys(): - key = QtCore.Qt.Key(int(key_and_modifiers) & ~QtCore.Qt.KeyboardModifierMask) + key = QtCore.Qt.Key( + int(key_and_modifiers) & ~QtCore.Qt.KeyboardModifierMask + ) modifiers = QtCore.Qt.KeyboardModifiers( # type: ignore[call-overload] - int(key_and_modifiers) & QtCore.Qt.KeyboardModifierMask) + int(key_and_modifiers) & QtCore.Qt.KeyboardModifierMask + ) yield KeyInfo(key=key, modifiers=modifiers) def __repr__(self) -> str: @@ -605,9 +612,11 @@ class KeySequence: # # In addition, Shift also *is* relevant when other modifiers are # involved. Shift-Ctrl-X should not be equivalent to Ctrl-X. - if (modifiers == QtCore.Qt.ShiftModifier and - _is_printable(key) and - not ev.text().isupper()): + if ( + modifiers == QtCore.Qt.ShiftModifier + and _is_printable(key) + and not ev.text().isupper() + ): modifiers = QtCore.Qt.KeyboardModifiers() # type: ignore[assignment] # On macOS, swap Ctrl and Meta back @@ -617,7 +626,10 @@ class KeySequence: # (or "Cmd") in a key binding name to actually represent what's on the # keyboard. if utils.is_mac: - if modifiers & QtCore.Qt.ControlModifier and modifiers & QtCore.Qt.MetaModifier: + if ( + modifiers & QtCore.Qt.ControlModifier + and modifiers & QtCore.Qt.MetaModifier + ): pass elif modifiers & QtCore.Qt.ControlModifier: modifiers &= ~QtCore.Qt.ControlModifier diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 665e88556..8d4e72879 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -269,8 +269,9 @@ class ModeManager(QtCore.QObject): def __repr__(self) -> str: return utils.get_repr(self, mode=self.mode) - def _handle_keypress(self, event: QtGui.QKeyEvent, *, - dry_run: bool = False) -> bool: + def _handle_keypress( + self, event: QtGui.QKeyEvent, *, dry_run: bool = False + ) -> bool: """Handle filtering of KeyPress events. Args: @@ -460,8 +461,9 @@ class ModeManager(QtCore.QObject): handlers: Mapping[QtCore.QEvent.Type, Callable[[QtGui.QKeyEvent], bool]] = { QtCore.QEvent.KeyPress: self._handle_keypress, QtCore.QEvent.KeyRelease: self._handle_keyrelease, - QtCore.QEvent.ShortcutOverride: - functools.partial(self._handle_keypress, dry_run=True), + QtCore.QEvent.ShortcutOverride: functools.partial( + self._handle_keypress, dry_run=True + ), } handler = handlers[event.type()] return handler(cast(QtGui.QKeyEvent, event)) diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py index 53ec37c49..cd75cdebf 100644 --- a/qutebrowser/keyinput/modeparsers.py +++ b/qutebrowser/keyinput/modeparsers.py @@ -58,16 +58,25 @@ class CommandKeyParser(basekeyparser.BaseKeyParser): _commandrunner: CommandRunner instance. """ - def __init__(self, *, mode: usertypes.KeyMode, - win_id: int, - commandrunner: 'runners.CommandRunner', - parent: QtCore.QObject = None, - do_log: bool = True, - passthrough: bool = False, - supports_count: bool = True) -> None: - super().__init__(mode=mode, win_id=win_id, parent=parent, - do_log=do_log, passthrough=passthrough, - supports_count=supports_count) + def __init__( + self, + *, + mode: usertypes.KeyMode, + win_id: int, + commandrunner: 'runners.CommandRunner', + parent: QtCore.QObject = None, + do_log: bool = True, + passthrough: bool = False, + supports_count: bool = True + ) -> None: + super().__init__( + mode=mode, + win_id=win_id, + parent=parent, + do_log=do_log, + passthrough=passthrough, + supports_count=supports_count, + ) self._commandrunner = commandrunner def execute(self, cmdstr: str, count: int = None) -> None: @@ -87,11 +96,19 @@ class NormalKeyParser(CommandKeyParser): _sequence: keyutils.KeySequence - def __init__(self, *, win_id: int, - commandrunner: 'runners.CommandRunner', - parent: QtCore.QObject = None) -> None: - super().__init__(mode=usertypes.KeyMode.normal, win_id=win_id, - commandrunner=commandrunner, parent=parent) + def __init__( + self, + *, + win_id: int, + commandrunner: 'runners.CommandRunner', + parent: QtCore.QObject = None + ) -> None: + super().__init__( + mode=usertypes.KeyMode.normal, + win_id=win_id, + commandrunner=commandrunner, + parent=parent, + ) self._partial_timer = usertypes.Timer(self, 'partial-match') self._partial_timer.setSingleShot(True) self._partial_timer.timeout.connect(self._clear_partial_match) @@ -102,8 +119,9 @@ class NormalKeyParser(CommandKeyParser): def __repr__(self) -> str: return utils.get_repr(self) - def handle(self, e: QtGui.QKeyEvent, *, - dry_run: bool = False) -> QtGui.QKeySequence.SequenceMatch: + def handle( + self, e: QtGui.QKeyEvent, *, dry_run: bool = False + ) -> QtGui.QKeySequence.SequenceMatch: """Override to abort if the key is a startchar.""" txt = e.text().strip() if self._inhibited: @@ -157,23 +175,35 @@ class HintKeyParser(basekeyparser.BaseKeyParser): _sequence: keyutils.KeySequence - def __init__(self, *, win_id: int, - commandrunner: 'runners.CommandRunner', - hintmanager: hints.HintManager, - parent: QtCore.QObject = None) -> None: - super().__init__(mode=usertypes.KeyMode.hint, win_id=win_id, - parent=parent, supports_count=False) - self._command_parser = CommandKeyParser(mode=usertypes.KeyMode.hint, - win_id=win_id, - commandrunner=commandrunner, - parent=self, - supports_count=False) + def __init__( + self, + *, + win_id: int, + commandrunner: 'runners.CommandRunner', + hintmanager: hints.HintManager, + parent: QtCore.QObject = None + ) -> None: + super().__init__( + mode=usertypes.KeyMode.hint, + win_id=win_id, + parent=parent, + supports_count=False, + ) + self._command_parser = CommandKeyParser( + mode=usertypes.KeyMode.hint, + win_id=win_id, + commandrunner=commandrunner, + parent=self, + supports_count=False, + ) self._hintmanager = hintmanager self._filtertext = '' self._last_press = LastPress.none self.keystring_updated.connect(self._hintmanager.handle_partial_key) - def _handle_filter_key(self, e: QtGui.QKeyEvent) -> QtGui.QKeySequence.SequenceMatch: + def _handle_filter_key( + self, e: QtGui.QKeyEvent + ) -> QtGui.QKeySequence.SequenceMatch: """Handle keys for string filtering.""" log.keyboard.debug("Got filter key 0x{:x} text {}".format( e.key(), e.text())) @@ -207,16 +237,16 @@ class HintKeyParser(basekeyparser.BaseKeyParser): self._last_press = LastPress.filtertext return QtGui.QKeySequence.ExactMatch - def handle(self, e: QtGui.QKeyEvent, *, - dry_run: bool = False) -> QtGui.QKeySequence.SequenceMatch: + def handle( + self, e: QtGui.QKeyEvent, *, dry_run: bool = False + ) -> QtGui.QKeySequence.SequenceMatch: """Handle a new keypress and call the respective handlers.""" if dry_run: return super().handle(e, dry_run=True) assert not dry_run - if (self._command_parser.handle(e, dry_run=True) != - QtGui.QKeySequence.NoMatch): + if self._command_parser.handle(e, dry_run=True) != QtGui.QKeySequence.NoMatch: log.keyboard.debug("Handling key via command parser") self.clear_keystring() return self._command_parser.handle(e) @@ -264,17 +294,26 @@ class RegisterKeyParser(CommandKeyParser): KeyMode.record_macro and KeyMode.run_macro. """ - def __init__(self, *, win_id: int, - mode: usertypes.KeyMode, - commandrunner: 'runners.CommandRunner', - parent: QtCore.QObject = None) -> None: - super().__init__(mode=usertypes.KeyMode.register, win_id=win_id, - commandrunner=commandrunner, parent=parent, - supports_count=False) + def __init__( + self, + *, + win_id: int, + mode: usertypes.KeyMode, + commandrunner: 'runners.CommandRunner', + parent: QtCore.QObject = None + ) -> None: + super().__init__( + mode=usertypes.KeyMode.register, + win_id=win_id, + commandrunner=commandrunner, + parent=parent, + supports_count=False, + ) self._register_mode = mode - def handle(self, e: QtGui.QKeyEvent, *, - dry_run: bool = False) -> QtGui.QKeySequence.SequenceMatch: + def handle( + self, e: QtGui.QKeyEvent, *, dry_run: bool = False + ) -> QtGui.QKeySequence.SequenceMatch: """Override to always match the next key and use the register.""" match = super().handle(e, dry_run=dry_run) if match or dry_run: diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 0efa8d5e0..b1848e4a2 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -89,7 +89,9 @@ def raise_window(window, alert=True): window.raise_() # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-69568 QtCore.QCoreApplication.processEvents( # type: ignore[call-overload] - QtCore.QEventLoop.ExcludeUserInputEvents | QtCore.QEventLoop.ExcludeSocketNotifiers) + QtCore.QEventLoop.ExcludeUserInputEvents + | QtCore.QEventLoop.ExcludeSocketNotifiers + ) if not sip.isdeleted(window): # Could be deleted by the events run above @@ -181,10 +183,13 @@ class MainWindow(QtWidgets.QWidget): } """ - def __init__(self, *, - private: bool, - geometry: Optional[QtCore.QByteArray] = None, - parent: Optional[QtWidgets.QWidget] = None) -> None: + def __init__( + self, + *, + private: bool, + geometry: Optional[QtCore.QByteArray] = None, + parent: Optional[QtWidgets.QWidget] = None + ) -> None: """Create a new main window. Args: @@ -337,8 +342,9 @@ class MainWindow(QtWidgets.QWidget): topleft = QtCore.QPoint(left, top) bottom = status_height + height bottom = qtutils.check_overflow(bottom, 'int', fatal=False) - bottomright = QtCore.QPoint(left + width, - min(self.height() - height_padding, bottom)) + bottomright = QtCore.QPoint( + left + width, min(self.height() - height_padding, bottom) + ) else: raise ValueError("Invalid position {}!".format(status_position)) @@ -560,7 +566,9 @@ class MainWindow(QtWidgets.QWidget): window_flags: int = QtCore.Qt.Window refresh_window = self.isVisible() if hidden: - window_flags |= QtCore.Qt.CustomizeWindowHint | QtCore.Qt.NoDropShadowWindowHint + window_flags |= ( + QtCore.Qt.CustomizeWindowHint | QtCore.Qt.NoDropShadowWindowHint + ) self.setWindowFlags(cast(QtCore.Qt.WindowFlags, window_flags)) if refresh_window: self.show() @@ -571,12 +579,16 @@ class MainWindow(QtWidgets.QWidget): if on: self.state_before_fullscreen = self.windowState() self.setWindowState( - QtCore.Qt.WindowFullScreen | # type: ignore[arg-type] - self.state_before_fullscreen) # type: ignore[operator] + QtCore.Qt.WindowFullScreen + | self.state_before_fullscreen # type: ignore[arg-type] + ) # type: ignore[operator] elif self.isFullScreen(): self.setWindowState(self.state_before_fullscreen) - log.misc.debug('on: {}, state before fullscreen: {}'.format( - on, debug.qflags_key(QtCore.Qt, self.state_before_fullscreen))) + log.misc.debug( + 'on: {}, state before fullscreen: {}'.format( + on, debug.qflags_key(QtCore.Qt, self.state_before_fullscreen) + ) + ) @cmdutils.register(instance='main-window', scope='window') @QtCore.pyqtSlot() diff --git a/qutebrowser/mainwindow/messageview.py b/qutebrowser/mainwindow/messageview.py index 4c6ca0ec2..120f34eea 100644 --- a/qutebrowser/mainwindow/messageview.py +++ b/qutebrowser/mainwindow/messageview.py @@ -31,11 +31,11 @@ class Message(QtWidgets.QLabel): """A single error/warning/info message.""" def __init__( - self, - level: usertypes.MessageLevel, - text: str, - replace: Optional[str], - parent: QtWidgets.QWidget = None, + self, + level: usertypes.MessageLevel, + text: str, + replace: Optional[str], + parent: QtWidgets.QWidget = None, ) -> None: super().__init__(text, parent) self.replace = replace @@ -150,5 +150,9 @@ class MessageView(QtWidgets.QWidget): def mousePressEvent(self, e): """Clear messages when they are clicked on.""" - if e.button() in [QtCore.Qt.LeftButton, QtCore.Qt.MiddleButton, QtCore.Qt.RightButton]: + if e.button() in [ + QtCore.Qt.LeftButton, + QtCore.Qt.MiddleButton, + QtCore.Qt.RightButton, + ]: self.clear_messages() diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py index a73076dfb..09376a7c5 100644 --- a/qutebrowser/mainwindow/prompt.py +++ b/qutebrowser/mainwindow/prompt.py @@ -190,8 +190,10 @@ class PromptQueue(QtCore.QObject): question.completed.connect(loop.quit) question.completed.connect(loop.deleteLater) log.prompt.debug("Starting loop.exec() for {}".format(question)) - flags = cast(QtCore.QEventLoop.ProcessEventsFlags, - QtCore.QEventLoop.ExcludeSocketNotifiers) + flags = cast( + QtCore.QEventLoop.ProcessEventsFlags, + QtCore.QEventLoop.ExcludeSocketNotifiers, + ) loop.exec(flags) log.prompt.debug("Ending loop.exec() for {}".format(question)) @@ -545,7 +547,9 @@ class _BasePrompt(QtWidgets.QWidget): binding = bindings[0] key_label = QtWidgets.QLabel('<b>{}</b>'.format(html.escape(binding))) else: - key_label = QtWidgets.QLabel(f'<b>unbound</b> (<tt>{html.escape(cmd)}</tt>)') + key_label = QtWidgets.QLabel( + f'<b>unbound</b> (<tt>{html.escape(cmd)}</tt>)' + ) text_label = QtWidgets.QLabel(text) labels.append((key_label, text_label)) @@ -636,7 +640,9 @@ class FilenamePrompt(_BasePrompt): self._set_fileview_root(question.default) if config.val.prompt.filebrowser: - self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + self.setSizePolicy( + QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred + ) self._to_complete = '' self._root_index = QtCore.QModelIndex() @@ -779,8 +785,9 @@ class FilenamePrompt(_BasePrompt): selmodel.setCurrentIndex( idx, - QtCore.QItemSelectionModel.ClearAndSelect | # type: ignore[arg-type] - QtCore.QItemSelectionModel.Rows) + QtCore.QItemSelectionModel.ClearAndSelect + | QtCore.QItemSelectionModel.Rows, # type: ignore[arg-type] + ) self._insert_path(idx, clicked=False) def _do_completion(self, idx, which): @@ -803,7 +810,8 @@ class DownloadFilenamePrompt(FilenamePrompt): def __init__(self, question, parent=None): super().__init__(question, parent) self._file_model.setFilter( - QtCore.QDir.AllDirs | QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot) # type: ignore[arg-type] + QtCore.QDir.AllDirs | QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot + ) # type: ignore[arg-type] def accept(self, value=None, save=False): done = super().accept(value, save) @@ -982,4 +990,5 @@ def init(): global prompt_queue prompt_queue = PromptQueue() message.global_bridge.ask_question.connect( # type: ignore[call-arg] - prompt_queue.ask_question, QtCore.Qt.DirectConnection) + prompt_queue.ask_question, QtCore.Qt.DirectConnection + ) diff --git a/qutebrowser/mainwindow/statusbar/command.py b/qutebrowser/mainwindow/statusbar/command.py index 34400337d..80319a9c9 100644 --- a/qutebrowser/mainwindow/statusbar/command.py +++ b/qutebrowser/mainwindow/statusbar/command.py @@ -56,9 +56,9 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): show_cmd = QtCore.pyqtSignal() hide_cmd = QtCore.pyqtSignal() - def __init__(self, *, win_id: int, - private: bool, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, *, win_id: int, private: bool, parent: QtWidgets.QWidget = None + ) -> None: misc.CommandLineEdit.__init__(self, parent=parent) misc.MinimalLineEditMixin.__init__(self) self._win_id = win_id @@ -66,7 +66,9 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): command_history = objreg.get('command-history') self.history.history = command_history.data self.history.changed.connect(command_history.changed) - self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Ignored) + self.setSizePolicy( + QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Ignored + ) self.cursorPositionChanged.connect(self.update_completion) self.textChanged.connect(self.update_completion) diff --git a/qutebrowser/mainwindow/statusbar/textbase.py b/qutebrowser/mainwindow/statusbar/textbase.py index 76d91f4c8..4fa0dc332 100644 --- a/qutebrowser/mainwindow/statusbar/textbase.py +++ b/qutebrowser/mainwindow/statusbar/textbase.py @@ -40,7 +40,9 @@ class TextBase(QtWidgets.QLabel): def __init__(self, parent=None, elidemode=QtCore.Qt.ElideRight): super().__init__(parent) - self.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + self.setSizePolicy( + QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum + ) self._elidemode = elidemode self._elided_text = '' @@ -55,7 +57,8 @@ class TextBase(QtWidgets.QLabel): """ if self.text(): self._elided_text = self.fontMetrics().elidedText( - self.text(), self._elidemode, width, QtCore.Qt.TextShowMnemonic) + self.text(), self._elidemode, width, QtCore.Qt.TextShowMnemonic + ) else: self._elided_text = '' diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 830f98120..113c60410 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -71,8 +71,9 @@ class TabDeque: size = config.val.tabs.focus_stack_size if size < 0: size = None - self._stack: Deque[weakref.ReferenceType[QtWidgets.QWidget]] = collections.deque( - maxlen=size) + self._stack: Deque[ + weakref.ReferenceType[QtWidgets.QWidget] + ] = collections.deque(maxlen=size) # Items that have been removed from the primary stack. self._stack_deleted: List[weakref.ReferenceType[QtWidgets.QWidget]] = [] self._ignore_next = False @@ -102,7 +103,9 @@ class TabDeque: self._ignore_next = True return tab - def next(self, cur_tab: QtWidgets.QWidget, *, keep_overflow: bool = True) -> QtWidgets.QWidget: + def next( + self, cur_tab: QtWidgets.QWidget, *, keep_overflow: bool = True + ) -> QtWidgets.QWidget: """Get the 'next' tab in the stack. Throws IndexError on failure. @@ -215,7 +218,9 @@ class TabbedBrowser(QtWidgets.QWidget): self.widget.new_tab_requested.connect(self.tabopen) self.widget.currentChanged.connect(self._on_current_changed) self.cur_fullscreen_requested.connect(self.widget.tabBar().maybe_hide) - self.widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.widget.setSizePolicy( + QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding + ) # load_finished instead of load_started as WORKAROUND for # https://bugreports.qt.io/browse/QTBUG-65223 @@ -564,10 +569,11 @@ class TabbedBrowser(QtWidgets.QWidget): @QtCore.pyqtSlot('QUrl', bool) @QtCore.pyqtSlot('QUrl', bool, bool) def tabopen( - self, url: QtCore.QUrl = None, - background: bool = None, - related: bool = True, - idx: int = None, + self, + url: QtCore.QUrl = None, + background: bool = None, + related: bool = True, + idx: int = None, ) -> browsertab.AbstractTab: """Open a new tab with a given URL. diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index c41e7e44c..092e69054 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -55,8 +55,9 @@ class TabWidget(QtWidgets.QTabWidget): self.setStyle(TabBarStyle()) self.setTabBar(bar) bar.tabCloseRequested.connect(self.tabCloseRequested) - bar.tabMoved.connect(functools.partial( - QtCore.QTimer.singleShot, 0, self.update_tab_titles)) + bar.tabMoved.connect( + functools.partial(QtCore.QTimer.singleShot, 0, self.update_tab_titles) + ) bar.currentChanged.connect(self._on_current_changed) bar.new_tab_requested.connect(self._on_new_tab_requested) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) @@ -77,7 +78,9 @@ class TabWidget(QtWidgets.QTabWidget): selection_behavior = config.val.tabs.select_on_remove self.setTabPosition(position) tabbar.vertical = position in [ # type: ignore[attr-defined] - QtWidgets.QTabWidget.West, QtWidgets.QTabWidget.East] + QtWidgets.QTabWidget.West, + QtWidgets.QTabWidget.East, + ] tabbar.setSelectionBehaviorOnRemove(selection_behavior) tabbar.refresh() @@ -532,8 +535,12 @@ class TabBar(QtWidgets.QTabBar): Also keep track of if we are currently in a drag.""" self.drag_in_progress = True button = config.val.tabs.close_mouse_button - if (e.button() == QtCore.Qt.RightButton and button == 'right' or - e.button() == QtCore.Qt.MiddleButton and button == 'middle'): + if ( + e.button() == QtCore.Qt.RightButton + and button == 'right' + or e.button() == QtCore.Qt.MiddleButton + and button == 'middle' + ): e.accept() idx = self.tabAt(e.pos()) if idx == -1: @@ -578,9 +585,9 @@ class TabBar(QtWidgets.QTabBar): icon_width, ellipsis, pinned) - def _minimum_tab_size_hint_helper_uncached(self, tab_text: str, - icon_width: int, - ellipsis: bool, pinned: bool) -> QtCore.QSize: + def _minimum_tab_size_hint_helper_uncached( + self, tab_text: str, icon_width: int, ellipsis: bool, pinned: bool + ) -> QtCore.QSize: """Helper function to cache tab results. Config values accessed in here should be added to _on_config_changed to @@ -692,10 +699,10 @@ class TabBar(QtWidgets.QTabBar): setting += '.selected' setting += '.odd' if (idx + 1) % 2 else '.even' - tab.palette.setColor(QtGui.QPalette.Window, - config.cache[setting + '.bg']) - tab.palette.setColor(QtGui.QPalette.WindowText, - config.cache[setting + '.fg']) + tab.palette.setColor(QtGui.QPalette.Window, config.cache[setting + '.bg']) + tab.palette.setColor( + QtGui.QPalette.WindowText, config.cache[setting + '.fg'] + ) indicator_color = self.tab_indicator_color(idx) tab.palette.setColor(QtGui.QPalette.Base, indicator_color) @@ -809,10 +816,16 @@ class TabBarStyle(QtWidgets.QCommonStyle): p: QPainter """ qtutils.ensure_valid(layouts.icon) - icon_mode = (QtGui.QIcon.Normal if opt.state & QtWidgets.QStyle.State_Enabled - else QtGui.QIcon.Disabled) - icon_state = (QtGui.QIcon.On if opt.state & QtWidgets.QStyle.State_Selected - else QtGui.QIcon.Off) + icon_mode = ( + QtGui.QIcon.Normal + if opt.state & QtWidgets.QStyle.State_Enabled + else QtGui.QIcon.Disabled + ) + icon_state = ( + QtGui.QIcon.On + if opt.state & QtWidgets.QStyle.State_Selected + else QtGui.QIcon.Off + ) icon = opt.icon.pixmap(opt.iconSize, icon_mode, icon_state) self._style.drawItemPixmap(p, layouts.icon, QtCore.Qt.AlignCenter, icon) @@ -828,8 +841,11 @@ class TabBarStyle(QtWidgets.QCommonStyle): p: QPainter widget: QWidget """ - if element not in [QtWidgets.QStyle.CE_TabBarTab, QtWidgets.QStyle.CE_TabBarTabShape, - QtWidgets.QStyle.CE_TabBarTabLabel]: + if element not in [ + QtWidgets.QStyle.CE_TabBarTab, + QtWidgets.QStyle.CE_TabBarTabShape, + QtWidgets.QStyle.CE_TabBarTabLabel, + ]: # Let the real style draw it. self._style.drawControl(element, opt, p, widget) return @@ -852,15 +868,20 @@ class TabBarStyle(QtWidgets.QCommonStyle): elif element == QtWidgets.QStyle.CE_TabBarTabLabel: if not opt.icon.isNull() and layouts.icon.isValid(): self._draw_icon(layouts, opt, p) - alignment = (config.cache['tabs.title.alignment'] | - QtCore.Qt.AlignVCenter | QtCore.Qt.TextHideMnemonic) - self._style.drawItemText(p, - layouts.text, - int(alignment), - opt.palette, - bool(opt.state & QtWidgets.QStyle.State_Enabled), - opt.text, - QtGui.QPalette.WindowText) + alignment = ( + config.cache['tabs.title.alignment'] + | QtCore.Qt.AlignVCenter + | QtCore.Qt.TextHideMnemonic + ) + self._style.drawItemText( + p, + layouts.text, + int(alignment), + opt.palette, + bool(opt.state & QtWidgets.QStyle.State_Enabled), + opt.text, + QtGui.QPalette.WindowText, + ) else: raise ValueError("Invalid element {!r}".format(element)) @@ -875,11 +896,13 @@ class TabBarStyle(QtWidgets.QCommonStyle): Return: An int. """ - if metric in [QtWidgets.QStyle.PM_TabBarTabShiftHorizontal, - QtWidgets.QStyle.PM_TabBarTabShiftVertical, - QtWidgets.QStyle.PM_TabBarTabHSpace, - QtWidgets.QStyle.PM_TabBarTabVSpace, - QtWidgets.QStyle.PM_TabBarScrollButtonWidth]: + if metric in [ + QtWidgets.QStyle.PM_TabBarTabShiftHorizontal, + QtWidgets.QStyle.PM_TabBarTabShiftVertical, + QtWidgets.QStyle.PM_TabBarTabHSpace, + QtWidgets.QStyle.PM_TabBarTabVSpace, + QtWidgets.QStyle.PM_TabBarScrollButtonWidth, + ]: return 0 else: return self._style.pixelMetric(metric, option, widget) @@ -901,8 +924,10 @@ class TabBarStyle(QtWidgets.QCommonStyle): log.misc.warning("Could not get layouts for tab!") return QtCore.QRect() return layouts.text - elif sr in [QtWidgets.QStyle.SE_TabWidgetTabBar, - QtWidgets.QStyle.SE_TabBarScrollLeftButton]: + elif sr in [ + QtWidgets.QStyle.SE_TabWidgetTabBar, + QtWidgets.QStyle.SE_TabBarScrollLeftButton, + ]: # Handling SE_TabBarScrollLeftButton so the left scroll button is # aligned properly. Otherwise, empty space will be shown after the # last tab even though the button width is set to 0 @@ -977,14 +1002,22 @@ class TabBarStyle(QtWidgets.QCommonStyle): if not icon_size.isValid(): icon_extent = self.pixelMetric(QtWidgets.QStyle.PM_SmallIconSize) icon_size = QtCore.QSize(icon_extent, icon_extent) - icon_mode = (QtGui.QIcon.Normal if opt.state & QtWidgets.QStyle.State_Enabled - else QtGui.QIcon.Disabled) - icon_state = (QtGui.QIcon.On if opt.state & QtWidgets.QStyle.State_Selected - else QtGui.QIcon.Off) + icon_mode = ( + QtGui.QIcon.Normal + if opt.state & QtWidgets.QStyle.State_Enabled + else QtGui.QIcon.Disabled + ) + icon_state = ( + QtGui.QIcon.On + if opt.state & QtWidgets.QStyle.State_Selected + else QtGui.QIcon.Off + ) # reserve space for favicon when tab bar is vertical (issue #1968) position = config.cache['tabs.position'] - if (position in [QtWidgets.QTabWidget.East, QtWidgets.QTabWidget.West] and - config.cache['tabs.favicons.show'] != 'never'): + if ( + position in [QtWidgets.QTabWidget.East, QtWidgets.QTabWidget.West] + and config.cache['tabs.favicons.show'] != 'never' + ): tab_icon_size = icon_size else: actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state) @@ -993,6 +1026,8 @@ class TabBarStyle(QtWidgets.QCommonStyle): min(actual_size.height(), icon_size.height())) icon_top = text_rect.center().y() + 1 - tab_icon_size.height() // 2 - icon_rect = QtCore.QRect(QtCore.QPoint(text_rect.left(), icon_top), tab_icon_size) + icon_rect = QtCore.QRect( + QtCore.QPoint(text_rect.left(), icon_top), tab_icon_size + ) icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect) return icon_rect diff --git a/qutebrowser/misc/backendproblem.py b/qutebrowser/misc/backendproblem.py index c318c2f80..46f11f1e3 100644 --- a/qutebrowser/misc/backendproblem.py +++ b/qutebrowser/misc/backendproblem.py @@ -29,7 +29,14 @@ import argparse import dataclasses from typing import Any, List, Sequence, Tuple, Optional -from qutebrowser.qt import QtWidgets, QtWebKitWidgets, QtWebKit, QtWebEngineWidgets, QtNetwork, QtCore +from qutebrowser.qt import ( + QtWidgets, + QtWebKitWidgets, + QtWebKit, + QtWebEngineWidgets, + QtNetwork, + QtCore, +) from qutebrowser.config import config, configfiles from qutebrowser.utils import (usertypes, version, qtutils, log, utils, @@ -95,11 +102,15 @@ class _Dialog(QtWidgets.QDialog): """A dialog which gets shown if there are issues with the backend.""" - def __init__(self, *, because: str, - text: str, - backend: usertypes.Backend, - buttons: Sequence[_Button] = None, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + *, + because: str, + text: str, + backend: usertypes.Backend, + buttons: Sequence[_Button] = None, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(parent) vbox = QtWidgets.QVBoxLayout(self) @@ -299,11 +310,13 @@ class _BackendProblemChecker: "affects downloads and :adblock-update.".format(version_text)) if fatal: - errbox = msgbox.msgbox(parent=None, - title="SSL error", - text="Could not initialize SSL support.", - icon=QtWidgets.QMessageBox.Critical, - plain_text=False) + errbox = msgbox.msgbox( + parent=None, + title="SSL error", + text="Could not initialize SSL support.", + icon=QtWidgets.QMessageBox.Critical, + plain_text=False, + ) errbox.exec() sys.exit(usertypes.Exit.err_init) @@ -317,19 +330,24 @@ class _BackendProblemChecker: if not imports.webkit_error and not imports.webengine_error: return elif imports.webkit_error and imports.webengine_error: - text = ("<p>qutebrowser needs QtWebKit or QtWebEngine, but " - "neither could be imported!</p>" - "<p>The errors encountered were:<ul>" - "<li><b>QtWebKit:</b> {webkit_error}" - "<li><b>QtWebEngine:</b> {webengine_error}" - "</ul></p>".format( - webkit_error=html.escape(imports.webkit_error), - webengine_error=html.escape(imports.webengine_error))) - errbox = msgbox.msgbox(parent=None, - title="No backend library found!", - text=text, - icon=QtWidgets.QMessageBox.Critical, - plain_text=False) + text = ( + "<p>qutebrowser needs QtWebKit or QtWebEngine, but " + "neither could be imported!</p>" + "<p>The errors encountered were:<ul>" + "<li><b>QtWebKit:</b> {webkit_error}" + "<li><b>QtWebEngine:</b> {webengine_error}" + "</ul></p>".format( + webkit_error=html.escape(imports.webkit_error), + webengine_error=html.escape(imports.webengine_error), + ) + ) + errbox = msgbox.msgbox( + parent=None, + title="No backend library found!", + text=text, + icon=QtWidgets.QMessageBox.Critical, + plain_text=False, + ) errbox.exec() sys.exit(usertypes.Exit.err_init) elif objects.backend == usertypes.Backend.QtWebKit: diff --git a/qutebrowser/misc/crashdialog.py b/qutebrowser/misc/crashdialog.py index bc484ea87..a22bc85a2 100644 --- a/qutebrowser/misc/crashdialog.py +++ b/qutebrowser/misc/crashdialog.py @@ -169,9 +169,11 @@ class _CrashDialog(QtWidgets.QDialog): def _init_contact_input(self): """Initialize the widget asking for contact info.""" - contact = QtWidgets.QLabel("I'd like to be able to follow up with you, to keep " - "you posted on the status of this crash and get more " - "information if I need it - how can I contact you?") + contact = QtWidgets.QLabel( + "I'd like to be able to follow up with you, to keep " + "you posted on the status of this crash and get more " + "information if I need it - how can I contact you?" + ) contact.setWordWrap(True) self._vbox.addWidget(contact) self._contact = QtWidgets.QTextEdit() @@ -220,11 +222,13 @@ class _CrashDialog(QtWidgets.QDialog): def _init_info_text(self): """Add an info text encouraging the user to report crashes.""" - info_label = QtWidgets.QLabel("<br/>There is currently a big backlog of crash " - "reports. Thus, it might take a while until your " - "report is seen.<br/>A new tool allowing for more " - "automation will fix this, but is not ready yet " - "at this point.") + info_label = QtWidgets.QLabel( + "<br/>There is currently a big backlog of crash " + "reports. Thus, it might take a while until your " + "report is seen.<br/>A new tool allowing for more " + "automation will fix this, but is not ready yet " + "at this point." + ) info_label.setWordWrap(True) self._vbox.addWidget(info_label) @@ -429,11 +433,13 @@ class ExceptionCrashDialog(_CrashDialog): log.misc.exception("Error while checking private browsing mode") self._chk_log.toggled.connect(self._set_crash_info) self._vbox.addWidget(self._chk_log) - info_label = QtWidgets.QLabel("This makes it a lot easier to diagnose the " - "crash.<br/><b>Note that the log might contain " - "sensitive information such as which pages you " - "visited or keyboard input.</b><br/>You can show " - "and edit the log above.") + info_label = QtWidgets.QLabel( + "This makes it a lot easier to diagnose the " + "crash.<br/><b>Note that the log might contain " + "sensitive information such as which pages you " + "visited or keyboard input.</b><br/>You can show " + "and edit the log above." + ) info_label.setWordWrap(True) self._vbox.addWidget(info_label) @@ -515,8 +521,9 @@ class FatalCrashDialog(_CrashDialog): def _init_checkboxes(self): """Add checkboxes to the dialog.""" super()._init_checkboxes() - self._chk_history = QtWidgets.QCheckBox("Include a history of the last " - "accessed pages in the report.") + self._chk_history = QtWidgets.QCheckBox( + "Include a history of the last " "accessed pages in the report." + ) self._chk_history.setChecked(True) try: if config.val.content.private_browsing: @@ -543,17 +550,22 @@ class FatalCrashDialog(_CrashDialog): @QtCore.pyqtSlot() def on_report_clicked(self): """Prevent empty reports.""" - if (not self._info.toPlainText().strip() and - not self._contact.toPlainText().strip() and - self._get_error_type() == 'segv' and - self._func == 'qt_mainloop'): - msgbox.msgbox(parent=self, title='Empty crash info', - text="Empty reports for fatal crashes are useless " - "and mean I'll spend time deleting reports I could " - "spend on developing qutebrowser instead.\n\nPlease " - "help making qutebrowser better by providing more " - "information, or don't report this.", - icon=QtWidgets.QMessageBox.Critical) + if ( + not self._info.toPlainText().strip() + and not self._contact.toPlainText().strip() + and self._get_error_type() == 'segv' + and self._func == 'qt_mainloop' + ): + msgbox.msgbox( + parent=self, + title='Empty crash info', + text="Empty reports for fatal crashes are useless " + "and mean I'll spend time deleting reports I could " + "spend on developing qutebrowser instead.\n\nPlease " + "help making qutebrowser better by providing more " + "information, or don't report this.", + icon=QtWidgets.QMessageBox.Critical, + ) else: super().on_report_clicked() @@ -611,12 +623,13 @@ class ReportErrorDialog(QtWidgets.QDialog): def __init__(self, exc_text, text, parent=None): super().__init__(parent) vbox = QtWidgets.QVBoxLayout(self) - label = QtWidgets.QLabel("<b>There was an error while reporting the crash</b>:" - "<br/>{}<br/><br/>" - "Please copy the text below and send a mail to " - "<a href='mailto:crash@qutebrowser.org'>" - "crash@qutebrowser.org</a> - Thanks!".format( - html.escape(exc_text))) + label = QtWidgets.QLabel( + "<b>There was an error while reporting the crash</b>:" + "<br/>{}<br/><br/>" + "Please copy the text below and send a mail to " + "<a href='mailto:crash@qutebrowser.org'>" + "crash@qutebrowser.org</a> - Thanks!".format(html.escape(exc_text)) + ) vbox.addWidget(label) txt = QtWidgets.QTextEdit() txt.setReadOnly(True) diff --git a/qutebrowser/misc/crashsignal.py b/qutebrowser/misc/crashsignal.py index ccfd51276..2daffcd26 100644 --- a/qutebrowser/misc/crashsignal.py +++ b/qutebrowser/misc/crashsignal.py @@ -132,7 +132,8 @@ class CrashHandler(QtCore.QObject): for tab in tabbed_browser.widgets(): try: urlstr = tab.url().toString( - QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded) + QtCore.QUrl.RemovePassword | QtCore.QUrl.FullyEncoded + ) if urlstr: win_pages.append(urlstr) except Exception: @@ -355,9 +356,9 @@ class SignalHandler(QtCore.QObject): for fd in [read_fd, write_fd]: flags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) - self._notifier = QtCore.QSocketNotifier(cast(sip.voidptr, read_fd), - QtCore.QSocketNotifier.Read, - self) + self._notifier = QtCore.QSocketNotifier( + cast(sip.voidptr, read_fd), QtCore.QSocketNotifier.Read, self + ) self._notifier.activated.connect( # type: ignore[attr-defined] self.handle_signal_wakeup) self._orig_wakeup_fd = signal.set_wakeup_fd(write_fd) @@ -415,10 +416,13 @@ class SignalHandler(QtCore.QObject): signal.signal(signal.SIGINT, self.interrupt_forcefully) signal.signal(signal.SIGTERM, self.interrupt_forcefully) # Signals can arrive anywhere, so we do this in the main thread - self._log_later("SIGINT/SIGTERM received, shutting down!", - "Do the same again to forcefully quit.") - QtCore.QTimer.singleShot(0, functools.partial( - self._quitter.shutdown, 128 + signum)) + self._log_later( + "SIGINT/SIGTERM received, shutting down!", + "Do the same again to forcefully quit.", + ) + QtCore.QTimer.singleShot( + 0, functools.partial(self._quitter.shutdown, 128 + signum) + ) def interrupt_forcefully(self, signum, _frame): """Interrupt forcefully on the second SIGINT/SIGTERM request. @@ -444,9 +448,9 @@ class SignalHandler(QtCore.QObject): sys.exit(128 + signum) -def init(q_app: QtWidgets.QApplication, - args: argparse.Namespace, - quitter: 'quitter.Quitter') -> None: +def init( + q_app: QtWidgets.QApplication, args: argparse.Namespace, quitter: 'quitter.Quitter' +) -> None: """Initialize crash/signal handlers.""" global crash_handler crash_handler = CrashHandler( diff --git a/qutebrowser/misc/earlyinit.py b/qutebrowser/misc/earlyinit.py index d0396ced8..7ebe2c69f 100644 --- a/qutebrowser/misc/earlyinit.py +++ b/qutebrowser/misc/earlyinit.py @@ -90,8 +90,9 @@ def _die(message, exception=None): else: if exception is not None: message = message.replace('%ERROR%', str(exception)) - msgbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "qutebrowser: Fatal error!", - message) + msgbox = QtWidgets.QMessageBox( + QtWidgets.QMessageBox.Critical, "qutebrowser: Fatal error!", message + ) msgbox.setTextFormat(QtCore.Qt.RichText) msgbox.resize(msgbox.sizeHint()) msgbox.exec() @@ -140,6 +141,7 @@ def check_pyqt(): pyqt_name = "PyQt6" try: import PyQt5 + pyqt_name = PyQt5.__name__ except ImportError: pass @@ -189,10 +191,17 @@ def check_qt_version(): # QVersionNumber was added in Qt 5.6, QLibraryInfo.version() in 5.8 recent_qt_runtime = False - if QtCore.QT_VERSION < 0x050C00 or QtCore.PYQT_VERSION < 0x050C00 or not recent_qt_runtime: - text = ("Fatal error: Qt >= 5.12.0 and PyQt >= 5.12.0 are required, " - "but Qt {} / PyQt {} is installed.".format(qt_version(), - QtCore.PYQT_VERSION_STR)) + if ( + QtCore.QT_VERSION < 0x050C00 + or QtCore.PYQT_VERSION < 0x050C00 + or not recent_qt_runtime + ): + text = ( + "Fatal error: Qt >= 5.12.0 and PyQt >= 5.12.0 are required, " + "but Qt {} / PyQt {} is installed.".format( + qt_version(), QtCore.PYQT_VERSION_STR + ) + ) _die(text) if qt_ver == QtCore.QVersionNumber(5, 12, 0): @@ -204,6 +213,7 @@ def check_qt_version(): def check_ssl_support(): """Check if SSL support is available.""" from qutebrowser.qt import QtNetwork + if not QtNetwork or not QtNetwork.QSslSocket: _die("Fatal error: Your Qt is built without SSL support.") @@ -238,9 +248,11 @@ def check_libraries(): pyqt_name = None try: import PyQt5 + pyqt_name = PyQt5.__name__ except ImportError: import PyQt6 # type: ignore[import] + pyqt_name = PyQt6.__name__ modules = { diff --git a/qutebrowser/misc/elf.py b/qutebrowser/misc/elf.py index 42442ff5f..2779bf2d3 100644 --- a/qutebrowser/misc/elf.py +++ b/qutebrowser/misc/elf.py @@ -314,7 +314,9 @@ def parse_webenginecore() -> Optional[Versions]: # Flatpak has Qt in /usr/lib/x86_64-linux-gnu, but QtWebEngine in /app/lib. library_path = pathlib.Path("/app/lib") else: - library_path = pathlib.Path(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.LibrariesPath)) + library_path = pathlib.Path( + QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.LibrariesPath) + ) library_name = sorted(library_path.glob('libQt5WebEngineCore.so*')) if not library_name: diff --git a/qutebrowser/misc/guiprocess.py b/qutebrowser/misc/guiprocess.py index e417b6de8..32f8cb99d 100644 --- a/qutebrowser/misc/guiprocess.py +++ b/qutebrowser/misc/guiprocess.py @@ -153,13 +153,13 @@ class GUIProcess(QtCore.QObject): started = QtCore.pyqtSignal() def __init__( - self, - what: str, - *, - verbose: bool = False, - additional_env: Mapping[str, str] = None, - output_messages: bool = False, - parent: QtCore.QObject = None, + self, + what: str, + *, + verbose: bool = False, + additional_env: Mapping[str, str] = None, + output_messages: bool = False, + parent: QtCore.QObject = None, ): super().__init__(parent) self.what = what diff --git a/qutebrowser/misc/httpclient.py b/qutebrowser/misc/httpclient.py index d401c83c1..5f1a1a37d 100644 --- a/qutebrowser/misc/httpclient.py +++ b/qutebrowser/misc/httpclient.py @@ -32,8 +32,10 @@ class HTTPRequest(QtNetwork.QNetworkRequest): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.setAttribute(QtNetwork.QNetworkRequest.RedirectPolicyAttribute, - QtNetwork.QNetworkRequest.NoLessSafeRedirectPolicy) + self.setAttribute( + QtNetwork.QNetworkRequest.RedirectPolicyAttribute, + QtNetwork.QNetworkRequest.NoLessSafeRedirectPolicy, + ) class HTTPClient(QtCore.QObject): @@ -75,8 +77,10 @@ class HTTPClient(QtCore.QObject): data = {} encoded_data = urllib.parse.urlencode(data).encode('utf-8') request = HTTPRequest(url) - request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, - 'application/x-www-form-urlencoded;charset=utf-8') + request.setHeader( + QtNetwork.QNetworkRequest.ContentTypeHeader, + 'application/x-www-form-urlencoded;charset=utf-8', + ) reply = self._nam.post(request, encoded_data) self._handle_reply(reply) diff --git a/qutebrowser/misc/ipc.py b/qutebrowser/misc/ipc.py index 8ecd6213b..c372837de 100644 --- a/qutebrowser/misc/ipc.py +++ b/qutebrowser/misc/ipc.py @@ -221,7 +221,10 @@ class IPCServer(QtCore.QObject): self._remove_server() ok = self._server.listen(self._socketname) if not ok: - if self._server.serverError() == QtNetwork.QAbstractSocket.AddressInUseError: + if ( + self._server.serverError() + == QtNetwork.QAbstractSocket.AddressInUseError + ): raise AddressInUseError(self._server) raise ListenError(self._server) @@ -273,8 +276,10 @@ class IPCServer(QtCore.QObject): log.ipc.debug("We can read a line immediately.") self.on_ready_read() socket.error.connect(self.on_error) # type: ignore[attr-defined] - if socket.error() not in [QtNetwork.QLocalSocket.UnknownSocketError, - QtNetwork.QLocalSocket.PeerClosedError]: + if socket.error() not in [ + QtNetwork.QLocalSocket.UnknownSocketError, + QtNetwork.QLocalSocket.PeerClosedError, + ]: log.ipc.debug("We got an error immediately.") self.on_error(socket.error()) socket.disconnected.connect( # type: ignore[attr-defined] @@ -497,8 +502,10 @@ def send_to_running_instance(socketname, command, target_arg, *, socket=None): socket.waitForDisconnected(CONNECT_TIMEOUT) return True else: - if socket.error() not in [QtNetwork.QLocalSocket.ConnectionRefusedError, - QtNetwork.QLocalSocket.ServerNotFoundError]: + if socket.error() not in [ + QtNetwork.QLocalSocket.ConnectionRefusedError, + QtNetwork.QLocalSocket.ServerNotFoundError, + ]: raise SocketError("connecting to running instance", socket) log.ipc.debug("No existing instance present (error {})".format( socket.error())) diff --git a/qutebrowser/misc/miscwidgets.py b/qutebrowser/misc/miscwidgets.py index 1e046caa8..381de9cbe 100644 --- a/qutebrowser/misc/miscwidgets.py +++ b/qutebrowser/misc/miscwidgets.py @@ -44,7 +44,8 @@ class MinimalLineEditMixin: """ ) self.setAttribute( # type: ignore[attr-defined] - QtCore.Qt.WA_MacShowFocusRect, False) + QtCore.Qt.WA_MacShowFocusRect, False + ) def keyPressEvent(self, e): """Override keyPressEvent to paste primary selection on Shift + Ins.""" @@ -337,8 +338,12 @@ class InspectorSplitter(QtWidgets.QSplitter): _PROTECTED_MAIN_SIZE = 150 _SMALL_SIZE_THRESHOLD = 300 - def __init__(self, win_id: int, main_webview: QtWidgets.QWidget, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + win_id: int, + main_webview: QtWidgets.QWidget, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(parent) self._win_id = win_id self.addWidget(main_webview) @@ -382,10 +387,11 @@ class InspectorSplitter(QtWidgets.QSplitter): self._inspector_idx = 0 self._main_idx = 1 - self.setOrientation(QtCore.Qt.Horizontal - if position in [inspector.Position.left, - inspector.Position.right] - else QtCore.Qt.Vertical) + self.setOrientation( + QtCore.Qt.Horizontal + if position in [inspector.Position.left, inspector.Position.right] + else QtCore.Qt.Vertical + ) self.insertWidget(self._inspector_idx, inspector_widget) self._position = position self._load_preferred_size() @@ -400,8 +406,11 @@ class InspectorSplitter(QtWidgets.QSplitter): def _load_preferred_size(self) -> None: """Load the preferred size of the inspector widget.""" assert self._position is not None - full = (self.width() if self.orientation() == QtCore.Qt.Horizontal - else self.height()) + full = ( + self.width() + if self.orientation() == QtCore.Qt.Horizontal + else self.height() + ) # If we first open the inspector with a window size of < 300px # (self._SMALL_SIZE_THRESHOLD), we don't want to default to half of the diff --git a/qutebrowser/misc/msgbox.py b/qutebrowser/misc/msgbox.py index a56b4fee8..f03eda8e3 100644 --- a/qutebrowser/misc/msgbox.py +++ b/qutebrowser/misc/msgbox.py @@ -33,8 +33,16 @@ class DummyBox: pass -def msgbox(parent, title, text, *, icon, buttons=QtWidgets.QMessageBox.Ok, - on_finished=None, plain_text=None): +def msgbox( + parent, + title, + text, + *, + icon, + buttons=QtWidgets.QMessageBox.Ok, + on_finished=None, + plain_text=None, +): """Display a QMessageBox with the given icon. Args: diff --git a/qutebrowser/misc/quitter.py b/qutebrowser/misc/quitter.py index 2eb7a7a36..4c7cca233 100644 --- a/qutebrowser/misc/quitter.py +++ b/qutebrowser/misc/quitter.py @@ -59,9 +59,9 @@ class Quitter(QtCore.QObject): shutting_down = QtCore.pyqtSignal() # Emitted immediately before shut down - def __init__(self, *, - args: argparse.Namespace, - parent: QtCore.QObject = None) -> None: + def __init__( + self, *, args: argparse.Namespace, parent: QtCore.QObject = None + ) -> None: super().__init__(parent) self.quit_status = { 'crash': True, @@ -227,10 +227,10 @@ class Quitter(QtCore.QObject): # one. # This means we need to defer the real shutdown to when we're back # in the real main event loop, or we'll get a segfault. - log.destroy.debug("Deferring real shutdown because question was " - "active.") - QtCore.QTimer.singleShot(0, functools.partial(self._shutdown_2, status, - is_restart=is_restart)) + log.destroy.debug("Deferring real shutdown because question was " "active.") + QtCore.QTimer.singleShot( + 0, functools.partial(self._shutdown_2, status, is_restart=is_restart) + ) else: # If we have no questions to shut down, we are already in the real # event loop, so we can shut down immediately. diff --git a/qutebrowser/misc/sql.py b/qutebrowser/misc/sql.py index 03de94a33..a3a560a8c 100644 --- a/qutebrowser/misc/sql.py +++ b/qutebrowser/misc/sql.py @@ -209,9 +209,13 @@ class Database: """Return a Query instance linked to this Database.""" return Query(self, querystr, forward_only) - def table(self, name: str, fields: List[str], - constraints: Optional[Dict[str, str]] = None, - parent: Optional[QtCore.QObject] = None) -> 'SqlTable': + def table( + self, + name: str, + fields: List[str], + constraints: Optional[Dict[str, str]] = None, + parent: Optional[QtCore.QObject] = None, + ) -> 'SqlTable': """Return a SqlTable instance linked to this Database.""" return SqlTable(self, name, fields, constraints, parent) @@ -393,9 +397,14 @@ class SqlTable(QtCore.QObject): changed = QtCore.pyqtSignal() database: Database - def __init__(self, database: Database, name: str, fields: List[str], - constraints: Optional[Dict[str, str]] = None, - parent: Optional[QtCore.QObject] = None) -> None: + def __init__( + self, + database: Database, + name: str, + fields: List[str], + constraints: Optional[Dict[str, str]] = None, + parent: Optional[QtCore.QObject] = None, + ) -> None: """Wrapper over a table in the SQL database. Args: diff --git a/qutebrowser/misc/throttle.py b/qutebrowser/misc/throttle.py index 567951878..be4fa4d29 100644 --- a/qutebrowser/misc/throttle.py +++ b/qutebrowser/misc/throttle.py @@ -44,10 +44,9 @@ class Throttle(QtCore.QObject): ends. If another request comes in, it will update the pending request. """ - def __init__(self, - func: Callable[..., None], - delay_ms: int, - parent: QtCore.QObject = None) -> None: + def __init__( + self, func: Callable[..., None], delay_ms: int, parent: QtCore.QObject = None + ) -> None: """Constructor. Args: diff --git a/qutebrowser/qt.py b/qutebrowser/qt.py index 23e92ba36..933d09054 100644 --- a/qutebrowser/qt.py +++ b/qutebrowser/qt.py @@ -25,9 +25,11 @@ import importlib PyQt5 = PyQt6 = False try: import PyQt5 as pyqt # noqa: N813 + PyQt5 = True except ImportError: import PyQt6 as pyqt # type: ignore[import, no-redef] # noqa: N813 + PyQt6 = True # While upstream recommends using PyQt5.sip ever since PyQt5 5.11, some distributions diff --git a/qutebrowser/utils/debug.py b/qutebrowser/utils/debug.py index b52220730..e4cf0cc28 100644 --- a/qutebrowser/utils/debug.py +++ b/qutebrowser/utils/debug.py @@ -40,8 +40,11 @@ def log_events(klass: Type[QtCore.QObject]) -> Type[QtCore.QObject]: @functools.wraps(old_event) def new_event(self: Any, e: QtCore.QEvent) -> bool: """Wrapper for event() which logs events.""" - log.misc.debug("Event in {}: {}".format(utils.qualname(klass), - qenum_key(QtCore.QEvent, e.type()))) + log.misc.debug( + "Event in {}: {}".format( + utils.qualname(klass), qenum_key(QtCore.QEvent, e.type()) + ) + ) return old_event(self, e) klass.event = new_event # type: ignore[assignment] @@ -53,7 +56,10 @@ def log_signals(obj: QtCore.QObject) -> QtCore.QObject: Can be used as class decorator. """ - def log_slot(obj: QtCore.QObject, signal: QtCore.pyqtBoundSignal, *args: Any) -> None: + + def log_slot( + obj: QtCore.QObject, signal: QtCore.pyqtBoundSignal, *args: Any + ) -> None: """Slot connected to a signal to log it.""" dbg = dbg_signal(signal, args) try: @@ -321,9 +327,9 @@ def _get_widgets() -> Sequence[str]: return [repr(w) for w in widgets] -def _get_pyqt_objects(lines: MutableSequence[str], - obj: QtCore.QObject, - depth: int = 0) -> None: +def _get_pyqt_objects( + lines: MutableSequence[str], obj: QtCore.QObject, depth: int = 0 +) -> None: """Recursive method for get_all_objects to get Qt objects.""" for kid in obj.findChildren(QtCore.QObject, '', QtCore.Qt.FindDirectChildrenOnly): lines.append(' ' * depth + repr(kid)) diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py index 5a3e4ba00..93b2cc33b 100644 --- a/qutebrowser/utils/message.py +++ b/qutebrowser/utils/message.py @@ -83,13 +83,16 @@ def info(message: str, *, replace: str = None) -> None: global_bridge.show(usertypes.MessageLevel.info, message, replace) -def _build_question(title: str, - text: str = None, *, - mode: usertypes.PromptMode, - default: Union[None, bool, str] = None, - abort_on: Iterable[QtCore.pyqtBoundSignal] = (), - url: str = None, - option: bool = None) -> usertypes.Question: +def _build_question( + title: str, + text: str = None, + *, + mode: usertypes.PromptMode, + default: Union[None, bool, str] = None, + abort_on: Iterable[QtCore.pyqtBoundSignal] = (), + url: str = None, + option: bool = None +) -> usertypes.Question: """Common function for ask/ask_async.""" question = usertypes.Question() question.title = title diff --git a/qutebrowser/utils/qtutils.py b/qutebrowser/utils/qtutils.py index 90e7d252a..45cb821a2 100644 --- a/qutebrowser/utils/qtutils.py +++ b/qutebrowser/utils/qtutils.py @@ -34,6 +34,7 @@ import contextlib from typing import (Any, AnyStr, TYPE_CHECKING, BinaryIO, IO, Iterator, Optional, Union, Tuple, cast) from qutebrowser.qt import QtWebKit, QtGui + if QtWebKit: qWebKitVersion = QtWebKit.qWebKitVersion # noqa: N816 else: @@ -170,11 +171,14 @@ def check_qdatastream(stream: QtCore.QDataStream) -> None: """Check the status of a QDataStream and raise OSError if it's not ok.""" status_to_str = { QtCore.QDataStream.Ok: "The data stream is operating normally.", - QtCore.QDataStream.ReadPastEnd: ("The data stream has read past the end of " - "the data in the underlying device."), + QtCore.QDataStream.ReadPastEnd: ( + "The data stream has read past the end of " + "the data in the underlying device." + ), QtCore.QDataStream.ReadCorruptData: "The data stream has read corrupt data.", - QtCore.QDataStream.WriteFailed: ("The data stream cannot write to the " - "underlying device."), + QtCore.QDataStream.WriteFailed: ( + "The data stream cannot write to the " "underlying device." + ), } if stream.status() != QtCore.QDataStream.Ok: raise OSError(status_to_str[stream.status()]) @@ -185,7 +189,7 @@ _QtSerializableType = Union[ QtCore.QByteArray, QtCore.QUrl, 'QtWebEngineWidgets.QWebEngineHistory', - 'QtWebKit.QWebHistory' + 'QtWebKit.QWebHistory', ] @@ -458,9 +462,10 @@ class EventLoop(QtCore.QEventLoop): self._executing = False def exec( - self, - flags: QtCore.QEventLoop.ProcessEventsFlags = - cast(QtCore.QEventLoop.ProcessEventsFlags, QtCore.QEventLoop.AllEvents) + self, + flags: QtCore.QEventLoop.ProcessEventsFlags = cast( + QtCore.QEventLoop.ProcessEventsFlags, QtCore.QEventLoop.AllEvents + ), ) -> int: """Override exec_ to raise an exception when re-running.""" if self._executing: @@ -496,10 +501,10 @@ def _get_color_percentage(x1: int, y1: int, z1: int, a1: int, def interpolate_color( - start: QtGui.QColor, - end: QtGui.QColor, - percent: int, - colorspace: Optional[QtGui.QColor.Spec] = QtGui.QColor.Rgb + start: QtGui.QColor, + end: QtGui.QColor, + percent: int, + colorspace: Optional[QtGui.QColor.Spec] = QtGui.QColor.Rgb, ) -> QtGui.QColor: """Get an interpolated color value. diff --git a/qutebrowser/utils/standarddir.py b/qutebrowser/utils/standarddir.py index 205e62f3d..b1372f109 100644 --- a/qutebrowser/utils/standarddir.py +++ b/qutebrowser/utils/standarddir.py @@ -80,8 +80,7 @@ def _init_config(args: Optional[argparse.Namespace]) -> None: path = _from_args(typ, args) if path is None: if utils.is_windows: - app_data_path = _writable_location( - QtCore.QStandardPaths.AppDataLocation) + app_data_path = _writable_location(QtCore.QStandardPaths.AppDataLocation) path = os.path.join(app_data_path, 'config') else: path = _writable_location(typ) @@ -220,7 +219,8 @@ def _init_runtime(args: Optional[argparse.Namespace]) -> None: if typ == QtCore.QStandardPaths.TempLocation: raise path = _writable_location( # pragma: no cover - QtCore.QStandardPaths.TempLocation) + QtCore.QStandardPaths.TempLocation + ) # This is generic, but per-user. # _writable_location makes sure we have a qutebrowser-specific subdir. @@ -262,10 +262,14 @@ def _writable_location(typ: QtCore.QStandardPaths.StandardLocation) -> str: # Types we are sure we handle correctly below. assert typ in [ - QtCore.QStandardPaths.ConfigLocation, QtCore.QStandardPaths.AppLocalDataLocation, - QtCore.QStandardPaths.CacheLocation, QtCore.QStandardPaths.DownloadLocation, - QtCore.QStandardPaths.RuntimeLocation, QtCore.QStandardPaths.TempLocation, - QtCore.QStandardPaths.AppDataLocation], typ_str + QtCore.QStandardPaths.ConfigLocation, + QtCore.QStandardPaths.AppLocalDataLocation, + QtCore.QStandardPaths.CacheLocation, + QtCore.QStandardPaths.DownloadLocation, + QtCore.QStandardPaths.RuntimeLocation, + QtCore.QStandardPaths.TempLocation, + QtCore.QStandardPaths.AppDataLocation, + ], typ_str with _unset_organization(): path = QtCore.QStandardPaths.writableLocation(typ) @@ -280,16 +284,17 @@ def _writable_location(typ: QtCore.QStandardPaths.StandardLocation) -> str: # Add the application name to the given path if needed. # This is in order for this to work without a QApplication (and thus # QStandardsPaths not knowing the application name). - if (typ != QtCore.QStandardPaths.DownloadLocation and - path.split(os.sep)[-1] != APPNAME): + if ( + typ != QtCore.QStandardPaths.DownloadLocation + and path.split(os.sep)[-1] != APPNAME + ): path = os.path.join(path, APPNAME) return path def _from_args( - typ: QtCore.QStandardPaths.StandardLocation, - args: Optional[argparse.Namespace] + typ: QtCore.QStandardPaths.StandardLocation, args: Optional[argparse.Namespace] ) -> Optional[str]: """Get the standard directory from an argparse namespace. diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index 2a6b55db7..3d022e95e 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -174,8 +174,10 @@ def _is_url_dns(urlstr: str) -> bool: url = QtCore.QUrl.fromUserInput(urlstr) assert url.isValid() - if (utils.raises(ValueError, ipaddress.ip_address, urlstr) and - not QtNetwork.QHostAddress(urlstr).isNull()): + if ( + utils.raises(ValueError, ipaddress.ip_address, urlstr) + and not QtNetwork.QHostAddress(urlstr).isNull() + ): log.url.debug("Bogus IP URL -> False") # Qt treats things like "23.42" or "1337" or "0xDEAD" as valid URLs # which we don't want to. @@ -190,11 +192,13 @@ def _is_url_dns(urlstr: str) -> bool: return not info.error() -def fuzzy_url(urlstr: str, - cwd: str = None, - relative: bool = False, - do_search: bool = True, - force_search: bool = False) -> QtCore.QUrl: +def fuzzy_url( + urlstr: str, + cwd: str = None, + relative: bool = False, + do_search: bool = True, + force_search: bool = False, +) -> QtCore.QUrl: """Get a QUrl based on a user input which is URL or search term. Args: diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index 748278db8..fc3cf94f4 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -43,6 +43,8 @@ except ImportError: # pragma: no cover class Protocol: """Empty stub at runtime.""" + + from qutebrowser.qt import QtWidgets import yaml diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 3c694b512..3870ea1cb 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -34,8 +34,16 @@ import datetime import getpass import functools import dataclasses -from typing import (Mapping, Optional, Sequence, Tuple, ClassVar, Dict, cast, - TYPE_CHECKING) +from typing import ( + Mapping, + Optional, + Sequence, + Tuple, + ClassVar, + Dict, + cast, + TYPE_CHECKING, +) from qutebrowser.qt import QtWidgets, QtWebKit, QtWebEngine, QtNetwork if QtWebKit: @@ -389,22 +397,23 @@ class ModuleInfo: return text -MODULE_INFO: Mapping[str, ModuleInfo] = collections.OrderedDict([ - # FIXME: Mypy doesn't understand this. See https://github.com/python/mypy/issues/9706 - (name, ModuleInfo(name, *args)) # type: ignore[arg-type, misc] - for (name, *args) in +MODULE_INFO: Mapping[str, ModuleInfo] = collections.OrderedDict( [ - ('sip', ['SIP_VERSION_STR']), - ('colorama', ['VERSION', '__version__']), - ('jinja2', ['__version__']), - ('pygments', ['__version__']), - ('yaml', ['__version__']), - ('adblock', ['__version__'], "0.3.2"), - (f'{pyqt.__name__}.QtWebEngineWidgets', []), - (f'{pyqt.__name__}.QtWebEngine', ['PYQT_WEBENGINE_VERSION_STR']), - (f'{pyqt.__name__}.QtWebKitWidgets', []), + # FIXME: Mypy doesn't understand this. See https://github.com/python/mypy/issues/9706 + (name, ModuleInfo(name, *args)) # type: ignore[arg-type, misc] + for (name, *args) in [ + ('sip', ['SIP_VERSION_STR']), + ('colorama', ['VERSION', '__version__']), + ('jinja2', ['__version__']), + ('pygments', ['__version__']), + ('yaml', ['__version__']), + ('adblock', ['__version__'], "0.3.2"), + (f'{pyqt.__name__}.QtWebEngineWidgets', []), + (f'{pyqt.__name__}.QtWebEngine', ['PYQT_WEBENGINE_VERSION_STR']), + (f'{pyqt.__name__}.QtWebKitWidgets', []), + ] ] -]) +) def _module_versions() -> Sequence[str]: @@ -769,8 +778,11 @@ def _backend() -> str: if objects.backend == usertypes.Backend.QtWebKit: return 'new QtWebKit (WebKit {})'.format(qWebKitVersion()) elif objects.backend == usertypes.Backend.QtWebEngine: - return str(qtwebengine_versions( - avoid_init='avoid-chromium-init' in objects.debug_flags)) + return str( + qtwebengine_versions( + avoid_init='avoid-chromium-init' in objects.debug_flags + ) + ) raise utils.Unreachable(objects.backend) @@ -806,8 +818,7 @@ def version_info() -> str: lines += [ '', - '{}: {}'.format(platform.python_implementation(), - platform.python_version()), + '{}: {}'.format(platform.python_implementation(), platform.python_version()), 'PyQt: {}'.format(QtCore.PYQT_VERSION_STR), '', ] @@ -817,8 +828,11 @@ def version_info() -> str: lines += [ 'pdf.js: {}'.format(_pdfjs_version()), 'sqlite: {}'.format(sql.version()), - 'QtNetwork SSL: {}\n'.format(QtNetwork.QSslSocket.sslLibraryVersionString() - if QtNetwork.QSslSocket.supportsSsl() else 'no'), + 'QtNetwork SSL: {}\n'.format( + QtNetwork.QSslSocket.sslLibraryVersionString() + if QtNetwork.QSslSocket.supportsSsl() + else 'no' + ), ] if objects.qapp: @@ -835,9 +849,7 @@ def version_info() -> str: ] dist = distribution() if dist is not None: - lines += [ - 'Linux distribution: {} ({})'.format(dist.pretty, dist.parsed.name) - ] + lines += ['Linux distribution: {} ({})'.format(dist.pretty, dist.parsed.name)] lines += [ 'Frozen: {}'.format(hasattr(sys, 'frozen')), @@ -845,8 +857,8 @@ def version_info() -> str: "Using Python from {}".format(sys.executable), "Qt library executable path: {}, data path: {}".format( QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.LibraryExecutablesPath), - QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.DataPath) - ) + QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.DataPath), + ), ] if not dist or dist.parsed == Distribution.unknown: @@ -942,7 +954,9 @@ def opengl_info() -> Optional[OpenGLInfo]: # pragma: no cover vendor, version = override.split(', ', maxsplit=1) return OpenGLInfo.parse(vendor=vendor, version=version) - old_context = cast(Optional[QtGui.QOpenGLContext], QtGui.QOpenGLContext.currentContext()) + old_context = cast( + Optional[QtGui.QOpenGLContext], QtGui.QOpenGLContext.currentContext() + ) old_surface = None if old_context is None else old_context.surface() surface = QtGui.QOffscreenSurface() @@ -1003,8 +1017,7 @@ def pastebin_version(pbclient: pastebin.PastebinClient = None) -> None: def _on_paste_version_err(text: str) -> None: assert pbclient is not None - message.error("Failed to pastebin version" - " info: {}".format(text)) + message.error("Failed to pastebin version" " info: {}".format(text)) pbclient.deleteLater() if pastebin_url: @@ -1015,8 +1028,9 @@ def pastebin_version(pbclient: pastebin.PastebinClient = None) -> None: http_client = httpclient.HTTPClient() misc_api = pastebin.PastebinClient.MISC_API_URL - pbclient = pbclient or pastebin.PastebinClient(http_client, parent=app, - api_url=misc_api) + pbclient = pbclient or pastebin.PastebinClient( + http_client, parent=app, api_url=misc_api + ) pbclient.success.connect(_on_paste_version_success) pbclient.error.connect(_on_paste_version_err) diff --git a/tests/conftest.py b/tests/conftest.py index 0d3f5b9bb..31e0531d2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -250,9 +250,11 @@ def _select_backend(config): # Fail early if selected backend is not available if backend == 'webkit': from qutebrowser.qt import QtWebKitWidgets + assert QtWebKitWidgets is not None elif backend == 'webengine': from qutebrowser.qt import QtWebEngineWidgets + assert QtWebEngineWidgets is not None else: raise utils.Unreachable(backend) @@ -263,9 +265,11 @@ def _select_backend(config): def _auto_select_backend(): # Try to use QtWebKit as the default backend from qutebrowser.qt import QtWebKitWidgets + if QtWebKitWidgets: return 'webkit' from qutebrowser.qt import QtWebEngineWidgets + if QtWebEngineWidgets: # Try to use QtWebEngine as a fallback and fail early # if that's also not available diff --git a/tests/end2end/fixtures/notificationserver.py b/tests/end2end/fixtures/notificationserver.py index d05e62aeb..97200817c 100644 --- a/tests/end2end/fixtures/notificationserver.py +++ b/tests/end2end/fixtures/notificationserver.py @@ -124,14 +124,14 @@ class TestNotificationServer(QtCore.QObject): img_width=img.width(), img_height=img.height()) def _parse_image( - self, - width: int, - height: int, - bytes_per_line: int, - has_alpha: bool, - bits_per_color: int, - channel_count: int, - data: QtCore.QByteArray, + self, + width: int, + height: int, + bytes_per_line: int, + has_alpha: bool, + bits_per_color: int, + channel_count: int, + data: QtCore.QByteArray, ) -> QtGui.QImage: """Make sure the given image data is valid and return a QImage.""" # Chromium limit? @@ -149,7 +149,9 @@ class TestNotificationServer(QtCore.QObject): assert channel_count == (4 if has_alpha else 3) assert bytes_per_line >= width * channel_count - qimage_format = QtGui.QImage.Format_RGBA8888 if has_alpha else QtGui.QImage.Format_RGB888 + qimage_format = ( + QtGui.QImage.Format_RGBA8888 if has_alpha else QtGui.QImage.Format_RGB888 + ) img = QtGui.QImage(data, width, height, bytes_per_line, qimage_format) assert not img.isNull() assert img.width() == width diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py index 338d00e4b..a15744c05 100644 --- a/tests/end2end/fixtures/quteprocess.py +++ b/tests/end2end/fixtures/quteprocess.py @@ -900,10 +900,10 @@ class QuteProc(testprocess.Process): return path.read_text(encoding='utf-8') def get_screenshot( - self, - *, - probe_pos: QtCore.QPoint = None, - probe_color: QtGui.QColor = testutils.Color(0, 0, 0), + self, + *, + probe_pos: QtCore.QPoint = None, + probe_color: QtGui.QColor = testutils.Color(0, 0, 0), ) -> QtGui.QImage: """Get a screenshot of the current page. diff --git a/tests/helpers/fixtures.py b/tests/helpers/fixtures.py index ebd9dcde2..80b93d5a6 100644 --- a/tests/helpers/fixtures.py +++ b/tests/helpers/fixtures.py @@ -174,13 +174,15 @@ def greasemonkey_manager(monkeypatch, data_tmpdir, config_tmpdir): @pytest.fixture(scope='session') def testdata_scheme(qapp): from qutebrowser.qt import QtWebEngine + if QtWebEngine: global _qute_scheme_handler from qutebrowser.browser.webengine import webenginequtescheme webenginequtescheme.init() - _qute_scheme_handler = webenginequtescheme.QuteSchemeHandler( - parent=qapp) - _qute_scheme_handler.install(QtWebEngineWidgets.QWebEngineProfile.defaultProfile()) + _qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=qapp) + _qute_scheme_handler.install( + QtWebEngineWidgets.QWebEngineProfile.defaultProfile() + ) @qutescheme.add_handler('testdata') def handler(url): diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index 6c8d75335..42ed748e3 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -196,9 +196,13 @@ class FakeProcess(QtCore.QProcess): self.start = mock.Mock(spec=QtCore.QProcess.start) self.startDetached = mock.Mock(spec=QtCore.QProcess.startDetached) self.readAllStandardOutput = mock.Mock( - spec=QtCore.QProcess.readAllStandardOutput, return_value=QtCore.QByteArray(b'')) + spec=QtCore.QProcess.readAllStandardOutput, + return_value=QtCore.QByteArray(b''), + ) self.readAllStandardError = mock.Mock( - spec=QtCore.QProcess.readAllStandardError, return_value=QtCore.QByteArray(b'')) + spec=QtCore.QProcess.readAllStandardError, + return_value=QtCore.QByteArray(b''), + ) self.terminate = mock.Mock(spec=QtCore.QProcess.terminate) self.kill = mock.Mock(spec=QtCore.QProcess.kill) @@ -252,10 +256,18 @@ class FakeWebTab(browsertab.AbstractTab): """Fake AbstractTab to use in tests.""" - def __init__(self, url=QtCore.QUrl(), title='', tab_id=0, *, - scroll_pos_perc=(0, 0), - load_status=usertypes.LoadStatus.success, - progress=0, can_go_back=None, can_go_forward=None): + def __init__( + self, + url=QtCore.QUrl(), + title='', + tab_id=0, + *, + scroll_pos_perc=(0, 0), + load_status=usertypes.LoadStatus.success, + progress=0, + can_go_back=None, + can_go_forward=None + ): super().__init__(win_id=0, mode_manager=None, private=False) self._load_status = load_status self._title = title diff --git a/tests/unit/browser/test_history.py b/tests/unit/browser/test_history.py index 9bb0a9eb7..a9401759c 100644 --- a/tests/unit/browser/test_history.py +++ b/tests/unit/browser/test_history.py @@ -55,8 +55,9 @@ class TestSpecialMethods: assert len(web_history) == 1 def test_contains(self, web_history): - web_history.add_url(QtCore.QUrl('http://www.example.com/'), - title='Title', atime=12345) + web_history.add_url( + QtCore.QUrl('http://www.example.com/'), title='Title', atime=12345 + ) assert 'http://www.example.com/' in web_history assert 'www.example.com' not in web_history assert 'Title' not in web_history @@ -160,10 +161,20 @@ class TestAdd: 'https://user@example.com', 'https://user@example.com'), ] ) - def test_add_url(self, qtbot, web_history, - url, atime, title, redirect, history_url, completion_url): - web_history.add_url(QtCore.QUrl(url), atime=atime, title=title, - redirect=redirect) + def test_add_url( + self, + qtbot, + web_history, + url, + atime, + title, + redirect, + history_url, + completion_url, + ): + web_history.add_url( + QtCore.QUrl(url), atime=atime, title=title, redirect=redirect + ) assert list(web_history) == [(history_url, title, atime, redirect)] if completion_url is None: assert not len(web_history.completion) @@ -173,8 +184,12 @@ class TestAdd: def test_no_sql_web_history(self, web_history, monkeypatch): monkeypatch.setattr(objects, 'debug_flags', {'no-sql-history'}) - web_history.add_url(QtCore.QUrl('https://www.example.com/'), atime=12346, - title='Hello World', redirect=False) + web_history.add_url( + QtCore.QUrl('https://www.example.com/'), + atime=12346, + title='Hello World', + redirect=False, + ) assert not list(web_history) def test_invalid(self, qtbot, web_history, caplog): @@ -281,8 +296,7 @@ class TestHistoryInterface: from qutebrowser.browser.webkit import webkithistory QWebHistoryInterface = QtWebKit.QWebHistoryInterface # pylint: enable=invalid-name - web_history.add_url(url=QtCore.QUrl('http://www.example.com/'), - title='example') + web_history.add_url(url=QtCore.QUrl('http://www.example.com/'), title='example') interface = webkithistory.WebHistoryInterface(web_history) QWebHistoryInterface.setDefaultInterface(interface) yield @@ -337,14 +351,21 @@ class TestInit: class TestDump: def test_debug_dump_history(self, web_history, tmpdir): - web_history.add_url(QtCore.QUrl('http://example.com/1'), - title="Title1", atime=12345) - web_history.add_url(QtCore.QUrl('http://example.com/2'), - title="Title2", atime=12346) - web_history.add_url(QtCore.QUrl('http://example.com/3'), - title="Title3", atime=12347) - web_history.add_url(QtCore.QUrl('http://example.com/4'), - title="Title4", atime=12348, redirect=True) + web_history.add_url( + QtCore.QUrl('http://example.com/1'), title="Title1", atime=12345 + ) + web_history.add_url( + QtCore.QUrl('http://example.com/2'), title="Title2", atime=12346 + ) + web_history.add_url( + QtCore.QUrl('http://example.com/3'), title="Title3", atime=12347 + ) + web_history.add_url( + QtCore.QUrl('http://example.com/4'), + title="Title4", + atime=12348, + redirect=True, + ) histfile = tmpdir / 'history' history.debug_dump_history(str(histfile)) expected = ['12345 http://example.com/1 Title1', @@ -408,10 +429,8 @@ class TestRebuild: """ config_stub.val.completion.web_history.exclude = ['*.example.org'] - web_history.add_url(QtCore.QUrl('http://example.com'), - redirect=False, atime=1) - web_history.add_url(QtCore.QUrl('http://example.org'), - redirect=False, atime=2) + web_history.add_url(QtCore.QUrl('http://example.com'), redirect=False, atime=1) + web_history.add_url(QtCore.QUrl('http://example.org'), redirect=False, atime=2) hist2 = history.WebHistory(web_history.database, progress=stubs.FakeHistoryProgress()) @@ -421,10 +440,8 @@ class TestRebuild: """Ensure that completion is rebuilt when exclude patterns change.""" config_stub.val.completion.web_history.exclude = ['*.example.org'] - web_history.add_url(QtCore.QUrl('http://example.com'), - redirect=False, atime=1) - web_history.add_url(QtCore.QUrl('http://example.org'), - redirect=False, atime=2) + web_history.add_url(QtCore.QUrl('http://example.com'), redirect=False, atime=1) + web_history.add_url(QtCore.QUrl('http://example.org'), redirect=False, atime=2) hist2 = history.WebHistory(web_history.database, progress=stubs.FakeHistoryProgress()) diff --git a/tests/unit/browser/test_inspector.py b/tests/unit/browser/test_inspector.py index 433afacf9..68e47c9da 100644 --- a/tests/unit/browser/test_inspector.py +++ b/tests/unit/browser/test_inspector.py @@ -26,12 +26,13 @@ from qutebrowser.misc import miscwidgets class FakeInspector(inspector.AbstractWebInspector): - - def __init__(self, - inspector_widget: QtWidgets.QWidget, - splitter: miscwidgets.InspectorSplitter, - win_id: int, - parent: QtWidgets.QWidget = None) -> None: + def __init__( + self, + inspector_widget: QtWidgets.QWidget, + splitter: miscwidgets.InspectorSplitter, + win_id: int, + parent: QtWidgets.QWidget = None, + ) -> None: super().__init__(splitter, win_id, parent) self._set_widget(inspector_widget) self._inspected_page = None diff --git a/tests/unit/browser/test_pdfjs.py b/tests/unit/browser/test_pdfjs.py index 7d7f0ecd4..5ed48e825 100644 --- a/tests/unit/browser/test_pdfjs.py +++ b/tests/unit/browser/test_pdfjs.py @@ -236,7 +236,9 @@ def test_should_use_pdfjs_url_pattern(config_stub, url, expected): def test_get_main_url(): - expected = QtCore.QUrl('qute://pdfjs/web/viewer.html?filename=hello?world.pdf&' - 'file=&source=http://a.com/hello?world.pdf') + expected = QtCore.QUrl( + 'qute://pdfjs/web/viewer.html?filename=hello?world.pdf&' + 'file=&source=http://a.com/hello?world.pdf' + ) original_url = QtCore.QUrl('http://a.com/hello?world.pdf') assert pdfjs.get_main_url('hello?world.pdf', original_url) == expected diff --git a/tests/unit/browser/test_qutescheme.py b/tests/unit/browser/test_qutescheme.py index 8b384a2fc..2066070ea 100644 --- a/tests/unit/browser/test_qutescheme.py +++ b/tests/unit/browser/test_qutescheme.py @@ -93,7 +93,9 @@ class TestProcessHandler: with qtbot.wait_signal(proc.finished, timeout=5000): proc.start(*py_proc("print('AT&T')")) - _mimetype, data = qutescheme.qute_process(QtCore.QUrl(f'qute://process/{proc.pid}')) + _mimetype, data = qutescheme.qute_process( + QtCore.QUrl(f'qute://process/{proc.pid}') + ) print(data) assert f'<title>Process {proc.pid}</title>' in data @@ -121,9 +123,11 @@ class TestHistoryHandler: items = [] for i in range(entry_count): entry_atime = now - i * interval - entry = {"atime": str(entry_atime), - "url": QtCore.QUrl("http://www.x.com/" + str(i)), - "title": "Page " + str(i)} + entry = { + "atime": str(entry_atime), + "url": QtCore.QUrl("http://www.x.com/" + str(i)), + "title": "Page " + str(i), + } items.insert(0, entry) return items @@ -229,7 +233,8 @@ class TestPDFJSHandler: def test_existing_resource(self): """Test with a resource that exists.""" _mimetype, data = qutescheme.data_for_url( - QtCore.QUrl('qute://pdfjs/existing/file.html')) + QtCore.QUrl('qute://pdfjs/existing/file.html') + ) assert data == b'foobar' def test_nonexisting_resource(self, caplog): @@ -253,7 +258,8 @@ class TestPDFJSHandler: f.write('<pdf content>') _mimetype, data = qutescheme.data_for_url( - QtCore.QUrl('qute://pdfjs/web/viewer.html?filename=' + filename)) + QtCore.QUrl('qute://pdfjs/web/viewer.html?filename=' + filename) + ) assert b'PDF.js' in data def test_viewer_no_filename(self): @@ -263,20 +269,25 @@ class TestPDFJSHandler: def test_viewer_inexistent_file(self): with pytest.raises(qutescheme.Redirect): - qutescheme.data_for_url(QtCore.QUrl('qute://pdfjs/web/viewer.html?' - 'filename=foobar&source=example.org')) + qutescheme.data_for_url( + QtCore.QUrl( + 'qute://pdfjs/web/viewer.html?' 'filename=foobar&source=example.org' + ) + ) def test_viewer_inexistent_file_no_source(self): with pytest.raises(qutescheme.UrlInvalidError, match='Missing source'): qutescheme.data_for_url( - QtCore.QUrl('qute://pdfjs/web/viewer.html?filename=foobar')) + QtCore.QUrl('qute://pdfjs/web/viewer.html?filename=foobar') + ) def test_file(self, download_tmpdir): """Load a file via qute://pdfjs/file.""" (download_tmpdir / 'testfile').write_binary(b'foo') _mimetype, data = qutescheme.data_for_url( - QtCore.QUrl('qute://pdfjs/file?filename=testfile')) + QtCore.QUrl('qute://pdfjs/file?filename=testfile') + ) assert data == b'foo' def test_file_no_filename(self): diff --git a/tests/unit/browser/webengine/test_webengine_cookies.py b/tests/unit/browser/webengine/test_webengine_cookies.py index bce2ffc9f..6d02d3cfb 100644 --- a/tests/unit/browser/webengine/test_webengine_cookies.py +++ b/tests/unit/browser/webengine/test_webengine_cookies.py @@ -20,6 +20,7 @@ import pytest from helpers import testutils + testutils.qt_module_skip('QtWebEngineCore') from qutebrowser.browser.webengine import cookies diff --git a/tests/unit/browser/webengine/test_webenginedownloads.py b/tests/unit/browser/webengine/test_webenginedownloads.py index e43807093..7651fc3ca 100644 --- a/tests/unit/browser/webengine/test_webenginedownloads.py +++ b/tests/unit/browser/webengine/test_webenginedownloads.py @@ -24,6 +24,7 @@ import dataclasses import pytest from helpers import testutils + testutils.qt_module_skip('QtWebEngineWidgets') from qutebrowser.qt import QtWebEngineWidgets diff --git a/tests/unit/browser/webengine/test_webengineinterceptor.py b/tests/unit/browser/webengine/test_webengineinterceptor.py index 592f7f69f..5d4255e4b 100644 --- a/tests/unit/browser/webengine/test_webengineinterceptor.py +++ b/tests/unit/browser/webengine/test_webengineinterceptor.py @@ -21,6 +21,7 @@ from helpers import testutils + testutils.qt_module_skip('QtWebEngineWidgets') from qutebrowser.qt import QtWebEngineCore @@ -30,8 +31,11 @@ from qutebrowser.browser.webengine import interceptor def test_no_missing_resource_types(): request_interceptor = interceptor.RequestInterceptor() qb_keys = request_interceptor._resource_types.keys() - qt_keys = {i for i in vars(QtWebEngineCore.QWebEngineUrlRequestInfo).values() - if isinstance(i, QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceType)} + qt_keys = { + i + for i in vars(QtWebEngineCore.QWebEngineUrlRequestInfo).values() + if isinstance(i, QtWebEngineCore.QWebEngineUrlRequestInfo.ResourceType) + } assert qt_keys == qb_keys diff --git a/tests/unit/browser/webengine/test_webenginesettings.py b/tests/unit/browser/webengine/test_webenginesettings.py index a365f54df..585bde540 100644 --- a/tests/unit/browser/webengine/test_webenginesettings.py +++ b/tests/unit/browser/webengine/test_webenginesettings.py @@ -22,6 +22,7 @@ import logging import pytest from helpers import testutils + QtWebEngineWidgets = testutils.qt_module_skip('QtWebEngineWidgets') from qutebrowser.browser.webengine import webenginesettings diff --git a/tests/unit/browser/webkit/network/test_networkreply.py b/tests/unit/browser/webkit/network/test_networkreply.py index 8682ff33d..04f348131 100644 --- a/tests/unit/browser/webkit/network/test_networkreply.py +++ b/tests/unit/browser/webkit/network/test_networkreply.py @@ -40,7 +40,8 @@ class TestFixedDataNetworkReply: assert reply.header(QtNetwork.QNetworkRequest.ContentTypeHeader) == 'test/foo' http_code = reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute) http_reason = reply.attribute( - QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute) + QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute + ) assert http_code == 200 assert http_reason == 'OK' assert reply.isFinished() @@ -74,7 +75,8 @@ class TestFixedDataNetworkReply: def test_error_network_reply(qtbot, req): reply = networkreply.ErrorNetworkReply( - req, "This is an error", QtNetwork.QNetworkReply.UnknownNetworkError) + req, "This is an error", QtNetwork.QNetworkReply.UnknownNetworkError + ) with qtbot.wait_signals([reply.error, reply.finished], order='strict'): pass diff --git a/tests/unit/browser/webkit/network/test_pac.py b/tests/unit/browser/webkit/network/test_pac.py index 9187e0d03..c88d390d9 100644 --- a/tests/unit/browser/webkit/network/test_pac.py +++ b/tests/unit/browser/webkit/network/test_pac.py @@ -40,7 +40,9 @@ def _pac_common_test(test_str): fun_str = fun_str_f.format(test_str) res = pac.PACResolver(fun_str) - proxies = res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + proxies = res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) assert len(proxies) == 3 assert proxies[0].type() == QtNetwork.QNetworkProxy.NoProxy assert proxies[1].type() == QtNetwork.QNetworkProxy.HttpProxy @@ -98,6 +100,7 @@ def test_dnsResolve(monkeypatch, domain, expected): if host == "known.domain": info.setAddresses([QtNetwork.QHostAddress("1.2.3.4")]) return info + monkeypatch.setattr(QtNetwork.QHostInfo, 'fromName', mock_fromName) _pac_equality_test("dnsResolve('{}')".format(domain), expected) @@ -128,7 +131,9 @@ def test_invalid_port(): res = pac.PACResolver(test_str) with pytest.raises(pac.ParseProxyError): - res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) @pytest.mark.parametrize('string', ["", "{"]) @@ -153,7 +158,9 @@ def test_fail_parse(value): res = pac.PACResolver(test_str_f.format(value)) with pytest.raises(pac.ParseProxyError): - res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) def test_fail_return(): @@ -165,7 +172,9 @@ def test_fail_return(): res = pac.PACResolver(test_str) with pytest.raises(pac.EvalProxyError): - res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) @pytest.mark.parametrize('url, has_secret', [ @@ -255,7 +264,9 @@ def test_fetch_success(): """ res = fetcher_test(test_str) - proxies = res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + proxies = res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) assert len(proxies) == 3 @@ -268,6 +279,8 @@ def test_fetch_evalerror(caplog): res = fetcher_test(test_str) with caplog.at_level(logging.ERROR): - proxies = res.resolve(QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test"))) + proxies = res.resolve( + QtNetwork.QNetworkProxyQuery(QtCore.QUrl("https://example.com/test")) + ) assert len(proxies) == 1 assert proxies[0].port() == 9 diff --git a/tests/unit/browser/webkit/test_certificateerror.py b/tests/unit/browser/webkit/test_certificateerror.py index 26bdb1b3b..5a5c4c4bd 100644 --- a/tests/unit/browser/webkit/test_certificateerror.py +++ b/tests/unit/browser/webkit/test_certificateerror.py @@ -32,41 +32,45 @@ class FakeError: return self.msg -@pytest.mark.parametrize('errors, expected', [ - ( - [QtNetwork.QSslError(QtNetwork.QSslError.UnableToGetIssuerCertificate)], - ['<p>The issuer certificate could not be found</p>'], - ), - ( - [ - QtNetwork.QSslError(QtNetwork.QSslError.UnableToGetIssuerCertificate), - QtNetwork.QSslError(QtNetwork.QSslError.UnableToDecryptCertificateSignature), - ], - [ - '<ul>', - '<li>The issuer certificate could not be found</li>', - '<li>The certificate signature could not be decrypted</li>', - '</ul>', - ], - ), - - ( - [FakeError('Escaping test: <>')], - ['<p>Escaping test: <></p>'], - ), - ( - [ - FakeError('Escaping test 1: <>'), - FakeError('Escaping test 2: <>'), - ], - [ - '<ul>', - '<li>Escaping test 1: <></li>', - '<li>Escaping test 2: <></li>', - '</ul>', - ], - ), -]) +@pytest.mark.parametrize( + 'errors, expected', + [ + ( + [QtNetwork.QSslError(QtNetwork.QSslError.UnableToGetIssuerCertificate)], + ['<p>The issuer certificate could not be found</p>'], + ), + ( + [ + QtNetwork.QSslError(QtNetwork.QSslError.UnableToGetIssuerCertificate), + QtNetwork.QSslError( + QtNetwork.QSslError.UnableToDecryptCertificateSignature + ), + ], + [ + '<ul>', + '<li>The issuer certificate could not be found</li>', + '<li>The certificate signature could not be decrypted</li>', + '</ul>', + ], + ), + ( + [FakeError('Escaping test: <>')], + ['<p>Escaping test: <></p>'], + ), + ( + [ + FakeError('Escaping test 1: <>'), + FakeError('Escaping test 2: <>'), + ], + [ + '<ul>', + '<li>Escaping test 1: <></li>', + '<li>Escaping test 2: <></li>', + '</ul>', + ], + ), + ], +) def test_html(errors, expected): wrapper = certificateerror.CertificateErrorWrapper(errors) lines = [line.strip() for line in wrapper.html().splitlines() if line.strip()] diff --git a/tests/unit/browser/webkit/test_tabhistory.py b/tests/unit/browser/webkit/test_tabhistory.py index db7b81fa9..8807def47 100644 --- a/tests/unit/browser/webkit/test_tabhistory.py +++ b/tests/unit/browser/webkit/test_tabhistory.py @@ -24,6 +24,7 @@ from typing import Any import pytest from helpers import testutils + testutils.qt_module_skip('QtWebKit') from qutebrowser.qt import QtWebKit @@ -40,18 +41,28 @@ ITEMS = [ Item(QtCore.QUrl('https://www.heise.de/'), 'heise'), Item(QtCore.QUrl('about:blank'), 'blank', active=True), Item(QtCore.QUrl('http://example.com/%E2%80%A6'), 'percent'), - Item(QtCore.QUrl('http://example.com/?foo=bar'), 'arg', - original_url=QtCore.QUrl('http://original.url.example.com/'), - user_data={'foo': 23, 'bar': 42}), + Item( + QtCore.QUrl('http://example.com/?foo=bar'), + 'arg', + original_url=QtCore.QUrl('http://original.url.example.com/'), + user_data={'foo': 23, 'bar': 42}, + ), # From https://github.com/OtterBrowser/otter-browser/issues/709#issuecomment-74749471 - Item(QtCore.QUrl('http://github.com/OtterBrowser/24/134/2344/otter-browser/' - 'issues/709/'), - 'Page not found | github', - user_data={'zoom': 149, 'scroll-pos': QtCore.QPoint(0, 0)}), - Item(QtCore.QUrl('https://mail.google.com/mail/u/0/#label/some+label/' - '234lkjsd0932lkjf884jqwerdf4'), - '"some label" - email@gmail.com - Gmail"', - user_data={'zoom': 120, 'scroll-pos': QtCore.QPoint(0, 0)}), + Item( + QtCore.QUrl( + 'http://github.com/OtterBrowser/24/134/2344/otter-browser/' 'issues/709/' + ), + 'Page not found | github', + user_data={'zoom': 149, 'scroll-pos': QtCore.QPoint(0, 0)}, + ), + Item( + QtCore.QUrl( + 'https://mail.google.com/mail/u/0/#label/some+label/' + '234lkjsd0932lkjf884jqwerdf4' + ), + '"some label" - email@gmail.com - Gmail"', + user_data={'zoom': 120, 'scroll-pos': QtCore.QPoint(0, 0)}, + ), ] @@ -133,9 +144,11 @@ def test_no_active_item(): def test_two_active_items(): """Check tabhistory.serialize with two active items.""" - items = [Item(QtCore.QUrl(), '', active=True), - Item(QtCore.QUrl(), ''), - Item(QtCore.QUrl(), '', active=True)] + items = [ + Item(QtCore.QUrl(), '', active=True), + Item(QtCore.QUrl(), ''), + Item(QtCore.QUrl(), '', active=True), + ] with pytest.raises(ValueError): tabhistory.serialize(items) diff --git a/tests/unit/browser/webkit/test_webkitelem.py b/tests/unit/browser/webkit/test_webkitelem.py index 6c34ef18d..ca1c39aed 100644 --- a/tests/unit/browser/webkit/test_webkitelem.py +++ b/tests/unit/browser/webkit/test_webkitelem.py @@ -29,6 +29,7 @@ import dataclasses import pytest from helpers import testutils + QWebElement = testutils.qt_module_skip('QtWebKit').QWebElement from qutebrowser.browser import browsertab @@ -517,13 +518,17 @@ class TestIsVisible: assert not elem.geometry().isValid() assert elem._is_visible(frame) - @pytest.mark.parametrize('geometry, visible', [ - (QtCore.QRect(5, 5, 4, 4), False), - (QtCore.QRect(10, 10, 1, 1), True), - ]) + @pytest.mark.parametrize( + 'geometry, visible', + [ + (QtCore.QRect(5, 5, 4, 4), False), + (QtCore.QRect(10, 10, 1, 1), True), + ], + ) def test_scrolled(self, geometry, visible, stubs): - scrolled_frame = stubs.FakeWebFrame(QtCore.QRect(0, 0, 100, 100), - scroll=QtCore.QPoint(10, 10)) + scrolled_frame = stubs.FakeWebFrame( + QtCore.QRect(0, 0, 100, 100), scroll=QtCore.QPoint(10, 10) + ) elem = get_webelem(geometry, scrolled_frame) assert elem._is_visible(scrolled_frame) == visible @@ -699,8 +704,9 @@ class TestRectOnView: @pytest.mark.parametrize('js_rect', [None, {}]) def test_scrolled(self, stubs, js_rect): geometry = QtCore.QRect(20, 20, 4, 4) - frame = stubs.FakeWebFrame(QtCore.QRect(0, 0, 100, 100), - scroll=QtCore.QPoint(10, 10)) + frame = stubs.FakeWebFrame( + QtCore.QRect(0, 0, 100, 100), scroll=QtCore.QPoint(10, 10) + ) elem = get_webelem(geometry, frame, js_rect_return=js_rect) assert elem.rect_on_view() == QtCore.QRect(20 - 10, 20 - 10, 4, 4) @@ -724,8 +730,7 @@ class TestRectOnView: frame = stubs.FakeWebFrame(QtCore.QRect(0, 0, 200, 200)) iframe = stubs.FakeWebFrame(QtCore.QRect(0, 10, 100, 100), parent=frame) assert frame.geometry().contains(iframe.geometry()) - elem = get_webelem(QtCore.QRect(20, 90, 10, 10), iframe, - js_rect_return=js_rect) + elem = get_webelem(QtCore.QRect(20, 90, 10, 10), iframe, js_rect_return=js_rect) assert elem.rect_on_view() == QtCore.QRect(20, 10 + 90, 10, 10) @pytest.mark.parametrize('js_rect', [None, {}]) @@ -885,16 +890,19 @@ class TestIsEditable: assert elem.is_editable() == editable -@pytest.mark.parametrize('attributes, expected', [ - # No attributes - ({}, None), - ({'href': 'foo'}, QtCore.QUrl('http://www.example.com/foo')), - ({'src': 'foo'}, QtCore.QUrl('http://www.example.com/foo')), - ({'href': 'foo', 'src': 'bar'}, QtCore.QUrl('http://www.example.com/foo')), - ({'href': '::garbage::'}, None), - ({'href': 'http://www.example.org/'}, QtCore.QUrl('http://www.example.org/')), - ({'href': ' foo '}, QtCore.QUrl('http://www.example.com/foo')), -]) +@pytest.mark.parametrize( + 'attributes, expected', + [ + # No attributes + ({}, None), + ({'href': 'foo'}, QtCore.QUrl('http://www.example.com/foo')), + ({'src': 'foo'}, QtCore.QUrl('http://www.example.com/foo')), + ({'href': 'foo', 'src': 'bar'}, QtCore.QUrl('http://www.example.com/foo')), + ({'href': '::garbage::'}, None), + ({'href': 'http://www.example.org/'}, QtCore.QUrl('http://www.example.org/')), + ({'href': ' foo '}, QtCore.QUrl('http://www.example.com/foo')), + ], +) def test_resolve_url(attributes, expected): elem = get_webelem(attributes=attributes) baseurl = QtCore.QUrl('http://www.example.com/') diff --git a/tests/unit/completion/test_completionwidget.py b/tests/unit/completion/test_completionwidget.py index 5103a5a1e..f19bfc0fe 100644 --- a/tests/unit/completion/test_completionwidget.py +++ b/tests/unit/completion/test_completionwidget.py @@ -191,8 +191,9 @@ class TestCompletionItemFocusPage: @pytest.fixture(autouse=True) def patch_heights(self, monkeypatch, completionview): """Patch the item/widget heights so that 10 items are always visible.""" - monkeypatch.setattr(completionview, 'visualRect', - lambda _idx: QtCore.QRect(0, 0, 100, 20)) + monkeypatch.setattr( + completionview, 'visualRect', lambda _idx: QtCore.QRect(0, 0, 100, 20) + ) monkeypatch.setattr(completionview, 'height', lambda: 200) @pytest.mark.parametrize('which, expected', [ diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py index b5affbd47..f771a8b16 100644 --- a/tests/unit/completion/test_models.py +++ b/tests/unit/completion/test_models.py @@ -840,7 +840,7 @@ def test_tab_completion_delete(qtmodeltester, fake_web_tab, win_registry, tabbed_browser_stubs[0].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://github.com'), 'GitHub', 0), fake_web_tab(QtCore.QUrl('https://wikipedia.org'), 'Wikipedia', 1), - fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2) + fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2), ] tabbed_browser_stubs[1].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://wiki.archlinux.org'), 'ArchWiki', 0), @@ -858,8 +858,10 @@ def test_tab_completion_delete(qtmodeltester, fake_web_tab, win_registry, model.delete_cur_item(idx) actual = [tab.url() for tab in tabbed_browser_stubs[0].widget.tabs] - assert actual == [QtCore.QUrl('https://github.com'), - QtCore.QUrl('https://duckduckgo.com')] + assert actual == [ + QtCore.QUrl('https://github.com'), + QtCore.QUrl('https://duckduckgo.com'), + ] def test_tab_focus_completion_delete(qtmodeltester, fake_web_tab, win_registry, @@ -868,7 +870,7 @@ def test_tab_focus_completion_delete(qtmodeltester, fake_web_tab, win_registry, tabbed_browser_stubs[0].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://github.com'), 'GitHub', 0), fake_web_tab(QtCore.QUrl('https://wikipedia.org'), 'Wikipedia', 1), - fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2) + fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2), ] tabbed_browser_stubs[1].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://wiki.archlinux.org'), 'ArchWiki', 0), @@ -886,8 +888,10 @@ def test_tab_focus_completion_delete(qtmodeltester, fake_web_tab, win_registry, model.delete_cur_item(idx) actual = [tab.url() for tab in tabbed_browser_stubs[0].widget.tabs] - assert actual == [QtCore.QUrl('https://github.com'), - QtCore.QUrl('https://duckduckgo.com')] + assert actual == [ + QtCore.QUrl('https://github.com'), + QtCore.QUrl('https://duckduckgo.com'), + ] def test_tab_completion_not_sorted(qtmodeltester, fake_web_tab, win_registry, @@ -1031,7 +1035,7 @@ def test_window_completion(qtmodeltester, fake_web_tab, tabbed_browser_stubs, tabbed_browser_stubs[0].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://github.com'), 'GitHub', 0), fake_web_tab(QtCore.QUrl('https://wikipedia.org'), 'Wikipedia', 1), - fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2) + fake_web_tab(QtCore.QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2), ] tabbed_browser_stubs[1].widget.tabs = [ fake_web_tab(QtCore.QUrl('https://wiki.archlinux.org'), 'ArchWiki', 0) @@ -1418,15 +1422,27 @@ def test_forward_completion(tab_with_history, info): def test_undo_completion(tabbed_browser_stubs, info): """Test :undo completion.""" - entry1 = tabbedbrowser._UndoEntry(url=QtCore.QUrl('https://example.org/'), - history=None, index=None, pinned=None, - created_at=datetime(2020, 1, 1)) - entry2 = tabbedbrowser._UndoEntry(url=QtCore.QUrl('https://example.com/'), - history=None, index=None, pinned=None, - created_at=datetime(2020, 1, 2)) - entry3 = tabbedbrowser._UndoEntry(url=QtCore.QUrl('https://example.net/'), - history=None, index=None, pinned=None, - created_at=datetime(2020, 1, 2)) + entry1 = tabbedbrowser._UndoEntry( + url=QtCore.QUrl('https://example.org/'), + history=None, + index=None, + pinned=None, + created_at=datetime(2020, 1, 1), + ) + entry2 = tabbedbrowser._UndoEntry( + url=QtCore.QUrl('https://example.com/'), + history=None, + index=None, + pinned=None, + created_at=datetime(2020, 1, 2), + ) + entry3 = tabbedbrowser._UndoEntry( + url=QtCore.QUrl('https://example.net/'), + history=None, + index=None, + pinned=None, + created_at=datetime(2020, 1, 2), + ) # Most recently closed is at the end tabbed_browser_stubs[0].undo_stack = [ diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index a8bdaecbe..34f1cd816 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -508,9 +508,11 @@ class TestConfig: ]) def test_get_for_url_fallback(self, conf, fallback, expected): """Test conf.get() with a URL and fallback.""" - value = conf.get('content.javascript.enabled', - url=QtCore.QUrl('https://example.com/'), - fallback=fallback) + value = conf.get( + 'content.javascript.enabled', + url=QtCore.QUrl('https://example.com/'), + fallback=fallback, + ) assert value is expected @pytest.mark.parametrize('value', [{}, {'normal': {'a': 'nop'}}]) @@ -755,10 +757,13 @@ class TestContainer: new_container = new_container.favicons assert new_container._prefix == 'tabs.favicons' - @pytest.mark.parametrize('configapi, expected', [ - (object(), 'rgb'), - (None, QtGui.QColor.Rgb), - ]) + @pytest.mark.parametrize( + 'configapi, expected', + [ + (object(), 'rgb'), + (None, QtGui.QColor.Rgb), + ], + ) def test_getattr_option(self, container, configapi, expected): container._configapi = configapi # Use an option with a to_py() so we can check the conversion. diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py index 82354bc32..50f22045a 100644 --- a/tests/unit/config/test_configcommands.py +++ b/tests/unit/config/test_configcommands.py @@ -725,12 +725,16 @@ class TestBind: """Get a dict with no bindings.""" return {'normal': {}} - @pytest.mark.parametrize("mode, url", [ - ("normal", QtCore.QUrl("qute://bindings")), - ("passthrough", QtCore.QUrl("qute://bindings#passthrough")), - ]) - def test_bind_no_args(self, commands, config_stub, no_bindings, - tabbed_browser_stubs, mode, url): + @pytest.mark.parametrize( + "mode, url", + [ + ("normal", QtCore.QUrl("qute://bindings")), + ("passthrough", QtCore.QUrl("qute://bindings#passthrough")), + ], + ) + def test_bind_no_args( + self, commands, config_stub, no_bindings, tabbed_browser_stubs, mode, url + ): """Run ':bind'. Should open qute://bindings.""" diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index 37a077775..ebba88a16 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -44,8 +44,9 @@ class Font(QtGui.QFont): """A QFont with a nicer repr().""" def __repr__(self): - weight = debug.qenum_key(QtGui.QFont, self.weight(), add_base=True, - klass=QtGui.QFont.Weight) + weight = debug.qenum_key( + QtGui.QFont, self.weight(), add_base=True, klass=QtGui.QFont.Weight + ) kwargs = { 'family': self.family(), 'pt': self.pointSize(), @@ -1271,22 +1272,22 @@ class TestQtColor: def klass(self): return configtypes.QtColor - @pytest.mark.parametrize('val, expected', [ - ('#123', QtGui.QColor('#123')), - ('#112233', QtGui.QColor('#112233')), - ('#44112233', QtGui.QColor('#44112233')), - ('#111222333', QtGui.QColor('#111222333')), - ('#111122223333', QtGui.QColor('#111122223333')), - ('red', QtGui.QColor('red')), - - ('rgb(0, 0, 0)', QtGui.QColor.fromRgb(0, 0, 0)), - ('rgb(0,0,0)', QtGui.QColor.fromRgb(0, 0, 0)), - - ('rgba(255, 255, 255, 1.0)', QtGui.QColor.fromRgb(255, 255, 255, 255)), - - ('hsv(10%,10%,10%)', QtGui.QColor.fromHsv(35, 25, 25)), - ('hsva(10%,20%,30%,40%)', QtGui.QColor.fromHsv(35, 51, 76, 102)), - ]) + @pytest.mark.parametrize( + 'val, expected', + [ + ('#123', QtGui.QColor('#123')), + ('#112233', QtGui.QColor('#112233')), + ('#44112233', QtGui.QColor('#44112233')), + ('#111222333', QtGui.QColor('#111222333')), + ('#111122223333', QtGui.QColor('#111122223333')), + ('red', QtGui.QColor('red')), + ('rgb(0, 0, 0)', QtGui.QColor.fromRgb(0, 0, 0)), + ('rgb(0,0,0)', QtGui.QColor.fromRgb(0, 0, 0)), + ('rgba(255, 255, 255, 1.0)', QtGui.QColor.fromRgb(255, 255, 255, 255)), + ('hsv(10%,10%,10%)', QtGui.QColor.fromHsv(35, 25, 25)), + ('hsva(10%,20%,30%,40%)', QtGui.QColor.fromHsv(35, 51, 76, 102)), + ], + ) def test_valid(self, klass, val, expected): assert klass().to_py(val) == expected @@ -1372,47 +1373,63 @@ class TestFont: TESTS = { # (style, weight, pointsize, pixelsize, family - '"Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, 'Foobar Neue'), - 'inconsolatazi4': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, - 'inconsolatazi4'), - 'Terminus (TTF)': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, - 'Terminus (TTF)'), - '10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, 10, None, 'Foobar Neue'), - '10PT "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, 10, None, 'Foobar Neue'), - '10px "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, None, 10, 'Foobar Neue'), - '10PX "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Normal, None, 10, 'Foobar Neue'), - 'bold "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Bold, -1, -1, 'Foobar Neue'), - 'italic "Foobar Neue"': - FontDesc(QtGui.QFont.StyleItalic, QtGui.QFont.Normal, -1, -1, 'Foobar Neue'), - 'oblique "Foobar Neue"': - FontDesc(QtGui.QFont.StyleOblique, QtGui.QFont.Normal, -1, -1, 'Foobar Neue'), - 'normal bold "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Bold, -1, -1, 'Foobar Neue'), - 'bold italic "Foobar Neue"': - FontDesc(QtGui.QFont.StyleItalic, QtGui.QFont.Bold, -1, -1, 'Foobar Neue'), - 'bold 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Bold, 10, None, 'Foobar Neue'), - 'italic 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleItalic, QtGui.QFont.Normal, 10, None, 'Foobar Neue'), - 'oblique 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleOblique, QtGui.QFont.Normal, 10, None, - 'Foobar Neue'), - 'normal bold 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, QtGui.QFont.Bold, 10, None, 'Foobar Neue'), - 'bold italic 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleItalic, QtGui.QFont.Bold, 10, None, 'Foobar Neue'), - 'normal 300 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, 37, 10, None, 'Foobar Neue'), - 'normal 800 10pt "Foobar Neue"': - FontDesc(QtGui.QFont.StyleNormal, 99, 10, None, 'Foobar Neue'), + '"Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, 'Foobar Neue' + ), + 'inconsolatazi4': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, 'inconsolatazi4' + ), + 'Terminus (TTF)': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, -1, -1, 'Terminus (TTF)' + ), + '10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, 10, None, 'Foobar Neue' + ), + '10PT "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, 10, None, 'Foobar Neue' + ), + '10px "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, None, 10, 'Foobar Neue' + ), + '10PX "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Normal, None, 10, 'Foobar Neue' + ), + 'bold "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Bold, -1, -1, 'Foobar Neue' + ), + 'italic "Foobar Neue"': FontDesc( + QtGui.QFont.StyleItalic, QtGui.QFont.Normal, -1, -1, 'Foobar Neue' + ), + 'oblique "Foobar Neue"': FontDesc( + QtGui.QFont.StyleOblique, QtGui.QFont.Normal, -1, -1, 'Foobar Neue' + ), + 'normal bold "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Bold, -1, -1, 'Foobar Neue' + ), + 'bold italic "Foobar Neue"': FontDesc( + QtGui.QFont.StyleItalic, QtGui.QFont.Bold, -1, -1, 'Foobar Neue' + ), + 'bold 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Bold, 10, None, 'Foobar Neue' + ), + 'italic 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleItalic, QtGui.QFont.Normal, 10, None, 'Foobar Neue' + ), + 'oblique 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleOblique, QtGui.QFont.Normal, 10, None, 'Foobar Neue' + ), + 'normal bold 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, QtGui.QFont.Bold, 10, None, 'Foobar Neue' + ), + 'bold italic 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleItalic, QtGui.QFont.Bold, 10, None, 'Foobar Neue' + ), + 'normal 300 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, 37, 10, None, 'Foobar Neue' + ), + 'normal 800 10pt "Foobar Neue"': FontDesc( + QtGui.QFont.StyleNormal, 99, 10, None, 'Foobar Neue' + ), } font_xfail = pytest.mark.xfail(reason='FIXME: #103') @@ -1887,19 +1904,37 @@ class TestProxy: def klass(self): return configtypes.Proxy - @pytest.mark.parametrize('val, expected', [ - ('system', configtypes.SYSTEM_PROXY), - ('none', QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.NoProxy)), - ('socks://example.com/', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com')), - ('socks5://foo:bar@example.com:2323', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 2323, - 'foo', 'bar')), - ('pac+http://example.com/proxy.pac', - pac.PACFetcher(QtCore.QUrl('pac+http://example.com/proxy.pac'))), - ('pac+file:///tmp/proxy.pac', - pac.PACFetcher(QtCore.QUrl('pac+file:///tmp/proxy.pac'))), - ]) + @pytest.mark.parametrize( + 'val, expected', + [ + ('system', configtypes.SYSTEM_PROXY), + ('none', QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.NoProxy)), + ( + 'socks://example.com/', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com' + ), + ), + ( + 'socks5://foo:bar@example.com:2323', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, + 'example.com', + 2323, + 'foo', + 'bar', + ), + ), + ( + 'pac+http://example.com/proxy.pac', + pac.PACFetcher(QtCore.QUrl('pac+http://example.com/proxy.pac')), + ), + ( + 'pac+file:///tmp/proxy.pac', + pac.PACFetcher(QtCore.QUrl('pac+file:///tmp/proxy.pac')), + ), + ], + ) def test_to_py_valid(self, klass, val, expected): actual = klass().to_py(val) if isinstance(actual, QtNetwork.QNetworkProxy): @@ -1955,10 +1990,13 @@ class TestFuzzyUrl: def klass(self): return configtypes.FuzzyUrl - @pytest.mark.parametrize('val, expected', [ - ('http://example.com/?q={}', QtCore.QUrl('http://example.com/?q={}')), - ('example.com', QtCore.QUrl('http://example.com')), - ]) + @pytest.mark.parametrize( + 'val, expected', + [ + ('http://example.com/?q={}', QtCore.QUrl('http://example.com/?q={}')), + ('example.com', QtCore.QUrl('http://example.com')), + ], + ) def test_to_py_valid(self, klass, val, expected): assert klass().to_py(val) == expected diff --git a/tests/unit/config/test_configutils.py b/tests/unit/config/test_configutils.py index 539524f2a..43ed37662 100644 --- a/tests/unit/config/test_configutils.py +++ b/tests/unit/config/test_configutils.py @@ -253,20 +253,23 @@ def test_get_trailing_dot(values): 'example.org value') -@pytest.mark.parametrize('func', [ - pytest.param(lambda values, pattern: - values.add(None, pattern), - id='add'), - pytest.param(lambda values, pattern: - values.remove(pattern), - id='remove'), - pytest.param(lambda values, pattern: - values.get_for_url(QtCore.QUrl('https://example.org/')), - id='get_for_url'), - pytest.param(lambda values, pattern: - values.get_for_pattern(pattern), - id='get_for_pattern'), -]) +@pytest.mark.parametrize( + 'func', + [ + pytest.param(lambda values, pattern: values.add(None, pattern), id='add'), + pytest.param(lambda values, pattern: values.remove(pattern), id='remove'), + pytest.param( + lambda values, pattern: values.get_for_url( + QtCore.QUrl('https://example.org/') + ), + id='get_for_url', + ), + pytest.param( + lambda values, pattern: values.get_for_pattern(pattern), + id='get_for_pattern', + ), + ], +) def test_no_pattern_support(func, opt, pattern): opt.supports_pattern = False values = configutils.Values(opt, []) diff --git a/tests/unit/javascript/conftest.py b/tests/unit/javascript/conftest.py index 13f78eee0..214e9afed 100644 --- a/tests/unit/javascript/conftest.py +++ b/tests/unit/javascript/conftest.py @@ -86,8 +86,7 @@ class JSTester: path: The string path from disk to load (relative to this file) force: Whether to force loading even if the file is invalid. """ - self.load_url(QtCore.QUrl.fromLocalFile( - str(JS_DIR / path)), force) + self.load_url(QtCore.QUrl.fromLocalFile(str(JS_DIR / path)), force) def load_url(self, url: QtCore.QUrl, force: bool = False): """Load a given QUrl. diff --git a/tests/unit/javascript/test_js_execution.py b/tests/unit/javascript/test_js_execution.py index ba088b1bf..cf0fda247 100644 --- a/tests/unit/javascript/test_js_execution.py +++ b/tests/unit/javascript/test_js_execution.py @@ -56,12 +56,16 @@ def test_element_js_webkit(webview, js_enabled, expected): def test_simple_js_webengine(qtbot, webengineview, qapp, js_enabled, world, expected): """With QtWebEngine, runJavaScript works even when JS is off.""" - assert world in [QtWebEngineWidgets.QWebEngineScript.MainWorld, - QtWebEngineWidgets.QWebEngineScript.ApplicationWorld, - QtWebEngineWidgets.QWebEngineScript.UserWorld] + assert world in [ + QtWebEngineWidgets.QWebEngineScript.MainWorld, + QtWebEngineWidgets.QWebEngineScript.ApplicationWorld, + QtWebEngineWidgets.QWebEngineScript.UserWorld, + ] settings = webengineview.settings() - settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.JavascriptEnabled, js_enabled) + settings.setAttribute( + QtWebEngineWidgets.QWebEngineSettings.JavascriptEnabled, js_enabled + ) qapp.processEvents() page = webengineview.page() diff --git a/tests/unit/javascript/test_js_quirks.py b/tests/unit/javascript/test_js_quirks.py index b65b03273..1d3691ae1 100644 --- a/tests/unit/javascript/test_js_quirks.py +++ b/tests/unit/javascript/test_js_quirks.py @@ -30,38 +30,41 @@ from qutebrowser.qt import QtCore from qutebrowser.utils import usertypes -@pytest.mark.parametrize('base_url, source, expected', [ - pytest.param( - QtCore.QUrl(), - '"This is a test".replaceAll("test", "fest")', - "This is a fest", - id='replace-all', - ), - pytest.param( - QtCore.QUrl(), - '"This is a test".replaceAll(/[tr]est/g, "fest")', - "This is a fest", - id='replace-all-regex', - ), - pytest.param( - QtCore.QUrl(), - '"This is a [test[".replaceAll("[", "<")', - "This is a <test<", - id='replace-all-reserved-string', - ), - pytest.param( - QtCore.QUrl('https://test.qutebrowser.org/test'), - 'typeof globalThis.setTimeout === "function"', - True, - id='global-this', - ), - pytest.param( - QtCore.QUrl(), - 'Object.fromEntries([["0", "a"], ["1", "b"]])', - {'0': 'a', '1': 'b'}, - id='object-fromentries', - ), -]) +@pytest.mark.parametrize( + 'base_url, source, expected', + [ + pytest.param( + QtCore.QUrl(), + '"This is a test".replaceAll("test", "fest")', + "This is a fest", + id='replace-all', + ), + pytest.param( + QtCore.QUrl(), + '"This is a test".replaceAll(/[tr]est/g, "fest")', + "This is a fest", + id='replace-all-regex', + ), + pytest.param( + QtCore.QUrl(), + '"This is a [test[".replaceAll("[", "<")', + "This is a <test<", + id='replace-all-reserved-string', + ), + pytest.param( + QtCore.QUrl('https://test.qutebrowser.org/test'), + 'typeof globalThis.setTimeout === "function"', + True, + id='global-this', + ), + pytest.param( + QtCore.QUrl(), + 'Object.fromEntries([["0", "a"], ["1", "b"]])', + {'0': 'a', '1': 'b'}, + id='object-fromentries', + ), + ], +) def test_js_quirks(config_stub, js_tester_webengine, base_url, source, expected): config_stub.val.content.site_specific_quirks.skip = [] js_tester_webengine.tab._scripts._inject_site_specific_quirks() diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py index 5a787cea5..f300b95d2 100644 --- a/tests/unit/keyinput/test_basekeyparser.py +++ b/tests/unit/keyinput/test_basekeyparser.py @@ -144,12 +144,18 @@ class TestHandle: prompt_keyparser.execute.assert_called_once_with( 'message-info ctrla', 5) - @pytest.mark.parametrize('keys', [ - [(QtCore.Qt.Key_B, QtCore.Qt.NoModifier), (QtCore.Qt.Key_C, QtCore.Qt.NoModifier)], - [(QtCore.Qt.Key_A, QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier)], - # Only modifier - [(QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier)], - ]) + @pytest.mark.parametrize( + 'keys', + [ + [ + (QtCore.Qt.Key_B, QtCore.Qt.NoModifier), + (QtCore.Qt.Key_C, QtCore.Qt.NoModifier), + ], + [(QtCore.Qt.Key_A, QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier)], + # Only modifier + [(QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier)], + ], + ) def test_invalid_keys(self, prompt_keyparser, keys): for key, modifiers in keys: info = keyutils.KeyInfo(key, modifiers) @@ -180,32 +186,39 @@ class TestHandle: assert not prompt_keyparser._sequence def test_valid_keychain(self, handle_text, prompt_keyparser): - handle_text(prompt_keyparser, - # Press 'x' which is ignored because of no match - QtCore.Qt.Key_X, - # Then start the real chain - QtCore.Qt.Key_B, QtCore.Qt.Key_A) + handle_text( + prompt_keyparser, + # Press 'x' which is ignored because of no match + QtCore.Qt.Key_X, + # Then start the real chain + QtCore.Qt.Key_B, + QtCore.Qt.Key_A, + ) prompt_keyparser.execute.assert_called_with('message-info ba', None) assert not prompt_keyparser._sequence - @pytest.mark.parametrize('key, modifiers, number', [ - (QtCore.Qt.Key_0, QtCore.Qt.NoModifier, 0), - (QtCore.Qt.Key_1, QtCore.Qt.NoModifier, 1), - (QtCore.Qt.Key_1, QtCore.Qt.KeypadModifier, 1), - ]) - def test_number_press(self, prompt_keyparser, - key, modifiers, number): + @pytest.mark.parametrize( + 'key, modifiers, number', + [ + (QtCore.Qt.Key_0, QtCore.Qt.NoModifier, 0), + (QtCore.Qt.Key_1, QtCore.Qt.NoModifier, 1), + (QtCore.Qt.Key_1, QtCore.Qt.KeypadModifier, 1), + ], + ) + def test_number_press(self, prompt_keyparser, key, modifiers, number): prompt_keyparser.handle(keyutils.KeyInfo(key, modifiers).to_event()) command = 'message-info {}'.format(number) prompt_keyparser.execute.assert_called_once_with(command, None) assert not prompt_keyparser._sequence - @pytest.mark.parametrize('modifiers, text', [ - (QtCore.Qt.NoModifier, '2'), - (QtCore.Qt.KeypadModifier, 'num-2'), - ]) - def test_number_press_keypad(self, keyparser, config_stub, - modifiers, text): + @pytest.mark.parametrize( + 'modifiers, text', + [ + (QtCore.Qt.NoModifier, '2'), + (QtCore.Qt.KeypadModifier, 'num-2'), + ], + ) + def test_number_press_keypad(self, keyparser, config_stub, modifiers, text): """Make sure a <Num+2> binding overrides the 2 binding.""" config_stub.val.bindings.commands = {'normal': { '2': 'message-info 2', @@ -248,9 +261,11 @@ class TestHandle: def test_binding_with_shift(self, prompt_keyparser): """Simulate a binding which involves shift.""" - for key, modifiers in [(QtCore.Qt.Key_Y, QtCore.Qt.NoModifier), - (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier), - (QtCore.Qt.Key_Y, QtCore.Qt.ShiftModifier)]: + for key, modifiers in [ + (QtCore.Qt.Key_Y, QtCore.Qt.NoModifier), + (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier), + (QtCore.Qt.Key_Y, QtCore.Qt.ShiftModifier), + ]: info = keyutils.KeyInfo(key, modifiers) prompt_keyparser.handle(info.to_event()) @@ -288,26 +303,48 @@ class TestCount: assert not prompt_keyparser._sequence def test_count_42(self, handle_text, prompt_keyparser): - handle_text(prompt_keyparser, QtCore.Qt.Key_4, QtCore.Qt.Key_2, QtCore.Qt.Key_B, QtCore.Qt.Key_A) + handle_text( + prompt_keyparser, + QtCore.Qt.Key_4, + QtCore.Qt.Key_2, + QtCore.Qt.Key_B, + QtCore.Qt.Key_A, + ) prompt_keyparser.execute.assert_called_once_with('message-info ba', 42) assert not prompt_keyparser._sequence def test_count_42_invalid(self, handle_text, prompt_keyparser): # Invalid call with ccx gets ignored - handle_text(prompt_keyparser, - QtCore.Qt.Key_4, QtCore.Qt.Key_2, QtCore.Qt.Key_C, QtCore.Qt.Key_C, QtCore.Qt.Key_X) + handle_text( + prompt_keyparser, + QtCore.Qt.Key_4, + QtCore.Qt.Key_2, + QtCore.Qt.Key_C, + QtCore.Qt.Key_C, + QtCore.Qt.Key_X, + ) assert not prompt_keyparser.execute.called assert not prompt_keyparser._sequence # Valid call with ccc gets the correct count - handle_text(prompt_keyparser, - QtCore.Qt.Key_2, QtCore.Qt.Key_3, QtCore.Qt.Key_C, QtCore.Qt.Key_C, QtCore.Qt.Key_C) - prompt_keyparser.execute.assert_called_once_with( - 'message-info ccc', 23) + handle_text( + prompt_keyparser, + QtCore.Qt.Key_2, + QtCore.Qt.Key_3, + QtCore.Qt.Key_C, + QtCore.Qt.Key_C, + QtCore.Qt.Key_C, + ) + prompt_keyparser.execute.assert_called_once_with('message-info ccc', 23) assert not prompt_keyparser._sequence def test_superscript(self, handle_text, prompt_keyparser): # https://github.com/qutebrowser/qutebrowser/issues/3743 - handle_text(prompt_keyparser, QtCore.Qt.Key_twosuperior, QtCore.Qt.Key_B, QtCore.Qt.Key_A) + handle_text( + prompt_keyparser, + QtCore.Qt.Key_twosuperior, + QtCore.Qt.Key_B, + QtCore.Qt.Key_A, + ) def test_count_keystring_update(self, qtbot, handle_text, prompt_keyparser): @@ -322,10 +359,12 @@ class TestCount: def test_numpad(self, prompt_keyparser): """Make sure we can enter a count via numpad.""" - for key, modifiers in [(QtCore.Qt.Key_4, QtCore.Qt.KeypadModifier), - (QtCore.Qt.Key_2, QtCore.Qt.KeypadModifier), - (QtCore.Qt.Key_B, QtCore.Qt.NoModifier), - (QtCore.Qt.Key_A, QtCore.Qt.NoModifier)]: + for key, modifiers in [ + (QtCore.Qt.Key_4, QtCore.Qt.KeypadModifier), + (QtCore.Qt.Key_2, QtCore.Qt.KeypadModifier), + (QtCore.Qt.Key_B, QtCore.Qt.NoModifier), + (QtCore.Qt.Key_A, QtCore.Qt.NoModifier), + ]: info = keyutils.KeyInfo(key, modifiers) prompt_keyparser.handle(info.to_event()) prompt_keyparser.execute.assert_called_once_with('message-info ba', 42) diff --git a/tests/unit/keyinput/test_bindingtrie.py b/tests/unit/keyinput/test_bindingtrie.py index 0a45a03c4..388be0f42 100644 --- a/tests/unit/keyinput/test_bindingtrie.py +++ b/tests/unit/keyinput/test_bindingtrie.py @@ -79,26 +79,43 @@ def test_str(): assert str(trie) == textwrap.dedent(expected).lstrip('\n') -@pytest.mark.parametrize('configured, expected', [ - ([], - # null match - [('a', QtGui.QKeySequence.NoMatch), - ('', QtGui.QKeySequence.NoMatch)]), - (['abcd'], - [('abcd', QtGui.QKeySequence.ExactMatch), - ('abc', QtGui.QKeySequence.PartialMatch)]), - (['aa', 'ab', 'ac', 'ad'], - [('ac', QtGui.QKeySequence.ExactMatch), - ('a', QtGui.QKeySequence.PartialMatch), - ('f', QtGui.QKeySequence.NoMatch), - ('acd', QtGui.QKeySequence.NoMatch)]), - (['aaaaaaab', 'aaaaaaac', 'aaaaaaad'], - [('aaaaaaab', QtGui.QKeySequence.ExactMatch), - ('z', QtGui.QKeySequence.NoMatch)]), - (string.ascii_letters, - [('a', QtGui.QKeySequence.ExactMatch), - ('!', QtGui.QKeySequence.NoMatch)]), -]) +@pytest.mark.parametrize( + 'configured, expected', + [ + ( + [], + # null match + [('a', QtGui.QKeySequence.NoMatch), ('', QtGui.QKeySequence.NoMatch)], + ), + ( + ['abcd'], + [ + ('abcd', QtGui.QKeySequence.ExactMatch), + ('abc', QtGui.QKeySequence.PartialMatch), + ], + ), + ( + ['aa', 'ab', 'ac', 'ad'], + [ + ('ac', QtGui.QKeySequence.ExactMatch), + ('a', QtGui.QKeySequence.PartialMatch), + ('f', QtGui.QKeySequence.NoMatch), + ('acd', QtGui.QKeySequence.NoMatch), + ], + ), + ( + ['aaaaaaab', 'aaaaaaac', 'aaaaaaad'], + [ + ('aaaaaaab', QtGui.QKeySequence.ExactMatch), + ('z', QtGui.QKeySequence.NoMatch), + ], + ), + ( + string.ascii_letters, + [('a', QtGui.QKeySequence.ExactMatch), ('!', QtGui.QKeySequence.NoMatch)], + ), + ], +) def test_matches_tree(configured, expected, benchmark): trie = basekeyparser.BindingTrie() trie.update({keyutils.KeySequence.parse(keys): "eeloo" @@ -107,11 +124,10 @@ def test_matches_tree(configured, expected, benchmark): def run(): for entered, match_type in expected: sequence = keyutils.KeySequence.parse(entered) - command = ("eeloo" if match_type == QtGui.QKeySequence.ExactMatch - else None) - result = basekeyparser.MatchResult(match_type=match_type, - command=command, - sequence=sequence) + command = "eeloo" if match_type == QtGui.QKeySequence.ExactMatch else None + result = basekeyparser.MatchResult( + match_type=match_type, command=command, sequence=sequence + ) assert trie.matches(sequence) == result benchmark(run) diff --git a/tests/unit/keyinput/test_keyutils.py b/tests/unit/keyinput/test_keyutils.py index 9756290a3..b43736478 100644 --- a/tests/unit/keyinput/test_keyutils.py +++ b/tests/unit/keyinput/test_keyutils.py @@ -59,9 +59,11 @@ def qtest_key(request): def test_key_data_keys(): """Make sure all possible keys are in key_data.KEYS.""" - key_names = {name[len("Key_"):] - for name, value in sorted(vars(QtCore.Qt).items()) - if isinstance(value, QtCore.Qt.Key)} + key_names = { + name[len("Key_") :] + for name, value in sorted(vars(QtCore.Qt).items()) + if isinstance(value, QtCore.Qt.Key) + } key_data_names = {key.attribute for key in sorted(key_data.KEYS)} diff = key_names - key_data_names assert not diff @@ -69,10 +71,12 @@ def test_key_data_keys(): def test_key_data_modifiers(): """Make sure all possible modifiers are in key_data.MODIFIERS.""" - mod_names = {name[:-len("Modifier")] - for name, value in sorted(vars(QtCore.Qt).items()) - if isinstance(value, QtCore.Qt.KeyboardModifier) and - value not in [QtCore.Qt.NoModifier, QtCore.Qt.KeyboardModifierMask]} + mod_names = { + name[: -len("Modifier")] + for name, value in sorted(vars(QtCore.Qt).items()) + if isinstance(value, QtCore.Qt.KeyboardModifier) + and value not in [QtCore.Qt.NoModifier, QtCore.Qt.KeyboardModifierMask] + } mod_data_names = {mod.attribute for mod in sorted(key_data.MODIFIERS)} diff = mod_names - mod_data_names assert not diff @@ -124,8 +128,9 @@ class TestKeyInfoText: with qtbot.wait_signal(key_tester.got_text): qtbot.keyPress(key_tester, qtest_key.member) - info = keyutils.KeyInfo(qtest_key.member, - modifiers=QtCore.Qt.KeyboardModifiers()) + info = keyutils.KeyInfo( + qtest_key.member, modifiers=QtCore.Qt.KeyboardModifiers() + ) assert info.text() == key_tester.text.lower() @@ -145,64 +150,101 @@ class TestKeyToString: assert keyutils._key_to_string(QtCore.Qt.Key_A) == 'A' -@pytest.mark.parametrize('key, modifiers, expected', [ - (QtCore.Qt.Key_A, QtCore.Qt.NoModifier, 'a'), - (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, 'A'), - - (QtCore.Qt.Key_Space, QtCore.Qt.NoModifier, '<Space>'), - (QtCore.Qt.Key_Space, QtCore.Qt.ShiftModifier, '<Shift+Space>'), - (QtCore.Qt.Key_Tab, QtCore.Qt.ShiftModifier, '<Shift+Tab>'), - (QtCore.Qt.Key_A, QtCore.Qt.ControlModifier, '<Ctrl+a>'), - (QtCore.Qt.Key_A, QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, '<Ctrl+Shift+a>'), - (QtCore.Qt.Key_A, - QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier | QtCore.Qt.MetaModifier | QtCore.Qt.ShiftModifier, - '<Meta+Ctrl+Alt+Shift+a>'), - (ord('Œ'), QtCore.Qt.NoModifier, '<Œ>'), - (ord('Œ'), QtCore.Qt.ShiftModifier, '<Shift+Œ>'), - (ord('Œ'), QtCore.Qt.GroupSwitchModifier, '<AltGr+Œ>'), - (ord('Œ'), QtCore.Qt.GroupSwitchModifier | QtCore.Qt.ShiftModifier, '<AltGr+Shift+Œ>'), - - (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier, '<Shift>'), - (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier, '<Ctrl+Shift>'), - (QtCore.Qt.Key_Alt, QtCore.Qt.AltModifier, '<Alt>'), - (QtCore.Qt.Key_Shift, QtCore.Qt.GroupSwitchModifier | QtCore.Qt.ShiftModifier, '<AltGr+Shift>'), - (QtCore.Qt.Key_AltGr, QtCore.Qt.GroupSwitchModifier, '<AltGr>'), -]) +@pytest.mark.parametrize( + 'key, modifiers, expected', + [ + (QtCore.Qt.Key_A, QtCore.Qt.NoModifier, 'a'), + (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, 'A'), + (QtCore.Qt.Key_Space, QtCore.Qt.NoModifier, '<Space>'), + (QtCore.Qt.Key_Space, QtCore.Qt.ShiftModifier, '<Shift+Space>'), + (QtCore.Qt.Key_Tab, QtCore.Qt.ShiftModifier, '<Shift+Tab>'), + (QtCore.Qt.Key_A, QtCore.Qt.ControlModifier, '<Ctrl+a>'), + ( + QtCore.Qt.Key_A, + QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, + '<Ctrl+Shift+a>', + ), + ( + QtCore.Qt.Key_A, + QtCore.Qt.ControlModifier + | QtCore.Qt.AltModifier + | QtCore.Qt.MetaModifier + | QtCore.Qt.ShiftModifier, + '<Meta+Ctrl+Alt+Shift+a>', + ), + (ord('Œ'), QtCore.Qt.NoModifier, '<Œ>'), + (ord('Œ'), QtCore.Qt.ShiftModifier, '<Shift+Œ>'), + (ord('Œ'), QtCore.Qt.GroupSwitchModifier, '<AltGr+Œ>'), + ( + ord('Œ'), + QtCore.Qt.GroupSwitchModifier | QtCore.Qt.ShiftModifier, + '<AltGr+Shift+Œ>', + ), + (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier, '<Shift>'), + ( + QtCore.Qt.Key_Shift, + QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier, + '<Ctrl+Shift>', + ), + (QtCore.Qt.Key_Alt, QtCore.Qt.AltModifier, '<Alt>'), + ( + QtCore.Qt.Key_Shift, + QtCore.Qt.GroupSwitchModifier | QtCore.Qt.ShiftModifier, + '<AltGr+Shift>', + ), + (QtCore.Qt.Key_AltGr, QtCore.Qt.GroupSwitchModifier, '<AltGr>'), + ], +) def test_key_info_str(key, modifiers, expected): assert str(keyutils.KeyInfo(key, modifiers)) == expected -@pytest.mark.parametrize('info1, info2, equal', [ - (keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), - keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), - True), - (keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), - keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.NoModifier), - False), - (keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), - keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.ControlModifier), - False), -]) +@pytest.mark.parametrize( + 'info1, info2, equal', + [ + ( + keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), + keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), + True, + ), + ( + keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), + keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.NoModifier), + False, + ), + ( + keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.NoModifier), + keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.ControlModifier), + False, + ), + ], +) def test_hash(info1, info2, equal): assert (hash(info1) == hash(info2)) == equal -@pytest.mark.parametrize('key, modifiers, text, expected', [ - (0xd83c, QtCore.Qt.NoModifier, '🏻', '<🏻>'), - (0xd867, QtCore.Qt.NoModifier, '𩷶', '<𩷶>'), - (0xd867, QtCore.Qt.ShiftModifier, '𩷶', '<Shift+𩷶>'), -]) +@pytest.mark.parametrize( + 'key, modifiers, text, expected', + [ + (0xD83C, QtCore.Qt.NoModifier, '🏻', '<🏻>'), + (0xD867, QtCore.Qt.NoModifier, '𩷶', '<𩷶>'), + (0xD867, QtCore.Qt.ShiftModifier, '𩷶', '<Shift+𩷶>'), + ], +) def test_surrogates(key, modifiers, text, expected): evt = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, key, modifiers, text) assert str(keyutils.KeyInfo.from_event(evt)) == expected -@pytest.mark.parametrize('keys, expected', [ - ([0x1f3fb], '<🏻>'), - ([0x29df6], '<𩷶>'), - ([QtCore.Qt.Key_Shift, 0x29df6], '<Shift><𩷶>'), - ([0x1f468, 0x200d, 0x1f468, 0x200d, 0x1f466], '<👨><><👨><><👦>'), -]) +@pytest.mark.parametrize( + 'keys, expected', + [ + ([0x1F3FB], '<🏻>'), + ([0x29DF6], '<𩷶>'), + ([QtCore.Qt.Key_Shift, 0x29DF6], '<Shift><𩷶>'), + ([0x1F468, 0x200D, 0x1F468, 0x200D, 0x1F466], '<👨><><👨><><👦>'), + ], +) def test_surrogate_sequences(keys, expected): seq = keyutils.KeySequence(*keys) assert str(seq) == expected @@ -210,7 +252,7 @@ def test_surrogate_sequences(keys, expected): # This shouldn't happen, but if it does we should handle it well def test_surrogate_error(): - evt = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, 0xd83e, QtCore.Qt.NoModifier, '🤞🏻') + evt = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, 0xD83E, QtCore.Qt.NoModifier, '🤞🏻') with pytest.raises(keyutils.KeyParseError): keyutils.KeyInfo.from_event(evt) @@ -245,8 +287,13 @@ def test_parse_keystr(keystr, parts): class TestKeySequence: def test_init(self): - seq = keyutils.KeySequence(QtCore.Qt.Key_A, QtCore.Qt.Key_B, QtCore.Qt.Key_C, QtCore.Qt.Key_D, - QtCore.Qt.Key_E) + seq = keyutils.KeySequence( + QtCore.Qt.Key_A, + QtCore.Qt.Key_B, + QtCore.Qt.Key_C, + QtCore.Qt.Key_D, + QtCore.Qt.Key_E, + ) assert len(seq._sequences) == 2 assert len(seq._sequences[0]) == 4 assert len(seq._sequences[1]) == 1 @@ -282,23 +329,30 @@ class TestKeySequence: assert str(keyutils.KeySequence.parse(orig)) == normalized def test_iter(self): - seq = keyutils.KeySequence(QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, - QtCore.Qt.Key_B | QtCore.Qt.ShiftModifier, - QtCore.Qt.Key_C, - QtCore.Qt.Key_D, - QtCore.Qt.Key_E) - expected = [keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.ControlModifier), - keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.ShiftModifier), - keyutils.KeyInfo(QtCore.Qt.Key_C, QtCore.Qt.NoModifier), - keyutils.KeyInfo(QtCore.Qt.Key_D, QtCore.Qt.NoModifier), - keyutils.KeyInfo(QtCore.Qt.Key_E, QtCore.Qt.NoModifier)] + seq = keyutils.KeySequence( + QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, + QtCore.Qt.Key_B | QtCore.Qt.ShiftModifier, + QtCore.Qt.Key_C, + QtCore.Qt.Key_D, + QtCore.Qt.Key_E, + ) + expected = [ + keyutils.KeyInfo(QtCore.Qt.Key_A, QtCore.Qt.ControlModifier), + keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.ShiftModifier), + keyutils.KeyInfo(QtCore.Qt.Key_C, QtCore.Qt.NoModifier), + keyutils.KeyInfo(QtCore.Qt.Key_D, QtCore.Qt.NoModifier), + keyutils.KeyInfo(QtCore.Qt.Key_E, QtCore.Qt.NoModifier), + ] assert list(seq) == expected def test_repr(self): - seq = keyutils.KeySequence(QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, - QtCore.Qt.Key_B | QtCore.Qt.ShiftModifier) - assert repr(seq) == ("<qutebrowser.keyinput.keyutils.KeySequence " - "keys='<Ctrl+a>B'>") + seq = keyutils.KeySequence( + QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, + QtCore.Qt.Key_B | QtCore.Qt.ShiftModifier, + ) + assert repr(seq) == ( + "<qutebrowser.keyinput.keyutils.KeySequence " "keys='<Ctrl+a>B'>" + ) @pytest.mark.parametrize('sequences, expected', [ (['a', ''], ['', 'a']), @@ -401,7 +455,8 @@ class TestKeySequence: # empty strings ('', '', QtGui.QKeySequence.ExactMatch), ('', 'a', QtGui.QKeySequence.PartialMatch), - ('a', '', QtGui.QKeySequence.NoMatch)] + ('a', '', QtGui.QKeySequence.NoMatch), + ] @pytest.mark.parametrize('entered, configured, match_type', MATCH_TESTS) def test_matches(self, entered, configured, match_type): @@ -409,35 +464,64 @@ class TestKeySequence: configured = keyutils.KeySequence.parse(configured) assert entered.matches(configured) == match_type - @pytest.mark.parametrize('old, key, modifiers, text, expected', [ - ('a', QtCore.Qt.Key_B, QtCore.Qt.NoModifier, 'b', 'ab'), - ('a', QtCore.Qt.Key_B, QtCore.Qt.ShiftModifier, 'B', 'aB'), - ('a', QtCore.Qt.Key_B, QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, 'B', - 'a<Alt+Shift+b>'), - - # Modifier stripping with symbols - ('', QtCore.Qt.Key_Colon, QtCore.Qt.NoModifier, ':', ':'), - ('', QtCore.Qt.Key_Colon, QtCore.Qt.ShiftModifier, ':', ':'), - ('', QtCore.Qt.Key_Colon, QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, ':', - '<Alt+Shift+:>'), - - # Swapping Control/Meta on macOS - ('', QtCore.Qt.Key_A, QtCore.Qt.ControlModifier, '', - '<Meta+A>' if utils.is_mac else '<Ctrl+A>'), - ('', QtCore.Qt.Key_A, QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, '', - '<Meta+Shift+A>' if utils.is_mac else '<Ctrl+Shift+A>'), - ('', QtCore.Qt.Key_A, QtCore.Qt.MetaModifier, '', - '<Ctrl+A>' if utils.is_mac else '<Meta+A>'), - - # Handling of Backtab - ('', QtCore.Qt.Key_Backtab, QtCore.Qt.NoModifier, '', '<Backtab>'), - ('', QtCore.Qt.Key_Backtab, QtCore.Qt.ShiftModifier, '', '<Shift+Tab>'), - ('', QtCore.Qt.Key_Backtab, QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, '', - '<Alt+Shift+Tab>'), - - # Stripping of Qt.GroupSwitchModifier - ('', QtCore.Qt.Key_A, QtCore.Qt.GroupSwitchModifier, 'a', 'a'), - ]) + @pytest.mark.parametrize( + 'old, key, modifiers, text, expected', + [ + ('a', QtCore.Qt.Key_B, QtCore.Qt.NoModifier, 'b', 'ab'), + ('a', QtCore.Qt.Key_B, QtCore.Qt.ShiftModifier, 'B', 'aB'), + ( + 'a', + QtCore.Qt.Key_B, + QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, + 'B', + 'a<Alt+Shift+b>', + ), + # Modifier stripping with symbols + ('', QtCore.Qt.Key_Colon, QtCore.Qt.NoModifier, ':', ':'), + ('', QtCore.Qt.Key_Colon, QtCore.Qt.ShiftModifier, ':', ':'), + ( + '', + QtCore.Qt.Key_Colon, + QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, + ':', + '<Alt+Shift+:>', + ), + # Swapping Control/Meta on macOS + ( + '', + QtCore.Qt.Key_A, + QtCore.Qt.ControlModifier, + '', + '<Meta+A>' if utils.is_mac else '<Ctrl+A>', + ), + ( + '', + QtCore.Qt.Key_A, + QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, + '', + '<Meta+Shift+A>' if utils.is_mac else '<Ctrl+Shift+A>', + ), + ( + '', + QtCore.Qt.Key_A, + QtCore.Qt.MetaModifier, + '', + '<Ctrl+A>' if utils.is_mac else '<Meta+A>', + ), + # Handling of Backtab + ('', QtCore.Qt.Key_Backtab, QtCore.Qt.NoModifier, '', '<Backtab>'), + ('', QtCore.Qt.Key_Backtab, QtCore.Qt.ShiftModifier, '', '<Shift+Tab>'), + ( + '', + QtCore.Qt.Key_Backtab, + QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier, + '', + '<Alt+Shift+Tab>', + ), + # Stripping of Qt.GroupSwitchModifier + ('', QtCore.Qt.Key_A, QtCore.Qt.GroupSwitchModifier, 'a', 'a'), + ], + ) def test_append_event(self, old, key, modifiers, text, expected): seq = keyutils.KeySequence.parse(old) event = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, key, modifiers, text) @@ -445,19 +529,26 @@ class TestKeySequence: assert new == keyutils.KeySequence.parse(expected) @pytest.mark.fake_os('mac') - @pytest.mark.parametrize('modifiers, expected', [ - (QtCore.Qt.ControlModifier, - QtCore.Qt.MetaModifier), - (QtCore.Qt.MetaModifier, - QtCore.Qt.ControlModifier), - (QtCore.Qt.ControlModifier | QtCore.Qt.MetaModifier, - QtCore.Qt.ControlModifier | QtCore.Qt.MetaModifier), - (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, - QtCore.Qt.MetaModifier | QtCore.Qt.ShiftModifier), - (QtCore.Qt.MetaModifier | QtCore.Qt.ShiftModifier, - QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier), - (QtCore.Qt.ShiftModifier, QtCore.Qt.ShiftModifier), - ]) + @pytest.mark.parametrize( + 'modifiers, expected', + [ + (QtCore.Qt.ControlModifier, QtCore.Qt.MetaModifier), + (QtCore.Qt.MetaModifier, QtCore.Qt.ControlModifier), + ( + QtCore.Qt.ControlModifier | QtCore.Qt.MetaModifier, + QtCore.Qt.ControlModifier | QtCore.Qt.MetaModifier, + ), + ( + QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, + QtCore.Qt.MetaModifier | QtCore.Qt.ShiftModifier, + ), + ( + QtCore.Qt.MetaModifier | QtCore.Qt.ShiftModifier, + QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier, + ), + (QtCore.Qt.ShiftModifier, QtCore.Qt.ShiftModifier), + ], + ) def test_fake_mac(self, modifiers, expected): """Make sure Control/Meta are swapped with a simulated Mac.""" seq = keyutils.KeySequence() @@ -473,12 +564,16 @@ class TestKeySequence: seq.append_event(event) def test_strip_modifiers(self): - seq = keyutils.KeySequence(QtCore.Qt.Key_0, - QtCore.Qt.Key_1 | QtCore.Qt.KeypadModifier, - QtCore.Qt.Key_A | QtCore.Qt.ControlModifier) - expected = keyutils.KeySequence(QtCore.Qt.Key_0, - QtCore.Qt.Key_1, - QtCore.Qt.Key_A | QtCore.Qt.ControlModifier) + seq = keyutils.KeySequence( + QtCore.Qt.Key_0, + QtCore.Qt.Key_1 | QtCore.Qt.KeypadModifier, + QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, + ) + expected = keyutils.KeySequence( + QtCore.Qt.Key_0, + QtCore.Qt.Key_1, + QtCore.Qt.Key_A | QtCore.Qt.ControlModifier, + ) assert seq.strip_modifiers() == expected @pytest.mark.parametrize('inp, mappings, expected', [ @@ -494,40 +589,67 @@ class TestKeySequence: }) assert seq2 == keyutils.KeySequence.parse(expected) - @pytest.mark.parametrize('keystr, expected', [ - ('<Ctrl-Alt-y>', - keyutils.KeySequence(QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier | QtCore.Qt.Key_Y)), - ('x', keyutils.KeySequence(QtCore.Qt.Key_X)), - ('X', keyutils.KeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_X)), - ('<Escape>', keyutils.KeySequence(QtCore.Qt.Key_Escape)), - ('xyz', keyutils.KeySequence(QtCore.Qt.Key_X, QtCore.Qt.Key_Y, QtCore.Qt.Key_Z)), - ('<Control-x><Meta-y>', - keyutils.KeySequence(QtCore.Qt.ControlModifier | QtCore.Qt.Key_X, - QtCore.Qt.MetaModifier | QtCore.Qt.Key_Y)), - - ('<Shift-x>', keyutils.KeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_X)), - ('<Alt-x>', keyutils.KeySequence(QtCore.Qt.AltModifier | QtCore.Qt.Key_X)), - ('<Control-x>', keyutils.KeySequence(QtCore.Qt.ControlModifier | QtCore.Qt.Key_X)), - ('<Meta-x>', keyutils.KeySequence(QtCore.Qt.MetaModifier | QtCore.Qt.Key_X)), - ('<Num-x>', keyutils.KeySequence(QtCore.Qt.KeypadModifier | QtCore.Qt.Key_X)), - - ('>', keyutils.KeySequence(QtCore.Qt.Key_Greater)), - ('<', keyutils.KeySequence(QtCore.Qt.Key_Less)), - ('a>', keyutils.KeySequence(QtCore.Qt.Key_A, QtCore.Qt.Key_Greater)), - ('a<', keyutils.KeySequence(QtCore.Qt.Key_A, QtCore.Qt.Key_Less)), - ('>a', keyutils.KeySequence(QtCore.Qt.Key_Greater, QtCore.Qt.Key_A)), - ('<a', keyutils.KeySequence(QtCore.Qt.Key_Less, QtCore.Qt.Key_A)), - ('<alt+greater>', - keyutils.KeySequence(QtCore.Qt.Key_Greater | QtCore.Qt.AltModifier)), - ('<alt+less>', - keyutils.KeySequence(QtCore.Qt.Key_Less | QtCore.Qt.AltModifier)), - - ('<alt+<>', keyutils.KeyParseError), - ('<alt+>>', keyutils.KeyParseError), - ('<blub>', keyutils.KeyParseError), - ('<>', keyutils.KeyParseError), - ('\U00010000', keyutils.KeyParseError), - ]) + @pytest.mark.parametrize( + 'keystr, expected', + [ + ( + '<Ctrl-Alt-y>', + keyutils.KeySequence( + QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier | QtCore.Qt.Key_Y + ), + ), + ('x', keyutils.KeySequence(QtCore.Qt.Key_X)), + ('X', keyutils.KeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_X)), + ('<Escape>', keyutils.KeySequence(QtCore.Qt.Key_Escape)), + ( + 'xyz', + keyutils.KeySequence(QtCore.Qt.Key_X, QtCore.Qt.Key_Y, QtCore.Qt.Key_Z), + ), + ( + '<Control-x><Meta-y>', + keyutils.KeySequence( + QtCore.Qt.ControlModifier | QtCore.Qt.Key_X, + QtCore.Qt.MetaModifier | QtCore.Qt.Key_Y, + ), + ), + ( + '<Shift-x>', + keyutils.KeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_X), + ), + ('<Alt-x>', keyutils.KeySequence(QtCore.Qt.AltModifier | QtCore.Qt.Key_X)), + ( + '<Control-x>', + keyutils.KeySequence(QtCore.Qt.ControlModifier | QtCore.Qt.Key_X), + ), + ( + '<Meta-x>', + keyutils.KeySequence(QtCore.Qt.MetaModifier | QtCore.Qt.Key_X), + ), + ( + '<Num-x>', + keyutils.KeySequence(QtCore.Qt.KeypadModifier | QtCore.Qt.Key_X), + ), + ('>', keyutils.KeySequence(QtCore.Qt.Key_Greater)), + ('<', keyutils.KeySequence(QtCore.Qt.Key_Less)), + ('a>', keyutils.KeySequence(QtCore.Qt.Key_A, QtCore.Qt.Key_Greater)), + ('a<', keyutils.KeySequence(QtCore.Qt.Key_A, QtCore.Qt.Key_Less)), + ('>a', keyutils.KeySequence(QtCore.Qt.Key_Greater, QtCore.Qt.Key_A)), + ('<a', keyutils.KeySequence(QtCore.Qt.Key_Less, QtCore.Qt.Key_A)), + ( + '<alt+greater>', + keyutils.KeySequence(QtCore.Qt.Key_Greater | QtCore.Qt.AltModifier), + ), + ( + '<alt+less>', + keyutils.KeySequence(QtCore.Qt.Key_Less | QtCore.Qt.AltModifier), + ), + ('<alt+<>', keyutils.KeyParseError), + ('<alt+>>', keyutils.KeyParseError), + ('<blub>', keyutils.KeyParseError), + ('<>', keyutils.KeyParseError), + ('\U00010000', keyutils.KeyParseError), + ], + ) def test_parse(self, keystr, expected): if expected is keyutils.KeyParseError: with pytest.raises(keyutils.KeyParseError): @@ -546,7 +668,9 @@ class TestKeySequence: def test_key_info_from_event(): - ev = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, 'A') + ev = QtGui.QKeyEvent( + QtCore.QEvent.KeyPress, QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, 'A' + ) info = keyutils.KeyInfo.from_event(ev) assert info.key == QtCore.Qt.Key_A assert info.modifiers == QtCore.Qt.ShiftModifier @@ -565,48 +689,56 @@ def test_key_info_to_int(): assert info.to_int() == QtCore.Qt.Key_A | QtCore.Qt.ShiftModifier -@pytest.mark.parametrize('key, printable', [ - (QtCore.Qt.Key_Control, False), - (QtCore.Qt.Key_Escape, False), - (QtCore.Qt.Key_Tab, False), - (QtCore.Qt.Key_Backtab, False), - (QtCore.Qt.Key_Backspace, False), - (QtCore.Qt.Key_Return, False), - (QtCore.Qt.Key_Enter, False), - (QtCore.Qt.Key_Space, False), - (0x0, False), # Used by Qt for unknown keys - - (QtCore.Qt.Key_ydiaeresis, True), - (QtCore.Qt.Key_X, True), -]) +@pytest.mark.parametrize( + 'key, printable', + [ + (QtCore.Qt.Key_Control, False), + (QtCore.Qt.Key_Escape, False), + (QtCore.Qt.Key_Tab, False), + (QtCore.Qt.Key_Backtab, False), + (QtCore.Qt.Key_Backspace, False), + (QtCore.Qt.Key_Return, False), + (QtCore.Qt.Key_Enter, False), + (QtCore.Qt.Key_Space, False), + (0x0, False), # Used by Qt for unknown keys + (QtCore.Qt.Key_ydiaeresis, True), + (QtCore.Qt.Key_X, True), + ], +) def test_is_printable(key, printable): assert keyutils._is_printable(key) == printable assert keyutils.is_special(key, QtCore.Qt.NoModifier) != printable -@pytest.mark.parametrize('key, modifiers, special', [ - (QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier, True), - (QtCore.Qt.Key_Escape, QtCore.Qt.ShiftModifier, True), - (QtCore.Qt.Key_Escape, QtCore.Qt.ControlModifier, True), - (QtCore.Qt.Key_X, QtCore.Qt.ControlModifier, True), - (QtCore.Qt.Key_X, QtCore.Qt.NoModifier, False), - (QtCore.Qt.Key_2, QtCore.Qt.KeypadModifier, True), - (QtCore.Qt.Key_2, QtCore.Qt.NoModifier, False), - (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier, True), - (QtCore.Qt.Key_Control, QtCore.Qt.ControlModifier, True), - (QtCore.Qt.Key_Alt, QtCore.Qt.AltModifier, True), - (QtCore.Qt.Key_Meta, QtCore.Qt.MetaModifier, True), - (QtCore.Qt.Key_Mode_switch, QtCore.Qt.GroupSwitchModifier, True), -]) +@pytest.mark.parametrize( + 'key, modifiers, special', + [ + (QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier, True), + (QtCore.Qt.Key_Escape, QtCore.Qt.ShiftModifier, True), + (QtCore.Qt.Key_Escape, QtCore.Qt.ControlModifier, True), + (QtCore.Qt.Key_X, QtCore.Qt.ControlModifier, True), + (QtCore.Qt.Key_X, QtCore.Qt.NoModifier, False), + (QtCore.Qt.Key_2, QtCore.Qt.KeypadModifier, True), + (QtCore.Qt.Key_2, QtCore.Qt.NoModifier, False), + (QtCore.Qt.Key_Shift, QtCore.Qt.ShiftModifier, True), + (QtCore.Qt.Key_Control, QtCore.Qt.ControlModifier, True), + (QtCore.Qt.Key_Alt, QtCore.Qt.AltModifier, True), + (QtCore.Qt.Key_Meta, QtCore.Qt.MetaModifier, True), + (QtCore.Qt.Key_Mode_switch, QtCore.Qt.GroupSwitchModifier, True), + ], +) def test_is_special(key, modifiers, special): assert keyutils.is_special(key, modifiers) == special -@pytest.mark.parametrize('key, ismodifier', [ - (QtCore.Qt.Key_Control, True), - (QtCore.Qt.Key_X, False), - (QtCore.Qt.Key_Super_L, False), # Modifier but not in _MODIFIER_MAP -]) +@pytest.mark.parametrize( + 'key, ismodifier', + [ + (QtCore.Qt.Key_Control, True), + (QtCore.Qt.Key_X, False), + (QtCore.Qt.Key_Super_L, False), # Modifier but not in _MODIFIER_MAP + ], +) def test_is_modifier_key(key, ismodifier): assert keyutils.is_modifier_key(key) == ismodifier diff --git a/tests/unit/keyinput/test_modeman.py b/tests/unit/keyinput/test_modeman.py index d160ad19f..21422f621 100644 --- a/tests/unit/keyinput/test_modeman.py +++ b/tests/unit/keyinput/test_modeman.py @@ -51,13 +51,16 @@ def set_qapp(monkeypatch, qapp): monkeypatch.setattr(objects, 'qapp', qapp) -@pytest.mark.parametrize('key, modifiers, filtered', [ - (QtCore.Qt.Key_A, QtCore.Qt.NoModifier, True), - (QtCore.Qt.Key_Up, QtCore.Qt.NoModifier, False), - # https://github.com/qutebrowser/qutebrowser/issues/1207 - (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, True), - (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier, False), -]) +@pytest.mark.parametrize( + 'key, modifiers, filtered', + [ + (QtCore.Qt.Key_A, QtCore.Qt.NoModifier, True), + (QtCore.Qt.Key_Up, QtCore.Qt.NoModifier, False), + # https://github.com/qutebrowser/qutebrowser/issues/1207 + (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier, True), + (QtCore.Qt.Key_A, QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier, False), + ], +) def test_non_alphanumeric(key, modifiers, filtered, modeman): """Make sure non-alphanumeric keys are passed through correctly.""" evt = keyutils.KeyInfo(key=key, modifiers=modifiers).to_event() diff --git a/tests/unit/keyinput/test_modeparsers.py b/tests/unit/keyinput/test_modeparsers.py index ac91d14c7..b8bce2291 100644 --- a/tests/unit/keyinput/test_modeparsers.py +++ b/tests/unit/keyinput/test_modeparsers.py @@ -64,7 +64,9 @@ class TestsNormalKeyParser: # Press 'b' for a partial match. # Then we check if the timer has been set up correctly - keyparser.handle(keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.NoModifier).to_event()) + keyparser.handle( + keyutils.KeyInfo(QtCore.Qt.Key_B, QtCore.Qt.NoModifier).to_event() + ) assert timer.isSingleShot() assert timer.interval() == 100 assert timer.isActive() diff --git a/tests/unit/mainwindow/statusbar/test_textbase.py b/tests/unit/mainwindow/statusbar/test_textbase.py index fbf1688e9..982b09736 100644 --- a/tests/unit/mainwindow/statusbar/test_textbase.py +++ b/tests/unit/mainwindow/statusbar/test_textbase.py @@ -25,12 +25,15 @@ import pytest from qutebrowser.mainwindow.statusbar.textbase import TextBase -@pytest.mark.parametrize('elidemode, check', [ - (QtCore.Qt.ElideRight, lambda s: s.endswith('…') or s.endswith('...')), - (QtCore.Qt.ElideLeft, lambda s: s.startswith('…') or s.startswith('...')), - (QtCore.Qt.ElideMiddle, lambda s: '…' in s or '...' in s), - (QtCore.Qt.ElideNone, lambda s: '…' not in s and '...' not in s), -]) +@pytest.mark.parametrize( + 'elidemode, check', + [ + (QtCore.Qt.ElideRight, lambda s: s.endswith('…') or s.endswith('...')), + (QtCore.Qt.ElideLeft, lambda s: s.startswith('…') or s.startswith('...')), + (QtCore.Qt.ElideMiddle, lambda s: '…' in s or '...' in s), + (QtCore.Qt.ElideNone, lambda s: '…' not in s and '...' not in s), + ], +) def test_elided_text(fake_statusbar, qtbot, elidemode, check): """Ensure that a widget too small to hold the entire label text will elide. diff --git a/tests/unit/mainwindow/statusbar/test_url.py b/tests/unit/mainwindow/statusbar/test_url.py index 5bc16f6e0..2f18ddf76 100644 --- a/tests/unit/mainwindow/statusbar/test_url.py +++ b/tests/unit/mainwindow/statusbar/test_url.py @@ -89,24 +89,28 @@ def test_on_load_status_changed(url_widget, status, expected): assert url_widget._urltype == expected -@pytest.mark.parametrize('load_status, qurl', [ - (usertypes.LoadStatus.success, - QtCore.QUrl('http://abc123.com/this/awesome/url.html')), - (usertypes.LoadStatus.success, - QtCore.QUrl('http://reddit.com/r/linux')), - (usertypes.LoadStatus.success, - QtCore.QUrl('http://ä.com/')), - (usertypes.LoadStatus.success_https, - QtCore.QUrl('www.google.com')), - (usertypes.LoadStatus.success_https, - QtCore.QUrl('https://supersecret.gov/nsa/files.txt')), - (usertypes.LoadStatus.warn, - QtCore.QUrl('www.shadysite.org/some/file/with/issues.htm')), - (usertypes.LoadStatus.error, - QtCore.QUrl('invalid::/url')), - (usertypes.LoadStatus.error, - QtCore.QUrl()), -]) +@pytest.mark.parametrize( + 'load_status, qurl', + [ + ( + usertypes.LoadStatus.success, + QtCore.QUrl('http://abc123.com/this/awesome/url.html'), + ), + (usertypes.LoadStatus.success, QtCore.QUrl('http://reddit.com/r/linux')), + (usertypes.LoadStatus.success, QtCore.QUrl('http://ä.com/')), + (usertypes.LoadStatus.success_https, QtCore.QUrl('www.google.com')), + ( + usertypes.LoadStatus.success_https, + QtCore.QUrl('https://supersecret.gov/nsa/files.txt'), + ), + ( + usertypes.LoadStatus.warn, + QtCore.QUrl('www.shadysite.org/some/file/with/issues.htm'), + ), + (usertypes.LoadStatus.error, QtCore.QUrl('invalid::/url')), + (usertypes.LoadStatus.error, QtCore.QUrl()), + ], +) def test_on_tab_changed(url_widget, fake_web_tab, load_status, qurl): tab_widget = fake_web_tab(load_status=load_status, url=qurl) url_widget.on_tab_changed(tab_widget) @@ -119,28 +123,31 @@ def test_on_tab_changed(url_widget, fake_web_tab, load_status, qurl): assert url_widget.text() == expected -@pytest.mark.parametrize('qurl, load_status, expected_status', [ - ( - QtCore.QUrl('http://abc123.com/this/awesome/url.html'), - usertypes.LoadStatus.success, - url.UrlType.success - ), - ( - QtCore.QUrl('https://supersecret.gov/nsa/files.txt'), - usertypes.LoadStatus.success_https, - url.UrlType.success_https - ), - ( - QtCore.QUrl('http://www.qutebrowser.org/CONTRIBUTING.html'), - usertypes.LoadStatus.loading, - url.UrlType.normal - ), - ( - QtCore.QUrl('www.whatisthisurl.com'), - usertypes.LoadStatus.warn, - url.UrlType.warn - ), -]) +@pytest.mark.parametrize( + 'qurl, load_status, expected_status', + [ + ( + QtCore.QUrl('http://abc123.com/this/awesome/url.html'), + usertypes.LoadStatus.success, + url.UrlType.success, + ), + ( + QtCore.QUrl('https://supersecret.gov/nsa/files.txt'), + usertypes.LoadStatus.success_https, + url.UrlType.success_https, + ), + ( + QtCore.QUrl('http://www.qutebrowser.org/CONTRIBUTING.html'), + usertypes.LoadStatus.loading, + url.UrlType.normal, + ), + ( + QtCore.QUrl('www.whatisthisurl.com'), + usertypes.LoadStatus.warn, + url.UrlType.warn, + ), + ], +) def test_normal_url(url_widget, qurl, load_status, expected_status): url_widget.set_url(qurl) url_widget.on_load_status_changed(load_status) diff --git a/tests/unit/mainwindow/test_messageview.py b/tests/unit/mainwindow/test_messageview.py index f4a4def60..05878f0f6 100644 --- a/tests/unit/mainwindow/test_messageview.py +++ b/tests/unit/mainwindow/test_messageview.py @@ -154,12 +154,15 @@ def test_replacing_geometry(qtbot, view): view.show_message(usertypes.MessageLevel.info, 'test 2', replace='testid') -@pytest.mark.parametrize('button, count', [ - (QtCore.Qt.LeftButton, 0), - (QtCore.Qt.MiddleButton, 0), - (QtCore.Qt.RightButton, 0), - (QtCore.Qt.BackButton, 2), -]) +@pytest.mark.parametrize( + 'button, count', + [ + (QtCore.Qt.LeftButton, 0), + (QtCore.Qt.MiddleButton, 0), + (QtCore.Qt.RightButton, 0), + (QtCore.Qt.BackButton, 2), + ], +) def test_click_messages(qtbot, view, button, count): """Messages should disappear when we click on them.""" view.show_message(usertypes.MessageLevel.info, 'test mouse click') diff --git a/tests/unit/mainwindow/test_prompt.py b/tests/unit/mainwindow/test_prompt.py index 223943148..208145d91 100644 --- a/tests/unit/mainwindow/test_prompt.py +++ b/tests/unit/mainwindow/test_prompt.py @@ -97,11 +97,14 @@ class TestFileCompletion: prompt.item_focus('next') assert prompt._lineedit.text() == str(testdir / 'foo') - @pytest.mark.parametrize("keys, expected", [ - ([], ['bar', 'bat', 'foo']), - ([QtCore.Qt.Key_F], ['foo']), - ([QtCore.Qt.Key_A], ['bar', 'bat']), - ]) + @pytest.mark.parametrize( + "keys, expected", + [ + ([], ['bar', 'bat', 'foo']), + ([QtCore.Qt.Key_F], ['foo']), + ([QtCore.Qt.Key_A], ['bar', 'bat']), + ], + ) def test_filtering_path(self, qtbot, tmp_path, get_prompt, keys, expected): testdir = tmp_path / 'test' diff --git a/tests/unit/misc/test_ipc.py b/tests/unit/misc/test_ipc.py index fdd543d2a..a536ee46e 100644 --- a/tests/unit/misc/test_ipc.py +++ b/tests/unit/misc/test_ipc.py @@ -54,8 +54,10 @@ def shutdown_server(): def ipc_server(qapp, qtbot): server = ipc.IPCServer('qute-test') yield server - if (server._socket is not None and - server._socket.state() != QtNetwork.QLocalSocket.UnconnectedState): + if ( + server._socket is not None + and server._socket.state() != QtNetwork.QLocalSocket.UnconnectedState + ): with qtbot.wait_signal(server._socket.disconnected, raising=False): server._socket.abort() try: @@ -102,8 +104,15 @@ class FakeSocket(QtCore.QObject): readyRead = QtCore.pyqtSignal() # noqa: N815 disconnected = QtCore.pyqtSignal() - def __init__(self, *, error=QtNetwork.QLocalSocket.UnknownSocketError, state=None, - data=None, connect_successful=True, parent=None): + def __init__( + self, + *, + error=QtNetwork.QLocalSocket.UnknownSocketError, + state=None, + data=None, + connect_successful=True, + parent=None + ): super().__init__(parent) self._error_val = error self._state_val = state @@ -301,16 +310,18 @@ class TestListen: def test_error(self, ipc_server, monkeypatch): """Simulate an error while listening.""" - monkeypatch.setattr(ipc.QtNetwork.QLocalServer, 'removeServer', - lambda self: True) + monkeypatch.setattr( + ipc.QtNetwork.QLocalServer, 'removeServer', lambda self: True + ) monkeypatch.setattr(ipc_server, '_socketname', None) with pytest.raises(ipc.ListenError): ipc_server.listen() @pytest.mark.posix def test_in_use(self, qlocalserver, ipc_server, monkeypatch): - monkeypatch.setattr(ipc.QtNetwork.QLocalServer, 'removeServer', - lambda self: True) + monkeypatch.setattr( + ipc.QtNetwork.QLocalServer, 'removeServer', lambda self: True + ) qlocalserver.listen('qute-test') with pytest.raises(ipc.AddressInUseError): ipc_server.listen() @@ -411,10 +422,10 @@ class TestOnError: def test_other_error(self, ipc_server, monkeypatch): socket = QtNetwork.QLocalSocket() ipc_server._socket = socket - monkeypatch.setattr(socket, 'error', - lambda: QtNetwork.QLocalSocket.ConnectionRefusedError) - monkeypatch.setattr(socket, 'errorString', - lambda: "Connection refused") + monkeypatch.setattr( + socket, 'error', lambda: QtNetwork.QLocalSocket.ConnectionRefusedError + ) + monkeypatch.setattr(socket, 'errorString', lambda: "Connection refused") socket.setErrorString("Connection refused.") with pytest.raises(ipc.Error, match=r"Error while handling IPC " @@ -597,10 +608,14 @@ class TestSendToRunningInstance: ipc.send_to_running_instance('qute-test', [], None, socket=socket) def test_socket_error_no_server(self): - socket = FakeSocket(error=QtNetwork.QLocalSocket.ConnectionError, - connect_successful=False) - with pytest.raises(ipc.Error, match=r"Error while connecting to " - r"running instance: Error string \(error 7\)"): + socket = FakeSocket( + error=QtNetwork.QLocalSocket.ConnectionError, connect_successful=False + ) + with pytest.raises( + ipc.Error, + match=r"Error while connecting to " + r"running instance: Error string \(error 7\)", + ): ipc.send_to_running_instance('qute-test', [], None, socket=socket) @@ -663,13 +678,12 @@ class TestSendOrListen: def qlocalsocket_mock(self, mocker): original_errors = { name: getattr(QtNetwork.QLocalSocket, name) - for name in - [ + for name in [ 'UnknownSocketError', 'UnconnectedState', 'ConnectionRefusedError', 'ServerNotFoundError', - 'PeerClosedError' + 'PeerClosedError', ] } m = mocker.patch('qutebrowser.misc.ipc.QtNetwork.QLocalSocket', autospec=True) diff --git a/tests/unit/misc/test_miscwidgets.py b/tests/unit/misc/test_miscwidgets.py index cd2cd64ed..15e3a5972 100644 --- a/tests/unit/misc/test_miscwidgets.py +++ b/tests/unit/misc/test_miscwidgets.py @@ -75,7 +75,9 @@ class TestCommandLineEdit: assert cmd_edit.text() == ':hello' assert cmd_edit.cursorPosition() == len(':hello') for _ in ':hello': - qtbot.keyClick(cmd_edit, QtCore.Qt.Key_Left, modifier=QtCore.Qt.ShiftModifier) + qtbot.keyClick( + cmd_edit, QtCore.Qt.Key_Left, modifier=QtCore.Qt.ShiftModifier + ) assert cmd_edit.cursorPosition() == len(':') assert cmd_edit.selectionStart() == len(':') @@ -259,8 +261,11 @@ class TestInspectorSplitter: new_window_size, exp_inspector_size, position, splitter, fake_inspector, qtbot): def resize(dim): - size = (QtCore.QSize(dim, 666) if splitter.orientation() == QtCore.Qt.Horizontal - else QtCore.QSize(666, dim)) + size = ( + QtCore.QSize(dim, 666) + if splitter.orientation() == QtCore.Qt.Horizontal + else QtCore.QSize(666, dim) + ) splitter.resize(size) if splitter.size() != size: pytest.skip("Resizing window failed") diff --git a/tests/unit/misc/test_msgbox.py b/tests/unit/misc/test_msgbox.py index 8544ac6ff..bf3e11b2b 100644 --- a/tests/unit/misc/test_msgbox.py +++ b/tests/unit/misc/test_msgbox.py @@ -51,14 +51,22 @@ def test_attributes(qtbot): assert box.parent() is parent -@pytest.mark.parametrize('plain_text, expected', [ - (True, QtCore.Qt.PlainText), - (False, QtCore.Qt.RichText), - (None, QtCore.Qt.AutoText), -]) +@pytest.mark.parametrize( + 'plain_text, expected', + [ + (True, QtCore.Qt.PlainText), + (False, QtCore.Qt.RichText), + (None, QtCore.Qt.AutoText), + ], +) def test_plain_text(qtbot, plain_text, expected): - box = msgbox.msgbox(parent=None, title='foo', text='foo', - icon=QtWidgets.QMessageBox.Information, plain_text=plain_text) + box = msgbox.msgbox( + parent=None, + title='foo', + text='foo', + icon=QtWidgets.QMessageBox.Information, + plain_text=plain_text, + ) qtbot.add_widget(box) assert box.textFormat() == expected @@ -71,8 +79,13 @@ def test_finished_signal(qtbot): nonlocal signal_triggered signal_triggered = True - box = msgbox.msgbox(parent=None, title='foo', text='foo', - icon=QtWidgets.QMessageBox.Information, on_finished=on_finished) + box = msgbox.msgbox( + parent=None, + title='foo', + text='foo', + icon=QtWidgets.QMessageBox.Information, + on_finished=on_finished, + ) qtbot.add_widget(box) diff --git a/tests/unit/misc/test_sessions.py b/tests/unit/misc/test_sessions.py index 66f36683f..1551a9e2a 100644 --- a/tests/unit/misc/test_sessions.py +++ b/tests/unit/misc/test_sessions.py @@ -25,6 +25,7 @@ import pytest import yaml from helpers import testutils + QWebView = testutils.qt_module_skip('QtWebKitWidgets').QWebView from qutebrowser.misc import sessions @@ -245,8 +246,9 @@ class TestSave: def test_utf_8_invalid(self, tmp_path, sess_man, fake_history): """Make sure data containing invalid UTF8 raises SessionError.""" session_path = tmp_path / 'foo.yml' - fake_history([Item(QtCore.QUrl('http://www.qutebrowser.org/'), '\ud800', - active=True)]) + fake_history( + [Item(QtCore.QUrl('http://www.qutebrowser.org/'), '\ud800', active=True)] + ) try: sess_man.save(str(session_path)) @@ -306,10 +308,13 @@ class TestLoadTab: with pytest.raises(sessions.SessionError): sess_man._load_tab(fake_webview, {'history': []}) - @pytest.mark.parametrize('key, val, expected', [ - ('zoom', 1.23, 1.23), - ('scroll-pos', {'x': 23, 'y': 42}, QtCore.QPoint(23, 42)), - ]) + @pytest.mark.parametrize( + 'key, val, expected', + [ + ('zoom', 1.23, 1.23), + ('scroll-pos', {'x': 23, 'y': 42}, QtCore.QPoint(23, 42)), + ], + ) @pytest.mark.parametrize('in_main_data', [True, False]) def test_user_data(self, sess_man, fake_webview, key, val, expected, in_main_data): diff --git a/tests/unit/misc/test_sql.py b/tests/unit/misc/test_sql.py index 3ea32dab9..bbdf5e8e5 100644 --- a/tests/unit/misc/test_sql.py +++ b/tests/unit/misc/test_sql.py @@ -95,13 +95,16 @@ class TestSqlError: (sql.SqliteErrorCode.CONSTRAINT, sql.BugError), ]) def test_known(self, error_code, exception): - sql_err = QtSql.QSqlError("driver text", "db text", QtSql.QSqlError.UnknownError, - error_code) + sql_err = QtSql.QSqlError( + "driver text", "db text", QtSql.QSqlError.UnknownError, error_code + ) with pytest.raises(exception): sql.raise_sqlite_error("Message", sql_err) def test_logging(self, caplog): - sql_err = QtSql.QSqlError("driver text", "db text", QtSql.QSqlError.UnknownError, '23') + sql_err = QtSql.QSqlError( + "driver text", "db text", QtSql.QSqlError.UnknownError, '23' + ) with pytest.raises(sql.BugError): sql.raise_sqlite_error("Message", sql_err) diff --git a/tests/unit/utils/test_debug.py b/tests/unit/utils/test_debug.py index fa31f2c53..2203e7452 100644 --- a/tests/unit/utils/test_debug.py +++ b/tests/unit/utils/test_debug.py @@ -132,13 +132,21 @@ class TestQEnumKey: assert not hasattr(QtWidgets.QStyle.PrimitiveElement, 'staticMetaObject') assert hasattr(QtWidgets.QFrame, 'staticMetaObject') - @pytest.mark.parametrize('base, value, klass, expected', [ - (QtWidgets.QStyle, QtWidgets.QStyle.PE_PanelButtonCommand, None, 'PE_PanelButtonCommand'), - (QtWidgets.QFrame, QtWidgets.QFrame.Sunken, None, 'Sunken'), - (QtWidgets.QFrame, 0x0030, QtWidgets.QFrame.Shadow, 'Sunken'), - (QtWidgets.QFrame, 0x1337, QtWidgets.QFrame.Shadow, '0x1337'), - (QtCore.Qt, QtCore.Qt.AnchorLeft, None, 'AnchorLeft'), - ]) + @pytest.mark.parametrize( + 'base, value, klass, expected', + [ + ( + QtWidgets.QStyle, + QtWidgets.QStyle.PE_PanelButtonCommand, + None, + 'PE_PanelButtonCommand', + ), + (QtWidgets.QFrame, QtWidgets.QFrame.Sunken, None, 'Sunken'), + (QtWidgets.QFrame, 0x0030, QtWidgets.QFrame.Shadow, 'Sunken'), + (QtWidgets.QFrame, 0x1337, QtWidgets.QFrame.Shadow, '0x1337'), + (QtCore.Qt, QtCore.Qt.AnchorLeft, None, 'AnchorLeft'), + ], + ) def test_qenum_key(self, base, value, klass, expected): key = debug.qenum_key(base, value, klass=klass) assert key == expected @@ -162,17 +170,35 @@ class TestQFlagsKey: fixme = pytest.mark.xfail(reason="See issue #42", raises=AssertionError) - @pytest.mark.parametrize('base, value, klass, expected', [ - (QtCore.Qt, QtCore.Qt.AlignTop, None, 'AlignTop'), - pytest.param(QtCore.Qt, QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop, None, - 'AlignLeft|AlignTop', marks=fixme), - (QtCore.Qt, QtCore.Qt.AlignCenter, None, 'AlignHCenter|AlignVCenter'), - pytest.param(QtCore.Qt, 0x0021, QtCore.Qt.Alignment, 'AlignLeft|AlignTop', - marks=fixme), - (QtCore.Qt, 0x1100, QtCore.Qt.Alignment, '0x0100|0x1000'), - (QtCore.Qt, QtCore.Qt.DockWidgetAreas(0), QtCore.Qt.DockWidgetArea, 'NoDockWidgetArea'), - (QtCore.Qt, QtCore.Qt.DockWidgetAreas(0), None, '0x0000'), - ]) + @pytest.mark.parametrize( + 'base, value, klass, expected', + [ + (QtCore.Qt, QtCore.Qt.AlignTop, None, 'AlignTop'), + pytest.param( + QtCore.Qt, + QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop, + None, + 'AlignLeft|AlignTop', + marks=fixme, + ), + (QtCore.Qt, QtCore.Qt.AlignCenter, None, 'AlignHCenter|AlignVCenter'), + pytest.param( + QtCore.Qt, + 0x0021, + QtCore.Qt.Alignment, + 'AlignLeft|AlignTop', + marks=fixme, + ), + (QtCore.Qt, 0x1100, QtCore.Qt.Alignment, '0x0100|0x1000'), + ( + QtCore.Qt, + QtCore.Qt.DockWidgetAreas(0), + QtCore.Qt.DockWidgetArea, + 'NoDockWidgetArea', + ), + (QtCore.Qt, QtCore.Qt.DockWidgetAreas(0), None, '0x0000'), + ], + ) def test_qflags_key(self, base, value, klass, expected): flags = debug.qflags_key(base, value, klass=klass) assert flags == expected @@ -208,12 +234,15 @@ class TestQFlagsKey: debug.qflags_key(QtCore.Qt, 42) -@pytest.mark.parametrize('cls, signal', [ - (SignalObject, 'signal1'), - (SignalObject, 'signal2'), - (QtCore.QTimer, 'timeout'), - (QtWidgets.QSpinBox, 'valueChanged'), # Overloaded signal -]) +@pytest.mark.parametrize( + 'cls, signal', + [ + (SignalObject, 'signal1'), + (SignalObject, 'signal2'), + (QtCore.QTimer, 'timeout'), + (QtWidgets.QSpinBox, 'valueChanged'), # Overloaded signal + ], +) @pytest.mark.parametrize('bound', [True, False]) def test_signal_name(cls, signal, bound): base = cls() if bound else cls diff --git a/tests/unit/utils/test_qtutils.py b/tests/unit/utils/test_qtutils.py index 8eaa58c75..84084de33 100644 --- a/tests/unit/utils/test_qtutils.py +++ b/tests/unit/utils/test_qtutils.py @@ -203,15 +203,28 @@ def test_ensure_valid(obj, raising, exc_reason, exc_str): qtutils.ensure_valid(obj) -@pytest.mark.parametrize('status, raising, message', [ - (QtCore.QDataStream.Ok, False, None), - (QtCore.QDataStream.ReadPastEnd, True, "The data stream has read past the end of " - "the data in the underlying device."), - (QtCore.QDataStream.ReadCorruptData, True, "The data stream has read corrupt " - "data."), - (QtCore.QDataStream.WriteFailed, True, "The data stream cannot write to the " - "underlying device."), -]) +@pytest.mark.parametrize( + 'status, raising, message', + [ + (QtCore.QDataStream.Ok, False, None), + ( + QtCore.QDataStream.ReadPastEnd, + True, + "The data stream has read past the end of " + "the data in the underlying device.", + ), + ( + QtCore.QDataStream.ReadCorruptData, + True, + "The data stream has read corrupt " "data.", + ), + ( + QtCore.QDataStream.WriteFailed, + True, + "The data stream cannot write to the " "underlying device.", + ), + ], +) def test_check_qdatastream(status, raising, message): """Test check_qdatastream. @@ -236,11 +249,14 @@ def test_qdatastream_status_count(): assert len(status_vals) == 4 -@pytest.mark.parametrize('color, expected', [ - (QtGui.QColor('red'), 'rgba(255, 0, 0, 255)'), - (QtGui.QColor('blue'), 'rgba(0, 0, 255, 255)'), - (QtGui.QColor(1, 3, 5, 7), 'rgba(1, 3, 5, 7)'), -]) +@pytest.mark.parametrize( + 'color, expected', + [ + (QtGui.QColor('red'), 'rgba(255, 0, 0, 255)'), + (QtGui.QColor('blue'), 'rgba(0, 0, 255, 255)'), + (QtGui.QColor(1, 3, 5, 7), 'rgba(1, 3, 5, 7)'), + ], +) def test_qcolor_to_qsscolor(color, expected): assert qtutils.qcolor_to_qsscolor(color) == expected @@ -250,10 +266,13 @@ def test_qcolor_to_qsscolor_invalid(): qtutils.qcolor_to_qsscolor(QtGui.QColor()) -@pytest.mark.parametrize('obj', [ - QtCore.QPoint(23, 42), - QtCore.QUrl('http://www.qutebrowser.org/'), -]) +@pytest.mark.parametrize( + 'obj', + [ + QtCore.QPoint(23, 42), + QtCore.QUrl('http://www.qutebrowser.org/'), + ], +) def test_serialize(obj): """Test a serialize/deserialize round trip. @@ -294,7 +313,8 @@ class TestSerializeStream: """Test serialize_stream with an error while serializing.""" obj = QtCore.QPoint() stream_mock.__lshift__.side_effect = lambda _other: self._set_status( - stream_mock, QtCore.QDataStream.ReadCorruptData) + stream_mock, QtCore.QDataStream.ReadCorruptData + ) with pytest.raises(OSError, match="The data stream has read corrupt " "data."): @@ -316,7 +336,8 @@ class TestSerializeStream: """Test deserialize_stream with an error while deserializing.""" obj = QtCore.QPoint() stream_mock.__rshift__.side_effect = lambda _other: self._set_status( - stream_mock, QtCore.QDataStream.ReadCorruptData) + stream_mock, QtCore.QDataStream.ReadCorruptData + ) with pytest.raises(OSError, match="The data stream has read corrupt " "data."): @@ -539,7 +560,9 @@ if test_file is not None: """Open an in-memory PyQIODevice instead of a real file.""" modes = { 'wb': QtCore.QIODevice.WriteOnly | QtCore.QIODevice.Truncate, - 'w': QtCore.QIODevice.WriteOnly | QtCore.QIODevice.Text | QtCore.QIODevice.Truncate, + 'w': QtCore.QIODevice.WriteOnly + | QtCore.QIODevice.Text + | QtCore.QIODevice.Truncate, 'rb': QtCore.QIODevice.ReadOnly, 'r': QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text, } @@ -798,11 +821,14 @@ class TestPyQIODevice: func = getattr(pyqiodev, method) assert func() == ret - @pytest.mark.parametrize('mode, readable, writable', [ - (QtCore.QIODevice.ReadOnly, True, False), - (QtCore.QIODevice.ReadWrite, True, True), - (QtCore.QIODevice.WriteOnly, False, True), - ]) + @pytest.mark.parametrize( + 'mode, readable, writable', + [ + (QtCore.QIODevice.ReadOnly, True, False), + (QtCore.QIODevice.ReadWrite, True, True), + (QtCore.QIODevice.WriteOnly, False, True), + ], + ) def test_readable_writable(self, mode, readable, writable, pyqiodev): """Test readable() and writable(). @@ -973,7 +999,9 @@ class TestInterpolateColor: with pytest.raises(ValueError): qtutils.interpolate_color(colors.white, colors.black, 10, QtGui.QColor.Cmyk) - @pytest.mark.parametrize('colorspace', [QtGui.QColor.Rgb, QtGui.QColor.Hsv, QtGui.QColor.Hsl]) + @pytest.mark.parametrize( + 'colorspace', [QtGui.QColor.Rgb, QtGui.QColor.Hsv, QtGui.QColor.Hsl] + ) def test_0_100(self, colors, colorspace): """Test 0% and 100% in different colorspaces.""" white = qtutils.interpolate_color(colors.white, colors.black, 0, colorspace) @@ -984,7 +1012,11 @@ class TestInterpolateColor: def test_interpolation_rgb(self): """Test an interpolation in the RGB colorspace.""" color = qtutils.interpolate_color( - testutils.Color(0, 40, 100), testutils.Color(0, 20, 200), 50, QtGui.QColor.Rgb) + testutils.Color(0, 40, 100), + testutils.Color(0, 20, 200), + 50, + QtGui.QColor.Rgb, + ) assert testutils.Color(color) == testutils.Color(0, 30, 150) def test_interpolation_hsv(self): @@ -1009,7 +1041,9 @@ class TestInterpolateColor: expected.setHsl(0, 30, 150) assert testutils.Color(color) == expected - @pytest.mark.parametrize('colorspace', [QtGui.QColor.Rgb, QtGui.QColor.Hsv, QtGui.QColor.Hsl]) + @pytest.mark.parametrize( + 'colorspace', [QtGui.QColor.Rgb, QtGui.QColor.Hsv, QtGui.QColor.Hsl] + ) def test_interpolation_alpha(self, colorspace): """Test interpolation of colorspace's alpha.""" start = testutils.Color(0, 0, 0, 30) diff --git a/tests/unit/utils/test_standarddir.py b/tests/unit/utils/test_standarddir.py index e601f1213..275af8a7d 100644 --- a/tests/unit/utils/test_standarddir.py +++ b/tests/unit/utils/test_standarddir.py @@ -99,8 +99,11 @@ def test_fake_mac_config(tmp_path, fake_home_envvar): @pytest.mark.fake_os('windows') def test_fake_windows(tmpdir, monkeypatch, what): """Make sure the config/data/cache dirs are correct on a fake Windows.""" - monkeypatch.setattr(standarddir.QtCore.QStandardPaths, 'writableLocation', - lambda typ: str(tmpdir / APPNAME)) + monkeypatch.setattr( + standarddir.QtCore.QStandardPaths, + 'writableLocation', + lambda typ: str(tmpdir / APPNAME), + ) standarddir._init_config(args=None) standarddir._init_data(args=None) @@ -117,8 +120,9 @@ def test_fake_haiku(tmpdir, monkeypatch): QtCore.QStandardPaths.AppDataLocation: '', QtCore.QStandardPaths.ConfigLocation: str(tmpdir / 'config' / APPNAME), } - monkeypatch.setattr(standarddir.QtCore.QStandardPaths, 'writableLocation', - locations.get) + monkeypatch.setattr( + standarddir.QtCore.QStandardPaths, 'writableLocation', locations.get + ) monkeypatch.setattr(standarddir.sys, 'platform', 'haiku1') standarddir._init_data(args=None) @@ -229,8 +233,9 @@ class TestStandardDir: @pytest.mark.fake_os('windows') def test_runtimedir_empty_tempdir(self, monkeypatch, tmpdir): """With an empty tempdir on non-Linux, we should raise.""" - monkeypatch.setattr(standarddir.QtCore.QStandardPaths, 'writableLocation', - lambda typ: '') + monkeypatch.setattr( + standarddir.QtCore.QStandardPaths, 'writableLocation', lambda typ: '' + ) with pytest.raises(standarddir.EmptyValueError): standarddir._init_runtime(args=None) diff --git a/tests/unit/utils/test_urlutils.py b/tests/unit/utils/test_urlutils.py index 110be1ee5..459f39f8c 100644 --- a/tests/unit/utils/test_urlutils.py +++ b/tests/unit/utils/test_urlutils.py @@ -158,10 +158,13 @@ class TestFuzzyUrl: assert not os_mock.path.exists.called assert url == QtCore.QUrl('http://foo') - @pytest.mark.parametrize('path, expected', [ - ('/foo', QtCore.QUrl('file:///foo')), - ('/bar\n', QtCore.QUrl('file:///bar')), - ]) + @pytest.mark.parametrize( + 'path, expected', + [ + ('/foo', QtCore.QUrl('file:///foo')), + ('/bar\n', QtCore.QUrl('file:///bar')), + ], + ) def test_file_absolute(self, path, expected, os_mock): """Test with an absolute path.""" os_mock.path.exists.return_value = True @@ -543,61 +546,78 @@ def test_raise_cmdexc_if_invalid(url, valid, has_err_string): urlutils.raise_cmdexc_if_invalid(qurl) -@pytest.mark.parametrize('qurl, output', [ - (QtCore.QUrl(), None), - (QtCore.QUrl('http://qutebrowser.org/test.html'), 'test.html'), - (QtCore.QUrl('http://qutebrowser.org/foo.html#bar'), 'foo.html'), - (QtCore.QUrl('http://user:password@qutebrowser.org/foo?bar=baz#fish'), 'foo'), - (QtCore.QUrl('http://qutebrowser.org/'), 'qutebrowser.org.html'), - (QtCore.QUrl('qute://'), None), - # data URL support - (QtCore.QUrl('data:text/plain,'), 'download.txt'), - (QtCore.QUrl('data:application/pdf,'), 'download.pdf'), - (QtCore.QUrl('data:foo/bar,'), 'download'), # unknown extension - (QtCore.QUrl('data:text/xul,'), 'download.xul'), # strict=False - (QtCore.QUrl('data:'), None), # invalid data URL -]) +@pytest.mark.parametrize( + 'qurl, output', + [ + (QtCore.QUrl(), None), + (QtCore.QUrl('http://qutebrowser.org/test.html'), 'test.html'), + (QtCore.QUrl('http://qutebrowser.org/foo.html#bar'), 'foo.html'), + (QtCore.QUrl('http://user:password@qutebrowser.org/foo?bar=baz#fish'), 'foo'), + (QtCore.QUrl('http://qutebrowser.org/'), 'qutebrowser.org.html'), + (QtCore.QUrl('qute://'), None), + # data URL support + (QtCore.QUrl('data:text/plain,'), 'download.txt'), + (QtCore.QUrl('data:application/pdf,'), 'download.pdf'), + (QtCore.QUrl('data:foo/bar,'), 'download'), # unknown extension + (QtCore.QUrl('data:text/xul,'), 'download.xul'), # strict=False + (QtCore.QUrl('data:'), None), # invalid data URL + ], +) def test_filename_from_url(qurl, output): assert urlutils.filename_from_url(qurl) == output -@pytest.mark.parametrize('qurl', [QtCore.QUrl(), QtCore.QUrl('qute://'), QtCore.QUrl('data:')]) +@pytest.mark.parametrize( + 'qurl', [QtCore.QUrl(), QtCore.QUrl('qute://'), QtCore.QUrl('data:')] +) def test_filename_from_url_fallback(qurl): assert urlutils.filename_from_url(qurl, fallback='fallback') == 'fallback' -@pytest.mark.parametrize('qurl, expected', [ - (QtCore.QUrl('ftp://example.com/'), ('ftp', 'example.com', 21)), - (QtCore.QUrl('ftp://example.com:2121/'), ('ftp', 'example.com', 2121)), - (QtCore.QUrl('http://qutebrowser.org:8010/waterfall'), - ('http', 'qutebrowser.org', 8010)), - (QtCore.QUrl('https://example.com/'), ('https', 'example.com', 443)), - (QtCore.QUrl('https://example.com:4343/'), ('https', 'example.com', 4343)), - (QtCore.QUrl('http://user:password@qutebrowser.org/foo?bar=baz#fish'), - ('http', 'qutebrowser.org', 80)), -]) +@pytest.mark.parametrize( + 'qurl, expected', + [ + (QtCore.QUrl('ftp://example.com/'), ('ftp', 'example.com', 21)), + (QtCore.QUrl('ftp://example.com:2121/'), ('ftp', 'example.com', 2121)), + ( + QtCore.QUrl('http://qutebrowser.org:8010/waterfall'), + ('http', 'qutebrowser.org', 8010), + ), + (QtCore.QUrl('https://example.com/'), ('https', 'example.com', 443)), + (QtCore.QUrl('https://example.com:4343/'), ('https', 'example.com', 4343)), + ( + QtCore.QUrl('http://user:password@qutebrowser.org/foo?bar=baz#fish'), + ('http', 'qutebrowser.org', 80), + ), + ], +) def test_host_tuple_valid(qurl, expected): assert urlutils.host_tuple(qurl) == expected -@pytest.mark.parametrize('qurl, expected', [ - (QtCore.QUrl(), urlutils.InvalidUrlError), - (QtCore.QUrl('qute://'), ValueError), - (QtCore.QUrl('qute://foobar'), ValueError), - (QtCore.QUrl('mailto:nobody'), ValueError), -]) +@pytest.mark.parametrize( + 'qurl, expected', + [ + (QtCore.QUrl(), urlutils.InvalidUrlError), + (QtCore.QUrl('qute://'), ValueError), + (QtCore.QUrl('qute://foobar'), ValueError), + (QtCore.QUrl('mailto:nobody'), ValueError), + ], +) def test_host_tuple_invalid(qurl, expected): with pytest.raises(expected): urlutils.host_tuple(qurl) class TestInvalidUrlError: - - @pytest.mark.parametrize('url, raising, has_err_string', [ - (QtCore.QUrl(), False, False), - (QtCore.QUrl('http://www.example.com/'), True, False), - (QtCore.QUrl('://'), False, True), - ]) + @pytest.mark.parametrize( + 'url, raising, has_err_string', + [ + (QtCore.QUrl(), False, False), + (QtCore.QUrl('http://www.example.com/'), True, False), + (QtCore.QUrl('://'), False, True), + ], + ) def test_invalid_url_error(self, url, raising, has_err_string): """Test InvalidUrlError. @@ -673,22 +693,26 @@ def test_data_url(): assert url == QtCore.QUrl('data:text/plain;base64,Zm9v') -@pytest.mark.parametrize('url, expected', [ - # No IDN - (QtCore.QUrl('http://www.example.com'), 'http://www.example.com'), - # IDN in domain - (QtCore.QUrl('http://www.ä.com'), '(www.xn--4ca.com) http://www.ä.com'), - # IDN with non-whitelisted TLD - (QtCore.QUrl('http://www.ä.foo'), 'http://www.xn--4ca.foo'), - # Unicode only in path - (QtCore.QUrl('http://www.example.com/ä'), 'http://www.example.com/ä'), - # Unicode only in TLD (looks like Qt shows Punycode with рф...) - (QtCore.QUrl('http://www.example.xn--p1ai'), - '(www.example.xn--p1ai) http://www.example.рф'), - # https://bugreports.qt.io/browse/QTBUG-60364 - (QtCore.QUrl('http://www.xn--80ak6aa92e.com'), - 'http://www.xn--80ak6aa92e.com'), -]) +@pytest.mark.parametrize( + 'url, expected', + [ + # No IDN + (QtCore.QUrl('http://www.example.com'), 'http://www.example.com'), + # IDN in domain + (QtCore.QUrl('http://www.ä.com'), '(www.xn--4ca.com) http://www.ä.com'), + # IDN with non-whitelisted TLD + (QtCore.QUrl('http://www.ä.foo'), 'http://www.xn--4ca.foo'), + # Unicode only in path + (QtCore.QUrl('http://www.example.com/ä'), 'http://www.example.com/ä'), + # Unicode only in TLD (looks like Qt shows Punycode with рф...) + ( + QtCore.QUrl('http://www.example.xn--p1ai'), + '(www.example.xn--p1ai) http://www.example.рф', + ), + # https://bugreports.qt.io/browse/QTBUG-60364 + (QtCore.QUrl('http://www.xn--80ak6aa92e.com'), 'http://www.xn--80ak6aa92e.com'), + ], +) def test_safe_display_string(url, expected): assert urlutils.safe_display_string(url) == expected @@ -699,24 +723,52 @@ def test_safe_display_string_invalid(): class TestProxyFromUrl: - - @pytest.mark.parametrize('url, expected', [ - ('socks://example.com/', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com')), - ('socks5://example.com', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com')), - ('socks5://example.com:2342', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 2342)), - ('socks5://foo@example.com', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 0, 'foo')), - ('socks5://foo:bar@example.com', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 0, 'foo', - 'bar')), - ('socks5://foo:bar@example.com:2323', - QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 2323, - 'foo', 'bar')), - ('direct://', QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.NoProxy)), - ]) + @pytest.mark.parametrize( + 'url, expected', + [ + ( + 'socks://example.com/', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com' + ), + ), + ( + 'socks5://example.com', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com' + ), + ), + ( + 'socks5://example.com:2342', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 2342 + ), + ), + ( + 'socks5://foo@example.com', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 0, 'foo' + ), + ), + ( + 'socks5://foo:bar@example.com', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, 'example.com', 0, 'foo', 'bar' + ), + ), + ( + 'socks5://foo:bar@example.com:2323', + QtNetwork.QNetworkProxy( + QtNetwork.QNetworkProxy.Socks5Proxy, + 'example.com', + 2323, + 'foo', + 'bar', + ), + ), + ('direct://', QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.NoProxy)), + ], + ) def test_proxy_from_url_valid(self, url, expected): assert urlutils.proxy_from_url(QtCore.QUrl(url)) == expected @@ -738,29 +790,46 @@ class TestProxyFromUrl: class TestParseJavascriptUrl: - - @pytest.mark.parametrize('url, message', [ - (QtCore.QUrl(), ""), - (QtCore.QUrl('https://example.com'), "Expected a javascript:... URL"), - (QtCore.QUrl('javascript://example.com'), - "URL contains unexpected components: example.com"), - (QtCore.QUrl('javascript://foo:bar@example.com:1234'), - "URL contains unexpected components: foo:bar@example.com:1234"), - ]) + @pytest.mark.parametrize( + 'url, message', + [ + (QtCore.QUrl(), ""), + (QtCore.QUrl('https://example.com'), "Expected a javascript:... URL"), + ( + QtCore.QUrl('javascript://example.com'), + "URL contains unexpected components: example.com", + ), + ( + QtCore.QUrl('javascript://foo:bar@example.com:1234'), + "URL contains unexpected components: foo:bar@example.com:1234", + ), + ], + ) def test_invalid(self, url, message): with pytest.raises(urlutils.Error, match=message): urlutils.parse_javascript_url(url) - @pytest.mark.parametrize('url, source', [ - (QtCore.QUrl('javascript:"hello" %0a "world"'), '"hello" \n "world"'), - (QtCore.QUrl('javascript:/'), '/'), - (QtCore.QUrl('javascript:///'), '///'), - # https://github.com/web-platform-tests/wpt/blob/master/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html - (QtCore.QUrl('javascript:"nope" ? "yep" : "what";'), '"nope" ? "yep" : "what";'), - (QtCore.QUrl('javascript:"wrong"; // # %0a "ok";'), '"wrong"; // # \n "ok";'), - (QtCore.QUrl('javascript:"%252525 ? %252525 # %252525"'), - '"%2525 ? %2525 # %2525"'), - ]) + @pytest.mark.parametrize( + 'url, source', + [ + (QtCore.QUrl('javascript:"hello" %0a "world"'), '"hello" \n "world"'), + (QtCore.QUrl('javascript:/'), '/'), + (QtCore.QUrl('javascript:///'), '///'), + # https://github.com/web-platform-tests/wpt/blob/master/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html + ( + QtCore.QUrl('javascript:"nope" ? "yep" : "what";'), + '"nope" ? "yep" : "what";', + ), + ( + QtCore.QUrl('javascript:"wrong"; // # %0a "ok";'), + '"wrong"; // # \n "ok";', + ), + ( + QtCore.QUrl('javascript:"%252525 ? %252525 # %252525"'), + '"%2525 ? %2525 # %2525"', + ), + ], + ) def test_valid(self, url, source): assert urlutils.parse_javascript_url(url) == source diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 94d48ae40..15012e31e 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -648,8 +648,9 @@ class TestGetSetClipboard: @pytest.fixture(autouse=True) def clipboard_mock(self, mocker): - m = mocker.patch('qutebrowser.utils.utils.QtWidgets.QApplication.clipboard', - autospec=True) + m = mocker.patch( + 'qutebrowser.utils.utils.QtWidgets.QApplication.clipboard', autospec=True + ) clipboard = m() clipboard.text.return_value = 'mocked clipboard text' mocker.patch('qutebrowser.utils.utils.fake_clipboard', None) @@ -657,8 +658,9 @@ class TestGetSetClipboard: def test_set(self, clipboard_mock, caplog): utils.set_clipboard('Hello World') - clipboard_mock.setText.assert_called_with('Hello World', - mode=QtGui.QClipboard.Clipboard) + clipboard_mock.setText.assert_called_with( + 'Hello World', mode=QtGui.QClipboard.Clipboard + ) assert not caplog.records def test_set_unsupported_selection(self, clipboard_mock): @@ -749,8 +751,11 @@ class TestOpenFile: @pytest.fixture def openurl_mock(self, mocker): - return mocker.patch('qutebrowser.qt.QtGui.QDesktopServices.openUrl', spec={}, - new_callable=mocker.Mock) + return mocker.patch( + 'qutebrowser.qt.QtGui.QDesktopServices.openUrl', + spec={}, + new_callable=mocker.Mock, + ) def test_system_default_application(self, caplog, config_stub, openurl_mock): @@ -978,11 +983,13 @@ class TestCleanupFileContext: class TestParseRect: - - @pytest.mark.parametrize('value, expected', [ - ('1x1+0+0', QtCore.QRect(0, 0, 1, 1)), - ('123x789+12+34', QtCore.QRect(12, 34, 123, 789)), - ]) + @pytest.mark.parametrize( + 'value, expected', + [ + ('1x1+0+0', QtCore.QRect(0, 0, 1, 1)), + ('123x789+12+34', QtCore.QRect(12, 34, 123, 789)), + ], + ) def test_valid(self, value, expected): assert utils.parse_rect(value) == expected diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 6be73ec76..252e18ca5 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -1078,7 +1078,9 @@ class TestChromiumVersion: def defaultProfile(self): raise AssertionError("Should not be called") - monkeypatch.setattr(webenginesettings.QtWebEngineWidgets, 'QWebEngineProfile', FakeProfile()) + monkeypatch.setattr( + webenginesettings.QtWebEngineWidgets, 'QWebEngineProfile', FakeProfile() + ) version.qtwebengine_versions() |