mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 00:12:25 -04:00
PEP8 decks.py
This commit is contained in:
parent
2a93355824
commit
62c23c6816
17 changed files with 188 additions and 253 deletions
|
@ -27,10 +27,14 @@ def partial_path(full_path: str, components: int) -> str:
|
|||
return os.path.join(*path.parts[-components:])
|
||||
|
||||
|
||||
def _print_deprecation_warning(old: str, doc: str) -> None:
|
||||
path, linenum, fn, y = traceback.extract_stack(limit=5)[2]
|
||||
def print_deprecation_warning(msg: str, frame: int = 2) -> None:
|
||||
path, linenum, fn, y = traceback.extract_stack(limit=5)[frame]
|
||||
path = partial_path(path, components=3)
|
||||
print(f"{path}:{linenum}:{old} is deprecated: {doc}")
|
||||
print(f"{path}:{linenum}:{msg}")
|
||||
|
||||
|
||||
def _print_warning(old: str, doc: str) -> None:
|
||||
return print_deprecation_warning(f"{old} is deprecated: {doc}", frame=1)
|
||||
|
||||
|
||||
class DeprecatedNamesMixin:
|
||||
|
@ -48,7 +52,7 @@ class DeprecatedNamesMixin:
|
|||
raise AttributeError
|
||||
|
||||
out = getattr(self, remapped)
|
||||
_print_deprecation_warning(f"'{name}'", f"please use '{remapped}'")
|
||||
_print_warning(f"'{name}'", f"please use '{remapped}'")
|
||||
|
||||
return out
|
||||
|
||||
|
@ -75,7 +79,7 @@ def deprecated(replaced_by: Optional[Callable] = None, info: str = "") -> Callab
|
|||
else:
|
||||
doc = info
|
||||
|
||||
_print_deprecation_warning(f"{func.__name__}()", doc)
|
||||
_print_warning(f"{func.__name__}()", doc)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -170,19 +170,21 @@ class Card(DeprecatedNamesMixin):
|
|||
|
||||
def time_limit(self) -> int:
|
||||
"Time limit for answering in milliseconds."
|
||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||
conf = self.col.decks.config_dict_for_deck_id(self.current_deck_id())
|
||||
return conf["maxTaken"] * 1000
|
||||
|
||||
def should_show_timer(self) -> bool:
|
||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||
conf = self.col.decks.config_dict_for_deck_id(self.current_deck_id())
|
||||
return conf["timer"]
|
||||
|
||||
def replay_question_audio_on_answer_side(self) -> bool:
|
||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||
conf = self.col.decks.config_dict_for_deck_id(self.current_deck_id())
|
||||
return conf.get("replayq", True)
|
||||
|
||||
def autoplay(self) -> bool:
|
||||
return self.col.decks.confForDid(self.current_deck_id())["autoplay"]
|
||||
return self.col.decks.config_dict_for_deck_id(self.current_deck_id())[
|
||||
"autoplay"
|
||||
]
|
||||
|
||||
def time_taken(self) -> int:
|
||||
"Time taken to answer card, in integer MS."
|
||||
|
|
|
@ -1,17 +1,30 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import pprint
|
||||
import sys
|
||||
import traceback
|
||||
from typing import Any, Dict, Iterable, List, NewType, Optional, Sequence, Tuple, Union
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
NewType,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Union,
|
||||
no_type_check,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import anki
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
from anki._legacy import deprecated
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated, print_deprecation_warning
|
||||
from anki.cards import CardId
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||
from anki.consts import *
|
||||
|
@ -26,10 +39,6 @@ DeckCollapseScope = _pb.SetDeckCollapsedRequest.Scope
|
|||
DeckConfigsForUpdate = _pb.DeckConfigsForUpdate
|
||||
UpdateDeckConfigs = _pb.UpdateDeckConfigsRequest
|
||||
|
||||
# legacy code may pass this in as the type argument to .id()
|
||||
defaultDeck = 0
|
||||
defaultDynamicDeck = 1
|
||||
|
||||
# type aliases until we can move away from dicts
|
||||
DeckDict = Dict[str, Any]
|
||||
DeckConfigDict = Dict[str, Any]
|
||||
|
@ -46,8 +55,9 @@ class DecksDictProxy:
|
|||
self._col = col.weakref()
|
||||
|
||||
def _warn(self) -> None:
|
||||
traceback.print_stack(file=sys.stdout)
|
||||
print("add-on should use methods on col.decks, not col.decks.decks dict")
|
||||
print_deprecation_warning(
|
||||
"add-on should use methods on col.decks, not col.decks.decks dict"
|
||||
)
|
||||
|
||||
def __getitem__(self, item: Any) -> Any:
|
||||
self._warn()
|
||||
|
@ -78,7 +88,7 @@ class DecksDictProxy:
|
|||
return self._col.decks.have(item)
|
||||
|
||||
|
||||
class DeckManager:
|
||||
class DeckManager(DeprecatedNamesMixin):
|
||||
# Registry save/load
|
||||
#############################################################
|
||||
|
||||
|
@ -86,27 +96,18 @@ class DeckManager:
|
|||
self.col = col.weakref()
|
||||
self.decks = DecksDictProxy(col)
|
||||
|
||||
def save(self, g: Union[DeckDict, DeckConfigDict] = None) -> None:
|
||||
def save(self, deck_or_config: Union[DeckDict, DeckConfigDict] = None) -> None:
|
||||
"Can be called with either a deck or a deck configuration."
|
||||
if not g:
|
||||
if not deck_or_config:
|
||||
print("col.decks.save() should be passed the changed deck")
|
||||
return
|
||||
|
||||
# deck conf?
|
||||
if "maxTaken" in g:
|
||||
self.update_config(g)
|
||||
if "maxTaken" in deck_or_config:
|
||||
self.update_config(deck_or_config)
|
||||
return
|
||||
else:
|
||||
self.update(g, preserve_usn=False)
|
||||
|
||||
# legacy
|
||||
def flush(self) -> None:
|
||||
pass
|
||||
|
||||
def __repr__(self) -> str:
|
||||
d = dict(self.__dict__)
|
||||
del d["col"]
|
||||
return f"{super().__repr__()} {pprint.pformat(d, width=300)}"
|
||||
self.update(deck_or_config, preserve_usn=False)
|
||||
|
||||
# Deck save/load
|
||||
#############################################################
|
||||
|
@ -146,14 +147,6 @@ class DeckManager:
|
|||
def remove(self, dids: Sequence[DeckId]) -> OpChangesWithCount:
|
||||
return self.col._backend.remove_decks(dids)
|
||||
|
||||
@deprecated(replaced_by=remove)
|
||||
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 all_names_and_ids(
|
||||
self, skip_empty_default: bool = False, include_filtered: bool = True
|
||||
) -> Sequence[DeckNameId]:
|
||||
|
@ -211,19 +204,6 @@ class DeckManager:
|
|||
"All decks. Expensive; prefer all_names_and_ids()"
|
||||
return self.get_all_legacy()
|
||||
|
||||
def allIds(self) -> List[str]:
|
||||
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[str]:
|
||||
print("decks.allNames() is deprecated, use .all_names_and_ids()")
|
||||
return [
|
||||
x.name
|
||||
for x in self.all_names_and_ids(
|
||||
skip_empty_default=not force_default, include_filtered=dyn
|
||||
)
|
||||
]
|
||||
|
||||
def set_collapsed(
|
||||
self, deck_id: DeckId, collapsed: bool, scope: DeckCollapseScope.V
|
||||
) -> OpChanges:
|
||||
|
@ -236,7 +216,7 @@ class DeckManager:
|
|||
deck["collapsed"] = not deck["collapsed"]
|
||||
self.save(deck)
|
||||
|
||||
def collapseBrowser(self, did: DeckId) -> None:
|
||||
def collapse_browser(self, did: DeckId) -> None:
|
||||
deck = self.get(did)
|
||||
collapsed = deck.get("browserCollapsed", False)
|
||||
deck["browserCollapsed"] = not collapsed
|
||||
|
@ -275,17 +255,17 @@ class DeckManager:
|
|||
else:
|
||||
return None
|
||||
|
||||
def byName(self, name: str) -> Optional[DeckDict]:
|
||||
def by_name(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: DeckDict, preserve_usn: bool = True) -> None:
|
||||
def update(self, deck: 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
|
||||
deck["id"] = self.col._backend.add_or_update_deck_legacy(
|
||||
deck=to_json_bytes(deck), preserve_usn_and_mtime=preserve_usn
|
||||
)
|
||||
|
||||
def update_dict(self, deck: DeckDict) -> OpChanges:
|
||||
|
@ -311,18 +291,6 @@ class DeckManager:
|
|||
deck_ids=deck_ids, new_parent=new_parent
|
||||
)
|
||||
|
||||
# legacy
|
||||
def renameForDragAndDrop(
|
||||
self,
|
||||
draggedDeckDid: Union[DeckId, str],
|
||||
ontoDeckDid: Optional[Union[DeckId, str]],
|
||||
) -> None:
|
||||
if not ontoDeckDid:
|
||||
onto = 0
|
||||
else:
|
||||
onto = int(ontoDeckDid)
|
||||
self.reparent([DeckId(int(draggedDeckDid))], DeckId(onto))
|
||||
|
||||
# Deck configurations
|
||||
#############################################################
|
||||
|
||||
|
@ -336,7 +304,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: DeckId) -> DeckConfigDict:
|
||||
def config_dict_for_deck_id(self, did: DeckId) -> DeckConfigDict:
|
||||
deck = self.get(did, default=False)
|
||||
assert deck
|
||||
if "conf" in deck:
|
||||
|
@ -382,43 +350,36 @@ class DeckManager:
|
|||
def remove_config(self, id: DeckConfigId) -> None:
|
||||
"Remove a configuration and update all decks using it."
|
||||
self.col.modSchema(check=True)
|
||||
for g in self.all():
|
||||
for deck in self.all():
|
||||
# ignore cram decks
|
||||
if "conf" not in g:
|
||||
if "conf" not in deck:
|
||||
continue
|
||||
if str(g["conf"]) == str(id):
|
||||
g["conf"] = 1
|
||||
self.save(g)
|
||||
if str(deck["conf"]) == str(id):
|
||||
deck["conf"] = 1
|
||||
self.save(deck)
|
||||
self.col._backend.remove_deck_config(id)
|
||||
|
||||
def setConf(self, grp: DeckConfigDict, id: DeckConfigId) -> None:
|
||||
grp["conf"] = id
|
||||
self.save(grp)
|
||||
def set_config_id_for_deck_dict(self, deck: DeckDict, id: DeckConfigId) -> None:
|
||||
deck["conf"] = id
|
||||
self.save(deck)
|
||||
|
||||
def didsForConf(self, conf: DeckConfigDict) -> List[DeckId]:
|
||||
def decks_using_config(self, conf: DeckConfigDict) -> List[DeckId]:
|
||||
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: DeckConfigDict) -> None:
|
||||
oldOrder = conf["new"]["order"]
|
||||
def restore_to_default(self, conf: DeckConfigDict) -> None:
|
||||
old_order = conf["new"]["order"]
|
||||
new = from_json_bytes(self.col._backend.new_deck_config_legacy())
|
||||
new["id"] = conf["id"]
|
||||
new["name"] = conf["name"]
|
||||
self.update_config(new)
|
||||
# if it was previously randomized, re-sort
|
||||
if not oldOrder:
|
||||
if not old_order:
|
||||
self.col.sched.resortConf(new)
|
||||
|
||||
# legacy
|
||||
allConf = all_config
|
||||
getConf = get_config
|
||||
updateConf = update_config
|
||||
remConf = remove_config
|
||||
confId = add_config_returning_id
|
||||
|
||||
# Deck utils
|
||||
#############################################################
|
||||
|
||||
|
@ -434,14 +395,6 @@ class DeckManager:
|
|||
return deck["name"]
|
||||
return 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,
|
||||
self.col.usn(),
|
||||
intTime(),
|
||||
)
|
||||
|
||||
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)
|
||||
|
@ -463,21 +416,19 @@ class DeckManager:
|
|||
"The currently selected deck ID."
|
||||
return DeckId(self.col._backend.get_current_deck().id)
|
||||
|
||||
# legacy
|
||||
|
||||
def current(self) -> DeckDict:
|
||||
return self.get(self.selected())
|
||||
|
||||
def active(self) -> List[DeckId]:
|
||||
# some add-ons assume this will always be non-empty
|
||||
return self.col.sched.active_decks or [DeckId(1)]
|
||||
|
||||
def select(self, did: DeckId) -> None:
|
||||
# make sure arg is an int; legacy callers may be passing in a string
|
||||
did = DeckId(did)
|
||||
self.set_current(did)
|
||||
self.col.reset()
|
||||
|
||||
def active(self) -> List[DeckId]:
|
||||
# some add-ons assume this will always be non-empty
|
||||
return self.col.sched.active_decks or [DeckId(1)]
|
||||
|
||||
selected = get_current_id
|
||||
|
||||
# Parents/children
|
||||
|
@ -487,23 +438,19 @@ class DeckManager:
|
|||
def path(name: str) -> List[str]:
|
||||
return name.split("::")
|
||||
|
||||
_path = path
|
||||
|
||||
@classmethod
|
||||
def basename(cls, name: str) -> str:
|
||||
return cls.path(name)[-1]
|
||||
|
||||
_basename = basename
|
||||
|
||||
@classmethod
|
||||
def immediate_parent_path(cls, name: str) -> List[str]:
|
||||
return cls._path(name)[:-1]
|
||||
return cls.path(name)[:-1]
|
||||
|
||||
@classmethod
|
||||
def immediate_parent(cls, name: str) -> Optional[str]:
|
||||
pp = cls.immediate_parent_path(name)
|
||||
if pp:
|
||||
return "::".join(pp)
|
||||
parent_path = cls.immediate_parent_path(name)
|
||||
if parent_path:
|
||||
return "::".join(parent_path)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
|
@ -514,9 +461,9 @@ class DeckManager:
|
|||
"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, DeckId(g.id)))
|
||||
for entry in self.all_names_and_ids():
|
||||
if entry.name.startswith(f"{name}::"):
|
||||
actv.append((entry.name, DeckId(entry.id)))
|
||||
return actv
|
||||
|
||||
def child_ids(self, parent_name: str) -> Iterable[DeckId]:
|
||||
|
@ -531,38 +478,8 @@ class DeckManager:
|
|||
out.extend(self.child_ids(parent_name))
|
||||
return out
|
||||
|
||||
childMapNode = Dict[DeckId, Any]
|
||||
# Change to Dict[int, "DeckManager.childMapNode"] when MyPy allow recursive type
|
||||
|
||||
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)
|
||||
gather(child, arr)
|
||||
|
||||
arr: List[int] = []
|
||||
gather(childMap[did], arr)
|
||||
return arr
|
||||
|
||||
def childMap(self) -> DeckManager.childMapNode:
|
||||
nameMap = self.nameMap()
|
||||
childMap: DeckManager.childMapNode = {}
|
||||
|
||||
# go through all decks, sorted by name
|
||||
for deck in sorted(self.all(), key=self.key):
|
||||
node: Dict[int, Any] = {}
|
||||
childMap[deck["id"]] = node
|
||||
|
||||
# add note to immediate parent
|
||||
immediateParent = self.immediate_parent(deck["name"])
|
||||
if immediateParent is not None:
|
||||
pid = nameMap[immediateParent]["id"]
|
||||
childMap[pid][deck["id"]] = node
|
||||
|
||||
return childMap
|
||||
|
||||
def parents(
|
||||
self, did: DeckId, nameMap: Optional[Dict[str, DeckDict]] = None
|
||||
self, did: DeckId, name_map: Optional[Dict[str, DeckDict]] = None
|
||||
) -> List[DeckDict]:
|
||||
"All parents of did."
|
||||
# get parent and grandparent names
|
||||
|
@ -575,14 +492,14 @@ class DeckManager:
|
|||
parents: List[DeckDict] = []
|
||||
# convert to objects
|
||||
for parent_name in parents_names:
|
||||
if nameMap:
|
||||
deck = nameMap[parent_name]
|
||||
if name_map:
|
||||
deck = name_map[parent_name]
|
||||
else:
|
||||
deck = self.get(self.id(parent_name))
|
||||
parents.append(deck)
|
||||
return parents
|
||||
|
||||
def parentsByName(self, name: str) -> List[DeckDict]:
|
||||
def parents_by_name(self, name: str) -> List[DeckDict]:
|
||||
"All existing parents of name"
|
||||
if "::" not in name:
|
||||
return []
|
||||
|
@ -592,15 +509,12 @@ class DeckManager:
|
|||
|
||||
while names:
|
||||
head.append(names.pop(0))
|
||||
deck = self.byName("::".join(head))
|
||||
deck = self.by_name("::".join(head))
|
||||
if deck:
|
||||
parents.append(deck)
|
||||
|
||||
return parents
|
||||
|
||||
def nameMap(self) -> Dict[str, DeckDict]:
|
||||
return {d["name"]: d for d in self.all()}
|
||||
|
||||
# Filtered decks
|
||||
##########################################################################
|
||||
|
||||
|
@ -610,11 +524,79 @@ class DeckManager:
|
|||
self.select(did)
|
||||
return did
|
||||
|
||||
# 1 for dyn, 0 for standard
|
||||
def isDyn(self, did: Union[DeckId, str]) -> int:
|
||||
return self.get(did)["dyn"]
|
||||
def is_filtered(self, did: Union[DeckId, str]) -> bool:
|
||||
return bool(self.get(did)["dyn"])
|
||||
|
||||
# legacy
|
||||
# Legacy
|
||||
#############
|
||||
|
||||
newDyn = new_filtered
|
||||
nameOrNone = name_if_exists
|
||||
@deprecated(info="no longer required")
|
||||
def flush(self) -> None:
|
||||
pass
|
||||
|
||||
@deprecated(replaced_by=remove)
|
||||
def rem(
|
||||
self,
|
||||
did: DeckId,
|
||||
**legacy_args: bool,
|
||||
) -> None:
|
||||
"Remove the deck. If cardsToo, delete any cards inside."
|
||||
if isinstance(did, str):
|
||||
did = int(did)
|
||||
self.remove([did])
|
||||
|
||||
@deprecated(replaced_by=all_names_and_ids)
|
||||
def name_map(self) -> Dict[str, DeckDict]:
|
||||
return {d["name"]: d for d in self.all()}
|
||||
|
||||
@deprecated(info="use col.set_deck() instead")
|
||||
def set_deck(self, cids: List[CardId], did: DeckId) -> None:
|
||||
self.col.set_deck(card_ids=cids, deck_id=did)
|
||||
self.col.db.execute(
|
||||
f"update cards set did=?,usn=?,mod=? where id in {ids2str(cids)}",
|
||||
did,
|
||||
self.col.usn(),
|
||||
intTime(),
|
||||
)
|
||||
|
||||
@deprecated(replaced_by=all_names_and_ids)
|
||||
def all_ids(self) -> List[str]:
|
||||
return [str(x.id) for x in self.all_names_and_ids()]
|
||||
|
||||
@deprecated(replaced_by=all_names_and_ids)
|
||||
def all_names(self, dyn: bool = True, force_default: bool = True) -> List[str]:
|
||||
return [
|
||||
x.name
|
||||
for x in self.all_names_and_ids(
|
||||
skip_empty_default=not force_default, include_filtered=dyn
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
DeckManager.register_deprecated_aliases(
|
||||
confForDid=DeckManager.config_dict_for_deck_id,
|
||||
setConf=DeckManager.set_config_id_for_deck_dict,
|
||||
didsForConf=DeckManager.decks_using_config,
|
||||
allConf=DeckManager.all_config,
|
||||
getConf=DeckManager.get_config,
|
||||
updateConf=DeckManager.update_config,
|
||||
remConf=DeckManager.remove_config,
|
||||
confId=DeckManager.add_config_returning_id,
|
||||
newDyn=DeckManager.new_filtered,
|
||||
isDyn=DeckManager.is_filtered,
|
||||
nameOrNone=DeckManager.name_if_exists,
|
||||
)
|
||||
|
||||
|
||||
@no_type_check
|
||||
def __getattr__(name):
|
||||
if name == "defaultDeck":
|
||||
print_deprecation_warning(
|
||||
"defaultDeck is deprecated; call decks.id() without it"
|
||||
)
|
||||
return 0
|
||||
elif name == "defaultDynamicDeck":
|
||||
print_deprecation_warning("defaultDynamicDeck is replaced with new_filtered()")
|
||||
return 1
|
||||
else:
|
||||
raise AttributeError(f"module {__name__} has no attribute {name}")
|
||||
|
|
|
@ -266,7 +266,7 @@ class AnkiExporter(Exporter):
|
|||
d["conf"] = 1
|
||||
self.dst.decks.update(d)
|
||||
# copy used deck confs
|
||||
for dc in self.src.decks.allConf():
|
||||
for dc in self.src.decks.all_config():
|
||||
if dc["id"] in dconfs:
|
||||
self.dst.decks.update_config(dc)
|
||||
# find used media
|
||||
|
|
|
@ -274,7 +274,7 @@ class Anki2Importer(Importer):
|
|||
idInSrc = self.src.decks.id(head)
|
||||
self._did(idInSrc)
|
||||
# if target is a filtered deck, we'll need a new deck name
|
||||
deck = self.dst.decks.byName(name)
|
||||
deck = self.dst.decks.by_name(name)
|
||||
if deck and deck["dyn"]:
|
||||
name = "%s %d" % (name, intTime())
|
||||
# create in local
|
||||
|
|
|
@ -210,7 +210,7 @@ class NoteImporter(Importer):
|
|||
# we randomize or order here, to ensure that siblings
|
||||
# have the same due#
|
||||
did = self.col.decks.selected()
|
||||
conf = self.col.decks.confForDid(did)
|
||||
conf = self.col.decks.config_dict_for_deck_id(did)
|
||||
# in order due?
|
||||
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
||||
self.col.sched.randomizeCards(did)
|
||||
|
|
|
@ -222,7 +222,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||
self.col._backend.sort_deck(deck_id=did, randomize=False)
|
||||
|
||||
def resortConf(self, conf: DeckConfigDict) -> None:
|
||||
for did in self.col.decks.didsForConf(conf):
|
||||
for did in self.col.decks.decks_using_config(conf):
|
||||
if conf["new"]["order"] == 0:
|
||||
self.randomizeCards(did)
|
||||
else:
|
||||
|
@ -232,7 +232,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||
def maybeRandomizeDeck(self, did: Optional[DeckId] = None) -> None:
|
||||
if not did:
|
||||
did = self.col.decks.selected()
|
||||
conf = self.col.decks.confForDid(did)
|
||||
conf = self.col.decks.config_dict_for_deck_id(did)
|
||||
# in order due?
|
||||
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
||||
self.randomizeCards(did)
|
||||
|
|
|
@ -113,7 +113,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) -> DeckConfigDict:
|
||||
return self.col.decks.confForDid(card.did)
|
||||
return self.col.decks.config_dict_for_deck_id(card.did)
|
||||
|
||||
def _fuzzIvlRange(self, ivl: int) -> Tuple[int, int]:
|
||||
return (ivl, ivl)
|
||||
|
|
|
@ -636,7 +636,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
|||
if not card.odid:
|
||||
return conf["new"]
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
oconf = self.col.decks.config_dict_for_deck_id(card.odid)
|
||||
delays = conf["delays"] or oconf["new"]["delays"]
|
||||
return dict(
|
||||
# original deck
|
||||
|
@ -655,7 +655,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
|||
if not card.odid:
|
||||
return conf["lapse"]
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
oconf = self.col.decks.config_dict_for_deck_id(card.odid)
|
||||
delays = conf["delays"] or oconf["lapse"]["delays"]
|
||||
return dict(
|
||||
# original deck
|
||||
|
|
|
@ -251,7 +251,7 @@ select count() from
|
|||
"Limit for deck without parent limits."
|
||||
if g["dyn"]:
|
||||
return self.dynReportLimit
|
||||
c = self.col.decks.confForDid(g["id"])
|
||||
c = self.col.decks.config_dict_for_deck_id(g["id"])
|
||||
limit = max(0, c["new"]["perDay"] - self.counts_for_deck_today(g["id"]).new)
|
||||
return hooks.scheduler_new_limit_for_single_deck(limit, g)
|
||||
|
||||
|
@ -400,7 +400,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
|||
if d["dyn"]:
|
||||
return self.dynReportLimit
|
||||
|
||||
c = self.col.decks.confForDid(d["id"])
|
||||
c = self.col.decks.config_dict_for_deck_id(d["id"])
|
||||
lim = max(0, c["rev"]["perDay"] - self.counts_for_deck_today(d["id"]).review)
|
||||
|
||||
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
||||
|
@ -503,7 +503,7 @@ limit ?"""
|
|||
card.odue = 0
|
||||
|
||||
def _cardConf(self, card: Card) -> DeckConfigDict:
|
||||
return self.col.decks.confForDid(card.did)
|
||||
return self.col.decks.config_dict_for_deck_id(card.did)
|
||||
|
||||
def _deckLimit(self) -> str:
|
||||
return ids2str(self.col.decks.active())
|
||||
|
@ -517,7 +517,7 @@ limit ?"""
|
|||
if not card.odid:
|
||||
return conf["new"]
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
oconf = self.col.decks.config_dict_for_deck_id(card.odid)
|
||||
return dict(
|
||||
# original deck
|
||||
ints=oconf["new"]["ints"],
|
||||
|
@ -535,7 +535,7 @@ limit ?"""
|
|||
if not card.odid:
|
||||
return conf["lapse"]
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
oconf = self.col.decks.config_dict_for_deck_id(card.odid)
|
||||
return dict(
|
||||
# original deck
|
||||
minInt=oconf["lapse"]["minInt"],
|
||||
|
@ -824,7 +824,7 @@ limit ?"""
|
|||
if not card.odid:
|
||||
return conf["rev"]
|
||||
# dynamic deck
|
||||
return self.col.decks.confForDid(card.odid)["rev"]
|
||||
return self.col.decks.config_dict_for_deck_id(card.odid)["rev"]
|
||||
|
||||
def _answerRevCard(self, card: Card, ease: int) -> None:
|
||||
delay = 0
|
||||
|
|
|
@ -94,56 +94,3 @@ def test_rename():
|
|||
child = col.decks.get(childId)
|
||||
assertException(DeckRenameError, lambda: col.decks.rename(child, "filtered::child"))
|
||||
assertException(DeckRenameError, lambda: col.decks.rename(child, "FILTERED::child"))
|
||||
|
||||
|
||||
def test_renameForDragAndDrop():
|
||||
col = getEmptyCol()
|
||||
|
||||
def deckNames():
|
||||
return [n.name for n in col.decks.all_names_and_ids(skip_empty_default=True)]
|
||||
|
||||
languages_did = col.decks.id("Languages")
|
||||
chinese_did = col.decks.id("Chinese")
|
||||
hsk_did = col.decks.id("Chinese::HSK")
|
||||
|
||||
# Renaming also renames children
|
||||
col.decks.renameForDragAndDrop(chinese_did, languages_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
|
||||
|
||||
# Dragging a deck onto itself is a no-op
|
||||
col.decks.renameForDragAndDrop(languages_did, languages_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
|
||||
|
||||
# Dragging a deck onto its parent is a no-op
|
||||
col.decks.renameForDragAndDrop(hsk_did, chinese_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
|
||||
|
||||
# Dragging a deck onto a descendant is a no-op
|
||||
col.decks.renameForDragAndDrop(languages_did, hsk_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
|
||||
|
||||
# Can drag a grandchild onto its grandparent. It becomes a child
|
||||
col.decks.renameForDragAndDrop(hsk_did, languages_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::HSK"]
|
||||
|
||||
# Can drag a deck onto its sibling
|
||||
col.decks.renameForDragAndDrop(hsk_did, chinese_did)
|
||||
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
|
||||
|
||||
# Can drag a deck back to the top level
|
||||
col.decks.renameForDragAndDrop(chinese_did, None)
|
||||
assert deckNames() == ["Chinese", "Chinese::HSK", "Languages"]
|
||||
|
||||
# Dragging a top level col to the top level is a no-op
|
||||
col.decks.renameForDragAndDrop(chinese_did, None)
|
||||
assert deckNames() == ["Chinese", "Chinese::HSK", "Languages"]
|
||||
|
||||
# decks are renamed if necessary
|
||||
new_hsk_did = col.decks.id("hsk")
|
||||
col.decks.renameForDragAndDrop(new_hsk_did, chinese_did)
|
||||
assert deckNames() == ["Chinese", "Chinese::HSK", "Chinese::hsk+", "Languages"]
|
||||
col.decks.remove([new_hsk_did])
|
||||
|
||||
# '' is a convenient alias for the top level DID
|
||||
col.decks.renameForDragAndDrop(hsk_did, "")
|
||||
assert deckNames() == ["Chinese", "HSK", "Languages"]
|
||||
|
|
|
@ -52,7 +52,7 @@ def test_export_anki():
|
|||
conf = col.decks.get_config(confId)
|
||||
conf["new"]["perDay"] = 5
|
||||
col.decks.save(conf)
|
||||
col.decks.setConf(dobj, confId)
|
||||
col.decks.set_config_id_for_deck_dict(dobj, confId)
|
||||
# export
|
||||
e = AnkiExporter(col)
|
||||
fd, newname = tempfile.mkstemp(prefix="ankitest", suffix=".anki2")
|
||||
|
@ -61,7 +61,7 @@ def test_export_anki():
|
|||
os.unlink(newname)
|
||||
e.exportInto(newname)
|
||||
# exporting should not have changed conf for original deck
|
||||
conf = col.decks.confForDid(did)
|
||||
conf = col.decks.config_dict_for_deck_id(did)
|
||||
assert conf["id"] != 1
|
||||
# connect to new deck
|
||||
col2 = aopen(newname)
|
||||
|
@ -69,7 +69,7 @@ def test_export_anki():
|
|||
# as scheduling was reset, should also revert decks to default conf
|
||||
did = col2.decks.id("test", create=False)
|
||||
assert did
|
||||
conf2 = col2.decks.confForDid(did)
|
||||
conf2 = col2.decks.config_dict_for_deck_id(did)
|
||||
assert conf2["new"]["perDay"] == 20
|
||||
dobj = col2.decks.get(did)
|
||||
# conf should be 1
|
||||
|
|
|
@ -94,7 +94,7 @@ def test_newLimits():
|
|||
col.addNote(note)
|
||||
# give the child deck a different configuration
|
||||
c2 = col.decks.add_config_returning_id("new conf")
|
||||
col.decks.setConf(col.decks.get(deck2), c2)
|
||||
col.decks.set_config_id_for_deck_dict(col.decks.get(deck2), c2)
|
||||
col.reset()
|
||||
# both confs have defaulted to a limit of 20
|
||||
assert col.sched.newCount == 20
|
||||
|
@ -102,13 +102,13 @@ def test_newLimits():
|
|||
c = col.sched.getCard()
|
||||
assert c.did == 1
|
||||
# limit the parent to 10 cards, meaning we get 10 in total
|
||||
conf1 = col.decks.confForDid(1)
|
||||
conf1 = col.decks.config_dict_for_deck_id(1)
|
||||
conf1["new"]["perDay"] = 10
|
||||
col.decks.save(conf1)
|
||||
col.reset()
|
||||
assert col.sched.newCount == 10
|
||||
# if we limit child to 4, we should get 9
|
||||
conf2 = col.decks.confForDid(deck2)
|
||||
conf2 = col.decks.config_dict_for_deck_id(deck2)
|
||||
conf2["new"]["perDay"] = 4
|
||||
col.decks.save(conf2)
|
||||
col.reset()
|
||||
|
@ -444,7 +444,7 @@ def test_nextIvl():
|
|||
note["Back"] = "two"
|
||||
col.addNote(note)
|
||||
col.reset()
|
||||
conf = col.decks.confForDid(1)
|
||||
conf = col.decks.config_dict_for_deck_id(1)
|
||||
conf["new"]["delays"] = [0.5, 3, 10]
|
||||
conf["lapse"]["delays"] = [1, 5, 9]
|
||||
col.decks.save(conf)
|
||||
|
|
|
@ -106,7 +106,7 @@ def test_newLimits():
|
|||
col.addNote(note)
|
||||
# give the child deck a different configuration
|
||||
c2 = col.decks.add_config_returning_id("new conf")
|
||||
col.decks.setConf(col.decks.get(deck2), c2)
|
||||
col.decks.set_config_id_for_deck_dict(col.decks.get(deck2), c2)
|
||||
col.reset()
|
||||
# both confs have defaulted to a limit of 20
|
||||
assert col.sched.newCount == 20
|
||||
|
@ -114,13 +114,13 @@ def test_newLimits():
|
|||
c = col.sched.getCard()
|
||||
assert c.did == 1
|
||||
# limit the parent to 10 cards, meaning we get 10 in total
|
||||
conf1 = col.decks.confForDid(1)
|
||||
conf1 = col.decks.config_dict_for_deck_id(1)
|
||||
conf1["new"]["perDay"] = 10
|
||||
col.decks.save(conf1)
|
||||
col.reset()
|
||||
assert col.sched.newCount == 10
|
||||
# if we limit child to 4, we should get 9
|
||||
conf2 = col.decks.confForDid(deck2)
|
||||
conf2 = col.decks.config_dict_for_deck_id(deck2)
|
||||
conf2["new"]["perDay"] = 4
|
||||
col.decks.save(conf2)
|
||||
col.reset()
|
||||
|
@ -245,7 +245,7 @@ def test_relearn_no_steps():
|
|||
c.type = QUEUE_TYPE_REV
|
||||
c.flush()
|
||||
|
||||
conf = col.decks.confForDid(1)
|
||||
conf = col.decks.config_dict_for_deck_id(1)
|
||||
conf["lapse"]["delays"] = []
|
||||
col.decks.save(conf)
|
||||
|
||||
|
@ -415,7 +415,7 @@ def test_reviews():
|
|||
assert c.factor == 2650
|
||||
# leech handling
|
||||
##################################################
|
||||
conf = col.decks.getConf(1)
|
||||
conf = col.decks.get_config(1)
|
||||
conf["lapse"]["leechAction"] = LEECH_SUSPEND
|
||||
col.decks.save(conf)
|
||||
c = copy.copy(cardcopy)
|
||||
|
@ -448,10 +448,10 @@ def review_limits_setup() -> Tuple[anki.collection.Collection, Dict]:
|
|||
|
||||
pconf["rev"]["perDay"] = 5
|
||||
col.decks.update_config(pconf)
|
||||
col.decks.setConf(parent, pconf["id"])
|
||||
col.decks.set_config_id_for_deck_dict(parent, pconf["id"])
|
||||
cconf["rev"]["perDay"] = 10
|
||||
col.decks.update_config(cconf)
|
||||
col.decks.setConf(child, cconf["id"])
|
||||
col.decks.set_config_id_for_deck_dict(child, cconf["id"])
|
||||
|
||||
m = col.models.current()
|
||||
m["did"] = child["id"]
|
||||
|
@ -519,7 +519,7 @@ def test_button_spacing():
|
|||
assert wo(ni(c, 4)) == "4d"
|
||||
|
||||
# if hard factor is <= 1, then hard may not increase
|
||||
conf = col.decks.confForDid(1)
|
||||
conf = col.decks.config_dict_for_deck_id(1)
|
||||
conf["rev"]["hardFactor"] = 1
|
||||
col.decks.save(conf)
|
||||
assert wo(ni(c, 2)) == "1d"
|
||||
|
@ -566,7 +566,7 @@ def test_nextIvl():
|
|||
note["Back"] = "two"
|
||||
col.addNote(note)
|
||||
col.reset()
|
||||
conf = col.decks.confForDid(1)
|
||||
conf = col.decks.config_dict_for_deck_id(1)
|
||||
conf["new"]["delays"] = [0.5, 3, 10]
|
||||
conf["lapse"]["delays"] = [1, 5, 9]
|
||||
col.decks.save(conf)
|
||||
|
|
|
@ -140,7 +140,7 @@ class CustomStudy(QDialog):
|
|||
elif i == RADIO_CRAM:
|
||||
tags = self._getTags()
|
||||
# the rest create a filtered deck
|
||||
cur = self.mw.col.decks.byName(tr.custom_study_custom_study_session())
|
||||
cur = self.mw.col.decks.by_name(tr.custom_study_custom_study_session())
|
||||
if cur:
|
||||
if not cur["dyn"]:
|
||||
showInfo(tr.custom_study_must_rename_deck())
|
||||
|
|
|
@ -97,7 +97,7 @@ class DeckChooser(QHBoxLayout):
|
|||
geomKey="selectDeck",
|
||||
)
|
||||
if ret.name:
|
||||
self.selected_deck_id = self.mw.col.decks.byName(ret.name)["id"]
|
||||
self.selected_deck_id = self.mw.col.decks.by_name(ret.name)["id"]
|
||||
|
||||
# legacy
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ class DeckConf(QDialog):
|
|||
|
||||
def loadConfs(self) -> None:
|
||||
current = self.deck["conf"]
|
||||
self.confList = self.mw.col.decks.allConf()
|
||||
self.confList = self.mw.col.decks.all_config()
|
||||
self.confList.sort(key=itemgetter("name"))
|
||||
startOn = 0
|
||||
self.ignoreConfChange = True
|
||||
|
@ -117,7 +117,7 @@ class DeckConf(QDialog):
|
|||
self.deck["conf"] = conf["id"]
|
||||
self.mw.col.decks.save(self.deck)
|
||||
self.loadConf()
|
||||
cnt = len(self.mw.col.decks.didsForConf(conf))
|
||||
cnt = len(self.mw.col.decks.decks_using_config(conf))
|
||||
if cnt > 1:
|
||||
txt = tr.scheduling_your_changes_will_affect_multiple_decks()
|
||||
else:
|
||||
|
@ -190,7 +190,7 @@ class DeckConf(QDialog):
|
|||
return ""
|
||||
lim = -1
|
||||
for d in self.mw.col.decks.parents(self.deck["id"]):
|
||||
c = self.mw.col.decks.confForDid(d["id"])
|
||||
c = self.mw.col.decks.config_dict_for_deck_id(d["id"])
|
||||
x = c[type]["perDay"]
|
||||
if lim == -1:
|
||||
lim = x
|
||||
|
@ -199,7 +199,7 @@ class DeckConf(QDialog):
|
|||
return tr.scheduling_parent_limit(val=lim)
|
||||
|
||||
def loadConf(self) -> None:
|
||||
self.conf = self.mw.col.decks.confForDid(self.deck["id"])
|
||||
self.conf = self.mw.col.decks.config_dict_for_deck_id(self.deck["id"])
|
||||
# new
|
||||
c = self.conf["new"]
|
||||
f = self.form
|
||||
|
@ -240,7 +240,7 @@ class DeckConf(QDialog):
|
|||
|
||||
def onRestore(self) -> None:
|
||||
self.mw.progress.start()
|
||||
self.mw.col.decks.restoreToDefault(self.conf)
|
||||
self.mw.col.decks.restore_to_default(self.conf)
|
||||
self.mw.progress.finish()
|
||||
self.loadConf()
|
||||
|
||||
|
|
Loading…
Reference in a new issue