diff options
author | Florian Bruhin <me@the-compiler.org> | 2023-06-08 16:38:29 +0200 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2023-06-08 16:47:26 +0200 |
commit | f80f454704eb362851ed68e835bd363a35e17892 (patch) | |
tree | f09bc941c3c69f1d98ef5f06f9b8578f8eedc269 | |
parent | 65c14730e3608fa48ac5a3fbfec49ffb99e7f4af (diff) | |
download | qutebrowser-f80f454704eb362851ed68e835bd363a35e17892.tar.gz qutebrowser-f80f454704eb362851ed68e835bd363a35e17892.zip |
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
-rw-r--r-- | qutebrowser/keyinput/keyutils.py | 27 |
1 files 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. <Shift+Shift> - 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) |