Update type annotation syntax (#3283)

* chore: add myself to CONTRIBUTORS file

* refactor: use newer type hints for Union/Optional

* refactor: fix deprecated type annotations

use collections.abc rather than typing

* refactor: use lower letter type annotations

* style: reformat with black

* refactor: remove unused imports

* refactor: add missing imports for type hints

* fixup! refactor: use newer type hints for Union/Optional

* fix: add missing imports for type annotations

* fixup! refactor: use newer type hints for Union/Optional

* fixup! style: reformat with black

* refactor: fix remaining imports re: type hints
This commit is contained in:
David Culley 2024-07-21 09:00:52 +02:00 committed by GitHub
parent 412e67db3e
commit 63afb0f8c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 171 additions and 134 deletions

View file

@ -6,8 +6,9 @@ from __future__ import annotations
import sys
import time
import traceback
from collections.abc import Iterable, Sequence
from threading import current_thread, main_thread
from typing import TYPE_CHECKING, Any, Iterable, Sequence
from typing import TYPE_CHECKING, Any
from weakref import ref
from markdown import markdown

View file

@ -3,7 +3,8 @@
from __future__ import annotations
from typing import Any, Generator, Iterable, Literal, Sequence, Union, cast
from collections.abc import Generator, Iterable, Sequence
from typing import Any, Literal, Union, cast
from anki import (
ankiweb_pb2,

View file

@ -4,8 +4,9 @@
from __future__ import annotations
import re
from collections.abc import Iterable, Sequence
from re import Match
from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence, Union
from typing import TYPE_CHECKING, Any, Callable, Union
if TYPE_CHECKING:
import anki._backend

View file

@ -4,7 +4,8 @@
from __future__ import annotations
import copy
from typing import TYPE_CHECKING, Any, Iterable, NewType, Sequence
from collections.abc import Iterable, Sequence
from typing import TYPE_CHECKING, Any, NewType
if TYPE_CHECKING:
import anki

View file

@ -13,8 +13,9 @@ import threading
import time
import unicodedata
import zipfile
from collections.abc import Sequence
from io import BufferedWriter
from typing import Any, Optional, Sequence
from typing import Any
from zipfile import ZipFile
from anki import hooks
@ -26,16 +27,16 @@ from anki.utils import ids2str, namedtmp, split_fields, strip_html
class Exporter:
includeHTML: bool | None = None
ext: Optional[str] = None
includeTags: Optional[bool] = None
includeSched: Optional[bool] = None
includeMedia: Optional[bool] = None
ext: str | None = None
includeTags: bool | None = None
includeSched: bool | None = None
includeMedia: bool | None = None
def __init__(
self,
col: Collection,
did: Optional[DeckId] = None,
cids: Optional[list[CardId]] = None,
did: DeckId | None = None,
cids: list[CardId] | None = None,
) -> None:
self.col = col.weakref()
self.did = did

View file

@ -94,8 +94,8 @@ class ForeignCard:
class ForeignNote:
fields: list[str] = field(default_factory=list)
tags: list[str] = field(default_factory=list)
notetype: Union[str, NotetypeId] = ""
deck: Union[str, DeckId] = ""
notetype: str | NotetypeId = ""
deck: str | DeckId = ""
cards: list[ForeignCard] = field(default_factory=list)
@ -103,7 +103,7 @@ class ForeignNote:
class ForeignData:
notes: list[ForeignNote] = field(default_factory=list)
notetypes: list[ForeignNotetype] = field(default_factory=list)
default_deck: Union[str, DeckId] = ""
default_deck: str | DeckId = ""
def serialize(self) -> str:
return json.dumps(self, cls=ForeignDataEncoder, separators=(",", ":"))

View file

@ -17,7 +17,6 @@ Notetype | Card Type
import re
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Tuple, Type
from anki.db import DB
from anki.decks import DeckId
@ -38,7 +37,7 @@ def serialize(db_path: str, deck_id: DeckId) -> str:
def gather_data(db: DB, deck_id: DeckId) -> ForeignData:
facts = gather_facts(db)
gather_cards_into_facts(db, facts)
used_fact_views: dict[Type[MnemoFactView], bool] = {}
used_fact_views: dict[type[MnemoFactView], bool] = {}
notes = [fact.foreign_note(used_fact_views) for fact in facts.values()]
notetypes = [fact_view.foreign_notetype() for fact_view in used_fact_views]
return ForeignData(notes, notetypes, deck_id)
@ -54,7 +53,7 @@ def open_mnemosyne_db(db_path: str) -> DB:
class MnemoFactView(ABC):
notetype: str
field_keys: Tuple[str, ...]
field_keys: tuple[str, ...]
@classmethod
@abstractmethod
@ -162,7 +161,7 @@ class MnemoFact:
cards: list[MnemoCard] = field(default_factory=list)
def foreign_note(
self, used_fact_views: dict[Type[MnemoFactView], bool]
self, used_fact_views: dict[type[MnemoFactView], bool]
) -> ForeignNote:
fact_view = self.fact_view()
used_fact_views[fact_view] = True
@ -173,7 +172,7 @@ class MnemoFact:
cards=self.foreign_cards(),
)
def fact_view(self) -> Type[MnemoFactView]:
def fact_view(self) -> type[MnemoFactView]:
try:
fact_view = self.cards[0].fact_view_id
except IndexError as err:
@ -190,7 +189,7 @@ class MnemoFact:
raise Exception(f"Fact {id} has unknown fact view: {fact_view}")
def anki_fields(self, fact_view: Type[MnemoFactView]) -> list[str]:
def anki_fields(self, fact_view: type[MnemoFactView]) -> list[str]:
return [munge_field(self.fields.get(k, "")) for k in fact_view.field_keys]
def anki_tags(self) -> list[str]:

View file

@ -14,6 +14,9 @@ modifying it.
from __future__ import annotations
from collections.abc import Callable
from typing import Any
import decorator
# You can find the definitions in ../tools/genhooks.py

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 typing import Any, Callable, Sequence, Type, Union
from collections.abc import Sequence
from typing import Any, Callable, Type, Union
import anki
from anki.collection import Collection

View file

@ -5,7 +5,7 @@
import os
import unicodedata
from typing import Optional
from typing import Any, Optional
from anki.cards import CardId
from anki.collection import Collection

View file

@ -7,7 +7,7 @@ from __future__ import annotations
import csv
import re
from typing import Any, Optional, TextIO
from typing import Any, TextIO
from anki.collection import Collection
from anki.importing.noteimp import ForeignNote, NoteImporter
@ -20,12 +20,12 @@ class TextImporter(NoteImporter):
def __init__(self, col: Collection, file: str) -> None:
NoteImporter.__init__(self, col, file)
self.lines = None
self.fileobj: Optional[TextIO] = None
self.delimiter: Optional[str] = None
self.fileobj: TextIO | None = None
self.delimiter: str | None = None
self.tagsToAdd: list[str] = []
self.numFields = 0
self.dialect: Optional[Any]
self.data: Optional[str | list[str]]
self.dialect: Any | None
self.data: str | list[str] | None
def foreignNotes(self) -> list[ForeignNote]:
self.open()

View file

@ -7,7 +7,7 @@ from __future__ import annotations
import html
import unicodedata
from typing import Optional, Union
from typing import Union
from anki.collection import Collection
from anki.config import Config
@ -76,8 +76,8 @@ class NoteImporter(Importer):
needDelimiter = False
allowHTML = False
importMode = UPDATE_MODE
mapping: Optional[list[str]]
tagModified: Optional[str]
mapping: list[str] | None
tagModified: str | None
def __init__(self, col: Collection, file: str) -> None:
Importer.__init__(self, col, file)
@ -268,7 +268,7 @@ class NoteImporter(Importer):
def updateData(
self, n: ForeignNote, id: NoteId, sflds: list[str]
) -> Optional[Updates]:
) -> Updates | None:
self._ids.append(id)
self.processFields(n, sflds)
if self._tagsMapped:
@ -316,9 +316,7 @@ where id = ? and flds != ?""",
changes2 = self.col.db.scalar("select total_changes()")
self.updateCount = changes2 - changes
def processFields(
self, note: ForeignNote, fields: Optional[list[str]] = None
) -> None:
def processFields(self, note: ForeignNote, fields: list[str] | None = None) -> None:
if not fields:
fields = [""] * len(self.model["flds"])
for c, f in enumerate(self.mapping):

View file

@ -8,7 +8,8 @@ import pprint
import re
import sys
import time
from typing import Callable, Sequence
from collections.abc import Sequence
from typing import Callable
from anki import media_pb2
from anki._legacy import DeprecatedNamesMixin, deprecated_keywords

View file

@ -7,7 +7,8 @@ import copy
import pprint
import sys
import time
from typing import Any, NewType, Sequence, Union
from collections.abc import Sequence
from typing import Any, NewType, Union
import anki # pylint: disable=unused-import
import anki.collection

View file

@ -4,7 +4,8 @@
from __future__ import annotations
import copy
from typing import NewType, Sequence
from collections.abc import Sequence
from typing import NewType
import anki # pylint: disable=unused-import
import anki.cards

View file

@ -22,7 +22,8 @@ ScheduleCardsAsNewDefaults = scheduler_pb2.ScheduleCardsAsNewDefaultsResponse
FilteredDeckForUpdate = decks_pb2.FilteredDeckForUpdate
RepositionDefaults = scheduler_pb2.RepositionDefaultsResponse
from typing import Sequence, overload
from collections.abc import Sequence
from typing import overload
from anki import config_pb2
from anki.cards import CardId

View file

@ -5,8 +5,6 @@
from __future__ import annotations
from typing import Optional
from anki._legacy import deprecated
from anki.cards import Card, CardId
from anki.consts import (
@ -54,7 +52,7 @@ class SchedulerBaseWithLegacy(SchedulerBase):
print("_nextDueMsg() is obsolete")
return ""
def rebuildDyn(self, did: Optional[DeckId] = None) -> Optional[int]:
def rebuildDyn(self, did: DeckId | None = None) -> int | None:
did = did or self.col.decks.selected()
count = self.rebuild_filtered_deck(did).count or None
if not count:
@ -63,7 +61,7 @@ class SchedulerBaseWithLegacy(SchedulerBase):
self.col.decks.select(did)
return count
def emptyDyn(self, did: Optional[DeckId], lim: Optional[str] = None) -> None:
def emptyDyn(self, did: DeckId | None, lim: str | None = None) -> None:
if lim is None:
self.empty_filtered_deck(did)
return

View file

@ -14,7 +14,8 @@ as '2' internally.
from __future__ import annotations
from typing import Literal, Optional, Sequence
from collections.abc import Sequence
from typing import Any, Literal
from anki import frontend_pb2, scheduler_pb2
from anki._legacy import deprecated
@ -109,7 +110,7 @@ class Scheduler(SchedulerBaseWithLegacy):
# backend automatically resets queues as operations are performed
pass
def getCard(self) -> Optional[Card]:
def getCard(self) -> Card | None:
"""Fetch the next card from the queue. None if finished."""
try:
queued_card = self.get_queued_cards().cards[0]
@ -125,7 +126,7 @@ class Scheduler(SchedulerBaseWithLegacy):
"Don't use this, it is a stop-gap until this code is refactored."
return not self.get_queued_cards().cards
def counts(self, card: Optional[Card] = None) -> tuple[int, int, int]:
def counts(self, card: Card | None = None) -> tuple[int, int, int]:
info = self.get_queued_cards()
return (info.new_count, info.learning_count, info.review_count)

View file

@ -8,7 +8,8 @@ from __future__ import annotations
import json
import random
import time
from typing import Sequence
from collections.abc import Sequence
from typing import Any
import anki.cards
import anki.collection

View file

@ -13,7 +13,8 @@ from __future__ import annotations
import pprint
import re
from typing import Collection, Match, Sequence
from collections.abc import Collection, Sequence
from typing import Match
import anki # pylint: disable=unused-import
import anki.collection

View file

@ -28,8 +28,9 @@ template_legacy.py file, using the legacy addHook() system.
from __future__ import annotations
from collections.abc import Sequence
from dataclasses import dataclass
from typing import Any, Sequence, Union
from typing import Any, Union
import anki
import anki.cards

View file

@ -13,9 +13,10 @@ import subprocess
import sys
import tempfile
import time
from collections.abc import Iterable, Iterator
from contextlib import contextmanager
from hashlib import sha1
from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator
from typing import TYPE_CHECKING, Any, Callable
from anki._legacy import DeprecatedNamesMixinForModule
from anki.dbproxy import DBProxy

View file

@ -385,7 +385,7 @@ def test_reviews():
assert "leech" in c.note().tags
def review_limits_setup() -> tuple[anki.collection.Collection, Dict]:
def review_limits_setup() -> tuple[anki.collection.Collection, dict]:
col = getEmptyCol()
parent = col.decks.get(col.decks.id("parent"))

View file

@ -5,6 +5,8 @@ from __future__ import annotations
import logging
import sys
from collections.abc import Callable
from typing import TYPE_CHECKING, Any, Union, cast
try:
import pip_system_certs.wrapt_requests
@ -50,7 +52,6 @@ import os
import tempfile
import traceback
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Optional, cast
import anki.lang
from anki._backend import RustBackend
@ -92,8 +93,8 @@ appHelpSite = HELP_SITE
from aqt.main import AnkiQt # isort:skip
from aqt.profiles import ProfileManager, VideoDriver # isort:skip
profiler: Optional[cProfile.Profile] = None
mw: Optional[AnkiQt] = None # set on init
profiler: cProfile.Profile | None = None
mw: AnkiQt | None = None # set on init
import aqt.forms
@ -154,7 +155,7 @@ class DialogManager:
def allClosed(self) -> bool:
return not any(x[1] for x in self._dialogs.values())
def closeAll(self, onsuccess: Callable[[], None]) -> Optional[bool]:
def closeAll(self, onsuccess: Callable[[], None]) -> bool | None:
# can we close immediately?
if self.allClosed():
onsuccess()
@ -181,7 +182,7 @@ class DialogManager:
return True
def register_dialog(
self, name: str, creator: Union[Callable, type], instance: Optional[Any] = None
self, name: str, creator: Callable | type, instance: Any | None = None
) -> None:
"""Allows add-ons to register a custom dialog to be managed by Anki's dialog
manager, which ensures that only one copy of the window is open at once,
@ -219,13 +220,13 @@ dialogs = DialogManager()
# A reference to the Qt translator needs to be held to prevent it from
# being immediately deallocated.
_qtrans: Optional[QTranslator] = None
_qtrans: QTranslator | None = None
def setupLangAndBackend(
pm: ProfileManager,
app: QApplication,
force: Optional[str] = None,
force: str | None = None,
firstTime: bool = False,
) -> RustBackend:
global _qtrans
@ -288,7 +289,7 @@ def setupLangAndBackend(
class NativeEventFilter(QAbstractNativeEventFilter):
def nativeEventFilter(
self, eventType: Any, message: Any
) -> tuple[bool, Optional[sip.voidptr]]:
) -> tuple[bool, sip.voidptr | None]:
if eventType == "windows_generic_MSG":
import ctypes
@ -563,7 +564,7 @@ def run() -> None:
)
def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiApp]:
def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None:
"""Start AnkiQt application or reuse an existing instance if one exists.
If the function is invoked with exec=False, the AnkiQt will not enter

View file

@ -2,6 +2,7 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import platform
from collections.abc import Callable
import aqt.forms
from anki.lang import without_unicode_isolation

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Callable, Optional
from typing import Callable
import aqt.editor
import aqt.forms
@ -54,7 +54,7 @@ class AddCards(QMainWindow):
self.setupButtons()
self.col.add_image_occlusion_notetype()
self.history: list[NoteId] = []
self._last_added_note: Optional[Note] = None
self._last_added_note: Note | None = None
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
restoreGeom(self, "add")
gui_hooks.add_cards_did_init(self)
@ -195,7 +195,7 @@ class AddCards(QMainWindow):
self, old_note.note_type(), new_note.note_type()
)
def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
def _load_new_note(self, sticky_fields_from: Note | None = None) -> None:
note = self._new_note()
if old_note := sticky_fields_from:
flds = note.note_type()["flds"]
@ -209,7 +209,7 @@ class AddCards(QMainWindow):
self.setAndFocusNote(note)
def on_operation_did_execute(
self, changes: OpChanges, handler: Optional[object]
self, changes: OpChanges, handler: object | None
) -> None:
if (changes.notetype or changes.deck) and handler is not self.editor:
self.on_notetype_change(

View file

@ -11,11 +11,12 @@ import os
import re
import zipfile
from collections import defaultdict
from collections.abc import Iterable, Sequence
from concurrent.futures import Future
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import IO, Any, Callable, Iterable, Sequence, Union
from typing import IO, Any, Callable, Union
from urllib.parse import parse_qs, urlparse
from zipfile import ZipFile

View file

@ -6,7 +6,8 @@ from __future__ import annotations
import json
import math
import re
from typing import Callable, Sequence
from collections.abc import Sequence
from typing import Any, Callable
import aqt
import aqt.browser

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
import aqt
import aqt.forms

View file

@ -2,8 +2,9 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from collections.abc import Iterable
from enum import Enum, auto
from typing import Callable, Iterable
from typing import Callable
from anki.collection import SearchNode
from aqt.theme import ColoredIcon

View file

@ -3,6 +3,7 @@
from __future__ import annotations
from collections.abc import Callable
from enum import Enum, auto
import aqt

View file

@ -2,8 +2,9 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from collections.abc import Callable, Iterable
from enum import Enum, auto
from typing import Iterable, cast
from typing import cast
import aqt
import aqt.browser
@ -266,7 +267,7 @@ class SidebarTreeView(QTreeView):
def update_search(
self,
*terms: Union[str, SearchNode],
*terms: str | SearchNode,
joiner: SearchJoiner = "AND",
) -> None:
"""Modify the current search string based on modifier keys, then refresh."""
@ -524,7 +525,7 @@ class SidebarTreeView(QTreeView):
*,
root: SidebarItem,
name: str,
icon: Union[str, ColoredIcon],
icon: str | ColoredIcon,
collapse_key: Config.Bool.V,
type: SidebarItemType | None = None,
) -> SidebarItem:

View file

@ -4,8 +4,9 @@ from __future__ import annotations
import copy
import time
from collections.abc import Generator, Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Generator, Sequence, Union
from typing import TYPE_CHECKING, Union
import aqt
import aqt.browser

View file

@ -3,7 +3,8 @@
from __future__ import annotations
import time
from typing import Any, Callable, Sequence
from collections.abc import Sequence
from typing import Any, Callable
import aqt
import aqt.browser

View file

@ -3,7 +3,8 @@
from __future__ import annotations
from abc import ABC, abstractmethod, abstractproperty
from typing import Sequence, cast
from collections.abc import Sequence
from typing import cast
from anki.browser import BrowserConfig
from anki.cards import Card, CardId

View file

@ -2,7 +2,8 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from typing import Any, Callable, Sequence
from collections.abc import Sequence
from typing import Any, Callable
import aqt
import aqt.browser

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
import aqt
import aqt.deckconf

View file

@ -5,8 +5,9 @@ from __future__ import annotations
import json
import re
from collections.abc import Callable
from concurrent.futures import Future
from typing import Any, Match, Optional, cast
from typing import Any, Match, cast
import aqt
import aqt.forms
@ -50,7 +51,7 @@ class CardLayout(QDialog):
mw: AnkiQt,
note: Note,
ord: int = 0,
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
fill_empty: bool = False,
) -> None:
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
@ -509,7 +510,7 @@ class CardLayout(QDialog):
# Preview
##########################################################################
_previewTimer: Optional[QTimer] = None
_previewTimer: QTimer | None = None
def renderPreview(self) -> None:
# schedule a preview when timing stops
@ -590,7 +591,7 @@ class CardLayout(QDialog):
return res
type_filter = r"\[\[type:.+?\]\]"
repl: Union[str, Callable]
repl: str | Callable
if type == "q":
repl = "<input id='typeans' type=text value='example' readonly='readonly'>"

View file

@ -3,8 +3,6 @@
from __future__ import annotations
from typing import Tuple
import aqt
import aqt.forms
import aqt.operations
@ -37,12 +35,12 @@ class CustomStudy(QDialog):
def fetch_data_and_show(mw: aqt.AnkiQt) -> None:
def fetch_data(
col: Collection,
) -> Tuple[DeckId, CustomStudyDefaults]:
) -> tuple[DeckId, CustomStudyDefaults]:
deck_id = mw.col.decks.get_current_id()
defaults = col.sched.custom_study_defaults(deck_id)
return (deck_id, defaults)
def show_dialog(data: Tuple[DeckId, CustomStudyDefaults]) -> None:
def show_dialog(data: tuple[DeckId, CustomStudyDefaults]) -> None:
deck_id, defaults = data
CustomStudy(mw=mw, deck_id=deck_id, defaults=defaults)

View file

@ -4,6 +4,7 @@
from __future__ import annotations
import os
from collections.abc import Callable
from dataclasses import dataclass
from functools import partial
from pathlib import Path

View file

@ -3,6 +3,8 @@
from __future__ import annotations
from collections.abc import Callable
from anki.collection import OpChanges
from anki.decks import DEFAULT_DECK_ID, DeckId
from aqt import AnkiQt, gui_hooks

View file

@ -173,8 +173,8 @@ class DeckConf(QDialog):
# Loading
##################################################
def listToUser(self, l: list[Union[int, float]]) -> str:
def num_to_user(n: Union[int, float]) -> str:
def listToUser(self, l: list[int | float]) -> str:
def num_to_user(n: int | float) -> str:
if n == round(n):
return str(int(n))
else:

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 collections.abc import Callable
from typing import Optional
import aqt.editor

View file

@ -5,7 +5,7 @@ from __future__ import annotations
import re
import time
from typing import TYPE_CHECKING, Optional, TextIO, cast
from typing import TYPE_CHECKING, TextIO, cast
from markdown import markdown
@ -169,7 +169,7 @@ class ErrorHandler(QObject):
def __init__(self, mw: AnkiQt) -> None:
QObject.__init__(self, mw)
self.mw = mw
self.timer: Optional[QTimer] = None
self.timer: QTimer | None = None
qconnect(self.errorTimer, self._setTimer)
self.pool = ""
self._oldstderr = sys.stderr

View file

@ -7,7 +7,6 @@ import os
import re
import time
from concurrent.futures import Future
from typing import Optional
import aqt
import aqt.forms
@ -35,7 +34,7 @@ class ExportDialog(QDialog):
mw: aqt.main.AnkiQt,
did: DeckId | None = None,
cids: list[CardId] | None = None,
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
):
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
self.mw = mw

View file

@ -3,8 +3,6 @@
from __future__ import annotations
from typing import Optional
import aqt
import aqt.forms
import aqt.operations
@ -32,7 +30,7 @@ class FieldDialog(QDialog):
self,
mw: AnkiQt,
nt: NotetypeDict,
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
open_at: int = 0,
) -> None:
QDialog.__init__(self, parent or mw)
@ -62,7 +60,7 @@ class FieldDialog(QDialog):
self.form.buttonBox.button(QDialogButtonBox.StandardButton.Save).setAutoDefault(
False
)
self.currentIdx: Optional[int] = None
self.currentIdx: int | None = None
self.fillFields()
self.setupSignals()
self.form.fieldList.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
@ -125,8 +123,8 @@ class FieldDialog(QDialog):
self.loadField(idx)
def _uniqueName(
self, prompt: str, ignoreOrd: Optional[int] = None, old: str = ""
) -> Optional[str]:
self, prompt: str, ignoreOrd: int | None = None, old: str = ""
) -> str | None:
txt = getOnlyText(prompt, default=old).replace('"', "").strip()
if not txt:
return None

View file

@ -7,8 +7,8 @@ import os
import re
import time
from abc import ABC, abstractmethod
from collections.abc import Sequence
from dataclasses import dataclass
from typing import Optional, Sequence, Type
import aqt.forms
import aqt.main
@ -42,7 +42,7 @@ class ExportDialog(QDialog):
mw: aqt.main.AnkiQt,
did: DeckId | None = None,
nids: Sequence[NoteId] | None = None,
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
):
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
self.mw = mw
@ -56,7 +56,7 @@ class ExportDialog(QDialog):
self.open()
def setup(self, did: DeckId | None) -> None:
self.exporter_classes: list[Type[Exporter]] = [
self.exporter_classes: list[type[Exporter]] = [
ApkgExporter,
ColpkgExporter,
NoteCsvExporter,

View file

@ -5,8 +5,8 @@ from __future__ import annotations
import re
from abc import ABC, abstractmethod
from collections.abc import Callable
from itertools import chain
from typing import Type
import aqt.main
from anki.collection import Collection, Progress
@ -124,7 +124,7 @@ class JsonImporter(Importer):
ImportDialog(mw, JsonFileArgs(path=path))
IMPORTERS: list[Type[Importer]] = [
IMPORTERS: list[type[Importer]] = [
ColpkgImporter,
ApkgImporter,
MnemosyneImporter,

View file

@ -4,6 +4,7 @@ import os
import re
import traceback
import zipfile
from collections.abc import Callable
from concurrent.futures import Future
from typing import Any, Optional

View file

@ -10,8 +10,9 @@ import re
import signal
import weakref
from argparse import Namespace
from collections.abc import Callable, Sequence
from concurrent.futures import Future
from typing import Any, Literal, Sequence, TypeVar, cast
from typing import Any, Literal, TypeVar, cast
import anki
import anki.cards

View file

@ -5,8 +5,9 @@ from __future__ import annotations
import itertools
import time
from collections.abc import Iterable, Sequence
from concurrent.futures import Future
from typing import Iterable, Sequence, TypeVar
from typing import TypeVar
import aqt
import aqt.progress

View file

@ -1,6 +1,7 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from collections.abc import Callable
from typing import Optional
from aqt import AnkiQt, gui_hooks

View file

@ -3,9 +3,10 @@
from __future__ import annotations
from collections.abc import Callable, Sequence
from concurrent.futures import Future
from operator import itemgetter
from typing import Any, Optional, Sequence
from typing import Any
import aqt.clayout
from anki import stdmodels
@ -40,9 +41,9 @@ class Models(QDialog):
def __init__(
self,
mw: AnkiQt,
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
fromMain: bool = False,
selected_notetype_id: Optional[NotetypeId] = None,
selected_notetype_id: NotetypeId | None = None,
):
self.mw = mw
parent = parent or mw
@ -231,13 +232,13 @@ class Models(QDialog):
class AddModel(QDialog):
model: Optional[NotetypeDict]
model: NotetypeDict | None
def __init__(
self,
mw: AnkiQt,
on_success: Callable[[NotetypeDict], None],
parent: Optional[QWidget] = None,
parent: QWidget | None = None,
) -> None:
self.parent_ = parent or mw
self.mw = mw
@ -249,9 +250,7 @@ class AddModel(QDialog):
self.setWindowModality(Qt.WindowModality.ApplicationModal)
disable_help_button(self)
# standard models
self.notetypes: list[
Union[NotetypeDict, Callable[[Collection], NotetypeDict]]
] = []
self.notetypes: list[NotetypeDict | Callable[[Collection], NotetypeDict]] = []
for name, func in stdmodels.get_stock_notetypes(self.col):
item = QListWidgetItem(tr.notetypes_add(val=name))
self.dialog.models.addItem(item)

View file

@ -3,6 +3,8 @@
from __future__ import annotations
from collections.abc import Callable
from anki.collection import OpChanges
from anki.models import NotetypeId
from aqt import AnkiQt, gui_hooks

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
from anki.cards import CardId
from anki.collection import OpChangesWithCount

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
from anki.decks import DeckCollapseScope, DeckDict, DeckId, UpdateDeckConfigs

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
from anki.collection import OpChanges, OpChangesWithCount
from anki.decks import DeckId

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
import aqt
import aqt.forms

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Sequence
from anki.collection import OpChanges, OpChangesWithCount
from anki.notes import NoteId

View file

@ -5,6 +5,7 @@ from __future__ import annotations
import functools
import re
from collections.abc import Callable
import anki.lang
import aqt

View file

@ -10,7 +10,7 @@ import shutil
import traceback
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any
import anki.lang
import aqt.forms
@ -544,7 +544,7 @@ create table if not exists profiles
def set_spacebar_rates_card(self, on: bool) -> None:
self.meta["spacebar_rates_card"] = on
def get_answer_key(self, ease: int) -> Optional[str]:
def get_answer_key(self, ease: int) -> str | None:
return self.meta.setdefault("answer_keys", self.default_answer_keys).get(ease)
def set_answer_key(self, ease: int, key: str):

View file

@ -3,6 +3,7 @@
from __future__ import annotations
import time
from collections.abc import Callable
from concurrent.futures import Future
from dataclasses import dataclass

View file

@ -8,6 +8,7 @@ PyQt5-only audio code
"""
import wave
from collections.abc import Callable
from concurrent.futures import Future
from typing import cast

