From edf59c2bb2a3dad36115af7518cdcbb3ee397089 Mon Sep 17 00:00:00 2001 From: Ben Nguyen <105088397+bpnguyen107@users.noreply.github.com> Date: Wed, 13 Nov 2024 01:06:55 -0800 Subject: [PATCH] Enable strict_optional for aqt/deckchooser, about, webview (#3573) * Enable strict_optional for deckchooser * Fix mypy errors * Enable strict_optional for about * Fix mypy errors * Enable strict_optional for webview * Fix mypy errors * Fix merge error * Revert utils * Add early returns --------- Co-authored-by: Abdo --- .mypy.ini | 6 ++++++ qt/aqt/about.py | 13 ++++++++--- qt/aqt/deckchooser.py | 4 +++- qt/aqt/webview.py | 50 +++++++++++++++++++++++++++++++------------ 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/.mypy.ini b/.mypy.ini index 729186b0a..e34bccf45 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -92,6 +92,12 @@ strict_optional = True strict_optional = True [mypy-aqt.toolbar] strict_optional = True +[mypy-aqt.deckchooser] +strict_optional = True +[mypy-aqt.about] +strict_optional = True +[mypy-aqt.webview] +strict_optional = True [mypy-anki.scheduler.base] strict_optional = True [mypy-anki._backend.rsbridge] diff --git a/qt/aqt/about.py b/qt/aqt/about.py index cf0173592..bf1ff41f8 100644 --- a/qt/aqt/about.py +++ b/qt/aqt/about.py @@ -37,14 +37,21 @@ def show(mw: aqt.AnkiQt) -> QDialog: txt = supportText() if mw.addonManager.dirty: txt += "\n" + addon_debug_info() - QApplication.clipboard().setText(txt) + clipboard = QApplication.clipboard() + assert clipboard is not None + clipboard.setText(txt) tooltip(tr.about_copied_to_clipboard(), parent=dialog) btn = QPushButton(tr.about_copy_debug_info()) qconnect(btn.clicked, on_copy) abt.buttonBox.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole) - abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setFocus() + + ok_button = abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok) + assert ok_button is not None + ok_button.setFocus() + btnLayout = abt.buttonBox.layout() + assert btnLayout is not None btnLayout.setContentsMargins(12, 12, 12, 12) # WebView cleanup @@ -52,7 +59,7 @@ def show(mw: aqt.AnkiQt) -> QDialog: def on_dialog_destroyed() -> None: abt.label.cleanup() - abt.label = None + abt.label = None # type: ignore qconnect(dialog.destroyed, on_dialog_destroyed) diff --git a/qt/aqt/deckchooser.py b/qt/aqt/deckchooser.py index 72894ed82..c25fcad1e 100644 --- a/qt/aqt/deckchooser.py +++ b/qt/aqt/deckchooser.py @@ -99,7 +99,9 @@ class DeckChooser(QHBoxLayout): def callback(ret: StudyDeck) -> None: if not ret.name: return - new_selected_deck_id = self.mw.col.decks.by_name(ret.name)["id"] + deck = self.mw.col.decks.by_name(ret.name) + assert deck is not None + new_selected_deck_id = deck["id"] if self.selected_deck_id != new_selected_deck_id: self.selected_deck_id = new_selected_deck_id if func := self.on_deck_changed: diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py index 065d5956e..aac3fb1b6 100644 --- a/qt/aqt/webview.py +++ b/qt/aqt/webview.py @@ -89,17 +89,23 @@ class AnkiWebPage(QWebEnginePage): script.setWorldId(QWebEngineScript.ScriptWorldId.MainWorld) script.setInjectionPoint(QWebEngineScript.InjectionPoint.DocumentReady) script.setRunsOnSubFrames(False) - self.profile().scripts().insert(script) + + profile = self.profile() + assert profile is not None + scripts = profile.scripts() + assert scripts is not None + scripts.insert(script) def javaScriptConsoleMessage( self, level: QWebEnginePage.JavaScriptConsoleMessageLevel, - msg: str, + msg: str | None, line: int, - srcID: str, + srcID: str | None, ) -> None: # not translated because console usually not visible, # and may only accept ascii text + assert srcID is not None if srcID.startswith("data"): srcID = "" else: @@ -162,10 +168,16 @@ class AnkiWebPage(QWebEnginePage): def _onCmd(self, str: str) -> Any: return self._onBridgeCmd(str) - def javaScriptAlert(self, frame: Any, text: str) -> None: + def javaScriptAlert(self, frame: Any, text: str | None) -> None: + if text is None: + return + showInfo(text) - def javaScriptConfirm(self, frame: Any, text: str) -> bool: + def javaScriptConfirm(self, frame: Any, text: str | None) -> bool: + if text is None: + return False + return askUser(text) @@ -328,7 +340,9 @@ class AnkiWebView(QWebEngineView): # with target="_blank") and return view return AnkiWebView() - def eventFilter(self, obj: QObject, evt: QEvent) -> bool: + def eventFilter(self, obj: QObject | None, evt: QEvent | None) -> bool: + if evt is None: + return False if self._disable_zoom and is_gesture_or_zoom_event(evt): return True @@ -377,7 +391,7 @@ class AnkiWebView(QWebEngineView): def onSelectAll(self) -> None: self.triggerPageAction(QWebEnginePage.WebAction.SelectAll) - def contextMenuEvent(self, evt: QContextMenuEvent) -> None: + def contextMenuEvent(self, evt: QContextMenuEvent | None) -> None: m = QMenu(self) self._maybe_add_copy_action(m) gui_hooks.webview_will_show_context_menu(self, m) @@ -387,9 +401,10 @@ class AnkiWebView(QWebEngineView): def _maybe_add_copy_action(self, menu: QMenu) -> None: if self.hasSelection(): a = menu.addAction(tr.actions_copy()) + assert a is not None qconnect(a.triggered, self.onCopy) - def dropEvent(self, evt: QDropEvent) -> None: + def dropEvent(self, evt: QDropEvent | None) -> None: if self.allow_drops: super().dropEvent(evt) @@ -455,7 +470,9 @@ class AnkiWebView(QWebEngineView): return 1 def setPlaybackRequiresGesture(self, value: bool) -> None: - self.settings().setAttribute( + settings = self.settings() + assert settings is not None + settings.setAttribute( QWebEngineSettings.WebAttribute.PlaybackRequiresUserGesture, value ) @@ -632,10 +649,13 @@ html {{ {font} }} def eval(self, js: str) -> None: self.evalWithCallback(js, None) - def evalWithCallback(self, js: str, cb: Callable) -> None: + def evalWithCallback(self, js: str, cb: Callable | None) -> None: self._queueAction("eval", js, cb) - def _evalWithCallback(self, js: str, cb: Callable[[Any], Any]) -> None: + def _evalWithCallback(self, js: str, cb: Callable[[Any], Any] | None) -> None: + page = self.page() + assert page is not None + if cb: def handler(val: Any) -> None: @@ -644,9 +664,9 @@ html {{ {font} }} return cb(val) - self.page().runJavaScript(js, handler) + page.runJavaScript(js, handler) else: - self.page().runJavaScript(js) + page.runJavaScript(js) def _queueAction(self, name: str, *args: Any) -> None: self._pendingActions.append((name, args)) @@ -685,7 +705,9 @@ html {{ {font} }} return if not self._filterSet: - self.focusProxy().installEventFilter(self) + focus_proxy = self.focusProxy() + assert focus_proxy is not None + focus_proxy.installEventFilter(self) self._filterSet = True if cmd == "domDone":