summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoofar <toofar@spalge.com>2022-08-25 08:41:16 +1200
committertoofar <toofar@spalge.com>2022-08-25 08:53:31 +1200
commitd20a58c26bf741846abeb5a2f3498a57ff6c6a4f (patch)
treee8d345fd858a061a9c08b6e2bdbe2aed6809fecc
parentdfde9798074eb5ed192ff8ba074032e8a42b219a (diff)
downloadqutebrowser-feat/pyqt6_and_mypy.tar.gz
qutebrowser-feat/pyqt6_and_mypy.zip
Some Qt6 mypy fixesfeat/pyqt6_and_mypy
I'm running mypy like so: mypy --always-true=USE_PYQT6 --always-false=USE_PYQT5 --always-false=USE_PYSIDE2 --always-false=USE_PYSIDE6 --always-false=IS_QT5 --always-true=IS_QT6 qutebrowser/ And I just went down the output fixing easy stuff. Currently I'm getting 61 errors on Qt5 and 207 errors on Qt6 (down from 230 or so). I think the comparison ignores I removed are still needed on Qt5. I'm not sure how best to deal with situations that need to be ignored on one implementation and not on another. One way to do it would be to have alternate implementations per backend, but that could become a bit or a maintenance burden, see https://github.com/python/mypy/issues/8823 I'm also seeing some "Statement is unreachable" errors popping up which might be due to the same scenario. Many of the errors are related to there being no webkit on Qt6 so the webkit modules get resolved as ANY which makes all the # type: ignore messages be complained about. Not sure what we can do about that, possibly something from https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-exclude I see that Phil said we shouldn't need separate stubs for PyQt6. I'm still using them and haven't tried without yet.
-rw-r--r--qutebrowser/browser/network/pac.py4
-rw-r--r--qutebrowser/keyinput/keyutils.py12
-rw-r--r--qutebrowser/misc/earlyinit.py2
-rw-r--r--qutebrowser/misc/sql.py6
-rw-r--r--qutebrowser/qt/sip.py2
-rw-r--r--qutebrowser/utils/debug.py14
-rw-r--r--qutebrowser/utils/qtutils.py27
-rw-r--r--qutebrowser/utils/usertypes.py4
-rw-r--r--qutebrowser/utils/utils.py8
9 files changed, 48 insertions, 31 deletions
diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py
index be25a2a41..cce6ea94e 100644
--- a/qutebrowser/browser/network/pac.py
+++ b/qutebrowser/browser/network/pac.py
@@ -219,8 +219,8 @@ class PACResolver:
else:
string_flags = QUrl.UrlFormattingOption.RemoveUserInfo # type: ignore[assignment]
if query.url().scheme() == 'https':
- string_flags |= QUrl.UrlFormattingOption.RemovePath # type: ignore[assignment]
- string_flags |= QUrl.UrlFormattingOption.RemoveQuery # type: ignore[assignment]
+ string_flags |= QUrl.UrlFormattingOption.RemovePath
+ string_flags |= QUrl.UrlFormattingOption.RemoveQuery
result = self._resolver.call([query.url().toString(string_flags),
query.peerHostName()])
diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py
index f91936257..fdf5340f7 100644
--- a/qutebrowser/keyinput/keyutils.py
+++ b/qutebrowser/keyinput/keyutils.py
@@ -37,10 +37,11 @@ from typing import Iterator, List, Mapping, Optional, Union, overload
from qutebrowser.qt.core import Qt, QEvent
from qutebrowser.qt.gui import QKeySequence, QKeyEvent
-try:
- from qutebrowser.qt.core import QKeyCombination
-except ImportError:
+from qutebrowser.qt import machinery
+if machinery.IS_QT5:
QKeyCombination = None # Qt 6 only
+else:
+ from qutebrowser.qt.core import QKeyCombination
from qutebrowser.utils import utils, qtutils, debug
@@ -69,7 +70,7 @@ try:
except ValueError:
# WORKAROUND for
# https://www.riverbankcomputing.com/pipermail/pyqt/2022-April/044607.html
- _NIL_KEY = 0
+ _NIL_KEY = 0 # type: ignore[assignment]
_ModifierType = Qt.KeyboardModifier
@@ -541,6 +542,7 @@ class KeySequence:
def __iter__(self) -> Iterator[KeyInfo]:
"""Iterate over KeyInfo objects."""
+ combination: QKeySequence
for combination in itertools.chain.from_iterable(self._sequences):
yield KeyInfo.from_qt(combination)
@@ -712,7 +714,7 @@ class KeySequence:
mappings: Mapping['KeySequence', 'KeySequence']
) -> 'KeySequence':
"""Get a new KeySequence with the given mappings applied."""
- infos = []
+ infos: List[KeyInfo] = []
for info in self:
key_seq = KeySequence(info)
if key_seq in mappings:
diff --git a/qutebrowser/misc/earlyinit.py b/qutebrowser/misc/earlyinit.py
index 39db7b710..690578188 100644
--- a/qutebrowser/misc/earlyinit.py
+++ b/qutebrowser/misc/earlyinit.py
@@ -183,7 +183,7 @@ def check_qt_version():
try:
from qutebrowser.qt.core import QVersionNumber, QLibraryInfo
qt_ver = QLibraryInfo.version().normalized()
- recent_qt_runtime = qt_ver >= QVersionNumber(5, 15) # type: ignore[operator]
+ recent_qt_runtime = qt_ver >= QVersionNumber(5, 15)
except (ImportError, AttributeError):
# QVersionNumber was added in Qt 5.6, QLibraryInfo.version() in 5.8
recent_qt_runtime = False
diff --git a/qutebrowser/misc/sql.py b/qutebrowser/misc/sql.py
index d7b3dda0d..4c182e351 100644
--- a/qutebrowser/misc/sql.py
+++ b/qutebrowser/misc/sql.py
@@ -28,7 +28,7 @@ from typing import Any, Dict, Iterator, List, Mapping, MutableSequence, Optional
from qutebrowser.qt.core import QObject, pyqtSignal
from qutebrowser.qt.sql import QSqlDatabase, QSqlError, QSqlQuery
-from qutebrowser.qt import sip
+from qutebrowser.qt import sip, machinery
from qutebrowser.utils import debug, log
@@ -323,10 +323,10 @@ class Query:
def _validate_bound_values(self):
"""Make sure all placeholders are bound."""
qt_bound_values = self.query.boundValues()
- try:
+ if machinery.IS_QT5:
# Qt 5: Returns a dict
values = qt_bound_values.values()
- except AttributeError:
+ else:
# Qt 6: Returns a list
values = qt_bound_values
diff --git a/qutebrowser/qt/sip.py b/qutebrowser/qt/sip.py
index 07682f24e..e24ad4826 100644
--- a/qutebrowser/qt/sip.py
+++ b/qutebrowser/qt/sip.py
@@ -17,7 +17,7 @@ elif machinery.USE_PYQT6:
try:
from PyQt6.sip import *
except ImportError:
- from sip import *
+ from sip import * # type: ignore[import]
elif machinery.USE_PYSIDE2:
raise machinery.Unavailable()
elif machinery.USE_PYSIDE6:
diff --git a/qutebrowser/utils/debug.py b/qutebrowser/utils/debug.py
index ff6c3b9c2..f4f73dfc7 100644
--- a/qutebrowser/utils/debug.py
+++ b/qutebrowser/utils/debug.py
@@ -33,7 +33,7 @@ from qutebrowser.qt.core import Qt, QEvent, QMetaMethod, QObject, pyqtBoundSigna
from qutebrowser.utils import log, utils, qtutils, objreg
from qutebrowser.misc import objects
-from qutebrowser.qt import sip
+from qutebrowser.qt import sip, machinery
def log_events(klass: Type[QObject]) -> Type[QObject]:
@@ -99,7 +99,10 @@ def log_signals(obj: QObject) -> QObject:
return obj
-_EnumValueType = Union[sip.simplewrapper, int]
+if machinery.IS_QT5:
+ _EnumValueType = Union[sip.simplewrapper, int]
+else:
+ _EnumValueType = Union[sip.wrapper ,int]
def _qenum_key_python(
@@ -109,8 +112,10 @@ def _qenum_key_python(
"""New-style PyQt6: Try getting value from Python enum."""
if isinstance(value, enum.Enum) and value.name:
return value.name
+ assert isinstance(value, int)
# We got an int with klass passed: Try asking Python enum for member
+ assert klass
if issubclass(klass, enum.Enum):
try:
name = klass(value).name
@@ -131,7 +136,7 @@ def _qenum_key_qt(
# However, not every Qt enum value has a staticMetaObject
try:
meta_obj = base.staticMetaObject # type: ignore[union-attr]
- idx = meta_obj.indexOfEnumerator(klass.__name__)
+ idx = meta_obj.indexOfEnumerator(klass.__name__) # type: ignore[union-attr]
meta_enum = meta_obj.enumerator(idx)
key = meta_enum.valueToKey(int(value)) # type: ignore[arg-type]
if key is not None:
@@ -140,6 +145,7 @@ def _qenum_key_qt(
pass
# PyQt5: Try finding value match in class
+ assert klass
for name, obj in vars(base).items():
if isinstance(obj, klass) and obj == value:
return name
@@ -222,7 +228,7 @@ def qflags_key(base: Type[_EnumValueType],
for bit in bits:
# We have to re-convert to an enum type here or we'll sometimes get an
# empty string back.
- enum_value = klass(bit) # type: ignore[call-arg]
+ enum_value = klass(bit)
names.append(qenum_key(base, enum_value, klass))
return '|'.join(names)
diff --git a/qutebrowser/utils/qtutils.py b/qutebrowser/utils/qtutils.py
index 0bd9c94e8..66a4f679f 100644
--- a/qutebrowser/utils/qtutils.py
+++ b/qutebrowser/utils/qtutils.py
@@ -40,13 +40,14 @@ from qutebrowser.qt.core import (qVersion, QEventLoop, QDataStream, QByteArray,
QIODevice, QFileDevice, QSaveFile, QT_VERSION_STR,
PYQT_VERSION_STR, QObject, QUrl, QLibraryInfo)
from qutebrowser.qt.gui import QColor
+from qutebrowser.qt import machinery
try:
from qutebrowser.qt.webkit import qWebKitVersion
except ImportError: # pragma: no cover
qWebKitVersion = None # type: ignore[assignment] # noqa: N816
if TYPE_CHECKING:
from qutebrowser.qt.webkit import QWebHistory
- from qutebrowser.qt.webenginewidgets import QWebEngineHistory
+ from qutebrowser.qt.webenginecore import QWebEngineHistory
from qutebrowser.misc import objects
from qutebrowser.utils import usertypes, utils
@@ -186,13 +187,21 @@ def check_qdatastream(stream: QDataStream) -> None:
raise OSError(status_to_str[stream.status()])
-_QtSerializableType = Union[
- QObject,
- QByteArray,
- QUrl,
- 'QWebEngineHistory',
- 'QWebHistory'
-]
+if machinery.IS_QT5:
+ _QtSerializableType = Union[
+ QObject,
+ QByteArray,
+ QUrl,
+ 'QWebEngineHistory',
+ 'QWebHistory'
+ ]
+else:
+ _QtSerializableType = Union[
+ QObject,
+ QByteArray,
+ QUrl,
+ 'QWebEngineHistory',
+ ]
def serialize(obj: _QtSerializableType) -> QByteArray:
@@ -581,7 +590,7 @@ class LibraryPath(enum.Enum):
def library_path(which: LibraryPath) -> pathlib.Path:
"""Wrapper around QLibraryInfo.path / .location."""
- if hasattr(QLibraryInfo, "path"):
+ if machinery.IS_QT6:
# Qt 6
val = getattr(QLibraryInfo.LibraryPath, which.value)
ret = QLibraryInfo.path(val)
diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py
index b84af4524..aadda000b 100644
--- a/qutebrowser/utils/usertypes.py
+++ b/qutebrowser/utils/usertypes.py
@@ -491,7 +491,7 @@ class AbstractCertificateErrorWrapper:
"""A wrapper over an SSL/certificate error."""
def __init__(self) -> None:
- self._certificate_accepted = None
+ self._certificate_accepted: Optional[bool] = None
def __str__(self) -> str:
raise NotImplementedError
@@ -514,7 +514,7 @@ class AbstractCertificateErrorWrapper:
def defer(self) -> None:
raise NotImplementedError
- def certificate_was_accepted(self) -> None:
+ def certificate_was_accepted(self) -> bool:
"""Check whether the certificate was accepted by the user."""
if not self.is_overridable():
return False
diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py
index 29c4be1d9..0817d4c56 100644
--- a/qutebrowser/utils/utils.py
+++ b/qutebrowser/utils/utils.py
@@ -138,16 +138,16 @@ class VersionNumber:
return self._ver != other._ver
def __ge__(self, other: 'VersionNumber') -> bool:
- return self._ver >= other._ver # type: ignore[operator]
+ return self._ver >= other._ver
def __gt__(self, other: 'VersionNumber') -> bool:
- return self._ver > other._ver # type: ignore[operator]
+ return self._ver > other._ver
def __le__(self, other: 'VersionNumber') -> bool:
- return self._ver <= other._ver # type: ignore[operator]
+ return self._ver <= other._ver
def __lt__(self, other: 'VersionNumber') -> bool:
- return self._ver < other._ver # type: ignore[operator]
+ return self._ver < other._ver
class Unreachable(Exception):