commit
c3f8f7dd94
@ -19,6 +19,21 @@ from anki.utils import ids2str, intTime
|
||||
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]
|
||||
|
||||
|
||||
class DecksDictProxy:
|
||||
def __init__(self, col: anki.collection.Collection):
|
||||
@ -64,7 +79,7 @@ class DeckManager:
|
||||
self.col = col.weakref()
|
||||
self.decks = DecksDictProxy(col)
|
||||
|
||||
def save(self, g: Dict = None) -> None:
|
||||
def save(self, g: Union[Deck, Config] = 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")
|
||||
@ -124,7 +139,7 @@ class DeckManager:
|
||||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def get_legacy(self, did: int) -> Optional[Dict]:
|
||||
def get_legacy(self, did: int) -> Optional[Deck]:
|
||||
try:
|
||||
return from_json_bytes(self.col.backend.get_deck_legacy(did))
|
||||
except NotFoundError:
|
||||
@ -133,10 +148,10 @@ class DeckManager:
|
||||
def have(self, id: int) -> bool:
|
||||
return not self.get_legacy(int(id))
|
||||
|
||||
def get_all_legacy(self) -> List[Dict]:
|
||||
def get_all_legacy(self) -> List[Deck]:
|
||||
return list(from_json_bytes(self.col.backend.get_all_decks_legacy()).values())
|
||||
|
||||
def new_deck_legacy(self, filtered: bool) -> Dict:
|
||||
def new_deck_legacy(self, filtered: bool) -> Deck:
|
||||
return from_json_bytes(self.col.backend.new_deck_legacy(filtered))
|
||||
|
||||
def deck_tree(self) -> pb.DeckTreeNode:
|
||||
@ -154,7 +169,7 @@ class DeckManager:
|
||||
return match
|
||||
return None
|
||||
|
||||
def all(self) -> List:
|
||||
def all(self) -> List[Deck]:
|
||||
"All decks. Expensive; prefer all_names_and_ids()"
|
||||
return self.get_all_legacy()
|
||||
|
||||
@ -162,7 +177,7 @@ class DeckManager:
|
||||
print("decks.allIds() is deprecated, use .all_names_and_ids()")
|
||||
return [str(x.id) for x in self.all_names_and_ids()]
|
||||
|
||||
def allNames(self, dyn: bool = True, force_default: bool = True) -> List:
|
||||
def allNames(self, dyn: bool = True, force_default: bool = True) -> List[str]:
|
||||
print("decks.allNames() is deprecated, use .all_names_and_ids()")
|
||||
return [
|
||||
x.name
|
||||
@ -185,7 +200,7 @@ class DeckManager:
|
||||
def count(self) -> int:
|
||||
return len(self.all_names_and_ids())
|
||||
|
||||
def get(self, did: Union[int, str], default: bool = True) -> Optional[Dict]:
|
||||
def get(self, did: Union[int, str], default: bool = True) -> Optional[Deck]:
|
||||
if not did:
|
||||
if default:
|
||||
return self.get_legacy(1)
|
||||
@ -200,14 +215,14 @@ class DeckManager:
|
||||
else:
|
||||
return None
|
||||
|
||||
def byName(self, name: str) -> Optional[Dict]:
|
||||
def byName(self, name: str) -> Optional[Deck]:
|
||||
"""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: Dict[str, Any], preserve_usn=True) -> None:
|
||||
def update(self, g: Deck, preserve_usn=True) -> None:
|
||||
"Add or update an existing deck. Used for syncing and merging."
|
||||
try:
|
||||
g["id"] = self.col.backend.add_or_update_deck_legacy(
|
||||
@ -216,7 +231,7 @@ class DeckManager:
|
||||
except anki.rsbackend.DeckIsFilteredError:
|
||||
raise DeckRenameError("deck was filtered")
|
||||
|
||||
def rename(self, g: Dict[str, Any], newName: str) -> None:
|
||||
def rename(self, g: Deck, newName: str) -> None:
|
||||
"Rename deck prefix to NAME if not exists. Updates children."
|
||||
g["name"] = newName
|
||||
self.update(g, preserve_usn=False)
|
||||
@ -225,7 +240,9 @@ class DeckManager:
|
||||
# Drag/drop
|
||||
#############################################################
|
||||
|
||||
def renameForDragAndDrop(self, draggedDeckDid: int, ontoDeckDid: Any) -> None:
|
||||
def renameForDragAndDrop(
|
||||
self, draggedDeckDid: int, ontoDeckDid: Optional[Union[int, str]]
|
||||
) -> None:
|
||||
draggedDeck = self.get(draggedDeckDid)
|
||||
draggedDeckName = draggedDeck["name"]
|
||||
ontoDeckName = self.get(ontoDeckDid)["name"]
|
||||
@ -252,23 +269,23 @@ class DeckManager:
|
||||
else:
|
||||
return True
|
||||
|
||||
def _isParent(self, parentDeckName: str, childDeckName: str) -> Any:
|
||||
def _isParent(self, parentDeckName: str, childDeckName: str) -> bool:
|
||||
return self.path(childDeckName) == self.path(parentDeckName) + [
|
||||
self.basename(childDeckName)
|
||||
]
|
||||
|
||||
def _isAncestor(self, ancestorDeckName: str, descendantDeckName: str) -> Any:
|
||||
def _isAncestor(self, ancestorDeckName: str, descendantDeckName: str) -> bool:
|
||||
ancestorPath = self.path(ancestorDeckName)
|
||||
return ancestorPath == self.path(descendantDeckName)[0 : len(ancestorPath)]
|
||||
|
||||
# Deck configurations
|
||||
#############################################################
|
||||
|
||||
def all_config(self) -> List:
|
||||
def all_config(self) -> List[Config]:
|
||||
"A list of all deck config."
|
||||
return list(from_json_bytes(self.col.backend.all_deck_config_legacy()))
|
||||
|
||||
def confForDid(self, did: int) -> Any:
|
||||
def confForDid(self, did: int) -> DeckConfig:
|
||||
deck = self.get(did, default=False)
|
||||
assert deck
|
||||
if "conf" in deck:
|
||||
@ -282,20 +299,20 @@ class DeckManager:
|
||||
# dynamic decks have embedded conf
|
||||
return deck
|
||||
|
||||
def get_config(self, conf_id: int) -> Any:
|
||||
def get_config(self, conf_id: int) -> Optional[DeckConfig]:
|
||||
try:
|
||||
return from_json_bytes(self.col.backend.get_deck_config_legacy(conf_id))
|
||||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def update_config(self, conf: Dict[str, Any], preserve_usn=False) -> None:
|
||||
def update_config(self, conf: DeckConfig, preserve_usn=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[Dict[str, Any]] = None
|
||||
) -> Dict[str, Any]:
|
||||
self, name: str, clone_from: Optional[DeckConfig] = None
|
||||
) -> DeckConfig:
|
||||
if clone_from is not None:
|
||||
conf = copy.deepcopy(clone_from)
|
||||
conf["id"] = 0
|
||||
@ -306,7 +323,7 @@ class DeckManager:
|
||||
return conf
|
||||
|
||||
def add_config_returning_id(
|
||||
self, name: str, clone_from: Optional[Dict[str, Any]] = None
|
||||
self, name: str, clone_from: Optional[DeckConfig] = None
|
||||
) -> int:
|
||||
return self.add_config(name, clone_from)["id"]
|
||||
|
||||
@ -322,11 +339,11 @@ class DeckManager:
|
||||
self.save(g)
|
||||
self.col.backend.remove_deck_config(id)
|
||||
|
||||
def setConf(self, grp: Dict[str, Any], id: int) -> None:
|
||||
def setConf(self, grp: DeckConfig, id: int) -> None:
|
||||
grp["conf"] = id
|
||||
self.save(grp)
|
||||
|
||||
def didsForConf(self, conf) -> List:
|
||||
def didsForConf(self, conf) -> List[int]:
|
||||
dids = []
|
||||
for deck in self.all():
|
||||
if "conf" in deck and deck["conf"] == conf["id"]:
|
||||
@ -353,13 +370,13 @@ class DeckManager:
|
||||
# Deck utils
|
||||
#############################################################
|
||||
|
||||
def name(self, did: int, default: bool = False) -> Any:
|
||||
def name(self, did: int, default: bool = False) -> str:
|
||||
deck = self.get(did, default=default)
|
||||
if deck:
|
||||
return deck["name"]
|
||||
return _("[no deck]")
|
||||
|
||||
def nameOrNone(self, did: int) -> Any:
|
||||
def nameOrNone(self, did: int) -> Optional[str]:
|
||||
deck = self.get(did, default=False)
|
||||
if deck:
|
||||
return deck["name"]
|
||||
@ -373,7 +390,7 @@ class DeckManager:
|
||||
intTime(),
|
||||
)
|
||||
|
||||
def cids(self, did: int, children: bool = False) -> Any:
|
||||
def cids(self, did: int, children: bool = False) -> List[int]:
|
||||
if not children:
|
||||
return self.col.db.list("select id from cards where did=?", did)
|
||||
dids = [did]
|
||||
@ -387,15 +404,15 @@ class DeckManager:
|
||||
# Deck selection
|
||||
#############################################################
|
||||
|
||||
def active(self) -> Any:
|
||||
def active(self) -> List[int]:
|
||||
"The currrently active dids."
|
||||
return self.col.get_config("activeDecks", [1])
|
||||
|
||||
def selected(self) -> Any:
|
||||
def selected(self) -> int:
|
||||
"The currently selected did."
|
||||
return self.col.conf["curDeck"]
|
||||
|
||||
def current(self) -> Any:
|
||||
def current(self) -> Deck:
|
||||
return self.get(self.selected())
|
||||
|
||||
def select(self, did: int) -> None:
|
||||
@ -416,32 +433,33 @@ class DeckManager:
|
||||
#############################################################
|
||||
|
||||
@staticmethod
|
||||
def path(name: str) -> Any:
|
||||
def path(name: str) -> List[str]:
|
||||
return name.split("::")
|
||||
|
||||
_path = path
|
||||
|
||||
@classmethod
|
||||
def basename(cls, name: str) -> Any:
|
||||
def basename(cls, name: str) -> str:
|
||||
return cls.path(name)[-1]
|
||||
|
||||
_basename = basename
|
||||
|
||||
@classmethod
|
||||
def immediate_parent_path(cls, name: str) -> Any:
|
||||
def immediate_parent_path(cls, name: str) -> List[str]:
|
||||
return cls._path(name)[:-1]
|
||||
|
||||
@classmethod
|
||||
def immediate_parent(cls, name: str) -> Any:
|
||||
def immediate_parent(cls, name: str) -> Optional[str]:
|
||||
pp = cls.immediate_parent_path(name)
|
||||
if pp:
|
||||
return "::".join(pp)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def key(cls, deck: Dict[str, Any]) -> List[str]:
|
||||
def key(cls, deck: Deck) -> List[str]:
|
||||
return cls.path(deck["name"])
|
||||
|
||||
def children(self, did: int) -> List[Tuple[Any, Any]]:
|
||||
def children(self, did: int) -> List[Tuple[str, int]]:
|
||||
"All children of did, as (name, id)."
|
||||
name = self.get(did)["name"]
|
||||
actv = []
|
||||
@ -460,19 +478,22 @@ class DeckManager:
|
||||
out.extend(self.child_ids(parent_name))
|
||||
return out
|
||||
|
||||
def childDids(self, did: int, childMap: Dict[int, Any]) -> List:
|
||||
def gather(node, arr):
|
||||
childMapNode = Dict[int, Any]
|
||||
# Change to Dict[int, "DeckManager.childMapNode"] when MyPy allow recursive type
|
||||
|
||||
def childDids(self, did: int, childMap: DeckManager.childMapNode) -> List:
|
||||
def gather(node: DeckManager.childMapNode, arr):
|
||||
for did, child in node.items():
|
||||
arr.append(did)
|
||||
gather(child, arr)
|
||||
|
||||
arr: List = []
|
||||
arr: List[int] = []
|
||||
gather(childMap[did], arr)
|
||||
return arr
|
||||
|
||||
def childMap(self) -> Dict[Any, Dict[Any, dict]]:
|
||||
def childMap(self) -> DeckManager.childMapNode:
|
||||
nameMap = self.nameMap()
|
||||
childMap = {}
|
||||
childMap: DeckManager.childMapNode = {}
|
||||
|
||||
# go through all decks, sorted by name
|
||||
for deck in sorted(self.all(), key=self.key):
|
||||
@ -487,31 +508,34 @@ class DeckManager:
|
||||
|
||||
return childMap
|
||||
|
||||
def parents(self, did: int, nameMap: Optional[Any] = None) -> List:
|
||||
def parents(
|
||||
self, did: int, nameMap: Optional[Dict[str, Deck]] = None
|
||||
) -> List[Deck]:
|
||||
"All parents of did."
|
||||
# get parent and grandparent names
|
||||
parents: List[str] = []
|
||||
parents_names: List[str] = []
|
||||
for part in self.immediate_parent_path(self.get(did)["name"]):
|
||||
if not parents:
|
||||
parents.append(part)
|
||||
if not parents_names:
|
||||
parents_names.append(part)
|
||||
else:
|
||||
parents.append(parents[-1] + "::" + part)
|
||||
parents_names.append(parents_names[-1] + "::" + part)
|
||||
parents: List[Deck] = []
|
||||
# convert to objects
|
||||
for c, p in enumerate(parents):
|
||||
for parent_name in parents_names:
|
||||
if nameMap:
|
||||
deck = nameMap[p]
|
||||
deck = nameMap[parent_name]
|
||||
else:
|
||||
deck = self.get(self.id(p))
|
||||
parents[c] = deck
|
||||
deck = self.get(self.id(parent_name))
|
||||
parents.append(deck)
|
||||
return parents
|
||||
|
||||
def parentsByName(self, name: str) -> List:
|
||||
def parentsByName(self, name: str) -> List[Deck]:
|
||||
"All existing parents of name"
|
||||
if "::" not in name:
|
||||
return []
|
||||
names = self.immediate_parent_path(name)
|
||||
head = []
|
||||
parents = []
|
||||
parents: List[Deck] = []
|
||||
|
||||
while names:
|
||||
head.append(names.pop(0))
|
||||
@ -521,7 +545,7 @@ class DeckManager:
|
||||
|
||||
return parents
|
||||
|
||||
def nameMap(self) -> dict:
|
||||
def nameMap(self) -> Dict[str, Deck]:
|
||||
return dict((d["name"], d) for d in self.all())
|
||||
|
||||
# Dynamic decks
|
||||
@ -533,5 +557,6 @@ class DeckManager:
|
||||
self.select(did)
|
||||
return did
|
||||
|
||||
def isDyn(self, did: Union[int, str]) -> Any:
|
||||
# 1 for dyn, 0 for standard
|
||||
def isDyn(self, did: Union[int, str]) -> int:
|
||||
return self.get(did)["dyn"]
|
||||
|
@ -175,20 +175,20 @@ card_will_flush = _CardWillFlushHook()
|
||||
class _DeckAddedHook:
|
||||
"""Obsolete, do not use."""
|
||||
|
||||
_hooks: List[Callable[[Dict[str, Any]], None]] = []
|
||||
_hooks: List[Callable[["anki.decks.Deck"], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
"""(deck: Dict[str, Any])"""
|
||||
def append(self, cb: Callable[["anki.decks.Deck"], None]) -> None:
|
||||
"""(deck: anki.decks.Deck)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
def remove(self, cb: Callable[["anki.decks.Deck"], None]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, deck: Dict[str, Any]) -> None:
|
||||
def __call__(self, deck: anki.decks.Deck) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(deck)
|
||||
@ -305,20 +305,20 @@ media_files_did_export = _MediaFilesDidExportHook()
|
||||
class _NoteTypeAddedHook:
|
||||
"""Obsolete, do not use."""
|
||||
|
||||
_hooks: List[Callable[[Dict[str, Any]], None]] = []
|
||||
_hooks: List[Callable[["anki.models.NoteType"], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
"""(notetype: Dict[str, Any])"""
|
||||
def append(self, cb: Callable[["anki.models.NoteType"], None]) -> None:
|
||||
"""(notetype: anki.models.NoteType)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
def remove(self, cb: Callable[["anki.models.NoteType"], None]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, notetype: Dict[str, Any]) -> None:
|
||||
def __call__(self, notetype: anki.models.NoteType) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(notetype)
|
||||
@ -397,20 +397,20 @@ class _SchedulerNewLimitForSingleDeckFilter:
|
||||
"""Allows changing the number of new card for this deck (without
|
||||
considering descendants)."""
|
||||
|
||||
_hooks: List[Callable[[int, Dict[str, Any]], int]] = []
|
||||
_hooks: List[Callable[[int, "anki.decks.Deck"], int]] = []
|
||||
|
||||
def append(self, cb: Callable[[int, Dict[str, Any]], int]) -> None:
|
||||
"""(count: int, deck: Dict[str, Any])"""
|
||||
def append(self, cb: Callable[[int, "anki.decks.Deck"], int]) -> None:
|
||||
"""(count: int, deck: anki.decks.Deck)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[int, Dict[str, Any]], int]) -> None:
|
||||
def remove(self, cb: Callable[[int, "anki.decks.Deck"], int]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, count: int, deck: Dict[str, Any]) -> int:
|
||||
def __call__(self, count: int, deck: anki.decks.Deck) -> int:
|
||||
for filter in self._hooks:
|
||||
try:
|
||||
count = filter(count, deck)
|
||||
@ -428,20 +428,20 @@ class _SchedulerReviewLimitForSingleDeckFilter:
|
||||
"""Allows changing the number of rev card for this deck (without
|
||||
considering descendants)."""
|
||||
|
||||
_hooks: List[Callable[[int, Dict[str, Any]], int]] = []
|
||||
_hooks: List[Callable[[int, "anki.decks.Deck"], int]] = []
|
||||
|
||||
def append(self, cb: Callable[[int, Dict[str, Any]], int]) -> None:
|
||||
"""(count: int, deck: Dict[str, Any])"""
|
||||
def append(self, cb: Callable[[int, "anki.decks.Deck"], int]) -> None:
|
||||
"""(count: int, deck: anki.decks.Deck)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[int, Dict[str, Any]], int]) -> None:
|
||||
def remove(self, cb: Callable[[int, "anki.decks.Deck"], int]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, count: int, deck: Dict[str, Any]) -> int:
|
||||
def __call__(self, count: int, deck: anki.decks.Deck) -> int:
|
||||
for filter in self._hooks:
|
||||
try:
|
||||
count = filter(count, deck)
|
||||
|
@ -138,7 +138,7 @@ class ModelManager:
|
||||
# Current note type
|
||||
#############################################################
|
||||
|
||||
def current(self, forDeck: bool = True) -> Any:
|
||||
def current(self, forDeck: bool = True) -> NoteType:
|
||||
"Get current model."
|
||||
m = self.get(self.col.decks.current().get("mid"))
|
||||
if not forDeck or not m:
|
||||
@ -243,21 +243,21 @@ class ModelManager:
|
||||
# Tools
|
||||
##################################################
|
||||
|
||||
def nids(self, ntid: int) -> Any:
|
||||
def nids(self, ntid: int) -> List[int]:
|
||||
"Note ids for M."
|
||||
if isinstance(ntid, dict):
|
||||
# legacy callers passed in note type
|
||||
ntid = ntid["id"]
|
||||
return self.col.db.list("select id from notes where mid = ?", ntid)
|
||||
|
||||
def useCount(self, m: NoteType) -> Any:
|
||||
def useCount(self, m: NoteType) -> int:
|
||||
"Number of note using M."
|
||||
return self.col.db.scalar("select count() from notes where mid = ?", m["id"])
|
||||
|
||||
# Copying
|
||||
##################################################
|
||||
|
||||
def copy(self, m: NoteType) -> Any:
|
||||
def copy(self, m: NoteType) -> NoteType:
|
||||
"Copy, save and return."
|
||||
m2 = copy.deepcopy(m)
|
||||
m2["name"] = _("%s copy") % m2["name"]
|
||||
@ -275,7 +275,7 @@ class ModelManager:
|
||||
def fieldNames(self, m: NoteType) -> List[str]:
|
||||
return [f["name"] for f in m["flds"]]
|
||||
|
||||
def sortIdx(self, m: NoteType) -> Any:
|
||||
def sortIdx(self, m: NoteType) -> int:
|
||||
return m["sortf"]
|
||||
|
||||
# Adding & changing fields
|
||||
@ -406,7 +406,12 @@ and notes.mid = ? and cards.ord = ?""",
|
||||
# - newModel should be self if model is not changing
|
||||
|
||||
def change(
|
||||
self, m: NoteType, nids: List[int], newModel: NoteType, fmap: Any, cmap: Any
|
||||
self,
|
||||
m: NoteType,
|
||||
nids: List[int],
|
||||
newModel: NoteType,
|
||||
fmap: Optional[Dict[int, Union[None, int]]],
|
||||
cmap: Optional[Dict[int, Union[None, int]]],
|
||||
) -> None:
|
||||
self.col.modSchema(check=True)
|
||||
assert newModel["id"] == m["id"] or (fmap and cmap)
|
||||
@ -483,7 +488,9 @@ and notes.mid = ? and cards.ord = ?""",
|
||||
# Cloze
|
||||
##########################################################################
|
||||
|
||||
def _availClozeOrds(self, m: NoteType, flds: str, allowEmpty: bool = True) -> List:
|
||||
def _availClozeOrds(
|
||||
self, m: NoteType, flds: str, allowEmpty: bool = True
|
||||
) -> List[int]:
|
||||
print("_availClozeOrds() is deprecated; use note.cloze_numbers_in_fields()")
|
||||
note = anki.rsbackend.BackendNote(fields=[flds])
|
||||
return list(self.col.backend.cloze_numbers_in_note(note))
|
||||
|
@ -6,12 +6,13 @@ from __future__ import annotations
|
||||
import random
|
||||
import time
|
||||
from heapq import *
|
||||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
||||
from typing import Any, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.decks import Deck, QueueConfig
|
||||
from anki.schedv2 import Scheduler as V2
|
||||
from anki.utils import ids2str, intTime
|
||||
|
||||
@ -299,13 +300,13 @@ limit %d"""
|
||||
card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN
|
||||
self._logLrn(card, ease, conf, leaving, type, lastLeft)
|
||||
|
||||
def _lrnConf(self, card: Card) -> Dict[str, Any]:
|
||||
def _lrnConf(self, card: Card) -> QueueConfig:
|
||||
if card.type == CARD_TYPE_REV:
|
||||
return self._lapseConf(card)
|
||||
else:
|
||||
return self._newConf(card)
|
||||
|
||||
def _rescheduleAsRev(self, card: Card, conf: Dict[str, Any], early: bool) -> None:
|
||||
def _rescheduleAsRev(self, card: Card, conf: QueueConfig, early: bool) -> None:
|
||||
lapse = card.type == CARD_TYPE_REV
|
||||
if lapse:
|
||||
if self._resched(card):
|
||||
@ -338,7 +339,7 @@ limit %d"""
|
||||
return tot + tod * 1000
|
||||
|
||||
def _graduatingIvl(
|
||||
self, card: Card, conf: Dict[str, Any], early: bool, adj: bool = True
|
||||
self, card: Card, conf: QueueConfig, early: bool, adj: bool = True
|
||||
) -> int:
|
||||
if card.type == CARD_TYPE_REV:
|
||||
# lapsed card being relearnt
|
||||
@ -357,7 +358,7 @@ limit %d"""
|
||||
else:
|
||||
return ideal
|
||||
|
||||
def _rescheduleNew(self, card: Card, conf: Dict[str, Any], early: bool) -> None:
|
||||
def _rescheduleNew(self, card: Card, conf: QueueConfig, early: bool) -> None:
|
||||
"Reschedule a new card that's graduated for the first time."
|
||||
card.ivl = self._graduatingIvl(card, conf, early)
|
||||
card.due = self.today + card.ivl
|
||||
@ -367,7 +368,7 @@ limit %d"""
|
||||
self,
|
||||
card: Card,
|
||||
ease: int,
|
||||
conf: Dict[str, Any],
|
||||
conf: QueueConfig,
|
||||
leaving: bool,
|
||||
type: int,
|
||||
lastLeft: int,
|
||||
@ -452,7 +453,7 @@ and due <= ? limit ?)""",
|
||||
def _deckRevLimit(self, did: int) -> int:
|
||||
return self._deckNewLimit(did, self._deckRevLimitSingle)
|
||||
|
||||
def _deckRevLimitSingle(self, d: Dict[str, Any]) -> int: # type: ignore[override]
|
||||
def _deckRevLimitSingle(self, d: Deck) -> int: # type: ignore[override]
|
||||
if d["dyn"]:
|
||||
return self.reportLimit
|
||||
c = self.col.decks.confForDid(d["id"])
|
||||
@ -567,7 +568,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
||||
card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN
|
||||
return delay
|
||||
|
||||
def _nextLapseIvl(self, card: Card, conf: Dict[str, Any]) -> int:
|
||||
def _nextLapseIvl(self, card: Card, conf: QueueConfig) -> int:
|
||||
return max(conf["minInt"], int(card.ivl * conf["mult"]))
|
||||
|
||||
def _rescheduleRev(self, card: Card, ease: int) -> None: # type: ignore[override]
|
||||
@ -607,7 +608,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
||||
# interval capped?
|
||||
return min(interval, conf["maxIvl"])
|
||||
|
||||
def _constrainedIvl(self, ivl: float, conf: Dict[str, Any], prev: int) -> int: # type: ignore[override]
|
||||
def _constrainedIvl(self, ivl: float, conf: QueueConfig, prev: int) -> int: # type: ignore[override]
|
||||
"Integer interval after interval factor and prev+1 constraints applied."
|
||||
new = ivl * conf.get("ivlFct", 1)
|
||||
return int(max(new, prev + 1))
|
||||
@ -641,7 +642,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
||||
self.col.decks.select(did)
|
||||
return ids
|
||||
|
||||
def _fillDyn(self, deck: Dict[str, Any]) -> Sequence[int]: # type: ignore[override]
|
||||
def _fillDyn(self, deck: Deck) -> Sequence[int]: # type: ignore[override]
|
||||
search, limit, order = deck["terms"][0]
|
||||
orderlimit = self._dynOrder(order, limit)
|
||||
if search.strip():
|
||||
@ -707,7 +708,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
|
||||
# Leeches
|
||||
##########################################################################
|
||||
|
||||
def _checkLeech(self, card: Card, conf: Dict[str, Any]) -> bool:
|
||||
def _checkLeech(self, card: Card, conf: QueueConfig) -> bool:
|
||||
"Leech handler. True if card was a leech."
|
||||
lf = conf["leechFails"]
|
||||
if not lf:
|
||||
@ -737,7 +738,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
|
||||
# Tools
|
||||
##########################################################################
|
||||
|
||||
def _newConf(self, card: Card) -> Dict[str, Any]:
|
||||
def _newConf(self, card: Card) -> QueueConfig:
|
||||
conf = self._cardConf(card)
|
||||
# normal deck
|
||||
if not card.odid:
|
||||
@ -756,7 +757,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
|
||||
perDay=self.reportLimit,
|
||||
)
|
||||
|
||||
def _lapseConf(self, card: Card) -> Dict[str, Any]:
|
||||
def _lapseConf(self, card: Card) -> QueueConfig:
|
||||
conf = self._cardConf(card)
|
||||
# normal deck
|
||||
if not card.odid:
|
||||
|
@ -13,6 +13,7 @@ import anki # pylint: disable=unused-import
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.decks import Deck, DeckConfig, DeckManager, FilteredDeck, QueueConfig
|
||||
from anki.lang import _
|
||||
from anki.rsbackend import (
|
||||
CountsForDeckToday,
|
||||
@ -355,7 +356,7 @@ order by due"""
|
||||
return None
|
||||
|
||||
def _deckNewLimit(
|
||||
self, did: int, fn: Optional[Callable[[Dict[str, Any]], int]] = None
|
||||
self, did: int, fn: Optional[Callable[[Deck], int]] = None
|
||||
) -> int:
|
||||
if not fn:
|
||||
fn = self._deckNewLimitSingle
|
||||
@ -383,7 +384,7 @@ select count() from
|
||||
lim,
|
||||
)
|
||||
|
||||
def _deckNewLimitSingle(self, g: Dict[str, Any]) -> int:
|
||||
def _deckNewLimitSingle(self, g: DeckConfig) -> int:
|
||||
"Limit for deck without parent limits."
|
||||
if g["dyn"]:
|
||||
return self.dynReportLimit
|
||||
@ -552,11 +553,11 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
|
||||
self._logLrn(card, ease, conf, leaving, type, lastLeft)
|
||||
|
||||
def _updateRevIvlOnFail(self, card: Card, conf: Dict[str, Any]) -> None:
|
||||
def _updateRevIvlOnFail(self, card: Card, conf: QueueConfig) -> None:
|
||||
card.lastIvl = card.ivl
|
||||
card.ivl = self._lapseIvl(card, conf)
|
||||
|
||||
def _moveToFirstStep(self, card: Card, conf: Dict[str, Any]) -> Any:
|
||||
def _moveToFirstStep(self, card: Card, conf: QueueConfig) -> Any:
|
||||
card.left = self._startingLeft(card)
|
||||
|
||||
# relearning card?
|
||||
@ -565,19 +566,19 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
|
||||
return self._rescheduleLrnCard(card, conf)
|
||||
|
||||
def _moveToNextStep(self, card: Card, conf: Dict[str, Any]) -> None:
|
||||
def _moveToNextStep(self, card: Card, conf: QueueConfig) -> None:
|
||||
# decrement real left count and recalculate left today
|
||||
left = (card.left % 1000) - 1
|
||||
card.left = self._leftToday(conf["delays"], left) * 1000 + left
|
||||
|
||||
self._rescheduleLrnCard(card, conf)
|
||||
|
||||
def _repeatStep(self, card: Card, conf: Dict[str, Any]) -> None:
|
||||
def _repeatStep(self, card: Card, conf: QueueConfig) -> None:
|
||||
delay = self._delayForRepeatingGrade(conf, card.left)
|
||||
self._rescheduleLrnCard(card, conf, delay=delay)
|
||||
|
||||
def _rescheduleLrnCard(
|
||||
self, card: Card, conf: Dict[str, Any], delay: Optional[int] = None
|
||||
self, card: Card, conf: QueueConfig, delay: Optional[int] = None
|
||||
) -> Any:
|
||||
# normal delay for the current step?
|
||||
if delay is None:
|
||||
@ -608,7 +609,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN
|
||||
return delay
|
||||
|
||||
def _delayForGrade(self, conf: Dict[str, Any], left: int) -> int:
|
||||
def _delayForGrade(self, conf: QueueConfig, left: int) -> int:
|
||||
left = left % 1000
|
||||
try:
|
||||
delay = conf["delays"][-left]
|
||||
@ -620,7 +621,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
delay = 1
|
||||
return delay * 60
|
||||
|
||||
def _delayForRepeatingGrade(self, conf: Dict[str, Any], left: int) -> Any:
|
||||
def _delayForRepeatingGrade(self, conf: QueueConfig, left: int) -> Any:
|
||||
# halfway between last and next
|
||||
delay1 = self._delayForGrade(conf, left)
|
||||
if len(conf["delays"]) > 1:
|
||||
@ -636,7 +637,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
else:
|
||||
return self._newConf(card)
|
||||
|
||||
def _rescheduleAsRev(self, card: Card, conf: Dict[str, Any], early: bool) -> None:
|
||||
def _rescheduleAsRev(self, card: Card, conf: QueueConfig, early: bool) -> None:
|
||||
lapse = card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING)
|
||||
|
||||
if lapse:
|
||||
@ -680,7 +681,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
return ok + 1
|
||||
|
||||
def _graduatingIvl(
|
||||
self, card: Card, conf: Dict[str, Any], early: bool, fuzz: bool = True
|
||||
self, card: Card, conf: QueueConfig, early: bool, fuzz: bool = True
|
||||
) -> Any:
|
||||
if card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING):
|
||||
bonus = early and 1 or 0
|
||||
@ -695,7 +696,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
ideal = self._fuzzedIvl(ideal)
|
||||
return ideal
|
||||
|
||||
def _rescheduleNew(self, card: Card, conf: Dict[str, Any], early: bool) -> None:
|
||||
def _rescheduleNew(self, card: Card, conf: QueueConfig, early: bool) -> None:
|
||||
"Reschedule a new card that's graduated for the first time."
|
||||
card.ivl = self._graduatingIvl(card, conf, early)
|
||||
card.due = self.today + card.ivl
|
||||
@ -706,7 +707,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
||||
self,
|
||||
card: Card,
|
||||
ease: int,
|
||||
conf: Dict[str, Any],
|
||||
conf: QueueConfig,
|
||||
leaving: bool,
|
||||
type: int,
|
||||
lastLeft: int,
|
||||
@ -791,7 +792,9 @@ and due <= ? limit ?)""",
|
||||
lim = min(lim, self._deckRevLimitSingle(parent, parentLimit=lim))
|
||||
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
||||
|
||||
def _revForDeck(self, did: int, lim: int, childMap: Dict[int, Any]) -> Any:
|
||||
def _revForDeck(
|
||||
self, did: int, lim: int, childMap: DeckManager.childMapNode
|
||||
) -> Any:
|
||||
dids = [did] + self.col.decks.childDids(did, childMap)
|
||||
lim = min(lim, self.reportLimit)
|
||||
return self.col.db.scalar(
|
||||
@ -888,7 +891,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
||||
|
||||
return delay
|
||||
|
||||
def _lapseIvl(self, card: Card, conf: Dict[str, Any]) -> Any:
|
||||
def _lapseIvl(self, card: Card, conf: QueueConfig) -> Any:
|
||||
ivl = max(1, conf["minInt"], int(card.ivl * conf["mult"]))
|
||||
return ivl
|
||||
|
||||
@ -975,7 +978,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
||||
return [ivl - fuzz, ivl + fuzz]
|
||||
|
||||
def _constrainedIvl(
|
||||
self, ivl: float, conf: Dict[str, Any], prev: int, fuzz: bool
|
||||
self, ivl: float, conf: QueueConfig, prev: int, fuzz: bool
|
||||
) -> int:
|
||||
ivl = int(ivl * conf.get("ivlFct", 1))
|
||||
if fuzz:
|
||||
@ -1058,7 +1061,7 @@ end)
|
||||
self.col.decks.select(did)
|
||||
return cnt
|
||||
|
||||
def _fillDyn(self, deck: Dict[str, Any]) -> int:
|
||||
def _fillDyn(self, deck: FilteredDeck) -> int:
|
||||
start = -100000
|
||||
total = 0
|
||||
for search, limit, order in deck["terms"]:
|
||||
@ -1167,7 +1170,7 @@ where id = ?
|
||||
# Leeches
|
||||
##########################################################################
|
||||
|
||||
def _checkLeech(self, card: Card, conf: Dict[str, Any]) -> bool:
|
||||
def _checkLeech(self, card: Card, conf: QueueConfig) -> bool:
|
||||
"Leech handler. True if card was a leech."
|
||||
lf = conf["leechFails"]
|
||||
if not lf:
|
||||
@ -1190,7 +1193,7 @@ where id = ?
|
||||
# Tools
|
||||
##########################################################################
|
||||
|
||||
def _cardConf(self, card: Card) -> Dict[str, Any]:
|
||||
def _cardConf(self, card: Card) -> DeckConfig:
|
||||
return self.col.decks.confForDid(card.did)
|
||||
|
||||
def _newConf(self, card: Card) -> Any:
|
||||
@ -1229,7 +1232,7 @@ where id = ?
|
||||
resched=conf["resched"],
|
||||
)
|
||||
|
||||
def _revConf(self, card: Card) -> Dict[str, Any]:
|
||||
def _revConf(self, card: Card) -> QueueConfig:
|
||||
conf = self._cardConf(card)
|
||||
# normal deck
|
||||
if not card.odid:
|
||||
|
@ -71,23 +71,25 @@ hooks = [
|
||||
),
|
||||
Hook(
|
||||
name="scheduler_new_limit_for_single_deck",
|
||||
args=["count: int", "deck: Dict[str, Any]"],
|
||||
args=["count: int", "deck: anki.decks.Deck"],
|
||||
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: Dict[str, Any]"],
|
||||
args=["count: int", "deck: anki.decks.Deck"],
|
||||
return_type="int",
|
||||
doc="""Allows changing the number of rev card for this deck (without
|
||||
considering descendants).""",
|
||||
),
|
||||
# obsolete
|
||||
Hook(name="deck_added", args=["deck: Dict[str, Any]"], doc="Obsolete, do not use."),
|
||||
Hook(
|
||||
name="deck_added", args=["deck: anki.decks.Deck"], doc="Obsolete, do not use."
|
||||
),
|
||||
Hook(
|
||||
name="note_type_added",
|
||||
args=["notetype: Dict[str, Any]"],
|
||||
args=["notetype: anki.models.NoteType"],
|
||||
doc="Obsolete, do not use.",
|
||||
),
|
||||
Hook(
|
||||
|
@ -254,7 +254,7 @@ class Editor:
|
||||
id: Optional[str] = None,
|
||||
toggleable: bool = False,
|
||||
disables: bool = True,
|
||||
):
|
||||
) -> str:
|
||||
if icon:
|
||||
if icon.startswith("qrc:/"):
|
||||
iconstr = icon
|
||||
|
@ -119,8 +119,8 @@ class FieldDialog(QDialog):
|
||||
def onDelete(self):
|
||||
if len(self.model["flds"]) < 2:
|
||||
return showWarning(_("Notes require at least one field."))
|
||||
c = self.mm.useCount(self.model)
|
||||
c = ngettext("%d note", "%d notes", c) % c
|
||||
count = self.mm.useCount(self.model)
|
||||
c = ngettext("%d note", "%d notes", count) % count
|
||||
if not askUser(_("Delete field from %s?") % c):
|
||||
return
|
||||
if not self.change_tracker.mark_schema():
|
||||
|
@ -7,12 +7,14 @@ See pylib/anki/hooks.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
from typing import Any, Callable, List, Optional, Tuple
|
||||
|
||||
import anki
|
||||
import aqt
|
||||
from anki.cards import Card
|
||||
from anki.decks import Deck, DeckConfig
|
||||
from anki.hooks import runFilter, runHook
|
||||
from anki.models import NoteType
|
||||
from aqt.qt import QDialog, QEvent, QMenu
|
||||
from aqt.tagedit import TagEdit
|
||||
|
||||
@ -827,20 +829,20 @@ collection_did_load = _CollectionDidLoadHook()
|
||||
|
||||
|
||||
class _CurrentNoteTypeDidChangeHook:
|
||||
_hooks: List[Callable[[Dict[str, Any]], None]] = []
|
||||
_hooks: List[Callable[[NoteType], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
"""(notetype: Dict[str, Any])"""
|
||||
def append(self, cb: Callable[[NoteType], None]) -> None:
|
||||
"""(notetype: NoteType)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
def remove(self, cb: Callable[[NoteType], None]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, notetype: Dict[str, Any]) -> None:
|
||||
def __call__(self, notetype: NoteType) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(notetype)
|
||||
@ -1046,16 +1048,18 @@ class _DeckConfDidAddConfigHook:
|
||||
Config groups are created as clones of the current one.
|
||||
"""
|
||||
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Any, Any, str, int], None]] = []
|
||||
_hooks: List[
|
||||
Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str, int], None]
|
||||
] = []
|
||||
|
||||
def append(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any, str, int], None]
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str, int], None]
|
||||
) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any, new_name: str, new_conf_id: int)"""
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig, new_name: str, new_conf_id: int)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any, str, int], None]
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str, int], None]
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
@ -1066,8 +1070,8 @@ class _DeckConfDidAddConfigHook:
|
||||
def __call__(
|
||||
self,
|
||||
deck_conf: aqt.deckconf.DeckConf,
|
||||
deck: Any,
|
||||
config: Any,
|
||||
deck: Deck,
|
||||
config: DeckConfig,
|
||||
new_name: str,
|
||||
new_conf_id: int,
|
||||
) -> None:
|
||||
@ -1086,13 +1090,17 @@ deck_conf_did_add_config = _DeckConfDidAddConfigHook()
|
||||
class _DeckConfDidLoadConfigHook:
|
||||
"""Called once widget state has been set from deck config"""
|
||||
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Any, Any], None]] = []
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any)"""
|
||||
def append(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
def remove(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
@ -1100,7 +1108,7 @@ class _DeckConfDidLoadConfigHook:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig
|
||||
) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
@ -1146,13 +1154,17 @@ deck_conf_did_setup_ui_form = _DeckConfDidSetupUiFormHook()
|
||||
class _DeckConfWillRemoveConfigHook:
|
||||
"""Called before current config group is removed"""
|
||||
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Any, Any], None]] = []
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any)"""
|
||||
def append(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
def remove(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
@ -1160,7 +1172,7 @@ class _DeckConfWillRemoveConfigHook:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig
|
||||
) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
@ -1177,16 +1189,16 @@ deck_conf_will_remove_config = _DeckConfWillRemoveConfigHook()
|
||||
class _DeckConfWillRenameConfigHook:
|
||||
"""Called before config group is renamed"""
|
||||
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Any, Any, str], None]] = []
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str], None]] = []
|
||||
|
||||
def append(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any, str], None]
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str], None]
|
||||
) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any, new_name: str)"""
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig, new_name: str)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any, str], None]
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig, str], None]
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
@ -1195,7 +1207,11 @@ class _DeckConfWillRenameConfigHook:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any, new_name: str
|
||||
self,
|
||||
deck_conf: aqt.deckconf.DeckConf,
|
||||
deck: Deck,
|
||||
config: DeckConfig,
|
||||
new_name: str,
|
||||
) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
@ -1212,13 +1228,17 @@ deck_conf_will_rename_config = _DeckConfWillRenameConfigHook()
|
||||
class _DeckConfWillSaveConfigHook:
|
||||
"""Called before widget state is saved to config"""
|
||||
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Any, Any], None]] = []
|
||||
_hooks: List[Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any)"""
|
||||
def append(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
"""(deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.deckconf.DeckConf", Any, Any], None]) -> None:
|
||||
def remove(
|
||||
self, cb: Callable[["aqt.deckconf.DeckConf", Deck, DeckConfig], None]
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
@ -1226,7 +1246,7 @@ class _DeckConfWillSaveConfigHook:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Any, config: Any
|
||||
self, deck_conf: aqt.deckconf.DeckConf, deck: Deck, config: DeckConfig
|
||||
) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
@ -1355,20 +1375,20 @@ editor_did_init = _EditorDidInitHook()
|
||||
|
||||
|
||||
class _EditorDidInitButtonsHook:
|
||||
_hooks: List[Callable[[List, "aqt.editor.Editor"], None]] = []
|
||||
_hooks: List[Callable[[List[str], "aqt.editor.Editor"], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[List, "aqt.editor.Editor"], None]) -> None:
|
||||
"""(buttons: List, editor: aqt.editor.Editor)"""
|
||||
def append(self, cb: Callable[[List[str], "aqt.editor.Editor"], None]) -> None:
|
||||
"""(buttons: List[str], editor: aqt.editor.Editor)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[List, "aqt.editor.Editor"], None]) -> None:
|
||||
def remove(self, cb: Callable[[List[str], "aqt.editor.Editor"], None]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def count(self) -> int:
|
||||
return len(self._hooks)
|
||||
|
||||
def __call__(self, buttons: List, editor: aqt.editor.Editor) -> None:
|
||||
def __call__(self, buttons: List[str], editor: aqt.editor.Editor) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(buttons, editor)
|
||||
|
@ -14,7 +14,7 @@ import weakref
|
||||
import zipfile
|
||||
from argparse import Namespace
|
||||
from threading import Thread
|
||||
from typing import Any, Callable, Dict, List, Optional, Sequence, TextIO, Tuple, cast
|
||||
from typing import Any, Callable, List, Optional, Sequence, TextIO, Tuple, cast
|
||||
|
||||
import anki
|
||||
import aqt
|
||||
@ -27,6 +27,7 @@ import aqt.toolbar
|
||||
import aqt.webview
|
||||
from anki import hooks
|
||||
from anki.collection import Collection
|
||||
from anki.decks import Deck
|
||||
from anki.hooks import runHook
|
||||
from anki.lang import _, ngettext
|
||||
from anki.rsbackend import RustBackend
|
||||
@ -652,7 +653,7 @@ from the profile screen."
|
||||
self.maybe_check_for_addon_updates()
|
||||
self.deckBrowser.show()
|
||||
|
||||
def _selectedDeck(self) -> Optional[Dict[str, Any]]:
|
||||
def _selectedDeck(self) -> Optional[Deck]:
|
||||
did = self.col.decks.selected()
|
||||
if not self.col.decks.nameOrNone(did):
|
||||
showInfo(_("Please select a deck."))
|
||||
|
@ -185,6 +185,8 @@ class Models(QDialog):
|
||||
|
||||
|
||||
class AddModel(QDialog):
|
||||
model: Optional[NoteType]
|
||||
|
||||
def __init__(self, mw: AnkiQt, parent: Optional[QWidget] = None):
|
||||
self.parent_ = parent or mw
|
||||
self.mw = mw
|
||||
|
@ -194,20 +194,20 @@ hooks = [
|
||||
),
|
||||
Hook(
|
||||
name="deck_conf_did_load_config",
|
||||
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Any", "config: Any"],
|
||||
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
|
||||
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: Any", "config: Any"],
|
||||
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
|
||||
doc="Called before widget state is saved to config",
|
||||
),
|
||||
Hook(
|
||||
name="deck_conf_did_add_config",
|
||||
args=[
|
||||
"deck_conf: aqt.deckconf.DeckConf",
|
||||
"deck: Any",
|
||||
"config: Any",
|
||||
"deck: Deck",
|
||||
"config: DeckConfig",
|
||||
"new_name: str",
|
||||
"new_conf_id: int",
|
||||
],
|
||||
@ -224,15 +224,15 @@ hooks = [
|
||||
),
|
||||
Hook(
|
||||
name="deck_conf_will_remove_config",
|
||||
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Any", "config: Any"],
|
||||
args=["deck_conf: aqt.deckconf.DeckConf", "deck: Deck", "config: DeckConfig"],
|
||||
doc="Called before current config group is removed",
|
||||
),
|
||||
Hook(
|
||||
name="deck_conf_will_rename_config",
|
||||
args=[
|
||||
"deck_conf: aqt.deckconf.DeckConf",
|
||||
"deck: Any",
|
||||
"config: Any",
|
||||
"deck: Deck",
|
||||
"config: DeckConfig",
|
||||
"new_name: str",
|
||||
],
|
||||
doc="Called before config group is renamed",
|
||||
@ -530,7 +530,7 @@ hooks = [
|
||||
###################
|
||||
Hook(
|
||||
name="editor_did_init_buttons",
|
||||
args=["buttons: List", "editor: aqt.editor.Editor"],
|
||||
args=["buttons: List[str]", "editor: aqt.editor.Editor"],
|
||||
),
|
||||
Hook(
|
||||
name="editor_did_init_shortcuts",
|
||||
@ -653,7 +653,7 @@ hooks = [
|
||||
###################
|
||||
Hook(
|
||||
name="current_note_type_did_change",
|
||||
args=["notetype: Dict[str, Any]"],
|
||||
args=["notetype: NoteType"],
|
||||
legacy_hook="currentModelChanged",
|
||||
legacy_no_args=True,
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user