mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 08:22:24 -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:])
|
return os.path.join(*path.parts[-components:])
|
||||||
|
|
||||||
|
|
||||||
def _print_deprecation_warning(old: str, doc: str) -> None:
|
def print_deprecation_warning(msg: str, frame: int = 2) -> None:
|
||||||
path, linenum, fn, y = traceback.extract_stack(limit=5)[2]
|
path, linenum, fn, y = traceback.extract_stack(limit=5)[frame]
|
||||||
path = partial_path(path, components=3)
|
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:
|
class DeprecatedNamesMixin:
|
||||||
|
@ -48,7 +52,7 @@ class DeprecatedNamesMixin:
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
out = getattr(self, remapped)
|
out = getattr(self, remapped)
|
||||||
_print_deprecation_warning(f"'{name}'", f"please use '{remapped}'")
|
_print_warning(f"'{name}'", f"please use '{remapped}'")
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
@ -75,7 +79,7 @@ def deprecated(replaced_by: Optional[Callable] = None, info: str = "") -> Callab
|
||||||
else:
|
else:
|
||||||
doc = info
|
doc = info
|
||||||
|
|
||||||
_print_deprecation_warning(f"{func.__name__}()", doc)
|
_print_warning(f"{func.__name__}()", doc)
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -170,19 +170,21 @@ class Card(DeprecatedNamesMixin):
|
||||||
|
|
||||||
def time_limit(self) -> int:
|
def time_limit(self) -> int:
|
||||||
"Time limit for answering in milliseconds."
|
"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
|
return conf["maxTaken"] * 1000
|
||||||
|
|
||||||
def should_show_timer(self) -> bool:
|
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"]
|
return conf["timer"]
|
||||||
|
|
||||||
def replay_question_audio_on_answer_side(self) -> bool:
|
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)
|
return conf.get("replayq", True)
|
||||||
|
|
||||||
def autoplay(self) -> bool:
|
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:
|
def time_taken(self) -> int:
|
||||||
"Time taken to answer card, in integer MS."
|
"Time taken to answer card, in integer MS."
|
||||||
|
|
|
@ -1,17 +1,30 @@
|
||||||
# Copyright: Ankitects Pty Ltd and contributors
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
# pylint: enable=invalid-name
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import pprint
|
from typing import (
|
||||||
import sys
|
TYPE_CHECKING,
|
||||||
import traceback
|
Any,
|
||||||
from typing import Any, Dict, Iterable, List, NewType, Optional, Sequence, Tuple, Union
|
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
|
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.cards import CardId
|
||||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
|
@ -26,10 +39,6 @@ DeckCollapseScope = _pb.SetDeckCollapsedRequest.Scope
|
||||||
DeckConfigsForUpdate = _pb.DeckConfigsForUpdate
|
DeckConfigsForUpdate = _pb.DeckConfigsForUpdate
|
||||||
UpdateDeckConfigs = _pb.UpdateDeckConfigsRequest
|
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
|
# type aliases until we can move away from dicts
|
||||||
DeckDict = Dict[str, Any]
|
DeckDict = Dict[str, Any]
|
||||||
DeckConfigDict = Dict[str, Any]
|
DeckConfigDict = Dict[str, Any]
|
||||||
|
@ -46,8 +55,9 @@ class DecksDictProxy:
|
||||||
self._col = col.weakref()
|
self._col = col.weakref()
|
||||||
|
|
||||||
def _warn(self) -> None:
|
def _warn(self) -> None:
|
||||||
traceback.print_stack(file=sys.stdout)
|
print_deprecation_warning(
|
||||||
print("add-on should use methods on col.decks, not col.decks.decks dict")
|
"add-on should use methods on col.decks, not col.decks.decks dict"
|
||||||
|
)
|
||||||
|
|
||||||
def __getitem__(self, item: Any) -> Any:
|
def __getitem__(self, item: Any) -> Any:
|
||||||
self._warn()
|
self._warn()
|
||||||
|
@ -78,7 +88,7 @@ class DecksDictProxy:
|
||||||
return self._col.decks.have(item)
|
return self._col.decks.have(item)
|
||||||
|
|
||||||
|
|
||||||
class DeckManager:
|
class DeckManager(DeprecatedNamesMixin):
|
||||||
# Registry save/load
|
# Registry save/load
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
|
@ -86,27 +96,18 @@ class DeckManager:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self.decks = DecksDictProxy(col)
|
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."
|
"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")
|
print("col.decks.save() should be passed the changed deck")
|
||||||
return
|
return
|
||||||
|
|
||||||
# deck conf?
|
# deck conf?
|
||||||
if "maxTaken" in g:
|
if "maxTaken" in deck_or_config:
|
||||||
self.update_config(g)
|
self.update_config(deck_or_config)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.update(g, preserve_usn=False)
|
self.update(deck_or_config, 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)}"
|
|
||||||
|
|
||||||
# Deck save/load
|
# Deck save/load
|
||||||
#############################################################
|
#############################################################
|
||||||
|
@ -146,14 +147,6 @@ class DeckManager:
|
||||||
def remove(self, dids: Sequence[DeckId]) -> OpChangesWithCount:
|
def remove(self, dids: Sequence[DeckId]) -> OpChangesWithCount:
|
||||||
return self.col._backend.remove_decks(dids)
|
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(
|
def all_names_and_ids(
|
||||||
self, skip_empty_default: bool = False, include_filtered: bool = True
|
self, skip_empty_default: bool = False, include_filtered: bool = True
|
||||||
) -> Sequence[DeckNameId]:
|
) -> Sequence[DeckNameId]:
|
||||||
|
@ -211,19 +204,6 @@ class DeckManager:
|
||||||
"All decks. Expensive; prefer all_names_and_ids()"
|
"All decks. Expensive; prefer all_names_and_ids()"
|
||||||
return self.get_all_legacy()
|
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(
|
def set_collapsed(
|
||||||
self, deck_id: DeckId, collapsed: bool, scope: DeckCollapseScope.V
|
self, deck_id: DeckId, collapsed: bool, scope: DeckCollapseScope.V
|
||||||
) -> OpChanges:
|
) -> OpChanges:
|
||||||
|
@ -236,7 +216,7 @@ class DeckManager:
|
||||||
deck["collapsed"] = not deck["collapsed"]
|
deck["collapsed"] = not deck["collapsed"]
|
||||||
self.save(deck)
|
self.save(deck)
|
||||||
|
|
||||||
def collapseBrowser(self, did: DeckId) -> None:
|
def collapse_browser(self, did: DeckId) -> None:
|
||||||
deck = self.get(did)
|
deck = self.get(did)
|
||||||
collapsed = deck.get("browserCollapsed", False)
|
collapsed = deck.get("browserCollapsed", False)
|
||||||
deck["browserCollapsed"] = not collapsed
|
deck["browserCollapsed"] = not collapsed
|
||||||
|
@ -275,17 +255,17 @@ class DeckManager:
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def byName(self, name: str) -> Optional[DeckDict]:
|
def by_name(self, name: str) -> Optional[DeckDict]:
|
||||||
"""Get deck with NAME, ignoring case."""
|
"""Get deck with NAME, ignoring case."""
|
||||||
id = self.id_for_name(name)
|
id = self.id_for_name(name)
|
||||||
if id:
|
if id:
|
||||||
return self.get_legacy(id)
|
return self.get_legacy(id)
|
||||||
return None
|
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."
|
"Add or update an existing deck. Used for syncing and merging."
|
||||||
g["id"] = self.col._backend.add_or_update_deck_legacy(
|
deck["id"] = self.col._backend.add_or_update_deck_legacy(
|
||||||
deck=to_json_bytes(g), preserve_usn_and_mtime=preserve_usn
|
deck=to_json_bytes(deck), preserve_usn_and_mtime=preserve_usn
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_dict(self, deck: DeckDict) -> OpChanges:
|
def update_dict(self, deck: DeckDict) -> OpChanges:
|
||||||
|
@ -311,18 +291,6 @@ class DeckManager:
|
||||||
deck_ids=deck_ids, new_parent=new_parent
|
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
|
# Deck configurations
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
|
@ -336,7 +304,7 @@ class DeckManager:
|
||||||
"A list of all deck config."
|
"A list of all deck config."
|
||||||
return list(from_json_bytes(self.col._backend.all_deck_config_legacy()))
|
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)
|
deck = self.get(did, default=False)
|
||||||
assert deck
|
assert deck
|
||||||
if "conf" in deck:
|
if "conf" in deck:
|
||||||
|
@ -382,43 +350,36 @@ class DeckManager:
|
||||||
def remove_config(self, id: DeckConfigId) -> None:
|
def remove_config(self, id: DeckConfigId) -> None:
|
||||||
"Remove a configuration and update all decks using it."
|
"Remove a configuration and update all decks using it."
|
||||||
self.col.modSchema(check=True)
|
self.col.modSchema(check=True)
|
||||||
for g in self.all():
|
for deck in self.all():
|
||||||
# ignore cram decks
|
# ignore cram decks
|
||||||
if "conf" not in g:
|
if "conf" not in deck:
|
||||||
continue
|
continue
|
||||||
if str(g["conf"]) == str(id):
|
if str(deck["conf"]) == str(id):
|
||||||
g["conf"] = 1
|
deck["conf"] = 1
|
||||||
self.save(g)
|
self.save(deck)
|
||||||
self.col._backend.remove_deck_config(id)
|
self.col._backend.remove_deck_config(id)
|
||||||
|
|
||||||
def setConf(self, grp: DeckConfigDict, id: DeckConfigId) -> None:
|
def set_config_id_for_deck_dict(self, deck: DeckDict, id: DeckConfigId) -> None:
|
||||||
grp["conf"] = id
|
deck["conf"] = id
|
||||||
self.save(grp)
|
self.save(deck)
|
||||||
|
|
||||||
def didsForConf(self, conf: DeckConfigDict) -> List[DeckId]:
|
def decks_using_config(self, conf: DeckConfigDict) -> List[DeckId]:
|
||||||
dids = []
|
dids = []
|
||||||
for deck in self.all():
|
for deck in self.all():
|
||||||
if "conf" in deck and deck["conf"] == conf["id"]:
|
if "conf" in deck and deck["conf"] == conf["id"]:
|
||||||
dids.append(deck["id"])
|
dids.append(deck["id"])
|
||||||
return dids
|
return dids
|
||||||
|
|
||||||
def restoreToDefault(self, conf: DeckConfigDict) -> None:
|
def restore_to_default(self, conf: DeckConfigDict) -> None:
|
||||||
oldOrder = conf["new"]["order"]
|
old_order = conf["new"]["order"]
|
||||||
new = from_json_bytes(self.col._backend.new_deck_config_legacy())
|
new = from_json_bytes(self.col._backend.new_deck_config_legacy())
|
||||||
new["id"] = conf["id"]
|
new["id"] = conf["id"]
|
||||||
new["name"] = conf["name"]
|
new["name"] = conf["name"]
|
||||||
self.update_config(new)
|
self.update_config(new)
|
||||||
# if it was previously randomized, re-sort
|
# if it was previously randomized, re-sort
|
||||||
if not oldOrder:
|
if not old_order:
|
||||||
self.col.sched.resortConf(new)
|
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
|
# Deck utils
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
|
@ -434,14 +395,6 @@ class DeckManager:
|
||||||
return deck["name"]
|
return deck["name"]
|
||||||
return None
|
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]:
|
def cids(self, did: DeckId, children: bool = False) -> List[CardId]:
|
||||||
if not children:
|
if not children:
|
||||||
return self.col.db.list("select id from cards where did=?", did)
|
return self.col.db.list("select id from cards where did=?", did)
|
||||||
|
@ -463,21 +416,19 @@ class DeckManager:
|
||||||
"The currently selected deck ID."
|
"The currently selected deck ID."
|
||||||
return DeckId(self.col._backend.get_current_deck().id)
|
return DeckId(self.col._backend.get_current_deck().id)
|
||||||
|
|
||||||
# legacy
|
|
||||||
|
|
||||||
def current(self) -> DeckDict:
|
def current(self) -> DeckDict:
|
||||||
return self.get(self.selected())
|
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:
|
def select(self, did: DeckId) -> None:
|
||||||
# make sure arg is an int; legacy callers may be passing in a string
|
# make sure arg is an int; legacy callers may be passing in a string
|
||||||
did = DeckId(did)
|
did = DeckId(did)
|
||||||
self.set_current(did)
|
self.set_current(did)
|
||||||
self.col.reset()
|
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
|
selected = get_current_id
|
||||||
|
|
||||||
# Parents/children
|
# Parents/children
|
||||||
|
@ -487,23 +438,19 @@ class DeckManager:
|
||||||
def path(name: str) -> List[str]:
|
def path(name: str) -> List[str]:
|
||||||
return name.split("::")
|
return name.split("::")
|
||||||
|
|
||||||
_path = path
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def basename(cls, name: str) -> str:
|
def basename(cls, name: str) -> str:
|
||||||
return cls.path(name)[-1]
|
return cls.path(name)[-1]
|
||||||
|
|
||||||
_basename = basename
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def immediate_parent_path(cls, name: str) -> List[str]:
|
def immediate_parent_path(cls, name: str) -> List[str]:
|
||||||
return cls._path(name)[:-1]
|
return cls.path(name)[:-1]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def immediate_parent(cls, name: str) -> Optional[str]:
|
def immediate_parent(cls, name: str) -> Optional[str]:
|
||||||
pp = cls.immediate_parent_path(name)
|
parent_path = cls.immediate_parent_path(name)
|
||||||
if pp:
|
if parent_path:
|
||||||
return "::".join(pp)
|
return "::".join(parent_path)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -514,9 +461,9 @@ class DeckManager:
|
||||||
"All children of did, as (name, id)."
|
"All children of did, as (name, id)."
|
||||||
name = self.get(did)["name"]
|
name = self.get(did)["name"]
|
||||||
actv = []
|
actv = []
|
||||||
for g in self.all_names_and_ids():
|
for entry in self.all_names_and_ids():
|
||||||
if g.name.startswith(f"{name}::"):
|
if entry.name.startswith(f"{name}::"):
|
||||||
actv.append((g.name, DeckId(g.id)))
|
actv.append((entry.name, DeckId(entry.id)))
|
||||||
return actv
|
return actv
|
||||||
|
|
||||||
def child_ids(self, parent_name: str) -> Iterable[DeckId]:
|
def child_ids(self, parent_name: str) -> Iterable[DeckId]:
|
||||||
|
@ -531,38 +478,8 @@ class DeckManager:
|
||||||
out.extend(self.child_ids(parent_name))
|
out.extend(self.child_ids(parent_name))
|
||||||
return out
|
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(
|
def parents(
|
||||||
self, did: DeckId, nameMap: Optional[Dict[str, DeckDict]] = None
|
self, did: DeckId, name_map: Optional[Dict[str, DeckDict]] = None
|
||||||
) -> List[DeckDict]:
|
) -> List[DeckDict]:
|
||||||
"All parents of did."
|
"All parents of did."
|
||||||
# get parent and grandparent names
|
# get parent and grandparent names
|
||||||
|
@ -575,14 +492,14 @@ class DeckManager:
|
||||||
parents: List[DeckDict] = []
|
parents: List[DeckDict] = []
|
||||||
# convert to objects
|
# convert to objects
|
||||||
for parent_name in parents_names:
|
for parent_name in parents_names:
|
||||||
if nameMap:
|
if name_map:
|
||||||
deck = nameMap[parent_name]
|
deck = name_map[parent_name]
|
||||||
else:
|
else:
|
||||||
deck = self.get(self.id(parent_name))
|
deck = self.get(self.id(parent_name))
|
||||||
parents.append(deck)
|
parents.append(deck)
|
||||||
return parents
|
return parents
|
||||||
|
|
||||||
def parentsByName(self, name: str) -> List[DeckDict]:
|
def parents_by_name(self, name: str) -> List[DeckDict]:
|
||||||
"All existing parents of name"
|
"All existing parents of name"
|
||||||
if "::" not in name:
|
if "::" not in name:
|
||||||
return []
|
return []
|
||||||
|
@ -592,15 +509,12 @@ class DeckManager:
|
||||||
|
|
||||||
while names:
|
while names:
|
||||||
head.append(names.pop(0))
|
head.append(names.pop(0))
|
||||||
deck = self.byName("::".join(head))
|
deck = self.by_name("::".join(head))
|
||||||
if deck:
|
if deck:
|
||||||
parents.append(deck)
|
parents.append(deck)
|
||||||
|
|
||||||
return parents
|
return parents
|
||||||
|
|
||||||
def nameMap(self) -> Dict[str, DeckDict]:
|
|
||||||
return {d["name"]: d for d in self.all()}
|
|
||||||
|
|
||||||
# Filtered decks
|
# Filtered decks
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
@ -610,11 +524,79 @@ class DeckManager:
|
||||||
self.select(did)
|
self.select(did)
|
||||||
return did
|
return did
|
||||||
|
|
||||||
# 1 for dyn, 0 for standard
|
def is_filtered(self, did: Union[DeckId, str]) -> bool:
|
||||||
def isDyn(self, did: Union[DeckId, str]) -> int:
|
return bool(self.get(did)["dyn"])
|
||||||
return self.get(did)["dyn"]
|
|
||||||
|
|
||||||
# legacy
|
# Legacy
|
||||||
|
#############
|
||||||
|
|
||||||
newDyn = new_filtered
|
@deprecated(info="no longer required")
|
||||||
nameOrNone = name_if_exists
|
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
|
d["conf"] = 1
|
||||||
self.dst.decks.update(d)
|
self.dst.decks.update(d)
|
||||||
# copy used deck confs
|
# copy used deck confs
|
||||||
for dc in self.src.decks.allConf():
|
for dc in self.src.decks.all_config():
|
||||||
if dc["id"] in dconfs:
|
if dc["id"] in dconfs:
|
||||||
self.dst.decks.update_config(dc)
|
self.dst.decks.update_config(dc)
|
||||||
# find used media
|
# find used media
|
||||||
|
|
|
@ -274,7 +274,7 @@ class Anki2Importer(Importer):
|
||||||
idInSrc = self.src.decks.id(head)
|
idInSrc = self.src.decks.id(head)
|
||||||
self._did(idInSrc)
|
self._did(idInSrc)
|
||||||
# if target is a filtered deck, we'll need a new deck name
|
# 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"]:
|
if deck and deck["dyn"]:
|
||||||
name = "%s %d" % (name, intTime())
|
name = "%s %d" % (name, intTime())
|
||||||
# create in local
|
# create in local
|
||||||
|
|
|
@ -210,7 +210,7 @@ class NoteImporter(Importer):
|
||||||
# we randomize or order here, to ensure that siblings
|
# we randomize or order here, to ensure that siblings
|
||||||
# have the same due#
|
# have the same due#
|
||||||
did = self.col.decks.selected()
|
did = self.col.decks.selected()
|
||||||
conf = self.col.decks.confForDid(did)
|
conf = self.col.decks.config_dict_for_deck_id(did)
|
||||||
# in order due?
|
# in order due?
|
||||||
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
||||||
self.col.sched.randomizeCards(did)
|
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)
|
self.col._backend.sort_deck(deck_id=did, randomize=False)
|
||||||
|
|
||||||
def resortConf(self, conf: DeckConfigDict) -> None:
|
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:
|
if conf["new"]["order"] == 0:
|
||||||
self.randomizeCards(did)
|
self.randomizeCards(did)
|
||||||
else:
|
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:
|
def maybeRandomizeDeck(self, did: Optional[DeckId] = None) -> None:
|
||||||
if not did:
|
if not did:
|
||||||
did = self.col.decks.selected()
|
did = self.col.decks.selected()
|
||||||
conf = self.col.decks.confForDid(did)
|
conf = self.col.decks.config_dict_for_deck_id(did)
|
||||||
# in order due?
|
# in order due?
|
||||||
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
if conf["new"]["order"] == NEW_CARDS_RANDOM:
|
||||||
self.randomizeCards(did)
|
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
|
# legacy in v3 but used by unit tests; redefined in v2/v1
|
||||||
|
|
||||||
def _cardConf(self, card: Card) -> DeckConfigDict:
|
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]:
|
def _fuzzIvlRange(self, ivl: int) -> Tuple[int, int]:
|
||||||
return (ivl, ivl)
|
return (ivl, ivl)
|
||||||
|
|
|
@ -636,7 +636,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
||||||
if not card.odid:
|
if not card.odid:
|
||||||
return conf["new"]
|
return conf["new"]
|
||||||
# dynamic deck; override some attributes, use original deck for others
|
# 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"]
|
delays = conf["delays"] or oconf["new"]["delays"]
|
||||||
return dict(
|
return dict(
|
||||||
# original deck
|
# original deck
|
||||||
|
@ -655,7 +655,7 @@ did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""",
|
||||||
if not card.odid:
|
if not card.odid:
|
||||||
return conf["lapse"]
|
return conf["lapse"]
|
||||||
# dynamic deck; override some attributes, use original deck for others
|
# 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"]
|
delays = conf["delays"] or oconf["lapse"]["delays"]
|
||||||
return dict(
|
return dict(
|
||||||
# original deck
|
# original deck
|
||||||
|
|
|
@ -251,7 +251,7 @@ select count() from
|
||||||
"Limit for deck without parent limits."
|
"Limit for deck without parent limits."
|
||||||
if g["dyn"]:
|
if g["dyn"]:
|
||||||
return self.dynReportLimit
|
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)
|
limit = max(0, c["new"]["perDay"] - self.counts_for_deck_today(g["id"]).new)
|
||||||
return hooks.scheduler_new_limit_for_single_deck(limit, g)
|
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"]:
|
if d["dyn"]:
|
||||||
return self.dynReportLimit
|
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)
|
lim = max(0, c["rev"]["perDay"] - self.counts_for_deck_today(d["id"]).review)
|
||||||
|
|
||||||
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
||||||
|
@ -503,7 +503,7 @@ limit ?"""
|
||||||
card.odue = 0
|
card.odue = 0
|
||||||
|
|
||||||
def _cardConf(self, card: Card) -> DeckConfigDict:
|
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:
|
def _deckLimit(self) -> str:
|
||||||
return ids2str(self.col.decks.active())
|
return ids2str(self.col.decks.active())
|
||||||
|
@ -517,7 +517,7 @@ limit ?"""
|
||||||
if not card.odid:
|
if not card.odid:
|
||||||
return conf["new"]
|
return conf["new"]
|
||||||
# dynamic deck; override some attributes, use original deck for others
|
# 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(
|
return dict(
|
||||||
# original deck
|
# original deck
|
||||||
ints=oconf["new"]["ints"],
|
ints=oconf["new"]["ints"],
|
||||||
|
@ -535,7 +535,7 @@ limit ?"""
|
||||||
if not card.odid:
|
if not card.odid:
|
||||||
return conf["lapse"]
|
return conf["lapse"]
|
||||||
# dynamic deck; override some attributes, use original deck for others
|
# 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(
|
return dict(
|
||||||
# original deck
|
# original deck
|
||||||
minInt=oconf["lapse"]["minInt"],
|
minInt=oconf["lapse"]["minInt"],
|
||||||
|
@ -824,7 +824,7 @@ limit ?"""
|
||||||
if not card.odid:
|
if not card.odid:
|
||||||
return conf["rev"]
|
return conf["rev"]
|
||||||
# dynamic deck
|
# 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:
|
def _answerRevCard(self, card: Card, ease: int) -> None:
|
||||||
delay = 0
|
delay = 0
|
||||||
|
|
|
@ -94,56 +94,3 @@ def test_rename():
|
||||||
child = col.decks.get(childId)
|
child = col.decks.get(childId)
|
||||||
assertException(DeckRenameError, lambda: col.decks.rename(child, "filtered::child"))
|
assertException(DeckRenameError, lambda: col.decks.rename(child, "filtered::child"))
|
||||||
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 = col.decks.get_config(confId)
|
||||||
conf["new"]["perDay"] = 5
|
conf["new"]["perDay"] = 5
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
col.decks.setConf(dobj, confId)
|
col.decks.set_config_id_for_deck_dict(dobj, confId)
|
||||||
# export
|
# export
|
||||||
e = AnkiExporter(col)
|
e = AnkiExporter(col)
|
||||||
fd, newname = tempfile.mkstemp(prefix="ankitest", suffix=".anki2")
|
fd, newname = tempfile.mkstemp(prefix="ankitest", suffix=".anki2")
|
||||||
|
@ -61,7 +61,7 @@ def test_export_anki():
|
||||||
os.unlink(newname)
|
os.unlink(newname)
|
||||||
e.exportInto(newname)
|
e.exportInto(newname)
|
||||||
# exporting should not have changed conf for original deck
|
# 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
|
assert conf["id"] != 1
|
||||||
# connect to new deck
|
# connect to new deck
|
||||||
col2 = aopen(newname)
|
col2 = aopen(newname)
|
||||||
|
@ -69,7 +69,7 @@ def test_export_anki():
|
||||||
# as scheduling was reset, should also revert decks to default conf
|
# as scheduling was reset, should also revert decks to default conf
|
||||||
did = col2.decks.id("test", create=False)
|
did = col2.decks.id("test", create=False)
|
||||||
assert did
|
assert did
|
||||||
conf2 = col2.decks.confForDid(did)
|
conf2 = col2.decks.config_dict_for_deck_id(did)
|
||||||
assert conf2["new"]["perDay"] == 20
|
assert conf2["new"]["perDay"] == 20
|
||||||
dobj = col2.decks.get(did)
|
dobj = col2.decks.get(did)
|
||||||
# conf should be 1
|
# conf should be 1
|
||||||
|
|
|
@ -94,7 +94,7 @@ def test_newLimits():
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# give the child deck a different configuration
|
# give the child deck a different configuration
|
||||||
c2 = col.decks.add_config_returning_id("new conf")
|
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()
|
col.reset()
|
||||||
# both confs have defaulted to a limit of 20
|
# both confs have defaulted to a limit of 20
|
||||||
assert col.sched.newCount == 20
|
assert col.sched.newCount == 20
|
||||||
|
@ -102,13 +102,13 @@ def test_newLimits():
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.did == 1
|
assert c.did == 1
|
||||||
# limit the parent to 10 cards, meaning we get 10 in total
|
# 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
|
conf1["new"]["perDay"] = 10
|
||||||
col.decks.save(conf1)
|
col.decks.save(conf1)
|
||||||
col.reset()
|
col.reset()
|
||||||
assert col.sched.newCount == 10
|
assert col.sched.newCount == 10
|
||||||
# if we limit child to 4, we should get 9
|
# 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
|
conf2["new"]["perDay"] = 4
|
||||||
col.decks.save(conf2)
|
col.decks.save(conf2)
|
||||||
col.reset()
|
col.reset()
|
||||||
|
@ -444,7 +444,7 @@ def test_nextIvl():
|
||||||
note["Back"] = "two"
|
note["Back"] = "two"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
col.reset()
|
col.reset()
|
||||||
conf = col.decks.confForDid(1)
|
conf = col.decks.config_dict_for_deck_id(1)
|
||||||
conf["new"]["delays"] = [0.5, 3, 10]
|
conf["new"]["delays"] = [0.5, 3, 10]
|
||||||
conf["lapse"]["delays"] = [1, 5, 9]
|
conf["lapse"]["delays"] = [1, 5, 9]
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
|
|
|
@ -106,7 +106,7 @@ def test_newLimits():
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# give the child deck a different configuration
|
# give the child deck a different configuration
|
||||||
c2 = col.decks.add_config_returning_id("new conf")
|
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()
|
col.reset()
|
||||||
# both confs have defaulted to a limit of 20
|
# both confs have defaulted to a limit of 20
|
||||||
assert col.sched.newCount == 20
|
assert col.sched.newCount == 20
|
||||||
|
@ -114,13 +114,13 @@ def test_newLimits():
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.did == 1
|
assert c.did == 1
|
||||||
# limit the parent to 10 cards, meaning we get 10 in total
|
# 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
|
conf1["new"]["perDay"] = 10
|
||||||
col.decks.save(conf1)
|
col.decks.save(conf1)
|
||||||
col.reset()
|
col.reset()
|
||||||
assert col.sched.newCount == 10
|
assert col.sched.newCount == 10
|
||||||
# if we limit child to 4, we should get 9
|
# 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
|
conf2["new"]["perDay"] = 4
|
||||||
col.decks.save(conf2)
|
col.decks.save(conf2)
|
||||||
col.reset()
|
col.reset()
|
||||||
|
@ -245,7 +245,7 @@ def test_relearn_no_steps():
|
||||||
c.type = QUEUE_TYPE_REV
|
c.type = QUEUE_TYPE_REV
|
||||||
c.flush()
|
c.flush()
|
||||||
|
|
||||||
conf = col.decks.confForDid(1)
|
conf = col.decks.config_dict_for_deck_id(1)
|
||||||
conf["lapse"]["delays"] = []
|
conf["lapse"]["delays"] = []
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ def test_reviews():
|
||||||
assert c.factor == 2650
|
assert c.factor == 2650
|
||||||
# leech handling
|
# leech handling
|
||||||
##################################################
|
##################################################
|
||||||
conf = col.decks.getConf(1)
|
conf = col.decks.get_config(1)
|
||||||
conf["lapse"]["leechAction"] = LEECH_SUSPEND
|
conf["lapse"]["leechAction"] = LEECH_SUSPEND
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
c = copy.copy(cardcopy)
|
c = copy.copy(cardcopy)
|
||||||
|
@ -448,10 +448,10 @@ def review_limits_setup() -> Tuple[anki.collection.Collection, Dict]:
|
||||||
|
|
||||||
pconf["rev"]["perDay"] = 5
|
pconf["rev"]["perDay"] = 5
|
||||||
col.decks.update_config(pconf)
|
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
|
cconf["rev"]["perDay"] = 10
|
||||||
col.decks.update_config(cconf)
|
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 = col.models.current()
|
||||||
m["did"] = child["id"]
|
m["did"] = child["id"]
|
||||||
|
@ -519,7 +519,7 @@ def test_button_spacing():
|
||||||
assert wo(ni(c, 4)) == "4d"
|
assert wo(ni(c, 4)) == "4d"
|
||||||
|
|
||||||
# if hard factor is <= 1, then hard may not increase
|
# 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
|
conf["rev"]["hardFactor"] = 1
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
assert wo(ni(c, 2)) == "1d"
|
assert wo(ni(c, 2)) == "1d"
|
||||||
|
@ -566,7 +566,7 @@ def test_nextIvl():
|
||||||
note["Back"] = "two"
|
note["Back"] = "two"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
col.reset()
|
col.reset()
|
||||||
conf = col.decks.confForDid(1)
|
conf = col.decks.config_dict_for_deck_id(1)
|
||||||
conf["new"]["delays"] = [0.5, 3, 10]
|
conf["new"]["delays"] = [0.5, 3, 10]
|
||||||
conf["lapse"]["delays"] = [1, 5, 9]
|
conf["lapse"]["delays"] = [1, 5, 9]
|
||||||
col.decks.save(conf)
|
col.decks.save(conf)
|
||||||
|
|
|
@ -140,7 +140,7 @@ class CustomStudy(QDialog):
|
||||||
elif i == RADIO_CRAM:
|
elif i == RADIO_CRAM:
|
||||||
tags = self._getTags()
|
tags = self._getTags()
|
||||||
# the rest create a filtered deck
|
# 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 cur:
|
||||||
if not cur["dyn"]:
|
if not cur["dyn"]:
|
||||||
showInfo(tr.custom_study_must_rename_deck())
|
showInfo(tr.custom_study_must_rename_deck())
|
||||||
|
|
|
@ -97,7 +97,7 @@ class DeckChooser(QHBoxLayout):
|
||||||
geomKey="selectDeck",
|
geomKey="selectDeck",
|
||||||
)
|
)
|
||||||
if ret.name:
|
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
|
# legacy
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ class DeckConf(QDialog):
|
||||||
|
|
||||||
def loadConfs(self) -> None:
|
def loadConfs(self) -> None:
|
||||||
current = self.deck["conf"]
|
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"))
|
self.confList.sort(key=itemgetter("name"))
|
||||||
startOn = 0
|
startOn = 0
|
||||||
self.ignoreConfChange = True
|
self.ignoreConfChange = True
|
||||||
|
@ -117,7 +117,7 @@ class DeckConf(QDialog):
|
||||||
self.deck["conf"] = conf["id"]
|
self.deck["conf"] = conf["id"]
|
||||||
self.mw.col.decks.save(self.deck)
|
self.mw.col.decks.save(self.deck)
|
||||||
self.loadConf()
|
self.loadConf()
|
||||||
cnt = len(self.mw.col.decks.didsForConf(conf))
|
cnt = len(self.mw.col.decks.decks_using_config(conf))
|
||||||
if cnt > 1:
|
if cnt > 1:
|
||||||
txt = tr.scheduling_your_changes_will_affect_multiple_decks()
|
txt = tr.scheduling_your_changes_will_affect_multiple_decks()
|
||||||
else:
|
else:
|
||||||
|
@ -190,7 +190,7 @@ class DeckConf(QDialog):
|
||||||
return ""
|
return ""
|
||||||
lim = -1
|
lim = -1
|
||||||
for d in self.mw.col.decks.parents(self.deck["id"]):
|
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"]
|
x = c[type]["perDay"]
|
||||||
if lim == -1:
|
if lim == -1:
|
||||||
lim = x
|
lim = x
|
||||||
|
@ -199,7 +199,7 @@ class DeckConf(QDialog):
|
||||||
return tr.scheduling_parent_limit(val=lim)
|
return tr.scheduling_parent_limit(val=lim)
|
||||||
|
|
||||||
def loadConf(self) -> None:
|
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
|
# new
|
||||||
c = self.conf["new"]
|
c = self.conf["new"]
|
||||||
f = self.form
|
f = self.form
|
||||||
|
@ -240,7 +240,7 @@ class DeckConf(QDialog):
|
||||||
|
|
||||||
def onRestore(self) -> None:
|
def onRestore(self) -> None:
|
||||||
self.mw.progress.start()
|
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.mw.progress.finish()
|
||||||
self.loadConf()
|
self.loadConf()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue