From 2ccd49ddf1bfa743271ad4700a2a2e9f57ea1ae5 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 23 Jun 2023 23:51:34 +0200 Subject: qt: Introduce _WRAPPER_OVERRIDE for packagers --- qutebrowser/qt/machinery.py | 15 +++-- tests/unit/test_qt_machinery.py | 130 +++++++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 48 deletions(-) diff --git a/qutebrowser/qt/machinery.py b/qutebrowser/qt/machinery.py index a5705a933..1269da4c1 100644 --- a/qutebrowser/qt/machinery.py +++ b/qutebrowser/qt/machinery.py @@ -18,11 +18,11 @@ import importlib import dataclasses from typing import Optional, Dict -# 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", @@ -78,6 +78,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" @@ -174,8 +177,10 @@ def _select_wrapper(args: Optional[argparse.Namespace]) -> SelectionInfo: ) return SelectionInfo(wrapper=env_wrapper, reason=SelectionReason.env) - # FIXME:qt6 Make sure to still consider _DEFAULT_WRAPPER for packagers - # (rename to _WRAPPER_OVERRIDE since our sed command is broken anyways then?) + if _WRAPPER_OVERRIDE is not None: + assert _WRAPPER_OVERRIDE in WRAPPERS, _WRAPPER_OVERRIDE + return SelectionInfo(wrapper=_WRAPPER_OVERRIDE, reason=SelectionReason.override) + return _autoselect_wrapper() diff --git a/tests/unit/test_qt_machinery.py b/tests/unit/test_qt_machinery.py index 40631accc..b144af030 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 @@ -230,84 +231,122 @@ def test_autoselect( assert machinery._autoselect_wrapper() == expected +@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( - "args, env, expected", + "tc", [ # Only argument given - ( - argparse.Namespace(qt_wrapper="PyQt6"), - None, - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt6-arg", + args=argparse.Namespace(qt_wrapper="PyQt6"), + expected=machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.cli ), ), - ( - argparse.Namespace(qt_wrapper="PyQt5"), - None, - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt5-arg", + args=argparse.Namespace(qt_wrapper="PyQt5"), + expected=machinery.SelectionInfo( wrapper="PyQt5", reason=machinery.SelectionReason.cli ), ), - ( - argparse.Namespace(qt_wrapper="PyQt5"), - "", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt6-arg-empty-env", + args=argparse.Namespace(qt_wrapper="PyQt5"), + env="", + expected=machinery.SelectionInfo( wrapper="PyQt5", reason=machinery.SelectionReason.cli ), ), # Only environment variable given - ( - None, - "PyQt6", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt6-env", + env="PyQt6", + expected=machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.env ), ), - ( - None, - "PyQt5", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt5-env", + env="PyQt5", + expected=machinery.SelectionInfo( wrapper="PyQt5", reason=machinery.SelectionReason.env ), ), # Both given - ( - argparse.Namespace(qt_wrapper="PyQt5"), - "PyQt6", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt5-arg-pyqt6-env", + args=argparse.Namespace(qt_wrapper="PyQt5"), + env="PyQt6", + expected=machinery.SelectionInfo( wrapper="PyQt5", reason=machinery.SelectionReason.cli ), ), - ( - argparse.Namespace(qt_wrapper="PyQt6"), - "PyQt5", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt6-arg-pyqt5-env", + args=argparse.Namespace(qt_wrapper="PyQt6"), + env="PyQt5", + expected=machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.cli ), ), - ( - argparse.Namespace(qt_wrapper="PyQt6"), - "PyQt6", - machinery.SelectionInfo( + SelectWrapperCase( + "pyqt6-arg-pyqt6-env", + args=argparse.Namespace(qt_wrapper="PyQt6"), + env="PyQt6", + expected=machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.cli ), ), + # Override + SelectWrapperCase( + "override-only", + override="PyQt6", + expected=machinery.SelectionInfo( + wrapper="PyQt6", reason=machinery.SelectionReason.override + ), + ), + SelectWrapperCase( + "override-arg", + args=argparse.Namespace(qt_wrapper="PyQt5"), + override="PyQt6", + expected=machinery.SelectionInfo( + wrapper="PyQt5", reason=machinery.SelectionReason.cli + ), + ), + SelectWrapperCase( + "override-env", + env="PyQt5", + override="PyQt6", + expected=machinery.SelectionInfo( + wrapper="PyQt5", reason=machinery.SelectionReason.env + ), + ), ], + ids=str, ) - def test_select( - self, - args: Optional[argparse.Namespace], - env: Optional[str], - expected: machinery.SelectionInfo, - monkeypatch: pytest.MonkeyPatch, - ): - if env is None: + 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", env) + monkeypatch.setenv("QUTE_QT_WRAPPER", tc.env) - assert machinery._select_wrapper(args) == expected + 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", @@ -339,6 +378,11 @@ class TestSelectWrapper: 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, match="invalid"): + machinery._select_wrapper(args=None) + class TestInit: @pytest.fixture -- cgit v1.2.3-54-g00ecf