PEP8 decks.py

This commit is contained in:
Damien Elmes 2021-06-27 14:02:48 +10:00
parent 2a93355824
commit 62c23c6816
17 changed files with 188 additions and 253 deletions

View file

@ -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)

View file

@ -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."

View file

@ -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}")

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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"]

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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())

View file

@ -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

View file

@ -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()