Update type annotations to use | operator (#3323)

* refactor: update to `|` operator

* refactor: add missing type hint

* refactor: enable `|` operator for older versions

* refactor: remove obsolete import
This commit is contained in:
David Culley 2024-07-26 13:15:39 +02:00 committed by GitHub
parent f0933cf06c
commit 0743e6e40e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 36 additions and 30 deletions

View file

@ -2,10 +2,11 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
# pylint: disable=invalid-name
from __future__ import annotations
import os
import unicodedata
from typing import Any, Optional
from typing import Any
from anki.cards import CardId
from anki.collection import Collection
@ -31,7 +32,7 @@ class MediaMapInvalid(Exception):
class Anki2Importer(Importer):
needMapper = False
deckPrefix: Optional[str] = None
deckPrefix: str | None = None
allowUpdate = True
src: Collection
dst: Collection
@ -409,7 +410,7 @@ insert or ignore into revlog values (?,?,?,?,?,?,?,?,?)""",
if fname.startswith("_") and not self.dst.media.have(fname):
self._writeDstMedia(fname, self._srcMediaData(fname))
def _mediaData(self, fname: str, dir: Optional[str] = None) -> bytes:
def _mediaData(self, fname: str, dir: str | None = None) -> bytes:
if not dir:
dir = self.src.media.dir()
path = os.path.join(dir, fname)

View file

@ -2,12 +2,13 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
# pylint: disable=invalid-name
from __future__ import annotations
import json
import os
import unicodedata
import zipfile
from typing import Any, Optional
from typing import Any
from anki.importing.anki2 import Anki2Importer, MediaMapInvalid
from anki.utils import tmpfile
@ -15,7 +16,7 @@ from anki.utils import tmpfile
class AnkiPackageImporter(Anki2Importer):
nameToNum: dict[str, str]
zip: Optional[zipfile.ZipFile]
zip: zipfile.ZipFile | None
def run(self) -> None: # type: ignore
# extract the deck from the zip file

View file

@ -2,8 +2,9 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
# pylint: disable=invalid-name
from __future__ import annotations
from typing import Any, Optional
from typing import Any
from anki.collection import Collection
from anki.utils import max_id
@ -15,7 +16,7 @@ from anki.utils import max_id
class Importer:
needMapper = False
needDelimiter = False
dst: Optional[Collection]
dst: Collection | None
def __init__(self, col: Collection, file: str) -> None:
self.file = file

View file

@ -3,13 +3,13 @@
# pytype: disable=attribute-error
# type: ignore
# pylint: disable=C
from __future__ import annotations
import re
import sys
import time
import unicodedata
from string import capwords
from typing import Optional, Union
from xml.dom import minidom
from xml.dom.minidom import Element, Text
@ -329,7 +329,7 @@ class SupermemoXmlImporter(NoteImporter):
self.logger("Load done.")
# PARSE
def parse(self, node: Optional[Union[Text, Element]] = None) -> None:
def parse(self, node: Text | Element | None = None) -> None:
"Parse method - parses document elements"
if node is None and self.xmldoc is not None:

View file

@ -5,12 +5,13 @@
Code for generating hooks.
"""
from __future__ import annotations
import os
import subprocess
import sys
from dataclasses import dataclass
from operator import attrgetter
from typing import Optional
sys.path.append("pylib/anki/_vendor")
@ -23,19 +24,19 @@ class Hook:
name: str
# string of the typed arguments passed to the callback, eg
# ["kind: str", "val: int"]
args: list[str] = None
args: list[str] | None = None
# string of the return type. if set, hook is a filter.
return_type: Optional[str] = None
return_type: str | None = None
# if add-ons may be relying on the legacy hook name, add it here
legacy_hook: Optional[str] = None
legacy_hook: str | None = None
# if legacy hook takes no arguments but the new hook does, set this
legacy_no_args: bool = False
# if the hook replaces a deprecated one, add its name here
replaces: Optional[str] = None
replaces: str | None = None
# arguments that the hook being replaced took
replaced_hook_args: Optional[list[str]] = None
replaced_hook_args: list[str] | None = None
# docstring to add to hook class
doc: Optional[str] = None
doc: str | None = None
def callable(self) -> str:
"Convert args into a Callable."
@ -47,7 +48,7 @@ class Hook:
types_str = ", ".join(types)
return f"Callable[[{types_str}], {self.return_type or 'None'}]"
def arg_names(self, args: Optional[list[str]]) -> list[str]:
def arg_names(self, args: list[str] | None) -> list[str]:
names = []
for arg in args or []:
if not arg:

View file

@ -1,7 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from collections.abc import Callable
from typing import Optional
import aqt.editor
from anki.collection import OpChanges
@ -38,7 +39,7 @@ class EditCurrent(QMainWindow):
self.show()
def on_operation_did_execute(
self, changes: OpChanges, handler: Optional[object]
self, changes: OpChanges, handler: object | None
) -> None:
if changes.note_text and handler is not self.editor:
# reload note

View file

@ -1,12 +1,14 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import os
import re
import traceback
import zipfile
from collections.abc import Callable
from concurrent.futures import Future
from typing import Any, Optional
from typing import Any
import anki.importing as importing
import aqt.deckchooser
@ -55,7 +57,7 @@ class ChangeMap(QDialog):
self.frm.fields.setCurrentRow(n)
else:
self.frm.fields.setCurrentRow(n + 1)
self.field: Optional[str] = None
self.field: str | None = None
def getField(self) -> str:
self.exec()
@ -231,13 +233,13 @@ class ImportDialog(QDialog):
self.frm.mappingArea.setWidget(self.frame)
self.mapbox = QVBoxLayout(self.frame)
self.mapbox.setContentsMargins(0, 0, 0, 0)
self.mapwidget: Optional[QWidget] = None
self.mapwidget: QWidget | None = None
def hideMapping(self) -> None:
self.frm.mappingGroup.hide()
def showMapping(
self, keepMapping: bool = False, hook: Optional[Callable] = None
self, keepMapping: bool = False, hook: Callable | None = None
) -> None:
if hook:
hook()

View file

@ -1,8 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from collections.abc import Callable
from typing import Optional
from aqt import AnkiQt, gui_hooks
from aqt.qt import *
@ -17,7 +17,7 @@ class ModelChooser(QHBoxLayout):
mw: AnkiQt,
widget: QWidget,
label: bool = True,
on_activated: Optional[Callable[[], None]] = None,
on_activated: Callable[[], None] | None = None,
) -> None:
"""If provided, on_activated() will be called when the button is clicked,
and the caller can call .onModelChange() to pull up the dialog when they

View file

@ -25,6 +25,7 @@
# ------------------------------------------------------------------------------
# pylint: disable=raise-missing-from
from __future__ import annotations
import inspect
import json
@ -38,7 +39,6 @@ import threading
import time
from queue import Empty, Full, Queue
from shutil import which
from typing import Optional
from anki.utils import is_win
@ -77,7 +77,7 @@ class MPVBase:
"""
executable = which("mpv")
popenEnv: Optional[dict[str, str]] = None
popenEnv: dict[str, str] | None = None
default_argv = [
"--idle",

View file

@ -3,6 +3,7 @@
# make sure not to optimize imports on this file
# pylint: disable=unused-import
from __future__ import annotations
import os
import sys
@ -55,9 +56,7 @@ if qtmajor < 5 or (qtmajor == 5 and qtminor < 14):
raise Exception("Anki does not support your Qt version.")
def qconnect(
signal: Union[Callable, pyqtSignal, pyqtBoundSignal], func: Callable
) -> None:
def qconnect(signal: Callable | pyqtSignal | pyqtBoundSignal, func: Callable) -> None:
"""Helper to work around type checking not working with signal.connect(func)."""
signal.connect(func) # type: ignore