rename&simplify the deck/config type aliases

- QueueConfig is only used by the scheduler
- DeckConfig was being used in places that Config should have been used
- Add "Dict" to the name so that the bare name is free for use with a
stronger type.
This commit is contained in:
Damien Elmes 2021-03-24 16:28:38 +10:00
parent 5a1b00b6e6
commit 181cda1979
10 changed files with 77 additions and 71 deletions

View File

@ -24,20 +24,9 @@ DeckNameID = _pb.DeckNameID
defaultDeck = 0
defaultDynamicDeck = 1
NonFilteredDeck = Dict[str, Any]
FilteredDeck = Dict[str, Any]
"""Any kind of deck """
Deck = Union[NonFilteredDeck, FilteredDeck]
"""Configuration of standard deck, as seen from the deck picker's gear."""
Config = Dict[str, Any]
"""Configurationf of some deck, filtered deck for filtered deck, config for standard deck"""
DeckConfig = Union[FilteredDeck, Config]
""" New/lrn/rev conf, from deck config"""
QueueConfig = Dict[str, Any]
# type aliases until we can move away from dicts
DeckDict = Dict[str, Any]
DeckConfigDict = Dict[str, Any]
DeckID = NewType("DeckID", int)
@ -87,7 +76,7 @@ class DeckManager:
self.col = col.weakref()
self.decks = DecksDictProxy(col)
def save(self, g: Union[Deck, Config] = None) -> None:
def save(self, g: Union[DeckDict, DeckConfigDict] = None) -> None:
"Can be called with either a deck or a deck configuration."
if not g:
print("col.decks.save() should be passed the changed deck")
@ -121,7 +110,7 @@ class DeckManager:
deck["name"] = name
return self.add_deck_legacy(deck)
def add_deck_legacy(self, deck: Deck) -> OpChangesWithID:
def add_deck_legacy(self, deck: DeckDict) -> OpChangesWithID:
"Add a deck created with new_deck_legacy(). Must have id of 0."
assert deck["id"] == 0
return self.col._backend.add_deck_legacy(to_json_bytes(deck))
@ -169,7 +158,7 @@ class DeckManager:
except NotFoundError:
return None
def get_legacy(self, did: int) -> Optional[Deck]:
def get_legacy(self, did: int) -> Optional[DeckDict]:
try:
return from_json_bytes(self.col._backend.get_deck_legacy(did))
except NotFoundError:
@ -178,10 +167,10 @@ class DeckManager:
def have(self, id: int) -> bool:
return not self.get_legacy(int(id))
def get_all_legacy(self) -> List[Deck]:
def get_all_legacy(self) -> List[DeckDict]:
return list(from_json_bytes(self.col._backend.get_all_decks_legacy()).values())
def new_deck_legacy(self, filtered: bool) -> Deck:
def new_deck_legacy(self, filtered: bool) -> DeckDict:
return from_json_bytes(self.col._backend.new_deck_legacy(filtered))
def deck_tree(self) -> DeckTreeNode:
@ -199,7 +188,7 @@ class DeckManager:
return match
return None
def all(self) -> List[Deck]:
def all(self) -> List[DeckDict]:
"All decks. Expensive; prefer all_names_and_ids()"
return self.get_all_legacy()
@ -245,7 +234,7 @@ class DeckManager:
)
return count
def get(self, did: Union[int, str], default: bool = True) -> Optional[Deck]:
def get(self, did: Union[int, str], default: bool = True) -> Optional[DeckDict]:
if not did:
if default:
return self.get_legacy(1)
@ -260,20 +249,20 @@ class DeckManager:
else:
return None
def byName(self, name: str) -> Optional[Deck]:
def byName(self, name: str) -> Optional[DeckDict]:
"""Get deck with NAME, ignoring case."""
id = self.id_for_name(name)
if id:
return self.get_legacy(id)
return None
def update(self, g: Deck, preserve_usn: bool = True) -> None:
def update(self, g: DeckDict, preserve_usn: bool = True) -> None:
"Add or update an existing deck. Used for syncing and merging."
g["id"] = self.col._backend.add_or_update_deck_legacy(
deck=to_json_bytes(g), preserve_usn_and_mtime=preserve_usn
)
def rename(self, deck: Union[Deck, DeckID], new_name: str) -> OpChanges:
def rename(self, deck: Union[DeckDict, DeckID], new_name: str) -> OpChanges:
"Rename deck prefix to NAME if not exists. Updates children."
if isinstance(deck, int):
deck_id = deck
@ -306,11 +295,11 @@ class DeckManager:
# Deck configurations
#############################################################
def all_config(self) -> List[Config]:
def all_config(self) -> List[DeckConfigDict]:
"A list of all deck config."
return list(from_json_bytes(self.col._backend.all_deck_config_legacy()))
def confForDid(self, did: int) -> DeckConfig:
def confForDid(self, did: int) -> DeckConfigDict:
deck = self.get(did, default=False)
assert deck
if "conf" in deck:
@ -324,20 +313,20 @@ class DeckManager:
# dynamic decks have embedded conf
return deck
def get_config(self, conf_id: int) -> Optional[DeckConfig]:
def get_config(self, conf_id: int) -> Optional[DeckConfigDict]:
try:
return from_json_bytes(self.col._backend.get_deck_config_legacy(conf_id))
except NotFoundError:
return None
def update_config(self, conf: DeckConfig, preserve_usn: bool = False) -> None:
def update_config(self, conf: DeckConfigDict, preserve_usn: bool = False) -> None:
conf["id"] = self.col._backend.add_or_update_deck_config_legacy(
config=to_json_bytes(conf), preserve_usn_and_mtime=preserve_usn
)
def add_config(
self, name: str, clone_from: Optional[DeckConfig] = None
) -> DeckConfig:
self, name: str, clone_from: Optional[DeckConfigDict] = None
) -> DeckConfigDict:
if clone_from is not None:
conf = copy.deepcopy(clone_from)
conf["id"] = 0
@ -348,7 +337,7 @@ class DeckManager:
return conf
def add_config_returning_id(
self, name: str, clone_from: Optional[DeckConfig] = None
self, name: str, clone_from: Optional[DeckConfigDict] = None
) -> int:
return self.add_config(name, clone_from)["id"]
@ -364,18 +353,18 @@ class DeckManager:
self.save(g)
self.col._backend.remove_deck_config(id)
def setConf(self, grp: DeckConfig, id: int) -> None:
def setConf(self, grp: DeckConfigDict, id: int) -> None:
grp["conf"] = id
self.save(grp)
def didsForConf(self, conf: DeckConfig) -> List[int]:
def didsForConf(self, conf: DeckConfigDict) -> List[int]:
dids = []
for deck in self.all():
if "conf" in deck and deck["conf"] == conf["id"]:
dids.append(deck["id"])
return dids
def restoreToDefault(self, conf: DeckConfig) -> None:
def restoreToDefault(self, conf: DeckConfigDict) -> None:
oldOrder = conf["new"]["order"]
new = from_json_bytes(self.col._backend.new_deck_config_legacy())
new["id"] = conf["id"]
@ -437,7 +426,7 @@ class DeckManager:
"The currently selected did."
return DeckID(int(self.col.conf["curDeck"]))
def current(self) -> Deck:
def current(self) -> DeckDict:
return self.get(self.selected())
def select(self, did: int) -> None:
@ -481,7 +470,7 @@ class DeckManager:
return None
@classmethod
def key(cls, deck: Deck) -> List[str]:
def key(cls, deck: DeckDict) -> List[str]:
return cls.path(deck["name"])
def children(self, did: int) -> List[Tuple[str, int]]:
@ -534,8 +523,8 @@ class DeckManager:
return childMap
def parents(
self, did: int, nameMap: Optional[Dict[str, Deck]] = None
) -> List[Deck]:
self, did: int, nameMap: Optional[Dict[str, DeckDict]] = None
) -> List[DeckDict]:
"All parents of did."
# get parent and grandparent names
parents_names: List[str] = []
@ -544,7 +533,7 @@ class DeckManager:
parents_names.append(part)
else:
parents_names.append(f"{parents_names[-1]}::{part}")
parents: List[Deck] = []
parents: List[DeckDict] = []
# convert to objects
for parent_name in parents_names:
if nameMap:
@ -554,13 +543,13 @@ class DeckManager:
parents.append(deck)
return parents
def parentsByName(self, name: str) -> List[Deck]:
def parentsByName(self, name: str) -> List[DeckDict]:
"All existing parents of name"
if "::" not in name:
return []
names = self.immediate_parent_path(name)
head = []
parents: List[Deck] = []
parents: List[DeckDict] = []
while names:
head.append(names.pop(0))
@ -570,7 +559,7 @@ class DeckManager:
return parents
def nameMap(self) -> Dict[str, Deck]:
def nameMap(self) -> Dict[str, DeckDict]:
return {d["name"]: d for d in self.all()}
# Dynamic decks

