summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2023-07-22 12:36:31 +0200
committerFlorian Bruhin <me@the-compiler.org>2023-07-22 12:36:31 +0200
commit273230eb07eb848e67abc8c1e6fc95cfe4c46b6f (patch)
treea198f4b32f439f3602c25a4942b9a0aabe511b87
parent1387b0598b90501dfa1dc8e4cbe5e1d0d05cd048 (diff)
parented70741587d0d7f5cc90b2f510c38474a7ad9375 (diff)
downloadqutebrowser-273230eb07eb848e67abc8c1e6fc95cfe4c46b6f.tar.gz
qutebrowser-273230eb07eb848e67abc8c1e6fc95cfe4c46b6f.zip
Merge remote-tracking branch 'origin/pr/7789'
-rw-r--r--.github/workflows/ci.yml20
-rw-r--r--.github/workflows/docker.yml1
-rw-r--r--.github/workflows/nightly.yml40
-rw-r--r--.pylintrc6
-rw-r--r--doc/changelog.asciidoc11
-rw-r--r--misc/qutebrowser.spec2
-rw-r--r--misc/requirements/requirements-pyqt.txt10
-rw-r--r--misc/requirements/requirements-pyqt.txt-raw6
-rwxr-xr-xmisc/userscripts/add-nextcloud-bookmarks4
-rwxr-xr-xmisc/userscripts/add-nextcloud-cookbook4
-rwxr-xr-xmisc/userscripts/qute-keepass8
-rw-r--r--qutebrowser/app.py8
-rw-r--r--qutebrowser/browser/qutescheme.py7
-rw-r--r--qutebrowser/browser/webengine/webenginetab.py3
-rw-r--r--qutebrowser/browser/webkit/webkitelem.py5
-rw-r--r--qutebrowser/browser/webkit/webkithistory.py5
-rw-r--r--qutebrowser/browser/webkit/webkitinspector.py4
-rw-r--r--qutebrowser/browser/webkit/webkitsettings.py5
-rw-r--r--qutebrowser/browser/webkit/webkittab.py4
-rw-r--r--qutebrowser/browser/webkit/webpage.py5
-rw-r--r--qutebrowser/browser/webkit/webview.py5
-rw-r--r--qutebrowser/html/warning-qt5.html28
-rw-r--r--qutebrowser/keyinput/keyutils.py30
-rw-r--r--qutebrowser/qt/_core_pyqtproperty.py2
-rw-r--r--qutebrowser/qt/machinery.py40
-rw-r--r--qutebrowser/qt/opengl.py2
-rw-r--r--qutebrowser/qutebrowser.py2
-rwxr-xr-xscripts/dev/build_release.py62
-rw-r--r--scripts/dev/misc_checks.py47
-rwxr-xr-xscripts/dev/run_vulture.py1
-rw-r--r--scripts/dev/standardpaths_tester.py2
-rw-r--r--scripts/keytester.py3
-rw-r--r--scripts/link_pyqt.py2
-rwxr-xr-xscripts/mkvenv.py10
-rw-r--r--scripts/opengl_info.py6
-rw-r--r--tests/unit/browser/webkit/test_tabhistory.py5
-rw-r--r--tests/unit/javascript/test_js_execution.py7
-rw-r--r--tests/unit/keyinput/key_data.py3
-rw-r--r--tests/unit/keyinput/test_basekeyparser.py2
-rw-r--r--tests/unit/keyinput/test_keyutils.py33
-rw-r--r--tests/unit/test_qt_machinery.py263
-rw-r--r--tox.ini41
42 files changed, 441 insertions, 313 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 64dddd2f8..580e532f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -56,7 +56,8 @@ jobs:
- name: Install dependencies
run: |
[[ ${{ matrix.testenv }} == eslint ]] && npm install -g eslint
- [[ ${{ matrix.testenv }} == docs ]] && sudo apt-get update && sudo apt-get install --no-install-recommends asciidoc
+ [[ ${{ matrix.testenv }} == docs ]] && sudo apt-get update && sudo apt-get install --no-install-recommends asciidoc libegl1-mesa
+ [[ ${{ matrix.testenv }} == vulture || ${{ matrix.testenv }} == pylint ]] && sudo apt-get update && sudo apt-get install --no-install-recommends libegl1-mesa
if [[ ${{ matrix.testenv }} == shellcheck ]]; then
scversion="stable"
bindir="$HOME/.local/bin"
@@ -89,17 +90,16 @@ jobs:
fail-fast: false
matrix:
include:
- - testenv: py
+ - testenv: py-qt5
image: archlinux-webkit
- - testenv: py
+ - testenv: py-qt5
image: archlinux-webengine
- - testenv: py-qt6
+ - testenv: py-qt5
+ image: archlinux-webengine-unstable
+ - testenv: py
image: archlinux-webengine-qt6
- testenv: py
- image: archlinux-webengine-unstable
- args: ""
- # - testenv: py
- # image: archlinux-webengine-unstable-qt6 # FIXME:qt6.5 activate
+ image: archlinux-webengine-unstable-qt6
container:
image: "qutebrowser/ci:${{ matrix.image }}"
env:
@@ -115,9 +115,9 @@ jobs:
with:
persist-credentials: false
- name: Set up problem matchers
- run: "python scripts/dev/ci/problemmatchers.py py38 ${{ runner.temp }}"
+ run: "python scripts/dev/ci/problemmatchers.py tests ${{ runner.temp }}"
- name: Run tox
- run: "dbus-run-session -- tox -e ${{ matrix.testenv }} -- ${{ matrix.args }}"
+ run: "dbus-run-session -- tox -e ${{ matrix.testenv }}"
tests:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index cabf2d8c4..68d2243a4 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -15,6 +15,7 @@ jobs:
- archlinux-webkit
- archlinux-webengine
- archlinux-webengine-unstable
+ - archlinux-webengine-unstable-qt6
- archlinux-webengine-qt6
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 2254abb4a..c1a8dda8a 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -16,50 +16,50 @@ jobs:
include:
- os: macos-11
branch: master
- toxenv: build-release
- name: macos
+ toxenv: build-release-qt5
+ name: qt5-macos
- os: windows-2019
args: --64bit
branch: master
- toxenv: build-release
- name: windows-64bit
+ toxenv: build-release-qt5
+ name: qt5-windows-64bit
- os: windows-2019
args: --32bit
branch: master
- toxenv: build-release
- name: windows-32bit
+ toxenv: build-release-qt5
+ name: qt5-windows-32bit
- os: macos-11
args: --debug
branch: master
- toxenv: build-release
- name: macos-debug
+ toxenv: build-release-qt5
+ name: qt5-macos-debug
- os: windows-2019
args: --64bit --debug
branch: master
- toxenv: build-release
- name: windows-64bit-debug
+ toxenv: build-release-qt5
+ name: qt5-windows-64bit-debug
- os: windows-2019
args: --32bit --debug
branch: master
- toxenv: build-release
- name: windows-32bit-debug
+ toxenv: build-release-qt5
+ name: qt5-windows-32bit-debug
- os: macos-11
- toxenv: build-release-qt6
- name: qt6-macos
+ toxenv: build-release
+ name: macos
- os: windows-2019
args: --64bit
- toxenv: build-release-qt6
- name: qt6-windows-64bit
+ toxenv: build-release
+ name: windows-64bit
- os: macos-11
args: --debug
- toxenv: build-release-qt6
- name: qt6-macos-debug
+ toxenv: build-release
+ name: macos-debug
- os: windows-2019
args: --64bit --debug
- toxenv: build-release-qt6
- name: qt6-windows-64bit-debug
+ toxenv: build-release
+ name: windows-64bit-debug
runs-on: "${{ matrix.os }}"
timeout-minutes: 45
steps:
diff --git a/.pylintrc b/.pylintrc
index f89e3fa50..341bbe8cb 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -1,6 +1,6 @@
[MASTER]
ignore=resources.py
-extension-pkg-whitelist=PyQt5,sip
+extension-pkg-whitelist=PyQt5,PyQt6,sip
load-plugins=qute_pylint.config,
pylint.extensions.docstyle,
pylint.extensions.emptystring,
@@ -58,8 +58,8 @@ disable=locally-disabled,
missing-type-doc,
missing-param-doc,
useless-param-doc,
- wrong-import-order, # FIXME:qt6 (lint)
- ungrouped-imports, # FIXME:qt6 (lint)
+ wrong-import-order, # doesn't work with qutebrowser.qt, even with known-third-party set
+ ungrouped-imports, # ditto
[BASIC]
function-rgx=[a-z_][a-z0-9_]{2,50}$
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 666e24177..b8bce1545 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -19,6 +19,17 @@ breaking changes (such as renamed commands) can happen in minor releases.
v3.0.0 (unreleased)
-------------------
+Major changes
+~~~~~~~~~~~~~
+
+- qutebrowser now supports Qt 6 and uses it by default. Qt 5.15 is used as a
+ fallback if Qt 6 is unavailable. This behavior can be customized in three ways
+ (in order of precedence):
+ * Via `--qt-wrapper PyQt5` or `--qt-wrapper PyQt6` command-line arguments.
+ * Via the `QUTE_QT_WRAPPER` environment variable, set to `PyQt6` or `PyQt5`.
+ * For packagers wanting to provide packages specific to a Qt version,
+ patch `qutebrowser/qt/machinery.py` and set `_WRAPPER_OVERRIDE`.
+
Added
~~~~~
diff --git a/misc/qutebrowser.spec b/misc/qutebrowser.spec
index 467994bab..1eee9161d 100644
--- a/misc/qutebrowser.spec
+++ b/misc/qutebrowser.spec
@@ -82,7 +82,7 @@ def get_data_files():
def get_hidden_imports():
- imports = [] if "PYINSTALLER_QT6" in os.environ else ['PyQt5.QtOpenGL']
+ imports = ["PyQt5.QtOpenGL"] if "PYINSTALLER_QT5" in os.environ else []
for info in loader.walk_components():
imports.append(info.name)
return imports
diff --git a/misc/requirements/requirements-pyqt.txt b/misc/requirements/requirements-pyqt.txt
index 029fb4a6b..26f81ab23 100644
--- a/misc/requirements/requirements-pyqt.txt
+++ b/misc/requirements/requirements-pyqt.txt
@@ -1,7 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-PyQt5==5.15.9
-PyQt5-Qt5==5.15.2
-PyQt5-sip==12.12.1
-PyQtWebEngine==5.15.6
-PyQtWebEngine-Qt5==5.15.2
+PyQt6==6.5.1
+PyQt6-Qt6==6.5.1
+PyQt6-sip==13.5.1
+PyQt6-WebEngine==6.5.0
+PyQt6-WebEngine-Qt6==6.5.1
diff --git a/misc/requirements/requirements-pyqt.txt-raw b/misc/requirements/requirements-pyqt.txt-raw
index 9c6afbf16..68a5db685 100644
--- a/misc/requirements/requirements-pyqt.txt-raw
+++ b/misc/requirements/requirements-pyqt.txt-raw
@@ -1,2 +1,4 @@
-PyQt5
-PyQtWebEngine
+PyQt6
+PyQt6-Qt6
+PyQt6-WebEngine
+PyQt6-WebEngine-Qt6
diff --git a/misc/userscripts/add-nextcloud-bookmarks b/misc/userscripts/add-nextcloud-bookmarks
index 86f4f5bc7..2a480ccff 100755
--- a/misc/userscripts/add-nextcloud-bookmarks
+++ b/misc/userscripts/add-nextcloud-bookmarks
@@ -41,7 +41,7 @@ from json import dumps
from os import environ, path
from sys import argv, exit
-from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
+from PyQt6.QtWidgets import QApplication, QInputDialog, QLineEdit
from requests import get, post
from requests.auth import HTTPBasicAuth
@@ -54,7 +54,7 @@ def get_text(name, info):
None,
"add-nextcloud-bookmarks userscript",
"Please enter {}".format(info),
- QLineEdit.Password,
+ QLineEdit.EchoMode.Password,
)
else:
text, ok = QInputDialog.getText(
diff --git a/misc/userscripts/add-nextcloud-cookbook b/misc/userscripts/add-nextcloud-cookbook
index 3952bb16f..151090785 100755
--- a/misc/userscripts/add-nextcloud-cookbook
+++ b/misc/userscripts/add-nextcloud-cookbook
@@ -37,7 +37,7 @@ import configparser
from os import environ, path
from sys import argv, exit
-from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
+from PyQt6.QtWidgets import QApplication, QInputDialog, QLineEdit
from requests import post
from requests.auth import HTTPBasicAuth
@@ -50,7 +50,7 @@ def get_text(name, info):
None,
"add-nextcloud-cookbook userscript",
"Please enter {}".format(info),
- QLineEdit.Password,
+ QLineEdit.EchoMode.Password,
)
else:
text, ok = QInputDialog.getText(
diff --git a/misc/userscripts/qute-keepass b/misc/userscripts/qute-keepass
index 285377ffc..f88493d8e 100755
--- a/misc/userscripts/qute-keepass
+++ b/misc/userscripts/qute-keepass
@@ -42,7 +42,7 @@ you do not do this, you will get 'element not editable' errors.
If keepass takes a while to open the DB, you might want to consider reducing
the number of transform rounds in your database settings.
-Dependencies: pykeepass (in python3), PyQt5. Without pykeepass, you will get an
+Dependencies: pykeepass (in python3), PyQt6. Without pykeepass, you will get an
exit code of 100.
********************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!******************
@@ -64,8 +64,8 @@ import shlex
import subprocess
import sys
-from PyQt5.QtCore import QUrl
-from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
+from PyQt6.QtCore import QUrl
+from PyQt6.QtWidgets import QApplication, QInputDialog, QLineEdit
try:
import pykeepass
@@ -152,7 +152,7 @@ def get_password():
text, ok = QInputDialog.getText(
None, "KeePass DB Password",
"Please enter your KeePass Master Password",
- QLineEdit.Password)
+ QLineEdit.EchoMode.Password)
if not ok:
stderr('Password Prompt Rejected.')
sys.exit(ExitCodes.USER_QUIT)
diff --git a/qutebrowser/app.py b/qutebrowser/app.py
index bb2ff56e7..fbfa3df12 100644
--- a/qutebrowser/app.py
+++ b/qutebrowser/app.py
@@ -367,6 +367,14 @@ def _open_special_pages(args):
os.environ.get("QTWEBENGINE_DISABLE_SANDBOX") == "1"
),
'qute://warning/sandboxing'),
+
+ ('qt5-warning-shown',
+ (
+ machinery.IS_QT5 and
+ machinery.INFO.reason == machinery.SelectionReason.auto and
+ objects.backend != usertypes.Backend.QtWebKit,
+ ),
+ 'qute://warning/qt5'),
]
if 'quickstart-done' not in general_sect:
diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py
index 25834670b..0073f9bd2 100644
--- a/qutebrowser/browser/qutescheme.py
+++ b/qutebrowser/browser/qutescheme.py
@@ -22,6 +22,7 @@ Module attributes:
_HANDLERS: The handlers registered via decorators.
"""
+import sys
import html
import json
import os
@@ -583,6 +584,12 @@ def qute_warning(url: QUrl) -> _HandlerRet:
elif path == '/sandboxing':
src = jinja.render('warning-sandboxing.html',
title='Qt 6 macOS sandboxing warning')
+ elif path == '/qt5':
+ is_venv = hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix
+ src = jinja.render('warning-qt5.html',
+ title='Switch to Qt 6',
+ is_venv=is_venv,
+ prefix=sys.prefix)
else:
raise NotFoundError("Invalid warning page {}".format(path))
return 'text/html', src
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index e55d75ecd..c2957181b 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -400,7 +400,8 @@ class WebEngineCaret(browsertab.AbstractCaret):
# https://bugreports.qt.io/browse/QTBUG-53134
# Even on Qt 5.10 selectedText() seems to work poorly, see
# https://github.com/qutebrowser/qutebrowser/issues/3523
- # FIXME:qt6 Reevaluate?
+ # With Qt 6.2-6.5, there still seem to be issues (especially with
+ # multi-line text)
self._tab.run_js_async(javascript.assemble('caret', 'getSelection'),
callback)
diff --git a/qutebrowser/browser/webkit/webkitelem.py b/qutebrowser/browser/webkit/webkitelem.py
index ef3e3bea5..8bf5031b1 100644
--- a/qutebrowser/browser/webkit/webkitelem.py
+++ b/qutebrowser/browser/webkit/webkitelem.py
@@ -15,16 +15,15 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""QtWebKit specific part of the web element API."""
from typing import cast, TYPE_CHECKING, Iterator, List, Optional, Set
from qutebrowser.qt.core import QRect, Qt
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebElement, QWebSettings
from qutebrowser.qt.webkitwidgets import QWebFrame
+# pylint: enable=no-name-in-module
from qutebrowser.config import config
from qutebrowser.utils import log, utils, javascript, usertypes
diff --git a/qutebrowser/browser/webkit/webkithistory.py b/qutebrowser/browser/webkit/webkithistory.py
index aea648361..d89c705e6 100644
--- a/qutebrowser/browser/webkit/webkithistory.py
+++ b/qutebrowser/browser/webkit/webkithistory.py
@@ -15,14 +15,13 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""QtWebKit specific part of history."""
import functools
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebHistoryInterface
+# pylint: enable=no-name-in-module
from qutebrowser.utils import debug
from qutebrowser.misc import debugcachestats
diff --git a/qutebrowser/browser/webkit/webkitinspector.py b/qutebrowser/browser/webkit/webkitinspector.py
index cb9cb5615..c181435d1 100644
--- a/qutebrowser/browser/webkit/webkitinspector.py
+++ b/qutebrowser/browser/webkit/webkitinspector.py
@@ -15,13 +15,13 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
"""Customized QWebInspector for QtWebKit."""
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebSettings
from qutebrowser.qt.webkitwidgets import QWebInspector, QWebPage
+# pylint: enable=no-name-in-module
from qutebrowser.qt.widgets import QWidget
from qutebrowser.browser import inspector
diff --git a/qutebrowser/browser/webkit/webkitsettings.py b/qutebrowser/browser/webkit/webkitsettings.py
index bd65be65b..a20811bae 100644
--- a/qutebrowser/browser/webkit/webkitsettings.py
+++ b/qutebrowser/browser/webkit/webkitsettings.py
@@ -15,9 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""Bridge from QWebSettings to our own settings.
Module attributes:
@@ -30,8 +27,10 @@ import os.path
from qutebrowser.qt.core import QUrl
from qutebrowser.qt.gui import QFont
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebSettings
from qutebrowser.qt.webkitwidgets import QWebPage
+# pylint: enable=no-name-in-module
from qutebrowser.config import config, websettings
from qutebrowser.config.websettings import AttributeInfo as Attr
diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py
index a756e1a3d..e0483a23a 100644
--- a/qutebrowser/browser/webkit/webkittab.py
+++ b/qutebrowser/browser/webkit/webkittab.py
@@ -15,8 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
"""Wrapper over our (QtWebKit) WebView."""
@@ -28,8 +26,10 @@ from typing import cast, Iterable, Optional
from qutebrowser.qt.core import pyqtSlot, Qt, QUrl, QPoint, QTimer, QSizeF, QSize
from qutebrowser.qt.gui import QIcon
from qutebrowser.qt.widgets import QWidget
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkitwidgets import QWebPage, QWebFrame
from qutebrowser.qt.webkit import QWebSettings, QWebHistory, QWebElement
+# pylint: enable=no-name-in-module
from qutebrowser.qt.printsupport import QPrinter
from qutebrowser.browser import browsertab, shared
diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py
index 27429f331..b3b1b7ceb 100644
--- a/qutebrowser/browser/webkit/webpage.py
+++ b/qutebrowser/browser/webkit/webpage.py
@@ -15,9 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""The main browser widgets."""
import html
@@ -28,7 +25,9 @@ from qutebrowser.qt.gui import QDesktopServices
from qutebrowser.qt.network import QNetworkReply, QNetworkRequest
from qutebrowser.qt.widgets import QFileDialog
from qutebrowser.qt.printsupport import QPrintDialog
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkitwidgets import QWebPage, QWebFrame
+# pylint: enable=no-name-in-module
from qutebrowser.config import websettings, config
from qutebrowser.browser import pdfjs, shared, downloads, greasemonkey
diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py
index 7a08a0736..831b2b689 100644
--- a/qutebrowser/browser/webkit/webview.py
+++ b/qutebrowser/browser/webkit/webview.py
@@ -15,14 +15,13 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""The main browser widgets."""
from qutebrowser.qt.core import pyqtSignal, Qt
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebSettings
from qutebrowser.qt.webkitwidgets import QWebView, QWebPage
+# pylint: enable=no-name-in-module
from qutebrowser.config import config, stylesheet
from qutebrowser.keyinput import modeman
diff --git a/qutebrowser/html/warning-qt5.html b/qutebrowser/html/warning-qt5.html
new file mode 100644
index 000000000..17af2f72c
--- /dev/null
+++ b/qutebrowser/html/warning-qt5.html
@@ -0,0 +1,28 @@
+{% extends "styled.html" %}
+
+{% block content %}
+<h1>{{ title }}</h1>
+<span class="note">Note this warning will only appear once. Use <span class="mono">:open
+qute://warning/qt5</span> to show it again at a later time.</span>
+
+<p>
+ qutebrowser <b>now supports Qt 6</b>.
+</p>
+<p>
+ However, in your environment, <b>Qt 6 is not installed</b>. Thus, qutebrowser is still using Qt 5 instead.
+
+ Qt 5.15 based on a very old Chromium version (83 or 87, from mid/late 2020).
+</p>
+{% if is_venv %}
+<p>
+ You are using a virtualenv. If you want to use Qt 6, you need to create a new
+ virtualenv with PyQt6 installed.
+
+ If using <span class="mono">mkvenv.py</span>, <b>rerun the script</b> to create a
+ new virtualenv with Qt 6.
+</p>
+{% endif %}
+<p>
+ <span class="note">Python installation prefix: <span class="mono">{{ prefix }}</span></span>
+</p>
+{% endblock %}
diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py
index e2a15b2c0..10f4d5378 100644
--- a/qutebrowser/keyinput/keyutils.py
+++ b/qutebrowser/keyinput/keyutils.py
@@ -37,9 +37,7 @@ from qutebrowser.qt import machinery
from qutebrowser.qt.core import Qt, QEvent
from qutebrowser.qt.gui import QKeySequence, QKeyEvent
if machinery.IS_QT6:
- # FIXME:qt6 (lint) how come pylint isn't picking this up with both backends
- # installed?
- from qutebrowser.qt.core import QKeyCombination # pylint: disable=no-name-in-module
+ from qutebrowser.qt.core import QKeyCombination
else:
QKeyCombination = None # QKeyCombination was added in Qt 6
@@ -349,7 +347,7 @@ def _unset_modifier_bits(
https://github.com/python/cpython/issues/105497
"""
if machinery.IS_QT5:
- return cast(_ModifierType, modifiers & ~mask)
+ return Qt.KeyboardModifiers(modifiers & ~mask) # can lose type if it's 0
else:
return Qt.KeyboardModifier(modifiers.value & ~mask.value)
@@ -369,11 +367,14 @@ class KeyInfo:
def __post_init__(self) -> None:
"""Run some validation on the key/modifier values."""
- # This is mainly useful while porting from Qt 5 to 6.
- # FIXME:qt6 do we want to remove or keep this (and fix the remaining
- # issues) when done?
- # assert isinstance(self.key, Qt.Key), self.key
- # assert isinstance(self.modifiers, Qt.KeyboardModifier), self.modifiers
+ # This changed with Qt 6, and e.g. to_qt() relies on this.
+ if machinery.IS_QT5:
+ modifier_classes = (Qt.KeyboardModifier, Qt.KeyboardModifiers)
+ elif machinery.IS_QT6:
+ modifier_classes = Qt.KeyboardModifier
+ assert isinstance(self.key, Qt.Key), self.key
+ assert isinstance(self.modifiers, modifier_classes), self.modifiers
+
_assert_plain_key(self.key)
_assert_plain_modifier(self.modifiers)
@@ -488,16 +489,7 @@ class KeyInfo:
if machinery.IS_QT5:
return int(self.key) | int(self.modifiers)
else:
- try:
- # FIXME:qt6 We might want to consider only supporting KeyInfo to be
- # instanciated with a real Qt.Key, not with ints. See __post_init__.
- key = Qt.Key(self.key)
- except ValueError as e:
- # WORKAROUND for
- # https://www.riverbankcomputing.com/pipermail/pyqt/2022-April/044607.html
- raise InvalidKeyError(e)
-
- return QKeyCombination(self.modifiers, key)
+ return QKeyCombination(self.modifiers, self.key)
def with_stripped_modifiers(self, modifiers: Qt.KeyboardModifier) -> "KeyInfo":
mods = _unset_modifier_bits(self.modifiers, modifiers)
diff --git a/qutebrowser/qt/_core_pyqtproperty.py b/qutebrowser/qt/_core_pyqtproperty.py
index 8ae62264f..ae6435039 100644
--- a/qutebrowser/qt/_core_pyqtproperty.py
+++ b/qutebrowser/qt/_core_pyqtproperty.py
@@ -5,7 +5,7 @@ https://github.com/python-qt-tools/PyQt5-stubs/blob/5.15.6.0/PyQt5-stubs/QtCore.
"""
# flake8: noqa
-# pylint: disable=invalid-name,missing-class-docstring,too-many-arguments,redefined-builtin,unused-argument,import-error
+# pylint: disable=invalid-name,missing-class-docstring,too-many-arguments,redefined-builtin,unused-argument,no-name-in-module
import typing
from PyQt6.QtCore import QObject, pyqtSignal
diff --git a/qutebrowser/qt/machinery.py b/qutebrowser/qt/machinery.py
index e626edcb4..616c7ccfc 100644
--- a/qutebrowser/qt/machinery.py
+++ b/qutebrowser/qt/machinery.py
@@ -3,6 +3,16 @@
"""Qt wrapper selection.
Contains selection logic and globals for Qt wrapper selection.
+
+All other files in this package are intended to be simple wrappers around Qt imports.
+Depending on what is set in this module, they import from PyQt5 or PyQt6.
+
+The import wrappers are intended to be as thin as possible. They will not unify
+API-level differences between Qt 5 and Qt 6. This is best handled by the calling code,
+which has a better picture of what changed between APIs and how to best handle it.
+
+What they *will* do is handle simple 1:1 renames of classes, or moves between
+modules (where they aim to always expose the Qt 6 API). See e.g. webenginecore.py.
"""
# NOTE: No qutebrowser or PyQt import should be done here (at import time),
@@ -20,11 +30,11 @@ from typing import Optional, Dict
from qutebrowser.utils import log
-# Packagers: Patch the line below to change the default wrapper for Qt 6 packages, e.g.:
-# sed -i 's/_DEFAULT_WRAPPER = "PyQt5"/_DEFAULT_WRAPPER = "PyQt6"/' qutebrowser/qt/machinery.py
+# Packagers: Patch the line below to enforce a Qt wrapper, e.g.:
+# sed -i 's/_WRAPPER_OVERRIDE = .*/_WRAPPER_OVERRIDE = "PyQt6"/' qutebrowser/qt/machinery.py
#
# Users: Set the QUTE_QT_WRAPPER environment variable to change the default wrapper.
-_DEFAULT_WRAPPER = "PyQt5"
+_WRAPPER_OVERRIDE = None
WRAPPERS = [
"PyQt6",
@@ -80,6 +90,9 @@ class SelectionReason(enum.Enum):
#: The wrapper was faked/patched out (e.g. in tests).
fake = "fake"
+ #: The wrapper was overridden by patching _WRAPPER_OVERRIDE.
+ override = "override"
+
#: The reason was not set.
unknown = "unknown"
@@ -152,7 +165,7 @@ def _select_wrapper(args: Optional[argparse.Namespace]) -> SelectionInfo:
- If --qt-wrapper is given, use that.
- Otherwise, if the QUTE_QT_WRAPPER environment variable is set, use that.
- - Otherwise, use PyQt5 (FIXME:qt6 autoselect).
+ - Otherwise, try the wrappers in WRAPPER in order (PyQt6 -> PyQt5)
"""
# If any Qt wrapper has been imported before this, something strange might
# be happening.
@@ -170,15 +183,17 @@ def _select_wrapper(args: Optional[argparse.Namespace]) -> SelectionInfo:
if env_wrapper == "auto":
return _autoselect_wrapper()
elif env_wrapper not in WRAPPERS:
- raise Error(f"Unknown wrapper {env_wrapper} set via {env_var}, "
- f"allowed: {', '.join(WRAPPERS)}")
+ raise Error(
+ f"Unknown wrapper {env_wrapper} set via {env_var}, "
+ f"allowed: {', '.join(WRAPPERS)}"
+ )
return SelectionInfo(wrapper=env_wrapper, reason=SelectionReason.env)
- # FIXME:qt6 Go back to the auto-detection once ready
- # FIXME:qt6 Make sure to still consider _DEFAULT_WRAPPER for packagers
- # (rename to _WRAPPER_OVERRIDE since our sed command is broken anyways then?)
- # return _autoselect_wrapper()
- return SelectionInfo(wrapper=_DEFAULT_WRAPPER, reason=SelectionReason.default)
+ if _WRAPPER_OVERRIDE is not None:
+ assert _WRAPPER_OVERRIDE in WRAPPERS # type: ignore[unreachable]
+ return SelectionInfo(wrapper=_WRAPPER_OVERRIDE, reason=SelectionReason.override)
+
+ return _autoselect_wrapper()
# Values are set in init(). If you see a NameError here, it means something tried to
@@ -219,8 +234,7 @@ def _set_globals(info: SelectionInfo) -> None:
Those are split into multiple global variables because that way we can teach mypy
about them via --always-true and --always-false, see tox.ini.
"""
- global INFO, USE_PYQT5, USE_PYQT6, USE_PYSIDE6, IS_QT5, IS_QT6, \
- IS_PYQT, IS_PYSIDE, _initialized
+ global INFO, USE_PYQT5, USE_PYQT6, USE_PYSIDE6, IS_QT5, IS_QT6, IS_PYQT, IS_PYSIDE, _initialized
assert info.wrapper is not None, info
assert not _initialized
diff --git a/qutebrowser/qt/opengl.py b/qutebrowser/qt/opengl.py
index 0a14dffad..bc5a31c11 100644
--- a/qutebrowser/qt/opengl.py
+++ b/qutebrowser/qt/opengl.py
@@ -1,4 +1,4 @@
-# pylint: disable=import-error,wildcard-import,unused-import
+# pylint: disable=import-error,wildcard-import,unused-import,unused-wildcard-import
"""Wrapped Qt imports for Qt OpenGL.
diff --git a/qutebrowser/qutebrowser.py b/qutebrowser/qutebrowser.py
index e778cc23a..fcca87feb 100644
--- a/qutebrowser/qutebrowser.py
+++ b/qutebrowser/qutebrowser.py
@@ -50,7 +50,7 @@ except ImportError:
sys.exit(100)
check_python_version()
-import argparse # FIXME:qt6 (lint): disable=wrong-import-order
+import argparse
from qutebrowser.misc import earlyinit
from qutebrowser.qt import machinery
diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py
index 996487693..d8f9693e7 100755
--- a/scripts/dev/build_release.py
+++ b/scripts/dev/build_release.py
@@ -136,7 +136,7 @@ def _smoke_test_run(
return subprocess.run(argv, check=True, capture_output=True)
-def smoke_test(executable: pathlib.Path, debug: bool, qt6: bool) -> None:
+def smoke_test(executable: pathlib.Path, debug: bool, qt5: bool) -> None:
"""Try starting the given qutebrowser executable."""
stdout_whitelist = []
stderr_whitelist = [
@@ -176,7 +176,7 @@ def smoke_test(executable: pathlib.Path, debug: bool, qt6: bool) -> None:
r'ContextResult::kTransientFailure: Failed to send '
r'.*CreateCommandBuffer\.'),
])
- if qt6:
+ if not qt5:
stderr_whitelist.extend([
# FIXME:qt6 Qt 6.3 on macOS
r'[0-9:]* WARNING: Incompatible version of OpenSSL',
@@ -257,10 +257,10 @@ def verify_windows_exe(exe_path: pathlib.Path) -> None:
assert pe.verify_checksum()
-def patch_mac_app(qt6: bool) -> None:
+def patch_mac_app(qt5: bool) -> None:
"""Patch .app to save some space and make it signable."""
dist_path = pathlib.Path('dist')
- ver = '6' if qt6 else '5'
+ ver = '5' if qt5 else '6'
app_path = dist_path / 'qutebrowser.app'
contents_path = app_path / 'Contents'
@@ -280,7 +280,7 @@ def patch_mac_app(qt6: bool) -> None:
file_path.unlink()
file_path.symlink_to(target)
- if qt6:
+ if not qt5:
# Symlinking QtWebEngineCore.framework does not seem to work with Qt 6.
# Also, the symlinking/moving before signing doesn't seem to be required.
return
@@ -333,7 +333,7 @@ def _mac_bin_path(base: pathlib.Path) -> pathlib.Path:
def build_mac(
*,
gh_token: Optional[str],
- qt6: bool,
+ qt5: bool,
skip_packaging: bool,
debug: bool,
) -> List[Artifact]:
@@ -348,20 +348,20 @@ def build_mac(
shutil.rmtree(d, ignore_errors=True)
utils.print_title("Updating 3rdparty content")
- update_3rdparty.run(ace=False, pdfjs=True, legacy_pdfjs=not qt6, fancy_dmg=False,
+ update_3rdparty.run(ace=False, pdfjs=True, legacy_pdfjs=qt5, fancy_dmg=False,
gh_token=gh_token)
utils.print_title("Building .app via pyinstaller")
- call_tox(f'pyinstaller-64bit{"-qt6" if qt6 else ""}', '-r', debug=debug)
+ call_tox(f'pyinstaller-64bit{"-qt5" if qt5 else ""}', '-r', debug=debug)
utils.print_title("Patching .app")
- patch_mac_app(qt6=qt6)
+ patch_mac_app(qt5=qt5)
utils.print_title("Re-signing .app")
sign_mac_app()
dist_path = pathlib.Path("dist")
utils.print_title("Running pre-dmg smoke test")
- smoke_test(_mac_bin_path(dist_path), debug=debug, qt6=qt6)
+ smoke_test(_mac_bin_path(dist_path), debug=debug, qt5=qt5)
if skip_packaging:
return []
@@ -371,7 +371,7 @@ def build_mac(
subprocess.run(['make', '-f', dmg_makefile_path], check=True)
suffix = "-debug" if debug else ""
- suffix += "-qt6" if qt6 else ""
+ suffix += "-qt5" if qt5 else ""
dmg_path = dist_path / f'qutebrowser-{qutebrowser.__version__}{suffix}.dmg'
pathlib.Path('qutebrowser.dmg').rename(dmg_path)
@@ -383,7 +383,7 @@ def build_mac(
subprocess.run(['hdiutil', 'attach', dmg_path,
'-mountpoint', tmp_path], check=True)
try:
- smoke_test(_mac_bin_path(tmp_path), debug=debug, qt6=qt6)
+ smoke_test(_mac_bin_path(tmp_path), debug=debug, qt5=qt5)
finally:
print("Waiting 10s for dmg to be detachable...")
time.sleep(10)
@@ -422,7 +422,7 @@ def _get_windows_python_path(x64: bool) -> pathlib.Path:
def _build_windows_single(
*, x64: bool,
- qt6: bool,
+ qt5: bool,
skip_packaging: bool,
debug: bool,
) -> List[Artifact]:
@@ -437,9 +437,9 @@ def _build_windows_single(
python = _get_windows_python_path(x64=x64)
suffix = "64bit" if x64 else "32bit"
- if qt6:
+ if qt5:
# FIXME:qt6 does this regress 391623d5ec983ecfc4512c7305c4b7a293ac3872?
- suffix += "-qt6"
+ suffix += "-qt5"
call_tox(f'pyinstaller-{suffix}', '-r', python=python, debug=debug)
out_pyinstaller = dist_path / "qutebrowser"
@@ -450,7 +450,7 @@ def _build_windows_single(
verify_windows_exe(exe_path)
utils.print_title(f"Running {human_arch} smoke test")
- smoke_test(exe_path, debug=debug, qt6=qt6)
+ smoke_test(exe_path, debug=debug, qt5=qt5)
if skip_packaging:
return []
@@ -463,7 +463,7 @@ def _build_windows_single(
desc_arch=human_arch,
desc_suffix='' if x64 else ' (only for 32-bit Windows!)',
debug=debug,
- qt6=qt6,
+ qt5=qt5,
)
@@ -472,12 +472,12 @@ def build_windows(
skip_packaging: bool,
only_32bit: bool,
only_64bit: bool,
- qt6: bool,
+ qt5: bool,
debug: bool,
) -> List[Artifact]:
"""Build windows executables/setups."""
utils.print_title("Updating 3rdparty content")
- update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=not qt6,
+ update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=qt5,
fancy_dmg=False, gh_token=gh_token)
utils.print_title("Building Windows binaries")
@@ -493,14 +493,14 @@ def build_windows(
x64=True,
skip_packaging=skip_packaging,
debug=debug,
- qt6=qt6,
+ qt5=qt5,
)
- if not only_64bit and not qt6:
+ if not only_64bit and not qt5:
artifacts += _build_windows_single(
x64=False,
skip_packaging=skip_packaging,
debug=debug,
- qt6=qt6,
+ qt5=qt5,
)
return artifacts
@@ -514,7 +514,7 @@ def _package_windows_single(
desc_suffix: str,
filename_arch: str,
debug: bool,
- qt6: bool,
+ qt5: bool,
) -> List[Artifact]:
"""Build the given installer/zip for windows."""
artifacts = []
@@ -532,8 +532,8 @@ def _package_windows_single(
]
if debug:
name_parts.append('debug')
- if qt6:
- name_parts.append('qt6')
+ if qt5:
+ name_parts.append('qt5')
name = '-'.join(name_parts) + '.exe'
artifacts.append(Artifact(
@@ -552,8 +552,8 @@ def _package_windows_single(
]
if debug:
zip_name_parts.append('debug')
- if qt6:
- zip_name_parts.append('qt6')
+ if qt5:
+ zip_name_parts.append('qt5')
zip_name = '-'.join(zip_name_parts) + '.zip'
zip_path = dist_path / zip_name
@@ -738,8 +738,8 @@ def main() -> None:
help="Skip Windows 32 bit build.", dest='only_64bit')
parser.add_argument('--debug', action='store_true', required=False,
help="Build a debug build.")
- parser.add_argument('--qt6', action='store_true', required=False,
- help="Build against PyQt6")
+ parser.add_argument('--qt5', action='store_true', required=False,
+ help="Build against PyQt5")
args = parser.parse_args()
utils.change_cwd()
@@ -768,14 +768,14 @@ def main() -> None:
skip_packaging=args.skip_packaging,
only_32bit=args.only_32bit,
only_64bit=args.only_64bit,
- qt6=args.qt6,
+ qt5=args.qt5,
debug=args.debug,
)
elif IS_MACOS:
artifacts = build_mac(
gh_token=gh_token,
skip_packaging=args.skip_packaging,
- qt6=args.qt6,
+ qt5=args.qt5,
debug=args.debug,
)
else:
diff --git a/scripts/dev/misc_checks.py b/scripts/dev/misc_checks.py
index 240b5e6f1..215a1cfa0 100644
--- a/scripts/dev/misc_checks.py
+++ b/scripts/dev/misc_checks.py
@@ -27,7 +27,7 @@ import subprocess
import tokenize
import traceback
import pathlib
-from typing import List, Iterator, Optional
+from typing import List, Iterator, Optional, Tuple
REPO_ROOT = pathlib.Path(__file__).resolve().parents[2]
sys.path.insert(0, str(REPO_ROOT))
@@ -152,6 +152,24 @@ def _check_spelling_file(path, fobj, patterns):
return ok
+def _check_spelling_all(
+ args: argparse.Namespace,
+ ignored: List[pathlib.Path],
+ patterns: List[Tuple[re.Pattern, str]],
+) -> Optional[bool]:
+ try:
+ ok = True
+ for path in _get_files(verbose=args.verbose, ignored=ignored):
+ with tokenize.open(str(path)) as f:
+ if not _check_spelling_file(path, f, patterns):
+ ok = False
+ print()
+ return ok
+ except Exception:
+ traceback.print_exc()
+ return None
+
+
def check_spelling(args: argparse.Namespace) -> Optional[bool]:
"""Check commonly misspelled words."""
# Words which I often misspell
@@ -273,25 +291,13 @@ def check_spelling(args: argparse.Namespace) -> Optional[bool]:
hint_data / 'ace' / 'ace.js',
hint_data / 'bootstrap' / 'bootstrap.css',
]
-
- try:
- ok = True
- for path in _get_files(verbose=args.verbose, ignored=ignored):
- with tokenize.open(path) as f:
- if not _check_spelling_file(path, f, patterns):
- ok = False
- print()
- return ok
- except Exception:
- traceback.print_exc()
- return None
+ return _check_spelling_all(args=args, ignored=ignored, patterns=patterns)
def check_pyqt_imports(args: argparse.Namespace) -> Optional[bool]:
"""Check for direct PyQt imports."""
ignored = [
pathlib.Path("qutebrowser", "qt"),
- # FIXME:qt6 fix those too?
pathlib.Path("misc", "userscripts"),
pathlib.Path("scripts"),
]
@@ -305,18 +311,7 @@ def check_pyqt_imports(args: argparse.Namespace) -> Optional[bool]:
"Use 'import qutebrowser.qt.MODULE' instead",
)
]
- # FIXME:qt6 unify this with check_spelling somehow?
- try:
- ok = True
- for path in _get_files(verbose=args.verbose, ignored=ignored):
- with tokenize.open(str(path)) as f:
- if not _check_spelling_file(path, f, patterns):
- ok = False
- print()
- return ok
- except Exception:
- traceback.print_exc()
- return None
+ return _check_spelling_all(args=args, ignored=ignored, patterns=patterns)
def check_vcs_conflict(args: argparse.Namespace) -> Optional[bool]:
diff --git a/scripts/dev/run_vulture.py b/scripts/dev/run_vulture.py
index 960b5a514..1e7ed0f61 100755
--- a/scripts/dev/run_vulture.py
+++ b/scripts/dev/run_vulture.py
@@ -60,7 +60,6 @@ def whitelist_generator(): # noqa: C901
yield 'qutebrowser.misc.sql.SqliteErrorCode.CONSTRAINT'
yield 'qutebrowser.misc.throttle.Throttle.set_delay'
yield 'qutebrowser.misc.guiprocess.GUIProcess.stderr'
- yield 'qutebrowser.qt.machinery._autoselect_wrapper' # FIXME:qt6
# Qt attributes
yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().baseUrl'
diff --git a/scripts/dev/standardpaths_tester.py b/scripts/dev/standardpaths_tester.py
index ff85b2a4c..bbd0a39fb 100644
--- a/scripts/dev/standardpaths_tester.py
+++ b/scripts/dev/standardpaths_tester.py
@@ -21,7 +21,7 @@
import os
import sys
-from PyQt5.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion,
+from PyQt6.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion,
QStandardPaths, QCoreApplication)
diff --git a/scripts/keytester.py b/scripts/keytester.py
index 6d994114d..861133c06 100644
--- a/scripts/keytester.py
+++ b/scripts/keytester.py
@@ -21,8 +21,7 @@
Use python3 -m scripts.keytester to launch it.
"""
-from PyQt5.QtWidgets import QApplication
-
+from qutebrowser.qt.widgets import QApplication
from qutebrowser.misc import miscwidgets
app = QApplication([])
diff --git a/scripts/link_pyqt.py b/scripts/link_pyqt.py
index 4581bef41..63bdde959 100644
--- a/scripts/link_pyqt.py
+++ b/scripts/link_pyqt.py
@@ -125,7 +125,7 @@ def get_lib_path(executable, name, required=True):
raise ValueError("Unexpected output: {!r}".format(output))
-def link_pyqt(executable, venv_path, *, version='5'):
+def link_pyqt(executable, venv_path, *, version):
"""Symlink the systemwide PyQt/sip into the venv.
Args:
diff --git a/scripts/mkvenv.py b/scripts/mkvenv.py
index 625cedd1a..9e9c1f4a2 100755
--- a/scripts/mkvenv.py
+++ b/scripts/mkvenv.py
@@ -134,8 +134,7 @@ def pyqt_versions() -> List[str]:
def _is_qt6_version(version: str) -> bool:
"""Check if the given version is Qt 6."""
- # FIXME:qt6 Adjust once auto = Qt 6
- return version == "6" or version.startswith("6.")
+ return version in ["auto", "6"] or version.startswith("6.")
def run_venv(
@@ -228,7 +227,7 @@ def requirements_file(name: str) -> pathlib.Path:
def pyqt_requirements_file(version: str) -> pathlib.Path:
"""Get the filename of the requirements file for the given PyQt version."""
- name = 'pyqt' if version == 'auto' else 'pyqt-{}'.format(version)
+ name = 'pyqt-6' if version == 'auto' else f'pyqt-{version}'
return requirements_file(name)
@@ -439,7 +438,7 @@ def run_qt_smoke_test_single(
def run_qt_smoke_test(venv_dir: pathlib.Path, *, pyqt_version: str) -> None:
"""Make sure the Qt installation works."""
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-104415
- no_debug = pyqt_version in ("6.3", "6") and sys.platform == "darwin"
+ no_debug = pyqt_version == "6.3" and sys.platform == "darwin"
if no_debug:
try:
run_qt_smoke_test_single(venv_dir, debug=False, pyqt_version=pyqt_version)
@@ -505,6 +504,9 @@ def install_pyqt(venv_dir, args):
install_pyqt_binary(venv_dir, args.pyqt_version)
if args.pyqt_snapshot:
install_pyqt_shapshot(venv_dir, args.pyqt_snapshot.split(','))
+ # Workaround until pyqt 6.5.2 is released on pypi
+ elif args.pyqt_version in ("6.5", "6", "auto"):
+ install_pyqt_shapshot(venv_dir, ["PyQt6-Qt6", "PyQt6-WebEngine-Qt6"])
elif args.pyqt_type == 'source':
install_pyqt_source(venv_dir, args.pyqt_version)
elif args.pyqt_type == 'link':
diff --git a/scripts/opengl_info.py b/scripts/opengl_info.py
index 5dc8f81c6..7c5ede6e7 100644
--- a/scripts/opengl_info.py
+++ b/scripts/opengl_info.py
@@ -18,8 +18,8 @@
"""Show information about the OpenGL setup."""
-from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile,
- QOffscreenSurface, QGuiApplication)
+from PyQt6.QtGui import QOpenGLContext, QOffscreenSurface, QGuiApplication
+from PyQt6.QtOpenGL import QOpenGLVersionProfile, QOpenGLVersionFunctionsFactory
app = QGuiApplication([])
@@ -38,7 +38,7 @@ print(f"GLES: {ctx.isOpenGLES()}")
vp = QOpenGLVersionProfile()
vp.setVersion(2, 0)
-vf = ctx.versionFunctions(vp)
+vf = QOpenGLVersionFunctionsFactory.get(vp, ctx)
print(f"Vendor: {vf.glGetString(vf.GL_VENDOR)}")
print(f"Renderer: {vf.glGetString(vf.GL_RENDERER)}")
print(f"Version: {vf.glGetString(vf.GL_VERSION)}")
diff --git a/tests/unit/browser/webkit/test_tabhistory.py b/tests/unit/browser/webkit/test_tabhistory.py
index 047454e25..cd40af6e8 100644
--- a/tests/unit/browser/webkit/test_tabhistory.py
+++ b/tests/unit/browser/webkit/test_tabhistory.py
@@ -15,9 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""Tests for webelement.tabhistory."""
import dataclasses
@@ -26,7 +23,9 @@ from typing import Any
import pytest
pytest.importorskip('qutebrowser.qt.webkit')
from qutebrowser.qt.core import QUrl, QPoint
+# pylint: disable=no-name-in-module
from qutebrowser.qt.webkit import QWebHistory
+# pylint: enable=no-name-in-module
from qutebrowser.browser.webkit import tabhistory
from qutebrowser.misc.sessions import TabHistoryItem as Item
diff --git a/tests/unit/javascript/test_js_execution.py b/tests/unit/javascript/test_js_execution.py
index 542b56975..fd2469148 100644
--- a/tests/unit/javascript/test_js_execution.py
+++ b/tests/unit/javascript/test_js_execution.py
@@ -15,9 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
-# FIXME:qt6 (lint)
-# pylint: disable=no-name-in-module
-
"""Check how Qt behaves when trying to execute JS."""
@@ -29,7 +26,7 @@ def test_simple_js_webkit(webview, js_enabled, expected):
"""With QtWebKit, evaluateJavaScript works when JS is on."""
# If we get there (because of the webview fixture) we can be certain
# QtWebKit is available
- from qutebrowser.qt.webkit import QWebSettings
+ from qutebrowser.qt.webkit import QWebSettings # pylint: disable=no-name-in-module
webview.settings().setAttribute(QWebSettings.WebAttribute.JavascriptEnabled, js_enabled)
result = webview.page().mainFrame().evaluateJavaScript('1 + 1')
assert result == expected
@@ -40,7 +37,7 @@ def test_element_js_webkit(webview, js_enabled, expected):
"""With QtWebKit, evaluateJavaScript on an element works with JS off."""
# If we get there (because of the webview fixture) we can be certain
# QtWebKit is available
- from qutebrowser.qt.webkit import QWebSettings
+ from qutebrowser.qt.webkit import QWebSettings # pylint: disable=no-name-in-module
webview.settings().setAttribute(QWebSettings.WebAttribute.JavascriptEnabled, js_enabled)
elem = webview.page().mainFrame().documentElement()
result = elem.evaluateJavaScript('1 + 1')
diff --git a/tests/unit/keyinput/key_data.py b/tests/unit/keyinput/key_data.py
index 3826d3ee9..5f151704a 100644
--- a/tests/unit/keyinput/key_data.py
+++ b/tests/unit/keyinput/key_data.py
@@ -24,6 +24,7 @@ import dataclasses
from typing import Optional
from qutebrowser.qt.core import Qt
+from qutebrowser.keyinput import keyutils
@dataclasses.dataclass(order=True)
@@ -606,7 +607,7 @@ KEYS = [
Key('unknown', 'Unknown', qtest=False),
# 0x0 is used by Qt for unknown keys...
- Key(attribute='', name='nil', member=0x0, qtest=False),
+ Key(attribute='', name='nil', member=keyutils._NIL_KEY, qtest=False),
]
diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py
index 52e0a01df..0ae0702e9 100644
--- a/tests/unit/keyinput/test_basekeyparser.py
+++ b/tests/unit/keyinput/test_basekeyparser.py
@@ -171,7 +171,7 @@ class TestHandle:
assert not prompt_keyparser._count
def test_invalid_key(self, prompt_keyparser):
- keys = [Qt.Key.Key_B, 0x0]
+ keys = [Qt.Key.Key_B, keyutils._NIL_KEY]
for key in keys:
info = keyutils.KeyInfo(key, Qt.KeyboardModifier.NoModifier)
prompt_keyparser.handle(info.to_event())
diff --git a/tests/unit/keyinput/test_keyutils.py b/tests/unit/keyinput/test_keyutils.py
index 2c0740c20..c3b6dc236 100644
--- a/tests/unit/keyinput/test_keyutils.py
+++ b/tests/unit/keyinput/test_keyutils.py
@@ -31,6 +31,16 @@ from qutebrowser.keyinput import keyutils
from qutebrowser.utils import utils
+pyqt_enum_workaround_skip = pytest.mark.skipif(
+ isinstance(keyutils._NIL_KEY, int),
+ reason="Can't create QKey for unknown keys with this PyQt version"
+)
+try:
+ OE_KEY = Qt.Key(ord('Œ'))
+except ValueError:
+ OE_KEY = None # affected tests skipped
+
+
@pytest.fixture(params=key_data.KEYS, ids=lambda k: k.attribute)
def qt_key(request):
"""Get all existing keys from key_data.py.
@@ -156,10 +166,14 @@ class TestKeyToString:
(Qt.Key.Key_A,
Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.AltModifier | Qt.KeyboardModifier.MetaModifier | Qt.KeyboardModifier.ShiftModifier,
'<Meta+Ctrl+Alt+Shift+a>'),
- (ord('Œ'), Qt.KeyboardModifier.NoModifier, '<Œ>'),
- (ord('Œ'), Qt.KeyboardModifier.ShiftModifier, '<Shift+Œ>'),
- (ord('Œ'), Qt.KeyboardModifier.GroupSwitchModifier, '<AltGr+Œ>'),
- (ord('Œ'), Qt.KeyboardModifier.GroupSwitchModifier | Qt.KeyboardModifier.ShiftModifier, '<AltGr+Shift+Œ>'),
+
+ pytest.param(OE_KEY, Qt.KeyboardModifier.NoModifier, '<Œ>',
+ marks=pyqt_enum_workaround_skip),
+ pytest.param(OE_KEY, Qt.KeyboardModifier.ShiftModifier, '<Shift+Œ>',
+ marks=pyqt_enum_workaround_skip),
+ pytest.param(OE_KEY, Qt.KeyboardModifier.GroupSwitchModifier, '<AltGr+Œ>',
+ marks=pyqt_enum_workaround_skip),
+ pytest.param(OE_KEY, Qt.KeyboardModifier.GroupSwitchModifier | Qt.KeyboardModifier.ShiftModifier, '<AltGr+Shift+Œ>'),
(Qt.Key.Key_Shift, Qt.KeyboardModifier.ShiftModifier, '<Shift>'),
(Qt.Key.Key_Shift, Qt.KeyboardModifier.ShiftModifier | Qt.KeyboardModifier.ControlModifier, '<Ctrl+Shift>'),
@@ -212,10 +226,10 @@ def test_surrogates(key, modifiers, text, expected, pyqt_enum_workaround):
([Qt.Key.Key_Shift, 0x29df6], '<Shift><𩷶>'),
([0x1f468, 0x200d, 0x1f468, 0x200d, 0x1f466], '<👨><‍><👨><‍><👦>'),
])
-def test_surrogate_sequences(keys, expected, pyqt_enum_workaround):
- infos = [keyutils.KeyInfo(key) for key in keys]
- with pyqt_enum_workaround(keyutils.KeyParseError):
- seq = keyutils.KeySequence(*infos)
+@pyqt_enum_workaround_skip
+def test_surrogate_sequences(keys, expected):
+ infos = [keyutils.KeyInfo(Qt.Key(key)) for key in keys]
+ seq = keyutils.KeySequence(*infos)
assert str(seq) == expected
@@ -590,7 +604,8 @@ def test_key_info_to_qt():
(Qt.Key.Key_Return, False),
(Qt.Key.Key_Enter, False),
(Qt.Key.Key_Space, False),
- (0x0, False), # Used by Qt for unknown keys
+ # Used by Qt for unknown keys
+ pytest.param(keyutils._NIL_KEY, False, marks=pyqt_enum_workaround_skip),
(Qt.Key.Key_ydiaeresis, True),
(Qt.Key.Key_X, True),
diff --git a/tests/unit/test_qt_machinery.py b/tests/unit/test_qt_machinery.py
index 1618e9e6f..32f63043b 100644
--- a/tests/unit/test_qt_machinery.py
+++ b/tests/unit/test_qt_machinery.py
@@ -23,6 +23,7 @@ import html
import argparse
import typing
from typing import Any, Optional, List, Dict, Union
+import dataclasses
import pytest
@@ -214,7 +215,7 @@ def modules():
reason=machinery.SelectionReason.auto,
outcomes={
"PyQt6": "ImportError: Fake ImportError for PyQt6.",
- }
+ },
),
id="import-error",
),
@@ -230,111 +231,157 @@ def test_autoselect(
assert machinery._autoselect_wrapper() == expected
-@pytest.mark.parametrize(
- "args, env, expected",
- [
- # Defaults with no overrides
- (
- None,
- None,
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.default
+@dataclasses.dataclass
+class SelectWrapperCase:
+ name: str
+ expected: machinery.SelectionInfo
+ args: Optional[argparse.Namespace] = None
+ env: Optional[str] = None
+ override: Optional[str] = None
+
+ def __str__(self):
+ return self.name
+
+
+class TestSelectWrapper:
+ @pytest.mark.parametrize(
+ "tc",
+ [
+ # Only argument given
+ SelectWrapperCase(
+ "pyqt6-arg",
+ args=argparse.Namespace(qt_wrapper="PyQt6"),
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper=None),
- None,
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.default
+ SelectWrapperCase(
+ "pyqt5-arg",
+ args=argparse.Namespace(qt_wrapper="PyQt5"),
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper=None),
- "",
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.default
+ SelectWrapperCase(
+ "pyqt6-arg-empty-env",
+ args=argparse.Namespace(qt_wrapper="PyQt5"),
+ env="",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- # Only argument given
- (
- argparse.Namespace(qt_wrapper="PyQt6"),
- None,
- machinery.SelectionInfo(
- wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ # Only environment variable given
+ SelectWrapperCase(
+ "pyqt6-env",
+ env="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt6", reason=machinery.SelectionReason.env
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper="PyQt5"),
- None,
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ SelectWrapperCase(
+ "pyqt5-env",
+ env="PyQt5",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.env
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper="PyQt5"),
- "",
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ # Both given
+ SelectWrapperCase(
+ "pyqt5-arg-pyqt6-env",
+ args=argparse.Namespace(qt_wrapper="PyQt5"),
+ env="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- # Only environment variable given
- (
- None,
- "PyQt6",
- machinery.SelectionInfo(
- wrapper="PyQt6", reason=machinery.SelectionReason.env
+ SelectWrapperCase(
+ "pyqt6-arg-pyqt5-env",
+ args=argparse.Namespace(qt_wrapper="PyQt6"),
+ env="PyQt5",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- (
- None,
- "PyQt5",
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.env
+ SelectWrapperCase(
+ "pyqt6-arg-pyqt6-env",
+ args=argparse.Namespace(qt_wrapper="PyQt6"),
+ env="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- # Both given
- (
- argparse.Namespace(qt_wrapper="PyQt5"),
- "PyQt6",
- machinery.SelectionInfo(
- wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ # Override
+ SelectWrapperCase(
+ "override-only",
+ override="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt6", reason=machinery.SelectionReason.override
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper="PyQt6"),
- "PyQt5",
- machinery.SelectionInfo(
- wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ SelectWrapperCase(
+ "override-arg",
+ args=argparse.Namespace(qt_wrapper="PyQt5"),
+ override="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.cli
+ ),
),
- ),
- (
- argparse.Namespace(qt_wrapper="PyQt6"),
- "PyQt6",
- machinery.SelectionInfo(
- wrapper="PyQt6", reason=machinery.SelectionReason.cli
+ SelectWrapperCase(
+ "override-env",
+ env="PyQt5",
+ override="PyQt6",
+ expected=machinery.SelectionInfo(
+ wrapper="PyQt5", reason=machinery.SelectionReason.env
+ ),
),
- ),
- ],
-)
-def test_select_wrapper(
- args: Optional[argparse.Namespace],
- env: Optional[str],
- expected: machinery.SelectionInfo,
- monkeypatch: pytest.MonkeyPatch,
- undo_init: None,
-):
- if env is None:
- monkeypatch.delenv("QUTE_QT_WRAPPER", raising=False)
- else:
- monkeypatch.setenv("QUTE_QT_WRAPPER", env)
+ ],
+ ids=str,
+ )
+ def test_select(self, tc: SelectWrapperCase, monkeypatch: pytest.MonkeyPatch):
+ if tc.env is None:
+ monkeypatch.delenv("QUTE_QT_WRAPPER", raising=False)
+ else:
+ monkeypatch.setenv("QUTE_QT_WRAPPER", tc.env)
+
+ if tc.override is not None:
+ monkeypatch.setattr(machinery, "_WRAPPER_OVERRIDE", tc.override)
+
+ assert machinery._select_wrapper(tc.args) == tc.expected
+
+ @pytest.mark.parametrize(
+ "args, env",
+ [
+ (None, None),
+ (argparse.Namespace(qt_wrapper=None), None),
+ (argparse.Namespace(qt_wrapper=None), ""),
+ ],
+ )
+ def test_autoselect_by_default(
+ self,
+ args: Optional[argparse.Namespace],
+ env: Optional[str],
+ monkeypatch: pytest.MonkeyPatch,
+ ):
+ """Test that the default behavior is to autoselect a wrapper.
+
+ Autoselection itself is tested further down.
+ """
+ if env is None:
+ monkeypatch.delenv("QUTE_QT_WRAPPER", raising=False)
+ else:
+ monkeypatch.setenv("QUTE_QT_WRAPPER", env)
- assert machinery._select_wrapper(args) == expected
+ assert machinery._select_wrapper(args).reason == machinery.SelectionReason.auto
+ def test_after_qt_import(self, monkeypatch: pytest.MonkeyPatch):
+ monkeypatch.setitem(sys.modules, "PyQt6", None)
+ with pytest.warns(UserWarning, match="PyQt6 already imported"):
+ machinery._select_wrapper(args=None)
-def test_select_wrapper_after_qt_import(monkeypatch: pytest.MonkeyPatch):
- monkeypatch.setitem(sys.modules, "PyQt6", None)
- with pytest.warns(UserWarning, match="PyQt6 already imported"):
- machinery._select_wrapper(args=None)
+ def test_invalid_override(self, monkeypatch: pytest.MonkeyPatch):
+ monkeypatch.setattr(machinery, "_WRAPPER_OVERRIDE", "invalid")
+ with pytest.raises(AssertionError):
+ machinery._select_wrapper(args=None)
class TestInit:
@@ -359,15 +406,34 @@ class TestInit:
):
machinery.init(args=empty_args)
+ @pytest.fixture(params=["auto", "", None])
+ def qt_auto_env(
+ self,
+ request: pytest.FixtureRequest,
+ monkeypatch: pytest.MonkeyPatch,
+ ):
+ """Trigger wrapper autoselection via environment variable.
+
+ Autoselection should be used in three scenarios:
+
+ - The environment variable is set to "auto".
+ - The environment variable is set to an empty string.
+ - The environment variable is not set at all.
+
+ We run test_none_available_*() for all three scenarios.
+ """
+ if request.param is None:
+ monkeypatch.delenv("QUTE_QT_WRAPPER", raising=False)
+ else:
+ monkeypatch.setenv("QUTE_QT_WRAPPER", request.param)
+
def test_none_available_implicit(
self,
stubs: Any,
modules: Dict[str, bool],
monkeypatch: pytest.MonkeyPatch,
- undo_init: None,
+ qt_auto_env: None,
):
- # FIXME:qt6 Also try without this once auto is default
- monkeypatch.setenv("QUTE_QT_WRAPPER", "auto")
stubs.ImportFake(modules, monkeypatch).patch()
message_lines = [
@@ -391,10 +457,8 @@ class TestInit:
modules: Dict[str, bool],
monkeypatch: pytest.MonkeyPatch,
empty_args: argparse.Namespace,
- undo_init: None,
+ qt_auto_env: None,
):
- # FIXME:qt6 Also try without this once auto is default
- monkeypatch.setenv("QUTE_QT_WRAPPER", "auto")
stubs.ImportFake(modules, monkeypatch).patch()
info = machinery.init(args=empty_args)
@@ -403,7 +467,7 @@ class TestInit:
reason=machinery.SelectionReason.auto,
outcomes={
"PyQt6": "ImportError: Fake ImportError for PyQt6.",
- }
+ },
)
@pytest.mark.parametrize(
@@ -422,7 +486,6 @@ class TestInit:
true_vars: str,
explicit: bool,
empty_args: argparse.Namespace,
- undo_init: None,
):
info = machinery.SelectionInfo(
wrapper=selected_wrapper,
diff --git a/tox.ini b/tox.ini
index bf1c6efa2..74eb5213a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,10 +11,10 @@ minversion = 3.20
[testenv]
setenv =
- PYTEST_QT_API=pyqt5
- QUTE_QT_WRAPPER=PyQt5
- pyqt{62,63,64,65}: PYTEST_QT_API=pyqt6
- pyqt{62,63,64,65}: QUTE_QT_WRAPPER=PyQt6
+ PYTEST_QT_API=pyqt6
+ QUTE_QT_WRAPPER=PyQt6
+ pyqt{515,5152}: PYTEST_QT_API=pyqt5
+ pyqt{515,5152}: QUTE_QT_WRAPPER=PyQt5
cov: PYTEST_ADDOPTS=--cov --cov-report xml --cov-report=html --cov-report=
py312: VIRTUALENV_PIP=23.2
py312: PIP_REQUIRE_VIRTUALENV=0
@@ -56,10 +56,10 @@ commands =
{envpython} -bb -m pytest {posargs:tests}
cov: {envpython} scripts/dev/check_coverage.py {posargs}
-[testenv:py-qt6]
+[testenv:py-qt5]
setenv =
- PYTEST_QT_API=pyqt6
- QUTE_QT_WRAPPER=PyQt6
+ PYTEST_QT_API=pyqt5
+ QUTE_QT_WRAPPER=PyQt5
[testenv:bleeding]
basepython = {env:PYTHON:python3}
@@ -112,6 +112,7 @@ deps =
-r{toxinidir}/misc/requirements/requirements-tests.txt
-r{toxinidir}/misc/requirements/requirements-pylint.txt
-r{toxinidir}/misc/requirements/requirements-pyqt.txt
+ -r{toxinidir}/misc/requirements/requirements-pyqt-5.txt
commands =
{envpython} -m pylint scripts qutebrowser --output-format=colorized --reports=no {posargs}
{envpython} scripts/dev/run_pylint_on_tests.py {toxinidir} --output-format=colorized --reports=no {posargs}
@@ -180,19 +181,19 @@ commands =
{envpython} scripts/dev/check_doc_changes.py {posargs}
{envpython} scripts/asciidoc2html.py {posargs}
-[testenv:pyinstaller-{64bit,32bit}{,-qt6}]
+[testenv:pyinstaller-{64bit,32bit}{,-qt5}]
basepython = {env:PYTHON:python3}
passenv =
APPDATA
HOME
PYINSTALLER_DEBUG
setenv =
- qt6: PYINSTALLER_QT6=true
+ qt5: PYINSTALLER_QT5=true
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/misc/requirements/requirements-pyinstaller.txt
- !qt6: -r{toxinidir}/misc/requirements/requirements-pyqt.txt
- qt6: -r{toxinidir}/misc/requirements/requirements-pyqt-6.txt
+ !qt5: -r{toxinidir}/misc/requirements/requirements-pyqt-6.txt
+ qt5: -r{toxinidir}/misc/requirements/requirements-pyqt-5.txt
commands =
{envbindir}/pyinstaller --noconfirm misc/qutebrowser.spec
@@ -246,9 +247,7 @@ commands =
basepython = {env:PYTHON:python3}
passenv = {[testenv:mypy-pyqt6]passenv}
deps = {[testenv:mypy-pyqt6]deps}
-setenv =
- pyqt6: QUTE_CONSTANTS_ARGS=--always-true=USE_PYQT6 --always-false=USE_PYQT5 --always-false=USE_PYSIDE2 --always-false=USE_PYSIDE6 --always-false=IS_QT5 --always-true=IS_QT6
- pyqt5: QUTE_CONSTANTS_ARGS=--always-false=USE_PYQT6 --always-true=USE_PYQT5 --always-false=USE_PYSIDE2 --always-false=USE_PYSIDE6 --always-true=IS_QT5 --always-false=IS_QT6
+setenv = {[testenv:mypy-pyqt6]setenv}
commands =
{envpython} -m mypy --cobertura-xml-report {envtmpdir} {env:QUTE_CONSTANTS_ARGS} qutebrowser tests {posargs}
{envdir}/bin/diff-cover --fail-under=100 --compare-branch={env:DIFF_BRANCH:origin/{env:GITHUB_BASE_REF:master}} {envtmpdir}/cobertura.xml
@@ -264,21 +263,21 @@ deps =
commands =
{envpython} -m sphinx -jauto -W --color {posargs} {toxinidir}/doc/extapi/ {toxinidir}/doc/extapi/_build/
-[testenv:build-release{,-qt6}]
+[testenv:build-release{,-qt5}]
basepython = {env:PYTHON:python3}
passenv = *
-# Override default PyQt5 from [testenv]
+# Override default PyQt6 from [testenv]
setenv =
- qt6: QUTE_QT_WRAPPER=PyQt6
+ qt5: QUTE_QT_WRAPPER=PyQt5
usedevelop = true
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/misc/requirements/requirements-tox.txt
-r{toxinidir}/misc/requirements/requirements-docs.txt
- !qt6: -r{toxinidir}/misc/requirements/requirements-pyqt.txt
- qt6: -r{toxinidir}/misc/requirements/requirements-pyqt-6.txt
+ !qt5: -r{toxinidir}/misc/requirements/requirements-pyqt.txt
+ qt5: -r{toxinidir}/misc/requirements/requirements-pyqt-5.txt
-r{toxinidir}/misc/requirements/requirements-dev.txt
-r{toxinidir}/misc/requirements/requirements-pyinstaller.txt
commands =
- !qt6: {envpython} {toxinidir}/scripts/dev/build_release.py {posargs}
- qt6: {envpython} {toxinidir}/scripts/dev/build_release.py --qt6 {posargs}
+ !qt5: {envpython} {toxinidir}/scripts/dev/build_release.py {posargs}
+ qt5: {envpython} {toxinidir}/scripts/dev/build_release.py --qt5 {posargs}