summaryrefslogtreecommitdiff
path: root/qutebrowser/utils
diff options
context:
space:
mode:
Diffstat (limited to 'qutebrowser/utils')
-rw-r--r--qutebrowser/utils/debug.py1
-rw-r--r--qutebrowser/utils/log.py18
-rw-r--r--qutebrowser/utils/qtutils.py65
-rw-r--r--qutebrowser/utils/standarddir.py4
-rw-r--r--qutebrowser/utils/urlutils.py6
-rw-r--r--qutebrowser/utils/utils.py13
-rw-r--r--qutebrowser/utils/version.py7
7 files changed, 98 insertions, 16 deletions
diff --git a/qutebrowser/utils/debug.py b/qutebrowser/utils/debug.py
index a8b436d79..82de30702 100644
--- a/qutebrowser/utils/debug.py
+++ b/qutebrowser/utils/debug.py
@@ -68,6 +68,7 @@ def log_signals(obj: QObject) -> QObject:
def connect_log_slot(obj: QObject) -> None:
"""Helper function to connect all signals to a logging slot."""
metaobj = obj.metaObject()
+ assert metaobj is not None
for i in range(metaobj.methodCount()):
meta_method = metaobj.method(i)
qtutils.ensure_valid(meta_method)
diff --git a/qutebrowser/utils/log.py b/qutebrowser/utils/log.py
index 521f52b5b..5ac150702 100644
--- a/qutebrowser/utils/log.py
+++ b/qutebrowser/utils/log.py
@@ -31,9 +31,10 @@ import json
import inspect
import argparse
from typing import (TYPE_CHECKING, Any, Iterator, Mapping, MutableSequence,
- Optional, Set, Tuple, Union, TextIO, Literal, cast)
+ Optional, Set, Tuple, Union, TextIO, Literal, cast, Callable)
from qutebrowser.qt import core as qtcore
+from qutebrowser.qt import machinery
# Optional imports
try:
import colorama
@@ -234,6 +235,19 @@ def _init_py_warnings() -> None:
def disable_qt_msghandler() -> Iterator[None]:
"""Contextmanager which temporarily disables the Qt message handler."""
old_handler = qtcore.qInstallMessageHandler(None)
+ if machinery.IS_QT6:
+ # cast str to Optional[str] to be compatible with PyQt6 type hints for
+ # qInstallMessageHandler
+ old_handler = cast(
+ Optional[
+ Callable[
+ [qtcore.QtMsgType, qtcore.QMessageLogContext, Optional[str]],
+ None
+ ]
+ ],
+ old_handler,
+ )
+
try:
yield
finally:
@@ -379,7 +393,7 @@ def change_console_formatter(level: int) -> None:
def qt_message_handler(msg_type: qtcore.QtMsgType,
context: qtcore.QMessageLogContext,
- msg: str) -> None:
+ msg: Optional[str]) -> None:
"""Qt message handler to redirect qWarning etc. to the logging system.
Args:
diff --git a/qutebrowser/utils/qtutils.py b/qutebrowser/utils/qtutils.py
index cc34057ef..781e43f08 100644
--- a/qutebrowser/utils/qtutils.py
+++ b/qutebrowser/utils/qtutils.py
@@ -32,7 +32,7 @@ import pathlib
import operator
import contextlib
from typing import (Any, AnyStr, TYPE_CHECKING, BinaryIO, IO, Iterator,
- Optional, Union, Tuple, Protocol, cast)
+ Optional, Union, Tuple, Protocol, cast, TypeVar)
from qutebrowser.qt import machinery, sip
from qutebrowser.qt.core import (qVersion, QEventLoop, QDataStream, QByteArray,
@@ -46,6 +46,7 @@ except ImportError: # pragma: no cover
if TYPE_CHECKING:
from qutebrowser.qt.webkit import QWebHistory
from qutebrowser.qt.webenginecore import QWebEngineHistory
+ from typing_extensions import TypeGuard # added in Python 3.10
from qutebrowser.misc import objects
from qutebrowser.utils import usertypes, utils
@@ -102,7 +103,11 @@ def version_check(version: str,
parsed = utils.VersionNumber.parse(version)
op = operator.eq if exact else operator.ge
- result = op(utils.VersionNumber.parse(qVersion()), parsed)
+
+ qversion = qVersion()
+ assert qversion is not None
+ result = op(utils.VersionNumber.parse(qversion), parsed)
+
if compiled and result:
# qVersion() ==/>= parsed, now check if QT_VERSION_STR ==/>= parsed.
result = op(utils.VersionNumber.parse(QT_VERSION_STR), parsed)
@@ -535,24 +540,58 @@ def interpolate_color(
if colorspace is None:
if percent == 100:
- return QColor(*end.getRgb())
+ r, g, b, a = end.getRgb()
+ assert r is not None
+ assert g is not None
+ assert b is not None
+ assert a is not None
+ return QColor(r, g, b, a)
else:
- return QColor(*start.getRgb())
+ r, g, b, a = start.getRgb()
+ assert r is not None
+ assert g is not None
+ assert b is not None
+ assert a is not None
+ return QColor(r, g, b, a)
out = QColor()
if colorspace == QColor.Spec.Rgb:
r1, g1, b1, a1 = start.getRgb()
r2, g2, b2, a2 = end.getRgb()
+ assert r1 is not None
+ assert g1 is not None
+ assert b1 is not None
+ assert a1 is not None
+ assert r2 is not None
+ assert g2 is not None
+ assert b2 is not None
+ assert a2 is not None
components = _get_color_percentage(r1, g1, b1, a1, r2, g2, b2, a2, percent)
out.setRgb(*components)
elif colorspace == QColor.Spec.Hsv:
h1, s1, v1, a1 = start.getHsv()
h2, s2, v2, a2 = end.getHsv()
+ assert h1 is not None
+ assert s1 is not None
+ assert v1 is not None
+ assert a1 is not None
+ assert h2 is not None
+ assert s2 is not None
+ assert v2 is not None
+ assert a2 is not None
components = _get_color_percentage(h1, s1, v1, a1, h2, s2, v2, a2, percent)
out.setHsv(*components)
elif colorspace == QColor.Spec.Hsl:
h1, s1, l1, a1 = start.getHsl()
h2, s2, l2, a2 = end.getHsl()
+ assert h1 is not None
+ assert s1 is not None
+ assert l1 is not None
+ assert a1 is not None
+ assert h2 is not None
+ assert s2 is not None
+ assert l2 is not None
+ assert a2 is not None
components = _get_color_percentage(h1, s1, l1, a1, h2, s2, l2, a2, percent)
out.setHsl(*components)
else:
@@ -611,3 +650,21 @@ def extract_enum_val(val: Union[sip.simplewrapper, int, enum.Enum]) -> int:
elif isinstance(val, sip.simplewrapper):
return int(val) # type: ignore[call-overload]
return val
+
+T = TypeVar("T")
+
+def is_not_none(obj: Optional[T]) -> "TypeGuard[T]":
+ """Check if a Qt object is None.
+
+ PyQt6 marks things as Optional[...], but PyQt5 doesn't.
+ By using this function, we can use the same type hints for both.
+ """
+ return obj is not None
+
+
+if machinery.IS_QT5:
+ def allow_none(obj: Optional[T]) -> T:
+ return cast(T, obj)
+else:
+ def allow_none(obj: Optional[T]) -> Optional[T]:
+ return obj
diff --git a/qutebrowser/utils/standarddir.py b/qutebrowser/utils/standarddir.py
index 884a26376..762125c11 100644
--- a/qutebrowser/utils/standarddir.py
+++ b/qutebrowser/utils/standarddir.py
@@ -28,7 +28,7 @@ from typing import Iterator, Optional
from qutebrowser.qt.core import QStandardPaths
from qutebrowser.qt.widgets import QApplication
-from qutebrowser.utils import log, debug, utils, version
+from qutebrowser.utils import log, debug, utils, version, qtutils
# The cached locations
_locations = {}
@@ -65,7 +65,7 @@ def _unset_organization() -> Iterator[None]:
qapp = QApplication.instance()
if qapp is not None:
orgname = qapp.organizationName()
- qapp.setOrganizationName(None) # type: ignore[arg-type]
+ qapp.setOrganizationName(qtutils.allow_none(None))
try:
yield
finally:
diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py
index e00c9dab2..b3f03b256 100644
--- a/qutebrowser/utils/urlutils.py
+++ b/qutebrowser/utils/urlutils.py
@@ -179,9 +179,9 @@ def _get_search_url(txt: str) -> QUrl:
url = QUrl.fromUserInput(evaluated)
else:
url = QUrl.fromUserInput(config.val.url.searchengines[engine])
- url.setPath(None) # type: ignore[arg-type]
- url.setFragment(None) # type: ignore[arg-type]
- url.setQuery(None) # type: ignore[call-overload]
+ url.setPath(qtutils.allow_none(None))
+ url.setFragment(qtutils.allow_none(None))
+ url.setQuery(qtutils.allow_none(None))
qtutils.ensure_valid(url)
return url
diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py
index 6b450aa29..dd3cf6ac3 100644
--- a/qutebrowser/utils/utils.py
+++ b/qutebrowser/utils/utils.py
@@ -519,6 +519,13 @@ def sanitize_filename(name: str,
return name
+def _clipboard() -> QClipboard:
+ """Get the QClipboard and make sure it's not None."""
+ clipboard = QApplication.clipboard()
+ assert clipboard is not None
+ return clipboard
+
+
def set_clipboard(data: str, selection: bool = False) -> None:
"""Set the clipboard to some given data."""
global fake_clipboard
@@ -530,7 +537,7 @@ def set_clipboard(data: str, selection: bool = False) -> None:
fake_clipboard = data
else:
mode = QClipboard.Mode.Selection if selection else QClipboard.Mode.Clipboard
- QApplication.clipboard().setText(data, mode=mode)
+ _clipboard().setText(data, mode=mode)
def get_clipboard(selection: bool = False, fallback: bool = False) -> str:
@@ -556,7 +563,7 @@ def get_clipboard(selection: bool = False, fallback: bool = False) -> str:
fake_clipboard = None
else:
mode = QClipboard.Mode.Selection if selection else QClipboard.Mode.Clipboard
- data = QApplication.clipboard().text(mode=mode)
+ data = _clipboard().text(mode=mode)
target = "Primary selection" if selection else "Clipboard"
if not data.strip():
@@ -568,7 +575,7 @@ def get_clipboard(selection: bool = False, fallback: bool = False) -> str:
def supports_selection() -> bool:
"""Check if the OS supports primary selection."""
- return QApplication.clipboard().supportsSelection()
+ return _clipboard().supportsSelection()
def open_file(filename: str, cmdline: str = None) -> None:
diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py
index 782261745..358e8e19b 100644
--- a/qutebrowser/utils/version.py
+++ b/qutebrowser/utils/version.py
@@ -886,7 +886,10 @@ def version_info() -> str:
if objects.qapp:
style = objects.qapp.style()
- lines.append('Style: {}'.format(style.metaObject().className()))
+ assert style is not None
+ metaobj = style.metaObject()
+ assert metaobj is not None
+ lines.append('Style: {}'.format(metaobj.className()))
lines.append('Platform plugin: {}'.format(objects.qapp.platformName()))
lines.append('OpenGL: {}'.format(opengl_info()))
@@ -1005,7 +1008,7 @@ 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[QOpenGLContext], QOpenGLContext.currentContext())
+ old_context: Optional[QOpenGLContext] = QOpenGLContext.currentContext()
old_surface = None if old_context is None else old_context.surface()
surface = QOffscreenSurface()