mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
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:
parent
412e67db3e
commit
63afb0f8c6
71 changed files with 171 additions and 134 deletions
|
@ -6,8 +6,9 @@ from __future__ import annotations
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
from collections.abc import Iterable, Sequence
|
||||||
from threading import current_thread, main_thread
|
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 weakref import ref
|
||||||
|
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
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 (
|
from anki import (
|
||||||
ankiweb_pb2,
|
ankiweb_pb2,
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from collections.abc import Iterable, Sequence
|
||||||
from re import Match
|
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:
|
if TYPE_CHECKING:
|
||||||
import anki._backend
|
import anki._backend
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
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:
|
if TYPE_CHECKING:
|
||||||
import anki
|
import anki
|
||||||
|
|
|
@ -13,8 +13,9 @@ import threading
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from collections.abc import Sequence
|
||||||
from io import BufferedWriter
|
from io import BufferedWriter
|
||||||
from typing import Any, Optional, Sequence
|
from typing import Any
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
@ -26,16 +27,16 @@ from anki.utils import ids2str, namedtmp, split_fields, strip_html
|
||||||
|
|
||||||
class Exporter:
|
class Exporter:
|
||||||
includeHTML: bool | None = None
|
includeHTML: bool | None = None
|
||||||
ext: Optional[str] = None
|
ext: str | None = None
|
||||||
includeTags: Optional[bool] = None
|
includeTags: bool | None = None
|
||||||
includeSched: Optional[bool] = None
|
includeSched: bool | None = None
|
||||||
includeMedia: Optional[bool] = None
|
includeMedia: bool | None = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
col: Collection,
|
col: Collection,
|
||||||
did: Optional[DeckId] = None,
|
did: DeckId | None = None,
|
||||||
cids: Optional[list[CardId]] = None,
|
cids: list[CardId] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self.did = did
|
self.did = did
|
||||||
|
|
|
@ -94,8 +94,8 @@ class ForeignCard:
|
||||||
class ForeignNote:
|
class ForeignNote:
|
||||||
fields: list[str] = field(default_factory=list)
|
fields: list[str] = field(default_factory=list)
|
||||||
tags: list[str] = field(default_factory=list)
|
tags: list[str] = field(default_factory=list)
|
||||||
notetype: Union[str, NotetypeId] = ""
|
notetype: str | NotetypeId = ""
|
||||||
deck: Union[str, DeckId] = ""
|
deck: str | DeckId = ""
|
||||||
cards: list[ForeignCard] = field(default_factory=list)
|
cards: list[ForeignCard] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class ForeignNote:
|
||||||
class ForeignData:
|
class ForeignData:
|
||||||
notes: list[ForeignNote] = field(default_factory=list)
|
notes: list[ForeignNote] = field(default_factory=list)
|
||||||
notetypes: list[ForeignNotetype] = field(default_factory=list)
|
notetypes: list[ForeignNotetype] = field(default_factory=list)
|
||||||
default_deck: Union[str, DeckId] = ""
|
default_deck: str | DeckId = ""
|
||||||
|
|
||||||
def serialize(self) -> str:
|
def serialize(self) -> str:
|
||||||
return json.dumps(self, cls=ForeignDataEncoder, separators=(",", ":"))
|
return json.dumps(self, cls=ForeignDataEncoder, separators=(",", ":"))
|
||||||
|
|
|
@ -17,7 +17,6 @@ Notetype | Card Type
|
||||||
import re
|
import re
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Tuple, Type
|
|
||||||
|
|
||||||
from anki.db import DB
|
from anki.db import DB
|
||||||
from anki.decks import DeckId
|
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:
|
def gather_data(db: DB, deck_id: DeckId) -> ForeignData:
|
||||||
facts = gather_facts(db)
|
facts = gather_facts(db)
|
||||||
gather_cards_into_facts(db, facts)
|
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()]
|
notes = [fact.foreign_note(used_fact_views) for fact in facts.values()]
|
||||||
notetypes = [fact_view.foreign_notetype() for fact_view in used_fact_views]
|
notetypes = [fact_view.foreign_notetype() for fact_view in used_fact_views]
|
||||||
return ForeignData(notes, notetypes, deck_id)
|
return ForeignData(notes, notetypes, deck_id)
|
||||||
|
@ -54,7 +53,7 @@ def open_mnemosyne_db(db_path: str) -> DB:
|
||||||
|
|
||||||
class MnemoFactView(ABC):
|
class MnemoFactView(ABC):
|
||||||
notetype: str
|
notetype: str
|
||||||
field_keys: Tuple[str, ...]
|
field_keys: tuple[str, ...]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -162,7 +161,7 @@ class MnemoFact:
|
||||||
cards: list[MnemoCard] = field(default_factory=list)
|
cards: list[MnemoCard] = field(default_factory=list)
|
||||||
|
|
||||||
def foreign_note(
|
def foreign_note(
|
||||||
self, used_fact_views: dict[Type[MnemoFactView], bool]
|
self, used_fact_views: dict[type[MnemoFactView], bool]
|
||||||
) -> ForeignNote:
|
) -> ForeignNote:
|
||||||
fact_view = self.fact_view()
|
fact_view = self.fact_view()
|
||||||
used_fact_views[fact_view] = True
|
used_fact_views[fact_view] = True
|
||||||
|
@ -173,7 +172,7 @@ class MnemoFact:
|
||||||
cards=self.foreign_cards(),
|
cards=self.foreign_cards(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def fact_view(self) -> Type[MnemoFactView]:
|
def fact_view(self) -> type[MnemoFactView]:
|
||||||
try:
|
try:
|
||||||
fact_view = self.cards[0].fact_view_id
|
fact_view = self.cards[0].fact_view_id
|
||||||
except IndexError as err:
|
except IndexError as err:
|
||||||
|
@ -190,7 +189,7 @@ class MnemoFact:
|
||||||
|
|
||||||
raise Exception(f"Fact {id} has unknown fact view: {fact_view}")
|
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]
|
return [munge_field(self.fields.get(k, "")) for k in fact_view.field_keys]
|
||||||
|
|
||||||
def anki_tags(self) -> list[str]:
|
def anki_tags(self) -> list[str]:
|
||||||
|
|
|
@ -14,6 +14,9 @@ modifying it.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import decorator
|
import decorator
|
||||||
|
|
||||||
# You can find the definitions in ../tools/genhooks.py
|
# You can find the definitions in ../tools/genhooks.py
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Copyright: Ankitects Pty Ltd and contributors
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# 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
|
import anki
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from typing import Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from anki.cards import CardId
|
from anki.cards import CardId
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
|
|
|
@ -7,7 +7,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import re
|
import re
|
||||||
from typing import Any, Optional, TextIO
|
from typing import Any, TextIO
|
||||||
|
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from anki.importing.noteimp import ForeignNote, NoteImporter
|
from anki.importing.noteimp import ForeignNote, NoteImporter
|
||||||
|
@ -20,12 +20,12 @@ class TextImporter(NoteImporter):
|
||||||
def __init__(self, col: Collection, file: str) -> None:
|
def __init__(self, col: Collection, file: str) -> None:
|
||||||
NoteImporter.__init__(self, col, file)
|
NoteImporter.__init__(self, col, file)
|
||||||
self.lines = None
|
self.lines = None
|
||||||
self.fileobj: Optional[TextIO] = None
|
self.fileobj: TextIO | None = None
|
||||||
self.delimiter: Optional[str] = None
|
self.delimiter: str | None = None
|
||||||
self.tagsToAdd: list[str] = []
|
self.tagsToAdd: list[str] = []
|
||||||
self.numFields = 0
|
self.numFields = 0
|
||||||
self.dialect: Optional[Any]
|
self.dialect: Any | None
|
||||||
self.data: Optional[str | list[str]]
|
self.data: str | list[str] | None
|
||||||
|
|
||||||
def foreignNotes(self) -> list[ForeignNote]:
|
def foreignNotes(self) -> list[ForeignNote]:
|
||||||
self.open()
|
self.open()
|
||||||
|
|
|
@ -7,7 +7,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import html
|
import html
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from typing import Optional, Union
|
from typing import Union
|
||||||
|
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from anki.config import Config
|
from anki.config import Config
|
||||||
|
@ -76,8 +76,8 @@ class NoteImporter(Importer):
|
||||||
needDelimiter = False
|
needDelimiter = False
|
||||||
allowHTML = False
|
allowHTML = False
|
||||||
importMode = UPDATE_MODE
|
importMode = UPDATE_MODE
|
||||||
mapping: Optional[list[str]]
|
mapping: list[str] | None
|
||||||
tagModified: Optional[str]
|
tagModified: str | None
|
||||||
|
|
||||||
def __init__(self, col: Collection, file: str) -> None:
|
def __init__(self, col: Collection, file: str) -> None:
|
||||||
Importer.__init__(self, col, file)
|
Importer.__init__(self, col, file)
|
||||||
|
@ -268,7 +268,7 @@ class NoteImporter(Importer):
|
||||||
|
|
||||||
def updateData(
|
def updateData(
|
||||||
self, n: ForeignNote, id: NoteId, sflds: list[str]
|
self, n: ForeignNote, id: NoteId, sflds: list[str]
|
||||||
) -> Optional[Updates]:
|
) -> Updates | None:
|
||||||
self._ids.append(id)
|
self._ids.append(id)
|
||||||
self.processFields(n, sflds)
|
self.processFields(n, sflds)
|
||||||
if self._tagsMapped:
|
if self._tagsMapped:
|
||||||
|
@ -316,9 +316,7 @@ where id = ? and flds != ?""",
|
||||||
changes2 = self.col.db.scalar("select total_changes()")
|
changes2 = self.col.db.scalar("select total_changes()")
|
||||||
self.updateCount = changes2 - changes
|
self.updateCount = changes2 - changes
|
||||||
|
|
||||||
def processFields(
|
def processFields(self, note: ForeignNote, fields: list[str] | None = None) -> None:
|
||||||
self, note: ForeignNote, fields: Optional[list[str]] = None
|
|
||||||
) -> None:
|
|
||||||
if not fields:
|
if not fields:
|
||||||
fields = [""] * len(self.model["flds"])
|
fields = [""] * len(self.model["flds"])
|
||||||
for c, f in enumerate(self.mapping):
|
for c, f in enumerate(self.mapping):
|
||||||
|
|
|
@ -8,7 +8,8 @@ import pprint
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from typing import Callable, Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from anki import media_pb2
|
from anki import media_pb2
|
||||||
from anki._legacy import DeprecatedNamesMixin, deprecated_keywords
|
from anki._legacy import DeprecatedNamesMixin, deprecated_keywords
|
||||||
|
|
|
@ -7,7 +7,8 @@ import copy
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
import time
|
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 # pylint: disable=unused-import
|
||||||
import anki.collection
|
import anki.collection
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from typing import NewType, Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import NewType
|
||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki.cards
|
import anki.cards
|
||||||
|
|
|
@ -22,7 +22,8 @@ ScheduleCardsAsNewDefaults = scheduler_pb2.ScheduleCardsAsNewDefaultsResponse
|
||||||
FilteredDeckForUpdate = decks_pb2.FilteredDeckForUpdate
|
FilteredDeckForUpdate = decks_pb2.FilteredDeckForUpdate
|
||||||
RepositionDefaults = scheduler_pb2.RepositionDefaultsResponse
|
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 import config_pb2
|
||||||
from anki.cards import CardId
|
from anki.cards import CardId
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from anki._legacy import deprecated
|
from anki._legacy import deprecated
|
||||||
from anki.cards import Card, CardId
|
from anki.cards import Card, CardId
|
||||||
from anki.consts import (
|
from anki.consts import (
|
||||||
|
@ -54,7 +52,7 @@ class SchedulerBaseWithLegacy(SchedulerBase):
|
||||||
print("_nextDueMsg() is obsolete")
|
print("_nextDueMsg() is obsolete")
|
||||||
return ""
|
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()
|
did = did or self.col.decks.selected()
|
||||||
count = self.rebuild_filtered_deck(did).count or None
|
count = self.rebuild_filtered_deck(did).count or None
|
||||||
if not count:
|
if not count:
|
||||||
|
@ -63,7 +61,7 @@ class SchedulerBaseWithLegacy(SchedulerBase):
|
||||||
self.col.decks.select(did)
|
self.col.decks.select(did)
|
||||||
return count
|
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:
|
if lim is None:
|
||||||
self.empty_filtered_deck(did)
|
self.empty_filtered_deck(did)
|
||||||
return
|
return
|
||||||
|
|
|
@ -14,7 +14,8 @@ as '2' internally.
|
||||||
|
|
||||||
from __future__ import annotations
|
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 import frontend_pb2, scheduler_pb2
|
||||||
from anki._legacy import deprecated
|
from anki._legacy import deprecated
|
||||||
|
@ -109,7 +110,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
# backend automatically resets queues as operations are performed
|
# backend automatically resets queues as operations are performed
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getCard(self) -> Optional[Card]:
|
def getCard(self) -> Card | None:
|
||||||
"""Fetch the next card from the queue. None if finished."""
|
"""Fetch the next card from the queue. None if finished."""
|
||||||
try:
|
try:
|
||||||
queued_card = self.get_queued_cards().cards[0]
|
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."
|
"Don't use this, it is a stop-gap until this code is refactored."
|
||||||
return not self.get_queued_cards().cards
|
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()
|
info = self.get_queued_cards()
|
||||||
return (info.new_count, info.learning_count, info.review_count)
|
return (info.new_count, info.learning_count, info.review_count)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import anki.cards
|
import anki.cards
|
||||||
import anki.collection
|
import anki.collection
|
||||||
|
|
|
@ -13,7 +13,8 @@ from __future__ import annotations
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import re
|
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 # pylint: disable=unused-import
|
||||||
import anki.collection
|
import anki.collection
|
||||||
|
|
|
@ -28,8 +28,9 @@ template_legacy.py file, using the legacy addHook() system.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Sequence, Union
|
from typing import Any, Union
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
import anki.cards
|
import anki.cards
|
||||||
|
|
|
@ -13,9 +13,10 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Iterable, Iterator
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from hashlib import sha1
|
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._legacy import DeprecatedNamesMixinForModule
|
||||||
from anki.dbproxy import DBProxy
|
from anki.dbproxy import DBProxy
|
||||||
|
|
|
@ -385,7 +385,7 @@ def test_reviews():
|
||||||
assert "leech" in c.note().tags
|
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()
|
col = getEmptyCol()
|
||||||
|
|
||||||
parent = col.decks.get(col.decks.id("parent"))
|
parent = col.decks.get(col.decks.id("parent"))
|
||||||
|
|
|
@ -5,6 +5,8 @@ from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import TYPE_CHECKING, Any, Union, cast
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pip_system_certs.wrapt_requests
|
import pip_system_certs.wrapt_requests
|
||||||
|
@ -50,7 +52,6 @@ import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import traceback
|
import traceback
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any, Callable, Optional, cast
|
|
||||||
|
|
||||||
import anki.lang
|
import anki.lang
|
||||||
from anki._backend import RustBackend
|
from anki._backend import RustBackend
|
||||||
|
@ -92,8 +93,8 @@ appHelpSite = HELP_SITE
|
||||||
from aqt.main import AnkiQt # isort:skip
|
from aqt.main import AnkiQt # isort:skip
|
||||||
from aqt.profiles import ProfileManager, VideoDriver # isort:skip
|
from aqt.profiles import ProfileManager, VideoDriver # isort:skip
|
||||||
|
|
||||||
profiler: Optional[cProfile.Profile] = None
|
profiler: cProfile.Profile | None = None
|
||||||
mw: Optional[AnkiQt] = None # set on init
|
mw: AnkiQt | None = None # set on init
|
||||||
|
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ class DialogManager:
|
||||||
def allClosed(self) -> bool:
|
def allClosed(self) -> bool:
|
||||||
return not any(x[1] for x in self._dialogs.values())
|
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?
|
# can we close immediately?
|
||||||
if self.allClosed():
|
if self.allClosed():
|
||||||
onsuccess()
|
onsuccess()
|
||||||
|
@ -181,7 +182,7 @@ class DialogManager:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def register_dialog(
|
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:
|
) -> None:
|
||||||
"""Allows add-ons to register a custom dialog to be managed by Anki's dialog
|
"""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,
|
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
|
# A reference to the Qt translator needs to be held to prevent it from
|
||||||
# being immediately deallocated.
|
# being immediately deallocated.
|
||||||
_qtrans: Optional[QTranslator] = None
|
_qtrans: QTranslator | None = None
|
||||||
|
|
||||||
|
|
||||||
def setupLangAndBackend(
|
def setupLangAndBackend(
|
||||||
pm: ProfileManager,
|
pm: ProfileManager,
|
||||||
app: QApplication,
|
app: QApplication,
|
||||||
force: Optional[str] = None,
|
force: str | None = None,
|
||||||
firstTime: bool = False,
|
firstTime: bool = False,
|
||||||
) -> RustBackend:
|
) -> RustBackend:
|
||||||
global _qtrans
|
global _qtrans
|
||||||
|
@ -288,7 +289,7 @@ def setupLangAndBackend(
|
||||||
class NativeEventFilter(QAbstractNativeEventFilter):
|
class NativeEventFilter(QAbstractNativeEventFilter):
|
||||||
def nativeEventFilter(
|
def nativeEventFilter(
|
||||||
self, eventType: Any, message: Any
|
self, eventType: Any, message: Any
|
||||||
) -> tuple[bool, Optional[sip.voidptr]]:
|
) -> tuple[bool, sip.voidptr | None]:
|
||||||
if eventType == "windows_generic_MSG":
|
if eventType == "windows_generic_MSG":
|
||||||
import ctypes
|
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.
|
"""Start AnkiQt application or reuse an existing instance if one exists.
|
||||||
|
|
||||||
If the function is invoked with exec=False, the AnkiQt will not enter
|
If the function is invoked with exec=False, the AnkiQt will not enter
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
from anki.lang import without_unicode_isolation
|
from anki.lang import without_unicode_isolation
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Callable, Optional
|
from typing import Callable
|
||||||
|
|
||||||
import aqt.editor
|
import aqt.editor
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
@ -54,7 +54,7 @@ class AddCards(QMainWindow):
|
||||||
self.setupButtons()
|
self.setupButtons()
|
||||||
self.col.add_image_occlusion_notetype()
|
self.col.add_image_occlusion_notetype()
|
||||||
self.history: list[NoteId] = []
|
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)
|
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
|
||||||
restoreGeom(self, "add")
|
restoreGeom(self, "add")
|
||||||
gui_hooks.add_cards_did_init(self)
|
gui_hooks.add_cards_did_init(self)
|
||||||
|
@ -195,7 +195,7 @@ class AddCards(QMainWindow):
|
||||||
self, old_note.note_type(), new_note.note_type()
|
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()
|
note = self._new_note()
|
||||||
if old_note := sticky_fields_from:
|
if old_note := sticky_fields_from:
|
||||||
flds = note.note_type()["flds"]
|
flds = note.note_type()["flds"]
|
||||||
|
@ -209,7 +209,7 @@ class AddCards(QMainWindow):
|
||||||
self.setAndFocusNote(note)
|
self.setAndFocusNote(note)
|
||||||
|
|
||||||
def on_operation_did_execute(
|
def on_operation_did_execute(
|
||||||
self, changes: OpChanges, handler: Optional[object]
|
self, changes: OpChanges, handler: object | None
|
||||||
) -> None:
|
) -> None:
|
||||||
if (changes.notetype or changes.deck) and handler is not self.editor:
|
if (changes.notetype or changes.deck) and handler is not self.editor:
|
||||||
self.on_notetype_change(
|
self.on_notetype_change(
|
||||||
|
|
|
@ -11,11 +11,12 @@ import os
|
||||||
import re
|
import re
|
||||||
import zipfile
|
import zipfile
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from collections.abc import Iterable, Sequence
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
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 urllib.parse import parse_qs, urlparse
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
from typing import Callable, Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Iterable
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from typing import Callable, Iterable
|
from typing import Callable
|
||||||
|
|
||||||
from anki.collection import SearchNode
|
from anki.collection import SearchNode
|
||||||
from aqt.theme import ColoredIcon
|
from aqt.theme import ColoredIcon
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable, Iterable
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from typing import Iterable, cast
|
from typing import cast
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
@ -266,7 +267,7 @@ class SidebarTreeView(QTreeView):
|
||||||
|
|
||||||
def update_search(
|
def update_search(
|
||||||
self,
|
self,
|
||||||
*terms: Union[str, SearchNode],
|
*terms: str | SearchNode,
|
||||||
joiner: SearchJoiner = "AND",
|
joiner: SearchJoiner = "AND",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Modify the current search string based on modifier keys, then refresh."""
|
"""Modify the current search string based on modifier keys, then refresh."""
|
||||||
|
@ -524,7 +525,7 @@ class SidebarTreeView(QTreeView):
|
||||||
*,
|
*,
|
||||||
root: SidebarItem,
|
root: SidebarItem,
|
||||||
name: str,
|
name: str,
|
||||||
icon: Union[str, ColoredIcon],
|
icon: str | ColoredIcon,
|
||||||
collapse_key: Config.Bool.V,
|
collapse_key: Config.Bool.V,
|
||||||
type: SidebarItemType | None = None,
|
type: SidebarItemType | None = None,
|
||||||
) -> SidebarItem:
|
) -> SidebarItem:
|
||||||
|
|
|
@ -4,8 +4,9 @@ from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Generator, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING, Generator, Sequence, Union
|
from typing import TYPE_CHECKING, Union
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from typing import Any, Callable, Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC, abstractmethod, abstractproperty
|
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.browser import BrowserConfig
|
||||||
from anki.cards import Card, CardId
|
from anki.cards import Card, CardId
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable, Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.deckconf
|
import aqt.deckconf
|
||||||
|
|
|
@ -5,8 +5,9 @@ from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
from collections.abc import Callable
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Any, Match, Optional, cast
|
from typing import Any, Match, cast
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
@ -50,7 +51,7 @@ class CardLayout(QDialog):
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
note: Note,
|
note: Note,
|
||||||
ord: int = 0,
|
ord: int = 0,
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
fill_empty: bool = False,
|
fill_empty: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
||||||
|
@ -509,7 +510,7 @@ class CardLayout(QDialog):
|
||||||
# Preview
|
# Preview
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
_previewTimer: Optional[QTimer] = None
|
_previewTimer: QTimer | None = None
|
||||||
|
|
||||||
def renderPreview(self) -> None:
|
def renderPreview(self) -> None:
|
||||||
# schedule a preview when timing stops
|
# schedule a preview when timing stops
|
||||||
|
@ -590,7 +591,7 @@ class CardLayout(QDialog):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
type_filter = r"\[\[type:.+?\]\]"
|
type_filter = r"\[\[type:.+?\]\]"
|
||||||
repl: Union[str, Callable]
|
repl: str | Callable
|
||||||
|
|
||||||
if type == "q":
|
if type == "q":
|
||||||
repl = "<input id='typeans' type=text value='example' readonly='readonly'>"
|
repl = "<input id='typeans' type=text value='example' readonly='readonly'>"
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
import aqt.operations
|
import aqt.operations
|
||||||
|
@ -37,12 +35,12 @@ class CustomStudy(QDialog):
|
||||||
def fetch_data_and_show(mw: aqt.AnkiQt) -> None:
|
def fetch_data_and_show(mw: aqt.AnkiQt) -> None:
|
||||||
def fetch_data(
|
def fetch_data(
|
||||||
col: Collection,
|
col: Collection,
|
||||||
) -> Tuple[DeckId, CustomStudyDefaults]:
|
) -> tuple[DeckId, CustomStudyDefaults]:
|
||||||
deck_id = mw.col.decks.get_current_id()
|
deck_id = mw.col.decks.get_current_id()
|
||||||
defaults = col.sched.custom_study_defaults(deck_id)
|
defaults = col.sched.custom_study_defaults(deck_id)
|
||||||
return (deck_id, defaults)
|
return (deck_id, defaults)
|
||||||
|
|
||||||
def show_dialog(data: Tuple[DeckId, CustomStudyDefaults]) -> None:
|
def show_dialog(data: tuple[DeckId, CustomStudyDefaults]) -> None:
|
||||||
deck_id, defaults = data
|
deck_id, defaults = data
|
||||||
CustomStudy(mw=mw, deck_id=deck_id, defaults=defaults)
|
CustomStudy(mw=mw, deck_id=deck_id, defaults=defaults)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from collections.abc import Callable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
from anki.collection import OpChanges
|
from anki.collection import OpChanges
|
||||||
from anki.decks import DEFAULT_DECK_ID, DeckId
|
from anki.decks import DEFAULT_DECK_ID, DeckId
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
|
|
@ -173,8 +173,8 @@ class DeckConf(QDialog):
|
||||||
# Loading
|
# Loading
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
def listToUser(self, l: list[Union[int, float]]) -> str:
|
def listToUser(self, l: list[int | float]) -> str:
|
||||||
def num_to_user(n: Union[int, float]) -> str:
|
def num_to_user(n: int | float) -> str:
|
||||||
if n == round(n):
|
if n == round(n):
|
||||||
return str(int(n))
|
return str(int(n))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright: Ankitects Pty Ltd and contributors
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
from collections.abc import Callable
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import aqt.editor
|
import aqt.editor
|
||||||
|
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Optional, TextIO, cast
|
from typing import TYPE_CHECKING, TextIO, cast
|
||||||
|
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ class ErrorHandler(QObject):
|
||||||
def __init__(self, mw: AnkiQt) -> None:
|
def __init__(self, mw: AnkiQt) -> None:
|
||||||
QObject.__init__(self, mw)
|
QObject.__init__(self, mw)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.timer: Optional[QTimer] = None
|
self.timer: QTimer | None = None
|
||||||
qconnect(self.errorTimer, self._setTimer)
|
qconnect(self.errorTimer, self._setTimer)
|
||||||
self.pool = ""
|
self.pool = ""
|
||||||
self._oldstderr = sys.stderr
|
self._oldstderr = sys.stderr
|
||||||
|
|
|
@ -7,7 +7,6 @@ import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
@ -35,7 +34,7 @@ class ExportDialog(QDialog):
|
||||||
mw: aqt.main.AnkiQt,
|
mw: aqt.main.AnkiQt,
|
||||||
did: DeckId | None = None,
|
did: DeckId | None = None,
|
||||||
cids: list[CardId] | None = None,
|
cids: list[CardId] | None = None,
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
):
|
):
|
||||||
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
import aqt.operations
|
import aqt.operations
|
||||||
|
@ -32,7 +30,7 @@ class FieldDialog(QDialog):
|
||||||
self,
|
self,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
nt: NotetypeDict,
|
nt: NotetypeDict,
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
open_at: int = 0,
|
open_at: int = 0,
|
||||||
) -> None:
|
) -> None:
|
||||||
QDialog.__init__(self, parent or mw)
|
QDialog.__init__(self, parent or mw)
|
||||||
|
@ -62,7 +60,7 @@ class FieldDialog(QDialog):
|
||||||
self.form.buttonBox.button(QDialogButtonBox.StandardButton.Save).setAutoDefault(
|
self.form.buttonBox.button(QDialogButtonBox.StandardButton.Save).setAutoDefault(
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
self.currentIdx: Optional[int] = None
|
self.currentIdx: int | None = None
|
||||||
self.fillFields()
|
self.fillFields()
|
||||||
self.setupSignals()
|
self.setupSignals()
|
||||||
self.form.fieldList.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
self.form.fieldList.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
||||||
|
@ -125,8 +123,8 @@ class FieldDialog(QDialog):
|
||||||
self.loadField(idx)
|
self.loadField(idx)
|
||||||
|
|
||||||
def _uniqueName(
|
def _uniqueName(
|
||||||
self, prompt: str, ignoreOrd: Optional[int] = None, old: str = ""
|
self, prompt: str, ignoreOrd: int | None = None, old: str = ""
|
||||||
) -> Optional[str]:
|
) -> str | None:
|
||||||
txt = getOnlyText(prompt, default=old).replace('"', "").strip()
|
txt = getOnlyText(prompt, default=old).replace('"', "").strip()
|
||||||
if not txt:
|
if not txt:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -7,8 +7,8 @@ import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
from collections.abc import Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, Sequence, Type
|
|
||||||
|
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
import aqt.main
|
import aqt.main
|
||||||
|
@ -42,7 +42,7 @@ class ExportDialog(QDialog):
|
||||||
mw: aqt.main.AnkiQt,
|
mw: aqt.main.AnkiQt,
|
||||||
did: DeckId | None = None,
|
did: DeckId | None = None,
|
||||||
nids: Sequence[NoteId] | None = None,
|
nids: Sequence[NoteId] | None = None,
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
):
|
):
|
||||||
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
@ -56,7 +56,7 @@ class ExportDialog(QDialog):
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
def setup(self, did: DeckId | None) -> None:
|
def setup(self, did: DeckId | None) -> None:
|
||||||
self.exporter_classes: list[Type[Exporter]] = [
|
self.exporter_classes: list[type[Exporter]] = [
|
||||||
ApkgExporter,
|
ApkgExporter,
|
||||||
ColpkgExporter,
|
ColpkgExporter,
|
||||||
NoteCsvExporter,
|
NoteCsvExporter,
|
||||||
|
|
|
@ -5,8 +5,8 @@ from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
from collections.abc import Callable
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import Type
|
|
||||||
|
|
||||||
import aqt.main
|
import aqt.main
|
||||||
from anki.collection import Collection, Progress
|
from anki.collection import Collection, Progress
|
||||||
|
@ -124,7 +124,7 @@ class JsonImporter(Importer):
|
||||||
ImportDialog(mw, JsonFileArgs(path=path))
|
ImportDialog(mw, JsonFileArgs(path=path))
|
||||||
|
|
||||||
|
|
||||||
IMPORTERS: list[Type[Importer]] = [
|
IMPORTERS: list[type[Importer]] = [
|
||||||
ColpkgImporter,
|
ColpkgImporter,
|
||||||
ApkgImporter,
|
ApkgImporter,
|
||||||
MnemosyneImporter,
|
MnemosyneImporter,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from collections.abc import Callable
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,9 @@ import re
|
||||||
import signal
|
import signal
|
||||||
import weakref
|
import weakref
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
from collections.abc import Callable, Sequence
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Any, Literal, Sequence, TypeVar, cast
|
from typing import Any, Literal, TypeVar, cast
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
import anki.cards
|
import anki.cards
|
||||||
|
|
|
@ -5,8 +5,9 @@ from __future__ import annotations
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Iterable, Sequence
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Iterable, Sequence, TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.progress
|
import aqt.progress
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright: Ankitects Pty Ltd and contributors
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable, Sequence
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from typing import Any, Optional, Sequence
|
from typing import Any
|
||||||
|
|
||||||
import aqt.clayout
|
import aqt.clayout
|
||||||
from anki import stdmodels
|
from anki import stdmodels
|
||||||
|
@ -40,9 +41,9 @@ class Models(QDialog):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
fromMain: bool = False,
|
fromMain: bool = False,
|
||||||
selected_notetype_id: Optional[NotetypeId] = None,
|
selected_notetype_id: NotetypeId | None = None,
|
||||||
):
|
):
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
parent = parent or mw
|
parent = parent or mw
|
||||||
|
@ -231,13 +232,13 @@ class Models(QDialog):
|
||||||
|
|
||||||
|
|
||||||
class AddModel(QDialog):
|
class AddModel(QDialog):
|
||||||
model: Optional[NotetypeDict]
|
model: NotetypeDict | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
on_success: Callable[[NotetypeDict], None],
|
on_success: Callable[[NotetypeDict], None],
|
||||||
parent: Optional[QWidget] = None,
|
parent: QWidget | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.parent_ = parent or mw
|
self.parent_ = parent or mw
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
@ -249,9 +250,7 @@ class AddModel(QDialog):
|
||||||
self.setWindowModality(Qt.WindowModality.ApplicationModal)
|
self.setWindowModality(Qt.WindowModality.ApplicationModal)
|
||||||
disable_help_button(self)
|
disable_help_button(self)
|
||||||
# standard models
|
# standard models
|
||||||
self.notetypes: list[
|
self.notetypes: list[NotetypeDict | Callable[[Collection], NotetypeDict]] = []
|
||||||
Union[NotetypeDict, Callable[[Collection], NotetypeDict]]
|
|
||||||
] = []
|
|
||||||
for name, func in stdmodels.get_stock_notetypes(self.col):
|
for name, func in stdmodels.get_stock_notetypes(self.col):
|
||||||
item = QListWidgetItem(tr.notetypes_add(val=name))
|
item = QListWidgetItem(tr.notetypes_add(val=name))
|
||||||
self.dialog.models.addItem(item)
|
self.dialog.models.addItem(item)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
from anki.collection import OpChanges
|
from anki.collection import OpChanges
|
||||||
from anki.models import NotetypeId
|
from anki.models import NotetypeId
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
from anki.cards import CardId
|
from anki.cards import CardId
|
||||||
from anki.collection import OpChangesWithCount
|
from anki.collection import OpChangesWithCount
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||||
from anki.decks import DeckCollapseScope, DeckDict, DeckId, UpdateDeckConfigs
|
from anki.decks import DeckCollapseScope, DeckDict, DeckId, UpdateDeckConfigs
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
from anki.collection import OpChanges, OpChangesWithCount
|
from anki.collection import OpChanges, OpChangesWithCount
|
||||||
from anki.decks import DeckId
|
from anki.decks import DeckId
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
from anki.collection import OpChanges, OpChangesWithCount
|
from anki.collection import OpChanges, OpChangesWithCount
|
||||||
from anki.notes import NoteId
|
from anki.notes import NoteId
|
||||||
|
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import re
|
import re
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
import anki.lang
|
import anki.lang
|
||||||
import aqt
|
import aqt
|
||||||
|
|
|
@ -10,7 +10,7 @@ import shutil
|
||||||
import traceback
|
import traceback
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any, Optional
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
import anki.lang
|
import anki.lang
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
|
@ -544,7 +544,7 @@ create table if not exists profiles
|
||||||
def set_spacebar_rates_card(self, on: bool) -> None:
|
def set_spacebar_rates_card(self, on: bool) -> None:
|
||||||
self.meta["spacebar_rates_card"] = on
|
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)
|
return self.meta.setdefault("answer_keys", self.default_answer_keys).get(ease)
|
||||||
|
|
||||||
def set_answer_key(self, ease: int, key: str):
|
def set_answer_key(self, ease: int, key: str):
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Callable
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ PyQt5-only audio code
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import wave
|
import wave
|
||||||
|
from collections.abc import Callable
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,10 @@ import functools
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
from collections.abc import Callable, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum, auto
|
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
|
||||||
import aqt.browser
|
import aqt.browser
|
||||||
|
@ -568,7 +569,7 @@ class Reviewer:
|
||||||
|
|
||||||
def korean_shortcuts(
|
def korean_shortcuts(
|
||||||
self,
|
self,
|
||||||
) -> Sequence[Union[tuple[str, Callable], tuple[Qt.Key, Callable]]]:
|
) -> Sequence[tuple[str, Callable] | tuple[Qt.Key, Callable]]:
|
||||||
return [
|
return [
|
||||||
("ㄷ", self.mw.onEditCurrent),
|
("ㄷ", self.mw.onEditCurrent),
|
||||||
("ㅡ", self.showContextMenu),
|
("ㅡ", self.showContextMenu),
|
||||||
|
@ -588,7 +589,7 @@ class Reviewer:
|
||||||
|
|
||||||
def _shortcutKeys(
|
def _shortcutKeys(
|
||||||
self,
|
self,
|
||||||
) -> Sequence[Union[tuple[str, Callable], tuple[Qt.Key, Callable]]]:
|
) -> Sequence[tuple[str, Callable] | tuple[Qt.Key, Callable]]:
|
||||||
return [
|
return [
|
||||||
("e", self.mw.onEditCurrent),
|
("e", self.mw.onEditCurrent),
|
||||||
(" ", self.onEnterKey),
|
(" ", self.onEnterKey),
|
||||||
|
@ -839,7 +840,7 @@ timerStopped = false;
|
||||||
if not self.mw.col.conf["dueCounts"]:
|
if not self.mw.col.conf["dueCounts"]:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
counts: list[Union[int, str]]
|
counts: list[int | str]
|
||||||
idx, counts_ = self._v3.counts()
|
idx, counts_ = self._v3.counts()
|
||||||
counts = cast(list[Union[int, str]], counts_)
|
counts = cast(list[Union[int, str]], counts_)
|
||||||
counts[idx] = f"<u>{counts[idx]}</u>"
|
counts[idx] = f"<u>{counts[idx]}</u>"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Callable
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Iterable
|
from collections.abc import Iterable
|
||||||
|
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from aqt import gui_hooks
|
from aqt import gui_hooks
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Sequence
|
from collections.abc import Callable, Sequence
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.customstudy
|
import aqt.customstudy
|
||||||
|
|
|
@ -8,7 +8,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Callable, List, Tuple
|
from typing import Callable
|
||||||
|
|
||||||
import anki.lang
|
import anki.lang
|
||||||
import aqt
|
import aqt
|
||||||
|
@ -386,7 +386,7 @@ def get_linux_dark_mode() -> bool:
|
||||||
|
|
||||||
return dbus_response[-1] == PREFER_DARK
|
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 "
|
"dbus-send --session --print-reply=literal --reply-timeout=1000 "
|
||||||
"--dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop "
|
"--dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop "
|
||||||
|
|
|
@ -4,7 +4,8 @@ from __future__ import annotations
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import re
|
import re
|
||||||
from typing import Any, Callable, Optional, cast
|
from collections.abc import Callable
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
from anki.sync import SyncStatus
|
from anki.sync import SyncStatus
|
||||||
|
@ -86,7 +87,7 @@ class TopWebView(ToolbarWebView):
|
||||||
|
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def _onHeight(self, qvar: Optional[int]) -> None:
|
def _onHeight(self, qvar: int | None) -> None:
|
||||||
super()._onHeight(qvar)
|
super()._onHeight(qvar)
|
||||||
if qvar:
|
if qvar:
|
||||||
self.web_height = int(qvar)
|
self.web_height = int(qvar)
|
||||||
|
|
|
@ -9,9 +9,10 @@ import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from collections.abc import Sequence
|
||||||
from functools import partial, wraps
|
from functools import partial, wraps
|
||||||
from pathlib import Path
|
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
|
from send2trash import send2trash
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,9 @@ import dataclasses
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from collections.abc import Sequence
|
||||||
from enum import Enum
|
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
|
||||||
import anki.lang
|
import anki.lang
|
||||||
|
@ -524,10 +525,10 @@ html {{ {font} }}
|
||||||
def stdHtml(
|
def stdHtml(
|
||||||
self,
|
self,
|
||||||
body: str,
|
body: str,
|
||||||
css: Optional[list[str]] = None,
|
css: list[str] | None = None,
|
||||||
js: Optional[list[str]] = None,
|
js: list[str] | None = None,
|
||||||
head: str = "",
|
head: str = "",
|
||||||
context: Optional[Any] = None,
|
context: Any | None = None,
|
||||||
default_css: bool = True,
|
default_css: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
css = (["css/webview.css"] if default_css else []) + (
|
css = (["css/webview.css"] if default_css else []) + (
|
||||||
|
@ -705,7 +706,7 @@ html {{ {font} }}
|
||||||
def adjustHeightToFit(self) -> None:
|
def adjustHeightToFit(self) -> None:
|
||||||
self.evalWithCallback("document.documentElement.offsetHeight", self._onHeight)
|
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
|
from aqt import mw
|
||||||
|
|
||||||
if qvar is None:
|
if qvar is None:
|
||||||
|
@ -842,5 +843,5 @@ html {{ {font} }}
|
||||||
)
|
)
|
||||||
|
|
||||||
@deprecated(info="use theme_manager.qcolor() instead")
|
@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)
|
return theme_manager.qcolor(colors.CANVAS)
|
||||||
|
|
Loading…
Reference in a new issue