View File

@ -14,7 +14,7 @@ SchedTimingToday = _pb.SchedTimingTodayOut
from typing import List, Optional, Sequence
from anki.consts import CARD_TYPE_NEW, NEW_CARDS_RANDOM, QUEUE_TYPE_NEW, QUEUE_TYPE_REV
from anki.decks import DeckConfig, DeckTreeNode
from anki.decks import DeckConfigDict, DeckTreeNode
from anki.notes import Note
from anki.utils import ids2str, intTime
@ -195,7 +195,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
def orderCards(self, did: int) -> None:
self.col._backend.sort_deck(deck_id=did, randomize=False)
def resortConf(self, conf: DeckConfig) -> None:
def resortConf(self, conf: DeckConfigDict) -> None:
for did in self.col.decks.didsForConf(conf):
if conf["new"]["order"] == 0:
self.randomizeCards(did)

View File

@ -5,7 +5,7 @@ from typing import List, Optional, Tuple
from anki.cards import Card
from anki.consts import CARD_TYPE_RELEARNING, QUEUE_TYPE_DAY_LEARN_RELEARN
from anki.decks import DeckConfig
from anki.decks import DeckConfigDict
from anki.scheduler.base import SchedulerBase, UnburyCurrentDeck
from anki.utils import from_json_bytes, ids2str
@ -115,7 +115,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe
# legacy in v3 but used by unit tests; redefined in v2/v1
def _cardConf(self, card: Card) -> DeckConfig:
def _cardConf(self, card: Card) -> DeckConfigDict:
return self.col.decks.confForDid(card.did)
def _fuzzIvlRange(self, ivl: int) -> Tuple[int, int]:

