miscellaneous pyqt6 compat fixes

- add a few gates for qt5-specific behaviour
- prepare for some changes to the typings in qt6
- map pickled Qt5 ByteArrays to Qt6 when running Qt6
This commit is contained in:
Damien Elmes 2021-10-07 15:36:50 +10:00
parent 4d0a915610
commit dfcefaebe3
9 changed files with 44 additions and 29 deletions

View File

@ -372,8 +372,6 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
category = "debug"
elif category == QtFatalMsg:
category = "fatal"
elif category == QtSystemMsg:
category = "system"
else:
category = "unknown"
context = ""

View File

@ -1032,7 +1032,7 @@ title="{}" {}>{}</button>""".format(
def clearStateShortcuts(self) -> None:
for qs in self.stateShortcuts:
sip.delete(qs)
sip.delete(qs) # type: ignore
self.stateShortcuts = []
def onStudyKey(self) -> None:

View File

@ -163,25 +163,32 @@ class ProfileManager:
def _unpickle(self, data: bytes) -> Any:
class Unpickler(pickle.Unpickler):
def find_class(self, module: str, name: str) -> Any:
if module == "PyQt5.sip":
try:
import PyQt5.sip # pylint: disable=unused-import
except:
# use old sip location
module = "sip"
fn = super().find_class(module, name)
if module == "sip" and name == "_unpickle_type":
def find_class(self, class_module: str, name: str) -> Any:
# handle sip lookup ourselves, mapping to current Qt version
if class_module == "sip" or class_module.endswith(".sip"):
def wrapper(mod, obj, args) -> Any: # type: ignore
if mod.startswith("PyQt4") and obj == "QByteArray":
# can't trust str objects from python 2
return QByteArray()
return fn(mod, obj, args)
def unpickle_type(module: str, klass: str, args: Any) -> Any:
if qtmajor > 5:
module = module.replace("Qt5", "Qt6")
else:
module = module.replace("Qt6", "Qt5")
if klass == "QByteArray":
if module.startswith("PyQt4"):
# can't trust str objects from python 2
return QByteArray()
else:
# return the bytes directly
return args[0]
elif name == "_unpickle_enum":
if qtmajor == 5:
return sip._unpickle_enum(module, klass, args) # type: ignore
else:
# old style enums can't be unpickled
return None
else:
return sip._unpickle_type(module, klass, args) # type: ignore
return wrapper
else:
return fn
return unpickle_type
up = Unpickler(io.BytesIO(data), errors="ignore")
return up.load()

View File

@ -57,6 +57,9 @@ if qtmajor < 5 or (qtmajor == 5 and qtminor < 14):
raise Exception("Anki does not support your Qt version.")
def qconnect(signal: Union[Callable, pyqtSignal], func: Callable) -> None:
"Helper to work around type checking not working with signal.connect(func)."
def qconnect(
signal: Union[Callable, pyqtSignal, pyqtBoundSignal], func: Callable
) -> None:
"""Helper to work around type checking not working with signal.connect(func).
Not needed in PyQt6"""
signal.connect(func) # type: ignore

View File

@ -23,7 +23,11 @@ class QtAudioInputRecorder(Recorder):
self.mw = mw
self._parent = parent
from PyQt5.QtMultimedia import QAudioDeviceInfo, QAudioFormat, QAudioInput
from PyQt5.QtMultimedia import ( # type: ignore
QAudioDeviceInfo,
QAudioFormat,
QAudioInput,
)
format = QAudioFormat()
format.setChannelCount(1)

View File

@ -1,5 +1,6 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from typing import cast
from aqt import colors
from aqt.qt import *
@ -128,7 +129,7 @@ class Switch(QAbstractButton):
self._animate_toggle()
def _animate_toggle(self) -> None:
animation = QPropertyAnimation(self, b"position", self)
animation = QPropertyAnimation(self, cast(QByteArray, b"position"), self)
animation.setDuration(100)
animation.setStartValue(self.start_position)
animation.setEndValue(self.end_position)

View File

@ -99,7 +99,7 @@ class TagEdit(QLineEdit):
self._completer.popup().hide()
def hideCompleter(self) -> None:
if sip.isdeleted(self._completer):
if sip.isdeleted(self._completer): # type: ignore
return
self._completer.popup().hide()

View File

@ -866,6 +866,8 @@ Add-ons, last update check: {}
# adapted from version detection in qutebrowser
def opengl_vendor() -> str | None:
if qtmajor != 5:
return "unknown"
old_context = QOpenGLContext.currentContext()
old_surface = None if old_context is None else old_context.surface()
@ -886,11 +888,11 @@ def opengl_vendor() -> str | None:
# Can't use versionFunctions there
return None
vp = QOpenGLVersionProfile()
vp = QOpenGLVersionProfile() # type: ignore
vp.setVersion(2, 0)
try:
vf = ctx.versionFunctions(vp)
vf = ctx.versionFunctions(vp) # type: ignore
except ImportError as e:
return None

View File

@ -350,9 +350,9 @@ class AnkiWebView(QWebEngineView):
if webscale:
return float(webscale)
if isMac:
if qtmajor > 5 or isMac:
return 1
screen = QApplication.desktop().screen()
screen = QApplication.desktop().screen() # type: ignore
if screen is None:
return 1