From 5a9027c54e01424fa79e3857df9d2d0ac90ad326 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 9 Jul 2023 00:53:29 +0200 Subject: mypy: Switch to upstream stubs for PyQt6 They are getting much better --- misc/requirements/requirements-mypy.txt | 1 - misc/requirements/requirements-mypy.txt-raw | 1 - qutebrowser/browser/history.py | 11 +++++++++-- qutebrowser/browser/network/pac.py | 3 ++- qutebrowser/browser/webengine/interceptor.py | 5 ++--- qutebrowser/browser/webengine/notification.py | 3 +-- qutebrowser/browser/webengine/webenginequtescheme.py | 3 +-- qutebrowser/completion/completiondelegate.py | 3 ++- qutebrowser/keyinput/eventfilter.py | 2 -- qutebrowser/keyinput/modeman.py | 6 +----- qutebrowser/mainwindow/statusbar/command.py | 3 +++ qutebrowser/misc/httpclient.py | 4 +--- qutebrowser/qt/_core_pyqtproperty.py | 6 ++++-- qutebrowser/utils/utils.py | 11 +++++++---- tox.ini | 1 + 15 files changed, 34 insertions(+), 29 deletions(-) diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 82b80bc01..724090575 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -11,7 +11,6 @@ mypy-extensions==1.0.0 pluggy==1.2.0 Pygments==2.15.1 PyQt5-stubs==5.15.6.0 -PyQt6-stubs @ git+https://github.com/python-qt-tools/PyQt6-stubs.git@f623a641cd5cdff53342177e4fbbf9cae8172336 tomli==2.0.1 types-colorama==0.4.15.11 types-docutils==0.20.0.1 diff --git a/misc/requirements/requirements-mypy.txt-raw b/misc/requirements/requirements-mypy.txt-raw index 487d30ca6..027f4fef6 100644 --- a/misc/requirements/requirements-mypy.txt-raw +++ b/misc/requirements/requirements-mypy.txt-raw @@ -3,7 +3,6 @@ lxml # For HTML reports diff-cover PyQt5-stubs -git+https://github.com/python-qt-tools/PyQt6-stubs.git types-PyYAML types-colorama types-Pygments diff --git a/qutebrowser/browser/history.py b/qutebrowser/browser/history.py index c0b23040c..a83621ae0 100644 --- a/qutebrowser/browser/history.py +++ b/qutebrowser/browser/history.py @@ -23,8 +23,9 @@ import contextlib import pathlib from typing import cast, Mapping, MutableSequence, Optional +from qutebrowser.qt import machinery from qutebrowser.qt.core import pyqtSlot, QUrl, QObject, pyqtSignal -from qutebrowser.qt.widgets import QProgressDialog, QApplication +from qutebrowser.qt.widgets import QProgressDialog, QApplication, QPushButton from qutebrowser.config import config from qutebrowser.api import cmdutils @@ -54,7 +55,13 @@ class HistoryProgress: self._progress.setMaximum(0) # unknown self._progress.setMinimumDuration(0) self._progress.setLabelText(text) - self._progress.setCancelButton(None) + + no_button = None + if machinery.IS_QT6: + # FIXME:mypy PyQt6 stubs issue + no_button = cast(QPushButton, None) + + self._progress.setCancelButton(no_button) self._progress.setAutoClose(False) self._progress.show() QApplication.processEvents() diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py index c66b6bc03..fcca5d45d 100644 --- a/qutebrowser/browser/network/pac.py +++ b/qutebrowser/browser/network/pac.py @@ -65,7 +65,8 @@ def _js_slot(*args): return self._error_con.callAsConstructor([e]) # pylint: enable=protected-access - deco = pyqtSlot(*args, result=QJSValue) + # FIXME:mypy PyQt6 stubs issue, passing type should work too + deco = pyqtSlot(*args, result="QJSValue") return deco(new_method) return _decorator diff --git a/qutebrowser/browser/webengine/interceptor.py b/qutebrowser/browser/webengine/interceptor.py index 75acb3252..f56db3a65 100644 --- a/qutebrowser/browser/webengine/interceptor.py +++ b/qutebrowser/browser/webengine/interceptor.py @@ -33,9 +33,8 @@ class WebEngineRequest(interceptors.Request): """QtWebEngine-specific request interceptor functionality.""" _WHITELISTED_REQUEST_METHODS = { - # FIXME:mypy PyQt6-stubs issue? - QByteArray(b'GET'), # type: ignore[call-overload,unused-ignore] - QByteArray(b'HEAD'), # type: ignore[call-overload,unused-ignore] + QByteArray(b'GET'), + QByteArray(b'HEAD'), } def __init__(self, *args, webengine_info, **kwargs): diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py index d140a8c61..4d08e914e 100644 --- a/qutebrowser/browser/webengine/notification.py +++ b/qutebrowser/browser/webengine/notification.py @@ -1109,8 +1109,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): return None bits = qimage.constBits().asstring(size) - # FIXME:mypy PyQt6-stubs issue - image_data.add(QByteArray(bits)) # type: ignore[call-overload,unused-ignore] + image_data.add(QByteArray(bits)) image_data.endStructure() return image_data diff --git a/qutebrowser/browser/webengine/webenginequtescheme.py b/qutebrowser/browser/webengine/webenginequtescheme.py index 4a09c81fb..010b00975 100644 --- a/qutebrowser/browser/webengine/webenginequtescheme.py +++ b/qutebrowser/browser/webengine/webenginequtescheme.py @@ -25,8 +25,7 @@ from qutebrowser.qt.webenginecore import (QWebEngineUrlSchemeHandler, from qutebrowser.browser import qutescheme from qutebrowser.utils import log, qtutils -# FIXME:mypy PyQt6-stubs issue? -_QUTE = QByteArray(b'qute') # type: ignore[call-overload,unused-ignore] +_QUTE = QByteArray(b'qute') class QuteSchemeHandler(QWebEngineUrlSchemeHandler): diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py index e497e1204..8c77a2036 100644 --- a/qutebrowser/completion/completiondelegate.py +++ b/qutebrowser/completion/completiondelegate.py @@ -299,7 +299,8 @@ class CompletionItemDelegate(QStyledItemDelegate): size = self._style.sizeFromContents(QStyle.ContentsType.CT_ItemViewItem, self._opt, docsize, self._opt.widget) qtutils.ensure_valid(size) - return size + QSize(10, 3) + # FIXME:mypy https://www.riverbankcomputing.com/pipermail/pyqt/2023-July/045400.html + return size + QSize(10, 3) # type: ignore[call-arg,unused-ignore] def paint(self, painter, option, index): """Override the QStyledItemDelegate paint function. diff --git a/qutebrowser/keyinput/eventfilter.py b/qutebrowser/keyinput/eventfilter.py index 007be6d15..ef1cd7c31 100644 --- a/qutebrowser/keyinput/eventfilter.py +++ b/qutebrowser/keyinput/eventfilter.py @@ -87,8 +87,6 @@ class EventFilter(QObject): True if the event should be filtered, False if it's passed through. """ ev_type = event.type() - if machinery.IS_QT6: - ev_type = cast(QEvent.Type, ev_type) if self._log_qt_events: try: diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index fe3650a2c..897318b66 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -474,11 +474,7 @@ class ModeManager(QObject): QEvent.Type.ShortcutOverride: functools.partial(self._handle_keypress, dry_run=True), } - ev_type = event.type() - if machinery.IS_QT6: - ev_type = cast(QEvent.Type, ev_type) - - handler = handlers[ev_type] + handler = handlers[event.type()] return handler(cast(QKeyEvent, event)) @cmdutils.register(instance='mode-manager', scope='window') diff --git a/qutebrowser/mainwindow/statusbar/command.py b/qutebrowser/mainwindow/statusbar/command.py index 4332316a3..b9c78d623 100644 --- a/qutebrowser/mainwindow/statusbar/command.py +++ b/qutebrowser/mainwindow/statusbar/command.py @@ -259,6 +259,9 @@ class Command(misc.CommandLineEdit): else: raise utils.Unreachable("setText got called with invalid text " "'{}'!".format(text)) + # FIXME:mypy PyQt6 stubs issue + if machinery.IS_QT6: + text = cast(str, text) super().setText(text) def keyPressEvent(self, e: QKeyEvent) -> None: diff --git a/qutebrowser/misc/httpclient.py b/qutebrowser/misc/httpclient.py index 1dddddba7..2bb152b03 100644 --- a/qutebrowser/misc/httpclient.py +++ b/qutebrowser/misc/httpclient.py @@ -78,9 +78,7 @@ class HTTPClient(QObject): request = HTTPRequest(url) request.setHeader(QNetworkRequest.KnownHeaders.ContentTypeHeader, 'application/x-www-form-urlencoded;charset=utf-8') - # FIXME:mypy PyQt6-stubs issue - reply = self._nam.post( # type: ignore[call-overload,unused-ignore] - request, encoded_data) + reply = self._nam.post(request, encoded_data) self._handle_reply(reply) def get(self, url): diff --git a/qutebrowser/qt/_core_pyqtproperty.py b/qutebrowser/qt/_core_pyqtproperty.py index ec57d4d1c..24f96ea12 100644 --- a/qutebrowser/qt/_core_pyqtproperty.py +++ b/qutebrowser/qt/_core_pyqtproperty.py @@ -1,16 +1,18 @@ """WORKAROUND for missing pyqtProperty typing, ported from PyQt5-stubs: FIXME:mypy PyQt6-stubs issue -https://github.com/python-qt-tools/PyQt5-stubs/blob/5.15.6.0/PyQt5-stubs/QtCore.pyi#L70-L111 +https://github.com/python-qt-tools/PyQt5-stubs/blob/5.15.6.0/PyQt5-stubs/QtCore.pyi#L68-L111 """ # flake8: noqa # pylint: disable=invalid-name,missing-class-docstring,too-many-arguments,redefined-builtin,unused-argument,import-error import typing -from PyQt6.QtCore import QObjectT, pyqtSignal +from PyQt6.QtCore import QObject, pyqtSignal if typing.TYPE_CHECKING: + QObjectT = typing.TypeVar("QObjectT", bound="QObject") + TPropertyTypeVal = typing.TypeVar("TPropertyTypeVal") TPropGetter = typing.TypeVar( diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index a81952b7d..6b450aa29 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -128,17 +128,20 @@ class VersionNumber: return NotImplemented return self._ver != other._ver + # FIXME:mypy type ignores below needed for PyQt5-stubs: + # Unsupported left operand type for ... ("QVersionNumber") + def __ge__(self, other: 'VersionNumber') -> bool: - return self._ver >= other._ver # type: ignore[operator] + return self._ver >= other._ver # type: ignore[operator,unused-ignore] def __gt__(self, other: 'VersionNumber') -> bool: - return self._ver > other._ver # type: ignore[operator] + return self._ver > other._ver # type: ignore[operator,unused-ignore] def __le__(self, other: 'VersionNumber') -> bool: - return self._ver <= other._ver # type: ignore[operator] + return self._ver <= other._ver # type: ignore[operator,unused-ignore] def __lt__(self, other: 'VersionNumber') -> bool: - return self._ver < other._ver # type: ignore[operator] + return self._ver < other._ver # type: ignore[operator,unused-ignore] class Unreachable(Exception): diff --git a/tox.ini b/tox.ini index ffb15e2f9..843126e36 100644 --- a/tox.ini +++ b/tox.ini @@ -225,6 +225,7 @@ deps = -r{toxinidir}/misc/requirements/requirements-tests.txt -r{toxinidir}/misc/requirements/requirements-mypy.txt pyqt6: -r{toxinidir}/misc/requirements/requirements-pyqt-6.txt +commands_pre = pip install --index-url https://www.riverbankcomputing.com/pypi/simple/ --pre --upgrade PyQt6 commands = {envpython} -m mypy {env:QUTE_CONSTANTS_ARGS} qutebrowser {posargs} -- cgit v1.2.3-54-g00ecf