View File

@ -12,9 +12,9 @@ import anki
from anki import hooks
from anki.cards import Card
from anki.consts import *
from anki.decks import QueueConfig
from anki.utils import ids2str, intTime
from .v2 import QueueConfig
from .v2 import Scheduler as V2
# queue types: 0=new/cram, 1=lrn, 2=rev, 3=day lrn, -1=suspended, -2=buried

View File

@ -13,7 +13,7 @@ import anki._backend.backend_pb2 as _pb
from anki import hooks
from anki.cards import Card
from anki.consts import *
from anki.decks import Deck, DeckConfig, QueueConfig
from anki.decks import DeckConfigDict, DeckDict
from anki.lang import FormatTimeSpan
from anki.scheduler.legacy import SchedulerBaseWithLegacy
from anki.utils import ids2str, intTime
@ -21,6 +21,9 @@ from anki.utils import ids2str, intTime
CountsForDeckToday = _pb.CountsForDeckTodayOut
SchedTimingToday = _pb.SchedTimingTodayOut
# legacy type alias
QueueConfig = Dict[str, Any]
# card types: 0=new, 1=lrn, 2=rev, 3=relrn
# queue types: 0=new, 1=(re)lrn, 2=rev, 3=day (re)lrn,
# 4=preview, -1=suspended, -2=sibling buried, -3=manually buried
@ -207,7 +210,7 @@ class Scheduler(SchedulerBaseWithLegacy):
return None
def _deckNewLimit(
self, did: int, fn: Optional[Callable[[Deck], int]] = None
self, did: int, fn: Optional[Callable[[DeckDict], int]] = None
) -> int:
if not fn:
fn = self._deckNewLimitSingle
@ -235,7 +238,7 @@ select count() from
lim,
)
def _deckNewLimitSingle(self, g: DeckConfig) -> int:
def _deckNewLimitSingle(self, g: DeckConfigDict) -> int:
"Limit for deck without parent limits."
if g["dyn"]:
return self.dynReportLimit
@ -490,7 +493,7 @@ limit ?"""
if card.odue:
card.odue = 0
def _cardConf(self, card: Card) -> DeckConfig:
def _cardConf(self, card: Card) -> DeckConfigDict:
return self.col.decks.confForDid(card.did)
def _deckLimit(self) -> str:

View File

@ -76,21 +76,23 @@ hooks = [
),
Hook(
name="scheduler_new_limit_for_single_deck",
args=["count: int", "deck: anki.decks.Deck"],
args=["count: int", "deck: anki.decks.DeckDict"],
return_type="int",
doc="""Allows changing the number of new card for this deck (without
considering descendants).""",
),
Hook(
name="scheduler_review_limit_for_single_deck",
args=["count: int", "deck: anki.decks.Deck"],
args=["count: int", "deck: anki.decks.DeckDict"],
return_type="int",
doc="""Allows changing the number of rev card for this deck (without
considering descendants).""",
),
# obsolete
Hook(
name="deck_added", args=["deck: anki.decks.Deck"], doc="Obsolete, do not use."
name="deck_added",
args=["deck: anki.decks.DeckDict"],
doc="Obsolete, do not use.",
),
Hook(
name="note_type_added",

View File

@ -7,7 +7,7 @@ from PyQt5.QtWidgets import QLineEdit
import aqt
from anki.consts import NEW_CARDS_RANDOM
from anki.decks import DeckConfig
from anki.decks import DeckConfigDict
from anki.lang import without_unicode_isolation
from aqt import gui_hooks
from aqt.qt import *
@ -72,7 +72,7 @@ class DeckConf(QDialog):
def setupConfs(self) -> None:
qconnect(self.form.dconf.currentIndexChanged, self.onConfChange)
self.conf: Optional[DeckConfig] = None
self.conf: Optional[DeckConfigDict] = None
self.loadConfs()
def loadConfs(self) -> None:

View File

@ -4,7 +4,7 @@ from typing import Callable, List, Optional, Tuple
import aqt
from anki.collection import SearchNode
from anki.decks import Deck
from anki.decks import DeckDict
from anki.errors import DeckIsFilteredError, InvalidInput
from anki.lang import without_unicode_isolation
from aqt import AnkiQt, colors, gui_hooks
@ -32,7 +32,7 @@ class FilteredDeckConfigDialog(QDialog):
mw: AnkiQt,
search: Optional[str] = None,
search_2: Optional[str] = None,
deck: Optional[Deck] = None,
deck: Optional[DeckDict] = None,
) -> None:
"""If 'deck' is an existing filtered deck, load and modify its settings.
Otherwise, build a new one and derive settings from the current deck.
@ -99,7 +99,7 @@ class FilteredDeckConfigDialog(QDialog):
_mw: AnkiQt,
search: Optional[str] = None,
search_2: Optional[str] = None,
_deck: Optional[Deck] = None,
_deck: Optional[DeckDict] = None,
) -> None:
self.set_custom_searches(search, search_2)
@ -222,7 +222,7 @@ class FilteredDeckConfigDialog(QDialog):
not self.form.resched.isChecked() and self.col.schedVer() > 1
)
def loadConf(self, deck: Optional[Deck] = None) -> None:
def loadConf(self, deck: Optional[DeckDict] = None) -> None:
f = self.form
d = deck or self.deck