View file

@ -7,9 +7,10 @@ import functools
import json
import random
import re
from collections.abc import Callable, Sequence
from dataclasses import dataclass
from enum import Enum, auto
from typing import Any, Literal, Match, Sequence, cast
from typing import Any, Literal, Match, Union, cast
import aqt
import aqt.browser
@ -568,7 +569,7 @@ class Reviewer:
def korean_shortcuts(
self,
) -> Sequence[Union[tuple[str, Callable], tuple[Qt.Key, Callable]]]:
) -> Sequence[tuple[str, Callable] | tuple[Qt.Key, Callable]]:
return [
("", self.mw.onEditCurrent),
("", self.showContextMenu),
@ -588,7 +589,7 @@ class Reviewer:
def _shortcutKeys(
self,
) -> Sequence[Union[tuple[str, Callable], tuple[Qt.Key, Callable]]]:
) -> Sequence[tuple[str, Callable] | tuple[Qt.Key, Callable]]:
return [
("e", self.mw.onEditCurrent),
(" ", self.onEnterKey),
@ -839,7 +840,7 @@ timerStopped = false;
if not self.mw.col.conf["dueCounts"]:
return ""
counts: list[Union[int, str]]
counts: list[int | str]
idx, counts_ = self._v3.counts()
counts = cast(list[Union[int, str]], counts_)
counts[idx] = f"<u>{counts[idx]}</u>"

View file

@ -3,6 +3,7 @@
from __future__ import annotations
import time
from collections.abc import Callable
from typing import Any
import aqt

View file

@ -4,7 +4,7 @@
from __future__ import annotations
import re
from typing import Iterable
from collections.abc import Iterable
from anki.collection import Collection
from aqt import gui_hooks

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Sequence
from collections.abc import Callable, Sequence
import aqt
import aqt.customstudy

View file

@ -8,7 +8,7 @@ import os
import re
import subprocess
from dataclasses import dataclass
from typing import Callable, List, Tuple
from typing import Callable
import anki.lang
import aqt
@ -386,7 +386,7 @@ def get_linux_dark_mode() -> bool:
return dbus_response[-1] == PREFER_DARK
dark_mode_detection_strategies: List[Tuple[str, Callable[[str], bool]]] = [
dark_mode_detection_strategies: list[tuple[str, Callable[[str], bool]]] = [
(
"dbus-send --session --print-reply=literal --reply-timeout=1000 "
"--dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop "

View file

@ -4,7 +4,8 @@ from __future__ import annotations
import enum
import re
from typing import Any, Callable, Optional, cast
from collections.abc import Callable
from typing import Any, cast
import aqt
from anki.sync import SyncStatus
@ -86,7 +87,7 @@ class TopWebView(ToolbarWebView):
self.show()
def _onHeight(self, qvar: Optional[int]) -> None:
def _onHeight(self, qvar: int | None) -> None:
super()._onHeight(qvar)
if qvar:
self.web_height = int(qvar)

View file

@ -9,9 +9,10 @@ import re
import shutil
import subprocess
import sys
from collections.abc import Sequence
from functools import partial, wraps
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Literal, Sequence, Union
from typing import TYPE_CHECKING, Any, Callable, Literal, Union
from send2trash import send2trash

View file

@ -7,8 +7,9 @@ import dataclasses
import json
import re
import sys
from collections.abc import Sequence
from enum import Enum
from typing import TYPE_CHECKING, Any, Callable, Optional, Sequence, cast
from typing import TYPE_CHECKING, Any, Callable, cast
import anki
import anki.lang
@ -524,10 +525,10 @@ html {{ {font} }}
def stdHtml(
self,
body: str,
css: Optional[list[str]] = None,
js: Optional[list[str]] = None,
css: list[str] | None = None,
js: list[str] | None = None,
head: str = "",
context: Optional[Any] = None,
context: Any | None = None,
default_css: bool = True,
) -> None:
css = (["css/webview.css"] if default_css else []) + (
@ -705,7 +706,7 @@ html {{ {font} }}
def adjustHeightToFit(self) -> None:
self.evalWithCallback("document.documentElement.offsetHeight", self._onHeight)
def _onHeight(self, qvar: Optional[int]) -> None:
def _onHeight(self, qvar: int | None) -> None:
from aqt import mw
if qvar is None:
@ -842,5 +843,5 @@ html {{ {font} }}
)
@deprecated(info="use theme_manager.qcolor() instead")
def get_window_bg_color(self, night_mode: Optional[bool] = None) -> QColor:
def get_window_bg_color(self, night_mode: bool | None = None) -> QColor:
return theme_manager.qcolor(colors.CANVAS)