diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index 703cf13fb..4e04bf453 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -37,6 +37,8 @@ class Card: ord: int nid: anki.notes.NoteID id: CardID + did: anki.decks.DeckID + odid: anki.decks.DeckID def __init__( self, col: anki.collection.Collection, id: Optional[CardID] = None @@ -62,7 +64,7 @@ class Card: self._note = None self.id = CardID(c.id) self.nid = anki.notes.NoteID(c.note_id) - self.did = c.deck_id + self.did = anki.decks.DeckID(c.deck_id) self.ord = c.template_idx self.mod = c.mtime_secs self.usn = c.usn @@ -75,7 +77,7 @@ class Card: self.lapses = c.lapses self.left = c.remaining_steps self.odue = c.original_due - self.odid = c.original_deck_id + self.odid = anki.decks.DeckID(c.original_deck_id) self.flags = c.flags self.data = c.data @@ -163,7 +165,7 @@ class Card: def startTimer(self) -> None: self.timerStarted = time.time() - def currentDeckID(self) -> int: + def currentDeckID(self) -> anki.decks.DeckID: return anki.decks.DeckID(self.odid or self.did) def timeLimit(self) -> int: diff --git a/pylib/anki/collection.py b/pylib/anki/collection.py index bf9d31519..761d66e65 100644 --- a/pylib/anki/collection.py +++ b/pylib/anki/collection.py @@ -38,7 +38,7 @@ from anki.cards import Card, CardID from anki.config import Config, ConfigManager from anki.consts import * from anki.dbproxy import DBProxy -from anki.decks import DeckManager +from anki.decks import DeckID, DeckManager from anki.errors import AnkiError, DBError from anki.lang import TR, FormatTimeSpan from anki.media import MediaManager, media_paths_from_col_path @@ -370,7 +370,7 @@ class Collection: def new_note(self, notetype: NoteType) -> Note: return Note(self, notetype) - def add_note(self, note: Note, deck_id: int) -> OpChanges: + def add_note(self, note: Note, deck_id: DeckID) -> OpChanges: out = self._backend.add_note(note=note._to_backend_note(), deck_id=deck_id) note.id = NoteID(out.note_id) return out.changes @@ -400,21 +400,23 @@ class Collection: if card := current_review_card: home_deck = card.currentDeckID() else: - home_deck = 0 + home_deck = DeckID(0) return self._backend.defaults_for_adding( home_deck_of_current_review_card=home_deck, ) - def default_deck_for_notetype(self, notetype_id: NoteID) -> Optional[int]: + def default_deck_for_notetype(self, notetype_id: NoteID) -> Optional[DeckID]: """If 'change deck depending on notetype' is enabled in the preferences, return the last deck used with the provided notetype, if any..""" if self.get_config_bool(Config.Bool.ADDING_DEFAULTS_TO_CURRENT_DECK): return None return ( - self._backend.default_deck_for_notetype( - ntid=notetype_id, + DeckID( + self._backend.default_deck_for_notetype( + ntid=notetype_id, + ) ) or None ) diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 7bc8dd37f..7dde55020 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -31,7 +31,7 @@ DeckDict = Dict[str, Any] DeckConfigDict = Dict[str, Any] DeckID = NewType("DeckID", int) -default_deck_id = 1 +default_deck_id = DeckID(1) default_deck_conf_id = 1 @@ -45,7 +45,7 @@ class DecksDictProxy: def __getitem__(self, item: Any) -> Any: self._warn() - return self._col.decks.get(int(item)) + return self._col.decks.get(DeckID(int(item))) def __setitem__(self, key: Any, val: Any) -> None: self._warn() @@ -124,7 +124,7 @@ class DeckManager: name: str, create: bool = True, type: int = 0, - ) -> Optional[int]: + ) -> Optional[DeckID]: "Add a deck with NAME. Reuse deck if already exists. Return id as int." id = self.id_for_name(name) if id: @@ -135,17 +135,17 @@ class DeckManager: deck = self.new_deck_legacy(bool(type)) deck["name"] = name out = self.add_deck_legacy(deck) - return out.id + return DeckID(out.id) @legacy_func(sub="remove") - def rem(self, did: int, cardsToo: bool = True, childrenToo: bool = True) -> None: + def rem(self, did: DeckID, cardsToo: bool = True, childrenToo: bool = True) -> None: "Remove the deck. If cardsToo, delete any cards inside." if isinstance(did, str): did = int(did) assert cardsToo and childrenToo self.remove([did]) - def remove(self, dids: Sequence[int]) -> OpChangesWithCount: + def remove(self, dids: Sequence[DeckID]) -> OpChangesWithCount: return self.col._backend.remove_decks(dids) def all_names_and_ids( @@ -156,20 +156,20 @@ class DeckManager: skip_empty_default=skip_empty_default, include_filtered=include_filtered ) - def id_for_name(self, name: str) -> Optional[int]: + def id_for_name(self, name: str) -> Optional[DeckID]: try: - return self.col._backend.get_deck_id_by_name(name) + return DeckID(self.col._backend.get_deck_id_by_name(name)) except NotFoundError: return None - def get_legacy(self, did: int) -> Optional[DeckDict]: + def get_legacy(self, did: DeckID) -> Optional[DeckDict]: try: return from_json_bytes(self.col._backend.get_deck_legacy(did)) except NotFoundError: return None - def have(self, id: int) -> bool: - return not self.get_legacy(int(id)) + def have(self, id: DeckID) -> bool: + return not self.get_legacy(id) def get_all_legacy(self) -> List[DeckDict]: return list(from_json_bytes(self.col._backend.get_all_decks_legacy()).values()) @@ -191,7 +191,7 @@ class DeckManager: @classmethod def find_deck_in_tree( - cls, node: DeckTreeNode, deck_id: int + cls, node: DeckTreeNode, deck_id: DeckID ) -> Optional[DeckTreeNode]: if node.deck_id == deck_id: return node @@ -218,12 +218,12 @@ class DeckManager: ) ] - def collapse(self, did: int) -> None: + def collapse(self, did: DeckID) -> None: deck = self.get(did) deck["collapsed"] = not deck["collapsed"] self.save(deck) - def collapseBrowser(self, did: int) -> None: + def collapseBrowser(self, did: DeckID) -> None: deck = self.get(did) collapsed = deck.get("browserCollapsed", False) deck["browserCollapsed"] = not collapsed @@ -233,7 +233,7 @@ class DeckManager: return len(self.all_names_and_ids()) def card_count( - self, dids: Union[int, Iterable[int]], include_subdecks: bool + self, dids: Union[DeckID, Iterable[DeckID]], include_subdecks: bool ) -> Any: if isinstance(dids, int): dids = {dids} @@ -247,13 +247,13 @@ class DeckManager: ) return count - def get(self, did: Union[int, str], default: bool = True) -> Optional[DeckDict]: + def get(self, did: Union[DeckID, str], default: bool = True) -> Optional[DeckDict]: if not did: if default: return self.get_legacy(default_deck_id) else: return None - id = int(did) + id = DeckID(int(did)) deck = self.get_legacy(id) if deck: return deck @@ -297,7 +297,9 @@ class DeckManager: # legacy def renameForDragAndDrop( - self, draggedDeckDid: Union[int, str], ontoDeckDid: Optional[Union[int, str]] + self, + draggedDeckDid: Union[DeckID, str], + ontoDeckDid: Optional[Union[DeckID, str]], ) -> None: if not ontoDeckDid: onto = 0 @@ -312,7 +314,7 @@ class DeckManager: "A list of all deck config." return list(from_json_bytes(self.col._backend.all_deck_config_legacy())) - def confForDid(self, did: int) -> DeckConfigDict: + def confForDid(self, did: DeckID) -> DeckConfigDict: deck = self.get(did, default=False) assert deck if "conf" in deck: @@ -370,7 +372,7 @@ class DeckManager: grp["conf"] = id self.save(grp) - def didsForConf(self, conf: DeckConfigDict) -> List[int]: + def didsForConf(self, conf: DeckConfigDict) -> List[DeckID]: dids = [] for deck in self.all(): if "conf" in deck and deck["conf"] == conf["id"]: @@ -397,19 +399,19 @@ class DeckManager: # Deck utils ############################################################# - def name(self, did: int, default: bool = False) -> str: + def name(self, did: DeckID, default: bool = False) -> str: deck = self.get(did, default=default) if deck: return deck["name"] return self.col.tr(TR.DECKS_NO_DECK) - def name_if_exists(self, did: int) -> Optional[str]: + def name_if_exists(self, did: DeckID) -> Optional[str]: deck = self.get(did, default=False) if deck: return deck["name"] return None - def setDeck(self, cids: List[CardID], did: int) -> None: + def setDeck(self, cids: List[CardID], did: DeckID) -> None: self.col.db.execute( f"update cards set did=?,usn=?,mod=? where id in {ids2str(cids)}", did, @@ -417,7 +419,7 @@ class DeckManager: intTime(), ) - def cids(self, did: int, children: bool = False) -> List[CardID]: + def cids(self, did: DeckID, children: bool = False) -> List[CardID]: if not children: return self.col.db.list("select id from cards where did=?", did) dids = [did] @@ -425,13 +427,13 @@ class DeckManager: dids.append(id) return self.col.db.list(f"select id from cards where did in {ids2str(dids)}") - def for_card_ids(self, cids: List[CardID]) -> List[int]: + def for_card_ids(self, cids: List[CardID]) -> List[DeckID]: return self.col.db.list(f"select did from cards where id in {ids2str(cids)}") # Deck selection ############################################################# - def active(self) -> List[int]: + def active(self) -> List[DeckID]: "The currrently active dids." return self.col.get_config("activeDecks", [1]) @@ -442,10 +444,9 @@ class DeckManager: def current(self) -> DeckDict: return self.get(self.selected()) - def select(self, did: int) -> None: + def select(self, did: DeckID) -> None: "Select a new branch." # make sure arg is an int - did = int(did) current = self.selected() active = self.deck_and_child_ids(did) if current != did or active != self.active(): @@ -486,29 +487,31 @@ class DeckManager: def key(cls, deck: DeckDict) -> List[str]: return cls.path(deck["name"]) - def children(self, did: int) -> List[Tuple[str, int]]: + def children(self, did: DeckID) -> List[Tuple[str, DeckID]]: "All children of did, as (name, id)." name = self.get(did)["name"] actv = [] for g in self.all_names_and_ids(): if g.name.startswith(f"{name}::"): - actv.append((g.name, g.id)) + actv.append((g.name, DeckID(g.id))) return actv - def child_ids(self, parent_name: str) -> Iterable[int]: + def child_ids(self, parent_name: str) -> Iterable[DeckID]: prefix = f"{parent_name}::" - return (d.id for d in self.all_names_and_ids() if d.name.startswith(prefix)) + return ( + DeckID(d.id) for d in self.all_names_and_ids() if d.name.startswith(prefix) + ) - def deck_and_child_ids(self, deck_id: int) -> List[int]: + def deck_and_child_ids(self, deck_id: DeckID) -> List[DeckID]: parent_name = self.get_legacy(deck_id)["name"] out = [deck_id] out.extend(self.child_ids(parent_name)) return out - childMapNode = Dict[int, Any] + childMapNode = Dict[DeckID, Any] # Change to Dict[int, "DeckManager.childMapNode"] when MyPy allow recursive type - def childDids(self, did: int, childMap: DeckManager.childMapNode) -> List: + def childDids(self, did: DeckID, childMap: DeckManager.childMapNode) -> List: def gather(node: DeckManager.childMapNode, arr: List) -> None: for did, child in node.items(): arr.append(did) @@ -536,7 +539,7 @@ class DeckManager: return childMap def parents( - self, did: int, nameMap: Optional[Dict[str, DeckDict]] = None + self, did: DeckID, nameMap: Optional[Dict[str, DeckDict]] = None ) -> List[DeckDict]: "All parents of did." # get parent and grandparent names @@ -578,14 +581,14 @@ class DeckManager: # Dynamic decks ########################################################################## - def new_filtered(self, name: str) -> int: + def new_filtered(self, name: str) -> DeckID: "Return a new dynamic deck and set it as the current deck." did = self.id(name, type=default_deck_conf_id) self.select(did) return did # 1 for dyn, 0 for standard - def isDyn(self, did: Union[int, str]) -> int: + def isDyn(self, did: Union[DeckID, str]) -> int: return self.get(did)["dyn"] # legacy diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 1a559c448..f169dfb91 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -14,6 +14,7 @@ from zipfile import ZipFile from anki import hooks from anki.cards import CardID from anki.collection import Collection +from anki.decks import DeckID from anki.lang import TR from anki.utils import ids2str, namedtmp, splitFields, stripHTML @@ -28,7 +29,7 @@ class Exporter: def __init__( self, col: Collection, - did: Optional[int] = None, + did: Optional[DeckID] = None, cids: Optional[List[CardID]] = None, ) -> None: self.col = col.weakref() @@ -185,7 +186,7 @@ class AnkiExporter(Exporter): def key(col: Collection) -> str: return col.tr(TR.EXPORTING_ANKI_20_DECK) - def deckIds(self) -> List[int]: + def deckIds(self) -> List[DeckID]: if self.cids: return self.col.decks.for_card_ids(self.cids) elif self.did: diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 15eb3b606..5cd5824d9 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional, Tuple from anki.cards import CardID from anki.collection import Collection from anki.consts import * -from anki.decks import DeckManager +from anki.decks import DeckID, DeckManager from anki.importing.base import Importer from anki.lang import TR from anki.notes import NoteID @@ -31,7 +31,7 @@ class Anki2Importer(Importer): super().__init__(col, file) # set later, defined here for typechecking - self._decks: Dict[int, int] = {} + self._decks: Dict[DeckID, DeckID] = {} self.source_needs_upgrade = False def run(self, media: None = None) -> None: @@ -256,7 +256,7 @@ class Anki2Importer(Importer): # Decks ###################################################################### - def _did(self, did: int) -> Any: + def _did(self, did: DeckID) -> Any: "Given did in src col, return local id." # already converted? if did in self._decks: diff --git a/pylib/anki/scheduler/base.py b/pylib/anki/scheduler/base.py index e61bae378..6c9e3ea8d 100644 --- a/pylib/anki/scheduler/base.py +++ b/pylib/anki/scheduler/base.py @@ -91,10 +91,10 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l # Filtered deck handling ########################################################################## - def rebuild_filtered_deck(self, deck_id: int) -> OpChangesWithCount: + def rebuild_filtered_deck(self, deck_id: DeckID) -> OpChangesWithCount: return self.col._backend.rebuild_filtered_deck(deck_id) - def empty_filtered_deck(self, deck_id: int) -> OpChanges: + def empty_filtered_deck(self, deck_id: DeckID) -> OpChanges: return self.col._backend.empty_filtered_deck(deck_id) def get_or_create_filtered_deck(self, deck_id: DeckID) -> FilteredDeckForUpdate: @@ -199,10 +199,10 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l shift_existing=shift_existing, ) - def randomizeCards(self, did: int) -> None: + def randomizeCards(self, did: DeckID) -> None: self.col._backend.sort_deck(deck_id=did, randomize=True) - def orderCards(self, did: int) -> None: + def orderCards(self, did: DeckID) -> None: self.col._backend.sort_deck(deck_id=did, randomize=False) def resortConf(self, conf: DeckConfigDict) -> None: @@ -213,7 +213,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l self.orderCards(did) # for post-import - def maybeRandomizeDeck(self, did: Optional[int] = None) -> None: + def maybeRandomizeDeck(self, did: Optional[DeckID] = None) -> None: if not did: did = self.col.decks.selected() conf = self.col.decks.confForDid(did) diff --git a/pylib/anki/scheduler/legacy.py b/pylib/anki/scheduler/legacy.py index 6eb2e1023..7aafc0192 100644 --- a/pylib/anki/scheduler/legacy.py +++ b/pylib/anki/scheduler/legacy.py @@ -5,7 +5,7 @@ from typing import List, Optional, Tuple from anki.cards import Card, CardID from anki.consts import CARD_TYPE_RELEARNING, QUEUE_TYPE_DAY_LEARN_RELEARN -from anki.decks import DeckConfigDict +from anki.decks import DeckConfigDict, DeckID from anki.notes import NoteID from anki.scheduler.base import SchedulerBase, UnburyCurrentDeck from anki.utils import from_json_bytes, ids2str @@ -49,7 +49,7 @@ class SchedulerBaseWithLegacy(SchedulerBase): print("_nextDueMsg() is obsolete") return "" - def rebuildDyn(self, did: Optional[int] = None) -> Optional[int]: + def rebuildDyn(self, did: Optional[DeckID] = None) -> Optional[int]: did = did or self.col.decks.selected() count = self.rebuild_filtered_deck(did).count or None if not count: @@ -58,7 +58,7 @@ class SchedulerBaseWithLegacy(SchedulerBase): self.col.decks.select(did) return count - def emptyDyn(self, did: Optional[int], lim: Optional[str] = None) -> None: + def emptyDyn(self, did: Optional[DeckID], lim: Optional[str] = None) -> None: if lim is None: self.empty_filtered_deck(did) return @@ -86,7 +86,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe # used by v2 scheduler and some add-ons def update_stats( self, - deck_id: int, + deck_id: DeckID, new_delta: int = 0, review_delta: int = 0, milliseconds_delta: int = 0, diff --git a/pylib/anki/scheduler/v1.py b/pylib/anki/scheduler/v1.py index 6aec92fab..3d1c3c39c 100644 --- a/pylib/anki/scheduler/v1.py +++ b/pylib/anki/scheduler/v1.py @@ -12,6 +12,7 @@ import anki from anki import hooks from anki.cards import Card from anki.consts import * +from anki.decks import DeckID from anki.utils import ids2str, intTime from .v2 import QueueConfig @@ -299,7 +300,7 @@ limit %d""" if card.odid: card.did = card.odid card.odue = 0 - card.odid = 0 + card.odid = DeckID(0) # if rescheduling is off, it needs to be set back to a new card if not resched and not lapse: card.queue = card.type = CARD_TYPE_NEW @@ -401,7 +402,7 @@ where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type = {CAR ) ) - def _lrnForDeck(self, did: int) -> int: + def _lrnForDeck(self, did: DeckID) -> int: cnt = ( self.col.db.scalar( f""" @@ -426,7 +427,7 @@ and due <= ? limit ?)""", # Reviews ########################################################################## - def _deckRevLimit(self, did: int) -> int: + def _deckRevLimit(self, did: DeckID) -> int: return self._deckNewLimit(did, self._deckRevLimitSingle) def _resetRev(self) -> None: @@ -541,7 +542,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""", card.due = card.odue if card.odid: card.did = card.odid - card.odid = 0 + card.odid = DeckID(0) card.odue = 0 # Interval management @@ -617,7 +618,8 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""", card.due = card.odue if card.odid: card.did = card.odid - card.odue = card.odid = 0 + card.odue = 0 + card.odid = DeckID(0) card.queue = QUEUE_TYPE_SUSPENDED # notify UI hooks.card_did_leech(card) diff --git a/pylib/anki/scheduler/v2.py b/pylib/anki/scheduler/v2.py index a6d1aa8c5..31fcd0f67 100644 --- a/pylib/anki/scheduler/v2.py +++ b/pylib/anki/scheduler/v2.py @@ -13,7 +13,7 @@ import anki._backend.backend_pb2 as _pb from anki import hooks from anki.cards import Card, CardID from anki.consts import * -from anki.decks import DeckConfigDict, DeckDict +from anki.decks import DeckConfigDict, DeckDict, DeckID from anki.lang import FormatTimeSpan from anki.scheduler.legacy import SchedulerBaseWithLegacy from anki.utils import ids2str, intTime @@ -75,7 +75,9 @@ class Scheduler(SchedulerBaseWithLegacy): def _reset_counts(self) -> None: tree = self.deck_due_tree(self.col.decks.selected()) - node = self.col.decks.find_deck_in_tree(tree, int(self.col.conf["curDeck"])) + node = self.col.decks.find_deck_in_tree( + tree, DeckID(int(self.col.conf["curDeck"])) + ) if not node: # current deck points to a missing deck self.newCount = 0 @@ -210,7 +212,7 @@ class Scheduler(SchedulerBaseWithLegacy): return None def _deckNewLimit( - self, did: int, fn: Optional[Callable[[DeckDict], int]] = None + self, did: DeckID, fn: Optional[Callable[[DeckDict], int]] = None ) -> int: if not fn: fn = self._deckNewLimitSingle @@ -225,7 +227,7 @@ class Scheduler(SchedulerBaseWithLegacy): lim = min(rem, lim) return lim - def _newForDeck(self, did: int, lim: int) -> int: + def _newForDeck(self, did: DeckID, lim: int) -> int: "New count for a single deck." if not lim: return 0 @@ -788,7 +790,7 @@ limit ?""" if card.odid: card.did = card.odid card.odue = 0 - card.odid = 0 + card.odid = DeckID(0) def _restorePreviewCard(self, card: Card) -> None: assert card.odid diff --git a/pylib/anki/tags.py b/pylib/anki/tags.py index fa57d7502..036fb4efa 100644 --- a/pylib/anki/tags.py +++ b/pylib/anki/tags.py @@ -19,6 +19,7 @@ import anki # pylint: disable=unused-import import anki._backend.backend_pb2 as _pb import anki.collection from anki.collection import OpChangesWithCount +from anki.decks import DeckID from anki.notes import NoteID from anki.utils import ids2str @@ -49,7 +50,7 @@ class TagManager: def clear_unused_tags(self) -> OpChangesWithCount: return self.col._backend.clear_unused_tags() - def byDeck(self, did: int, children: bool = False) -> List[str]: + def byDeck(self, did: DeckID, children: bool = False) -> List[str]: basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id" if not children: query = f"{basequery} AND c.did=?" diff --git a/qt/aqt/addcards.py b/qt/aqt/addcards.py index fc57e8831..66f13c037 100644 --- a/qt/aqt/addcards.py +++ b/qt/aqt/addcards.py @@ -8,6 +8,7 @@ import aqt.editor import aqt.forms from anki.collection import OpChanges, SearchNode from anki.consts import MODEL_CLOZE +from anki.decks import DeckID from anki.notes import DuplicateOrEmptyResult, Note, NoteID from anki.utils import htmlToTextLine, isMac from aqt import AnkiQt, gui_hooks @@ -69,7 +70,7 @@ class AddCards(QDialog): on_notetype_changed=self.on_notetype_change, ) self.deck_chooser = aqt.deckchooser.DeckChooser( - self.mw, self.form.deckArea, starting_deck_id=defaults.deck_id + self.mw, self.form.deckArea, starting_deck_id=DeckID(defaults.deck_id) ) def helpRequested(self) -> None: diff --git a/qt/aqt/deckbrowser.py b/qt/aqt/deckbrowser.py index ddf297189..ecb326d00 100644 --- a/qt/aqt/deckbrowser.py +++ b/qt/aqt/deckbrowser.py @@ -40,7 +40,7 @@ class DeckBrowserContent: @dataclass class RenderDeckNodeContext: - current_deck_id: int + current_deck_id: DeckID class DeckBrowser: @@ -101,7 +101,7 @@ class DeckBrowser: source, target = arg.split(",") self._handle_drag_and_drop(DeckID(int(source)), DeckID(int(target or 0))) elif cmd == "collapse": - self._collapse(int(arg)) + self._collapse(DeckID(int(arg))) elif cmd == "v2upgrade": self._confirm_upgrade() elif cmd == "v2upgradeinfo": @@ -112,7 +112,7 @@ class DeckBrowser: return False def _selDeck(self, did: str) -> None: - self.mw.col.decks.select(int(did)) + self.mw.col.decks.select(DeckID(int(did))) self.mw.onOverview() # HTML generation @@ -255,13 +255,13 @@ class DeckBrowser: a = m.addAction(tr(TR.ACTIONS_OPTIONS)) qconnect(a.triggered, lambda b, did=did: self._options(DeckID(int(did)))) a = m.addAction(tr(TR.ACTIONS_EXPORT)) - qconnect(a.triggered, lambda b, did=did: self._export(int(did))) + qconnect(a.triggered, lambda b, did=did: self._export(DeckID(int(did)))) a = m.addAction(tr(TR.ACTIONS_DELETE)) qconnect(a.triggered, lambda b, did=did: self._delete(DeckID(int(did)))) gui_hooks.deck_browser_will_show_options_menu(m, int(did)) m.exec_(QCursor.pos()) - def _export(self, did: int) -> None: + def _export(self, did: DeckID) -> None: self.mw.onExport(did=did) def _rename(self, did: DeckID) -> None: @@ -279,7 +279,7 @@ class DeckBrowser: self.mw.col.decks.select(did) self.mw.onDeckConf() - def _collapse(self, did: int) -> None: + def _collapse(self, did: DeckID) -> None: self.mw.col.decks.collapse(did) node = self.mw.col.decks.find_deck_in_tree(self._dueTree, did) if node: diff --git a/qt/aqt/deckchooser.py b/qt/aqt/deckchooser.py index a6fc08da8..81ddc5ba8 100644 --- a/qt/aqt/deckchooser.py +++ b/qt/aqt/deckchooser.py @@ -3,7 +3,7 @@ from typing import Optional -from anki.decks import default_deck_id +from anki.decks import DeckID, default_deck_id from aqt import AnkiQt from aqt.qt import * from aqt.utils import TR, HelpPage, shortcut, tr @@ -15,17 +15,17 @@ class DeckChooser(QHBoxLayout): mw: AnkiQt, widget: QWidget, label: bool = True, - starting_deck_id: Optional[int] = None, + starting_deck_id: Optional[DeckID] = None, ) -> None: QHBoxLayout.__init__(self) self._widget = widget # type: ignore self.mw = mw self._setup_ui(show_label=label) - self._selected_deck_id = 0 + self._selected_deck_id = DeckID(0) # default to current deck if starting id not provided if starting_deck_id is None: - starting_deck_id = self.mw.col.get_config("curDeck", default=1) or 1 + starting_deck_id = DeckID(self.mw.col.get_config("curDeck", default=1) or 1) self.selected_deck_id = starting_deck_id def _setup_ui(self, show_label: bool) -> None: @@ -57,13 +57,13 @@ class DeckChooser(QHBoxLayout): ) @property - def selected_deck_id(self) -> int: + def selected_deck_id(self) -> DeckID: self._ensure_selected_deck_valid() return self._selected_deck_id @selected_deck_id.setter - def selected_deck_id(self, id: int) -> None: + def selected_deck_id(self, id: DeckID) -> None: if id != self._selected_deck_id: self._selected_deck_id = id self._ensure_selected_deck_valid() @@ -104,7 +104,7 @@ class DeckChooser(QHBoxLayout): onDeckChange = choose_deck deckName = selected_deck_name - def selectedId(self) -> int: + def selectedId(self) -> DeckID: return self.selected_deck_id def cleanup(self) -> None: diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index bb5ec145c..45fc0a1b5 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -12,6 +12,7 @@ from typing import List, Optional import aqt from anki import hooks from anki.cards import CardID +from anki.decks import DeckID from anki.exporting import Exporter, exporters from aqt.qt import * from aqt.utils import ( @@ -29,7 +30,7 @@ class ExportDialog(QDialog): def __init__( self, mw: aqt.main.AnkiQt, - did: Optional[int] = None, + did: Optional[DeckID] = None, cids: Optional[List[CardID]] = None, ): QDialog.__init__(self, mw, Qt.Window) @@ -43,7 +44,7 @@ class ExportDialog(QDialog): self.setup(did) self.exec_() - def setup(self, did: Optional[int]) -> None: + def setup(self, did: Optional[DeckID]) -> None: self.exporters = exporters(self.col) # if a deck specified, start with .apkg type selected idx = 0 diff --git a/qt/aqt/main.py b/qt/aqt/main.py index e8e8fcd59..ca67ac452 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -52,7 +52,7 @@ from anki.collection import ( UndoResult, UndoStatus, ) -from anki.decks import DeckDict +from anki.decks import DeckDict, DeckID from anki.hooks import runHook from anki.notes import NoteID from anki.sound import AVTag, SoundOrVideoTag @@ -518,7 +518,7 @@ class AnkiQt(QMainWindow): except Exception as e: if "FileTooNew" in str(e): showWarning( - "This profile requires a newer version of Anki to open. Did you forget to use the Downgrade button prior to switching Anki versions?" + "This profile requires a newer version of Anki to open. DeckID you forget to use the Downgrade button prior to switching Anki versions?" ) else: showWarning( @@ -1382,7 +1382,7 @@ title="%s" %s>%s""" % ( aqt.importing.onImport(self) - def onExport(self, did: Optional[int] = None) -> None: + def onExport(self, did: Optional[DeckID] = None) -> None: import aqt.exporting aqt.exporting.ExportDialog(self, did=did) diff --git a/qt/aqt/note_ops.py b/qt/aqt/note_ops.py index 042490988..6df6a028e 100644 --- a/qt/aqt/note_ops.py +++ b/qt/aqt/note_ops.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import Callable, Sequence +from anki.decks import DeckID from anki.notes import Note, NoteID from aqt import AnkiQt from aqt.main import PerformOpOptionalSuccessCallback @@ -14,7 +15,7 @@ def add_note( *, mw: AnkiQt, note: Note, - target_deck_id: int, + target_deck_id: DeckID, success: PerformOpOptionalSuccessCallback = None, ) -> None: mw.perform_op(lambda: mw.col.add_note(note, target_deck_id), success=success) diff --git a/qt/aqt/sidebar.py b/qt/aqt/sidebar.py index 1827da0e0..e773b28fe 100644 --- a/qt/aqt/sidebar.py +++ b/qt/aqt/sidebar.py @@ -976,7 +976,7 @@ class SidebarTreeView(QTreeView): for node in nodes: def toggle_expand() -> Callable[[bool], None]: - did = node.deck_id # pylint: disable=cell-var-from-loop + did = DeckID(node.deck_id) # pylint: disable=cell-var-from-loop return lambda _: self.mw.col.decks.collapseBrowser(did) item = SidebarItem( @@ -1158,7 +1158,7 @@ class SidebarTreeView(QTreeView): ########################### def rename_deck(self, item: SidebarItem, new_name: str) -> None: - deck = self.mw.col.decks.get(item.id) + deck = self.mw.col.decks.get(DeckID(item.id)) if not new_name: return new_name = item.name_prefix + new_name diff --git a/qt/aqt/studydeck.py b/qt/aqt/studydeck.py index 6e18a3e8a..1156d662c 100644 --- a/qt/aqt/studydeck.py +++ b/qt/aqt/studydeck.py @@ -5,6 +5,7 @@ from typing import List, Optional import aqt from anki.collection import OpChangesWithID +from anki.decks import DeckID from aqt import gui_hooks from aqt.deck_ops import add_deck_dialog from aqt.qt import * @@ -167,7 +168,7 @@ class StudyDeck(QDialog): default = self.names[self.form.list.currentRow()] def success(out: OpChangesWithID) -> None: - deck = self.mw.col.decks.get(out.id) + deck = self.mw.col.decks.get(DeckID(out.id)) self.name = deck["name"] # make sure we clean up reset hook when manually exiting