View File

@ -52,7 +52,7 @@ from anki.collection import (
UndoResult,
UndoStatus,
)
from anki.decks import Deck
from anki.decks import DeckDict
from anki.hooks import runHook
from anki.sound import AVTag, SoundOrVideoTag
from anki.types import assert_exhaustive
@ -695,7 +695,7 @@ class AnkiQt(QMainWindow):
self.maybe_check_for_addon_updates()
self.deckBrowser.show()
def _selectedDeck(self) -> Optional[Deck]:
def _selectedDeck(self) -> Optional[DeckDict]:
did = self.col.decks.selected()
if not self.col.decks.name_if_exists(did):
showInfo(tr(TR.QT_MISC_PLEASE_SELECT_A_DECK))
@ -1319,7 +1319,7 @@ title="%s" %s>%s</button>""" % (
def onEditCurrent(self) -> None:
aqt.dialogs.open("EditCurrent", self)
def onDeckConf(self, deck: Optional[Deck] = None) -> None:
def onDeckConf(self, deck: Optional[DeckDict] = None) -> None:
import aqt.deckconf
if not deck:

View File

@ -21,7 +21,7 @@ from typing import Any, Callable, List, Sequence, Tuple, Optional, Union
import anki
import aqt
from anki.cards import Card
from anki.decks import Deck, DeckConfig
from anki.decks import DeckDict, DeckConfigDict
from anki.hooks import runFilter, runHook
from anki.models import NoteType
from aqt.qt import QDialog, QEvent, QMenu, QWidget
@ -229,20 +229,28 @@ hooks = [
),
Hook(
name="deck_conf_did_load_config",
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
args=[
"deck_conf: aqt.deckconf.DeckConf",
"deck: DeckDict",
"config: DeckConfigDict",
],
doc="Called once widget state has been set from deck config",
),
Hook(
name="deck_conf_will_save_config",
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
args=[
"deck_conf: aqt.deckconf.DeckConf",
"deck: DeckDict",
"config: DeckConfigDict",
],
doc="Called before widget state is saved to config",
),
Hook(
name="deck_conf_did_add_config",
args=[
"deck_conf: aqt.deckconf.DeckConf",
"deck: Deck",
"config: DeckConfig",
"deck: DeckDict",
"config: DeckConfigDict",
"new_name: str",
"new_conf_id: int",
],
@ -259,15 +267,19 @@ hooks = [
),
Hook(
name="deck_conf_will_remove_config",
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
args=[
"deck_conf: aqt.deckconf.DeckConf",
"deck: DeckDict",
"config: DeckConfigDict",
],
doc="Called before current config group is removed",
),
Hook(
name="deck_conf_will_rename_config",
args=[
"deck_conf: aqt.deckconf.DeckConf",
"deck: Deck",
"config: DeckConfig",
"deck: DeckDict",
"config: DeckConfigDict",
"new_name: str",
],
doc="Called before config group is renamed",