From f80f454704eb362851ed68e835bd363a35e17892 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 8 Jun 2023 16:38:29 +0200 Subject: keyutils: Work around broken Python 3.11.4 enum.Flag inversion Take a detour via .value if on Qt 6, because Python 3.11.4 seems to be unable to invert enum.Flag values with a mask set. Fixes #7735 See: - https://github.com/python/cpython/issues/105497 - https://www.riverbankcomputing.com/pipermail/pyqt/2023-June/045323.html --- qutebrowser/keyinput/keyutils.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py index 2d3e11864..aecca59a8 100644 --- a/qutebrowser/keyinput/keyutils.py +++ b/qutebrowser/keyinput/keyutils.py @@ -260,7 +260,7 @@ def _modifiers_to_string(modifiers: _ModifierType) -> str: _assert_plain_modifier(modifiers) altgr = Qt.KeyboardModifier.GroupSwitchModifier if modifiers & altgr: - modifiers &= ~altgr # type: ignore[assignment] + modifiers = _unset_modifier_bits(modifiers, altgr) result = 'AltGr+' else: result = '' @@ -341,6 +341,21 @@ def _parse_single_key(keystr: str) -> str: return 'Shift+' + keystr if keystr.isupper() else keystr +def _unset_modifier_bits( + modifiers: _ModifierType, mask: _ModifierType +) -> _ModifierType: + """Unset all bits in modifiers which are given in mask. + + Equivalent to modifiers & ~mask, but with a WORKAROUND with PyQt 6, + for a bug in Python 3.11.4 where that isn't possible with an enum.Flag...: + https://github.com/python/cpython/issues/105497 + """ + if machinery.IS_QT5: + return cast(_ModifierType, modifiers & ~mask) + return Qt.KeyboardModifier( # type: ignore[unreachable] + modifiers.value & ~mask.value) + + @dataclasses.dataclass(frozen=True, order=True) class KeyInfo: @@ -420,7 +435,7 @@ class KeyInfo: if self.key in _MODIFIER_MAP: # Don't return e.g. - modifiers &= ~_MODIFIER_MAP[self.key] # type: ignore[assignment] + modifiers = _unset_modifier_bits(modifiers, _MODIFIER_MAP[self.key]) elif _is_printable(self.key): # "normal" binding if not key_string: # pragma: no cover @@ -487,7 +502,7 @@ class KeyInfo: return QKeyCombination(self.modifiers, key) def with_stripped_modifiers(self, modifiers: Qt.KeyboardModifier) -> "KeyInfo": - mods = self.modifiers & ~modifiers + mods = _unset_modifier_bits(self.modifiers, modifiers) return KeyInfo(key=self.key, modifiers=mods) def is_special(self) -> bool: @@ -670,7 +685,7 @@ class KeySequence: # We always remove Qt.KeyboardModifier.GroupSwitchModifier because QKeySequence has no # way to mention that in a binding anyways... - modifiers &= ~Qt.KeyboardModifier.GroupSwitchModifier + modifiers = _unset_modifier_bits(modifiers, Qt.KeyboardModifier.GroupSwitchModifier) # We change Qt.Key.Key_Backtab to Key_Tab here because nobody would # configure "Shift-Backtab" in their config. @@ -703,10 +718,10 @@ class KeySequence: if modifiers & Qt.KeyboardModifier.ControlModifier and modifiers & Qt.KeyboardModifier.MetaModifier: pass elif modifiers & Qt.KeyboardModifier.ControlModifier: - modifiers &= ~Qt.KeyboardModifier.ControlModifier + modifiers = _unset_modifier_bits(modifiers, Qt.KeyboardModifier.ControlModifier) modifiers |= Qt.KeyboardModifier.MetaModifier elif modifiers & Qt.KeyboardModifier.MetaModifier: - modifiers &= ~Qt.KeyboardModifier.MetaModifier + modifiers = _unset_modifier_bits(modifiers, Qt.KeyboardModifier.MetaModifier) modifiers |= Qt.KeyboardModifier.ControlModifier infos = list(self) -- cgit v1.2.3-54-g00ecf