From 69c21a57512ab4913319341f5f0139aac88515db Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 14 Jun 2023 18:57:23 +0200 Subject: qt: Use outcomes dict instead of attributes for SelectionInfo --- qutebrowser/qt/machinery.py | 28 +++++++++++----------- tests/unit/test_qt_machinery.py | 51 ++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/qutebrowser/qt/machinery.py b/qutebrowser/qt/machinery.py index 27c54f081..e0a5e4cdd 100644 --- a/qutebrowser/qt/machinery.py +++ b/qutebrowser/qt/machinery.py @@ -16,7 +16,7 @@ import html import argparse import importlib import dataclasses -from typing import Optional +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 @@ -86,33 +86,31 @@ class SelectionReason(enum.Enum): class SelectionInfo: """Information about outcomes of importing Qt wrappers.""" - pyqt5: Optional[str] = None - pyqt6: Optional[str] = None wrapper: Optional[str] = None + outcomes: Dict[str, str] = dataclasses.field(default_factory=dict) reason: SelectionReason = SelectionReason.unknown def set_module_error(self, name: str, error: Exception) -> None: """Set the outcome for a module import.""" - setattr(self, name.lower(), f"{type(error).__name__}: {error}") + self.outcomes[name] = f"{type(error).__name__}: {error}" def use_wrapper(self, wrapper: str) -> None: """Set the wrapper to use.""" self.wrapper = wrapper - setattr(self, wrapper.lower(), "success") + self.outcomes[wrapper] = "success" def __str__(self) -> str: - if self.pyqt5 is None and self.pyqt6 is None: - # No autoselect -> shorter output + if not self.outcomes: + # No modules were tried to be imported (no autoselection) + # Thus, we can have a shorter output instead of adding noise. return f"Qt wrapper: {self.wrapper} (via {self.reason.value})" - pyqt6 = self.pyqt6 or "not imported" - pyqt5 = self.pyqt5 or "not imported" - lines = [ - "Qt wrapper info:", - f" PyQt6: {pyqt6}", - f" PyQt5: {pyqt5}", - f" -> selected: {self.wrapper} (via {self.reason.value})" - ] + lines = ["Qt wrapper info:"] + for wrapper in WRAPPERS: + outcome = self.outcomes.get(wrapper, "not imported") + lines.append(f" {wrapper}: {outcome}") + + lines.append(f" -> selected: {self.wrapper} (via {self.reason.value})") return "\n".join(lines) def to_html(self) -> str: diff --git a/tests/unit/test_qt_machinery.py b/tests/unit/test_qt_machinery.py index c49a2850b..d4e6a4736 100644 --- a/tests/unit/test_qt_machinery.py +++ b/tests/unit/test_qt_machinery.py @@ -24,7 +24,7 @@ import sys import html import argparse import typing -from typing import Any, Optional, Dict, Union +from typing import Any, Optional, List, Dict, Union import pytest @@ -76,8 +76,7 @@ def test_selectioninfo_set_module_error(): assert info == machinery.SelectionInfo( wrapper=None, reason=machinery.SelectionReason.unknown, - pyqt5="ImportError: Python imploded", - pyqt6=None, + outcomes={"PyQt5": "ImportError: Python imploded"}, ) @@ -87,8 +86,7 @@ def test_selectioninfo_use_wrapper(): assert info == machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.unknown, - pyqt5=None, - pyqt6="success", + outcomes={"PyQt6": "success"}, ) @@ -113,8 +111,10 @@ def test_selectioninfo_use_wrapper(): machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.auto, - pyqt5="ImportError: Python imploded", - pyqt6="success", + outcomes={ + "PyQt6": "success", + "PyQt5": "ImportError: Python imploded", + }, ), ( "Qt wrapper info:\n" @@ -131,14 +131,16 @@ def test_selectioninfo_str(info: machinery.SelectionInfo, expected: str): assert info.to_html() == html.escape(expected).replace("\n", "
") -def test_selectioninfo_str_wrapper_precedence(): +@pytest.mark.parametrize("order", [["PyQt5", "PyQt6"], ["PyQt6", "PyQt5"]]) +def test_selectioninfo_str_wrapper_precedence(order: List[str]): """The order of the wrappers should be the same as in machinery.WRAPPERS.""" info = machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.auto, - pyqt5="ImportError: Python imploded", - pyqt6="success", ) + for module in order: + info.set_module_error(module, ImportError("Python imploded")) + lines = str(info).splitlines()[1:-1] wrappers = [line.split(":")[0].strip() for line in lines] assert wrappers == machinery.WRAPPERS @@ -161,8 +163,10 @@ def modules(): machinery.SelectionInfo( wrapper=None, reason=machinery.SelectionReason.auto, - pyqt6="ModuleNotFoundError: hiding somewhere", - pyqt5="ModuleNotFoundError: hiding somewhere", + outcomes={ + "PyQt5": "ModuleNotFoundError: hiding somewhere", + "PyQt6": "ModuleNotFoundError: hiding somewhere", + }, ), id="none-available", ), @@ -172,7 +176,9 @@ def modules(): "PyQt6": True, }, machinery.SelectionInfo( - wrapper="PyQt6", reason=machinery.SelectionReason.auto, pyqt6="success" + wrapper="PyQt6", + reason=machinery.SelectionReason.auto, + outcomes={"PyQt6": "success"}, ), id="only-pyqt6", ), @@ -184,8 +190,10 @@ def modules(): machinery.SelectionInfo( wrapper="PyQt5", reason=machinery.SelectionReason.auto, - pyqt6="ModuleNotFoundError: hiding somewhere", - pyqt5="success", + outcomes={ + "PyQt6": "ModuleNotFoundError: hiding somewhere", + "PyQt5": "success", + }, ), id="only-pyqt5", ), @@ -194,8 +202,7 @@ def modules(): machinery.SelectionInfo( wrapper="PyQt6", reason=machinery.SelectionReason.auto, - pyqt6="success", - pyqt5=None, + outcomes={"PyQt6": "success"}, ), id="both", ), @@ -207,8 +214,9 @@ def modules(): machinery.SelectionInfo( wrapper=None, reason=machinery.SelectionReason.auto, - pyqt6="ImportError: Fake ImportError for PyQt6.", - pyqt5=None, + outcomes={ + "PyQt6": "ImportError: Fake ImportError for PyQt6.", + } ), id="import-error", ), @@ -395,8 +403,9 @@ class TestInit: assert info == machinery.SelectionInfo( wrapper=None, reason=machinery.SelectionReason.auto, - pyqt6="ImportError: Fake ImportError for PyQt6.", - pyqt5=None, + outcomes={ + "PyQt6": "ImportError: Fake ImportError for PyQt6.", + } ) @pytest.mark.parametrize( -- cgit v1.2.3-54-g00ecf