mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
PEP8 cards.py
This commit is contained in:
parent
1cabe9507c
commit
2a93355824
26 changed files with 209 additions and 197 deletions
|
@ -3,7 +3,11 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable, Dict, Optional, Tuple, Union
|
import functools
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import traceback
|
||||||
|
from typing import Any, Callable, Dict, Optional, Tuple, Union, no_type_check
|
||||||
|
|
||||||
import stringcase
|
import stringcase
|
||||||
|
|
||||||
|
@ -18,20 +22,37 @@ def _target_to_string(target: DeprecatedAliasTarget) -> str:
|
||||||
return target[1] # type: ignore
|
return target[1] # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def partial_path(full_path: str, components: int) -> str:
|
||||||
|
path = pathlib.Path(full_path)
|
||||||
|
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]
|
||||||
|
path = partial_path(path, components=3)
|
||||||
|
print(f"{path}:{linenum}:{old} is deprecated: {doc}")
|
||||||
|
|
||||||
|
|
||||||
class DeprecatedNamesMixin:
|
class DeprecatedNamesMixin:
|
||||||
"Expose instance methods/vars as camelCase for legacy callers."
|
"Expose instance methods/vars as camelCase for legacy callers."
|
||||||
|
|
||||||
|
# the @no_type_check lines are required to prevent mypy allowing arbitrary
|
||||||
|
# attributes on the consuming class
|
||||||
|
|
||||||
_deprecated_aliases: Dict[str, str] = {}
|
_deprecated_aliases: Dict[str, str] = {}
|
||||||
|
|
||||||
|
@no_type_check
|
||||||
def __getattr__(self, name: str) -> Any:
|
def __getattr__(self, name: str) -> Any:
|
||||||
remapped = self._deprecated_aliases.get(name) or stringcase.snakecase(name)
|
remapped = self._deprecated_aliases.get(name) or stringcase.snakecase(name)
|
||||||
if remapped == name:
|
if remapped == name:
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
out = getattr(self, remapped)
|
out = getattr(self, remapped)
|
||||||
print(f"please use {remapped} instead of {name} on {self}")
|
_print_deprecation_warning(f"'{name}'", f"please use '{remapped}'")
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
@no_type_check
|
||||||
@classmethod
|
@classmethod
|
||||||
def register_deprecated_aliases(cls, **kwargs: DeprecatedAliasTarget) -> None:
|
def register_deprecated_aliases(cls, **kwargs: DeprecatedAliasTarget) -> None:
|
||||||
"""Manually add aliases that are not a simple transform.
|
"""Manually add aliases that are not a simple transform.
|
||||||
|
@ -47,15 +68,15 @@ def deprecated(replaced_by: Optional[Callable] = None, info: str = "") -> Callab
|
||||||
"""Print a deprecation warning, telling users to use `replaced_by`, or show `doc`."""
|
"""Print a deprecation warning, telling users to use `replaced_by`, or show `doc`."""
|
||||||
|
|
||||||
def decorator(func: Callable) -> Callable:
|
def decorator(func: Callable) -> Callable:
|
||||||
|
@functools.wraps(func)
|
||||||
def decorated_func(*args: Any, **kwargs: Any) -> Any:
|
def decorated_func(*args: Any, **kwargs: Any) -> Any:
|
||||||
if replaced_by:
|
if replaced_by:
|
||||||
doc = f"please use {replaced_by.__name__} instead."
|
doc = f"please use {replaced_by.__name__} instead."
|
||||||
else:
|
else:
|
||||||
doc = info
|
doc = info
|
||||||
print(
|
|
||||||
f"'{func.__name__}' is deprecated, and will be removed in the future: ",
|
_print_deprecation_warning(f"{func.__name__}()", doc)
|
||||||
doc,
|
|
||||||
)
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return decorated_func
|
return decorated_func
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# 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 pprint
|
import pprint
|
||||||
|
@ -10,6 +12,7 @@ from typing import List, NewType, Optional
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.models import NotetypeDict, TemplateDict
|
from anki.models import NotetypeDict, TemplateDict
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
|
@ -22,7 +25,7 @@ from anki.sound import AVTag
|
||||||
# Queue: same as above, and:
|
# Queue: same as above, and:
|
||||||
# -1=suspended, -2=user buried, -3=sched buried
|
# -1=suspended, -2=user buried, -3=sched buried
|
||||||
# Due is used differently for different queues.
|
# Due is used differently for different queues.
|
||||||
# - new queue: note id or random int
|
# - new queue: position
|
||||||
# - rev queue: integer day
|
# - rev queue: integer day
|
||||||
# - lrn queue: integer timestamp
|
# - lrn queue: integer timestamp
|
||||||
|
|
||||||
|
@ -31,9 +34,8 @@ CardId = NewType("CardId", int)
|
||||||
BackendCard = _pb.Card
|
BackendCard = _pb.Card
|
||||||
|
|
||||||
|
|
||||||
class Card:
|
class Card(DeprecatedNamesMixin):
|
||||||
_note: Optional[Note]
|
_note: Optional[Note]
|
||||||
timerStarted: Optional[float]
|
|
||||||
lastIvl: int
|
lastIvl: int
|
||||||
ord: int
|
ord: int
|
||||||
nid: anki.notes.NoteId
|
nid: anki.notes.NoteId
|
||||||
|
@ -50,7 +52,7 @@ class Card:
|
||||||
backend_card: Optional[BackendCard] = None,
|
backend_card: Optional[BackendCard] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self.timerStarted = None
|
self.timer_started: Optional[float] = None
|
||||||
self._render_output: Optional[anki.template.TemplateRenderOutput] = None
|
self._render_output: Optional[anki.template.TemplateRenderOutput] = None
|
||||||
if id:
|
if id:
|
||||||
# existing card
|
# existing card
|
||||||
|
@ -63,31 +65,31 @@ class Card:
|
||||||
self._load_from_backend_card(_pb.Card())
|
self._load_from_backend_card(_pb.Card())
|
||||||
|
|
||||||
def load(self) -> None:
|
def load(self) -> None:
|
||||||
c = self.col._backend.get_card(self.id)
|
card = self.col._backend.get_card(self.id)
|
||||||
assert c
|
assert card
|
||||||
self._load_from_backend_card(c)
|
self._load_from_backend_card(card)
|
||||||
|
|
||||||
def _load_from_backend_card(self, c: _pb.Card) -> None:
|
def _load_from_backend_card(self, card: _pb.Card) -> None:
|
||||||
self._render_output = None
|
self._render_output = None
|
||||||
self._note = None
|
self._note = None
|
||||||
self.id = CardId(c.id)
|
self.id = CardId(card.id)
|
||||||
self.nid = anki.notes.NoteId(c.note_id)
|
self.nid = anki.notes.NoteId(card.note_id)
|
||||||
self.did = anki.decks.DeckId(c.deck_id)
|
self.did = anki.decks.DeckId(card.deck_id)
|
||||||
self.ord = c.template_idx
|
self.ord = card.template_idx
|
||||||
self.mod = c.mtime_secs
|
self.mod = card.mtime_secs
|
||||||
self.usn = c.usn
|
self.usn = card.usn
|
||||||
self.type = CardType(c.ctype)
|
self.type = CardType(card.ctype)
|
||||||
self.queue = CardQueue(c.queue)
|
self.queue = CardQueue(card.queue)
|
||||||
self.due = c.due
|
self.due = card.due
|
||||||
self.ivl = c.interval
|
self.ivl = card.interval
|
||||||
self.factor = c.ease_factor
|
self.factor = card.ease_factor
|
||||||
self.reps = c.reps
|
self.reps = card.reps
|
||||||
self.lapses = c.lapses
|
self.lapses = card.lapses
|
||||||
self.left = c.remaining_steps
|
self.left = card.remaining_steps
|
||||||
self.odue = c.original_due
|
self.odue = card.original_due
|
||||||
self.odid = anki.decks.DeckId(c.original_deck_id)
|
self.odid = anki.decks.DeckId(card.original_deck_id)
|
||||||
self.flags = c.flags
|
self.flags = card.flags
|
||||||
self.data = c.data
|
self.data = card.data
|
||||||
|
|
||||||
def _to_backend_card(self) -> _pb.Card:
|
def _to_backend_card(self) -> _pb.Card:
|
||||||
# mtime & usn are set by backend
|
# mtime & usn are set by backend
|
||||||
|
@ -131,10 +133,6 @@ class Card:
|
||||||
def answer_av_tags(self) -> List[AVTag]:
|
def answer_av_tags(self) -> List[AVTag]:
|
||||||
return self.render_output().answer_av_tags
|
return self.render_output().answer_av_tags
|
||||||
|
|
||||||
# legacy
|
|
||||||
def css(self) -> str:
|
|
||||||
return f"<style>{self.render_output().css}</style>"
|
|
||||||
|
|
||||||
def render_output(
|
def render_output(
|
||||||
self, reload: bool = False, browser: bool = False
|
self, reload: bool = False, browser: bool = False
|
||||||
) -> anki.template.TemplateRenderOutput:
|
) -> anki.template.TemplateRenderOutput:
|
||||||
|
@ -157,31 +155,25 @@ class Card:
|
||||||
def note_type(self) -> NotetypeDict:
|
def note_type(self) -> NotetypeDict:
|
||||||
return self.col.models.get(self.note().mid)
|
return self.col.models.get(self.note().mid)
|
||||||
|
|
||||||
# legacy aliases
|
|
||||||
flushSched = flush
|
|
||||||
q = question
|
|
||||||
a = answer
|
|
||||||
model = note_type
|
|
||||||
|
|
||||||
def template(self) -> TemplateDict:
|
def template(self) -> TemplateDict:
|
||||||
m = self.model()
|
notetype = self.note_type()
|
||||||
if m["type"] == MODEL_STD:
|
if notetype["type"] == MODEL_STD:
|
||||||
return self.model()["tmpls"][self.ord]
|
return self.note_type()["tmpls"][self.ord]
|
||||||
else:
|
else:
|
||||||
return self.model()["tmpls"][0]
|
return self.note_type()["tmpls"][0]
|
||||||
|
|
||||||
def startTimer(self) -> None:
|
def start_timer(self) -> None:
|
||||||
self.timerStarted = time.time()
|
self.timer_started = time.time()
|
||||||
|
|
||||||
def current_deck_id(self) -> anki.decks.DeckId:
|
def current_deck_id(self) -> anki.decks.DeckId:
|
||||||
return anki.decks.DeckId(self.odid or self.did)
|
return anki.decks.DeckId(self.odid or self.did)
|
||||||
|
|
||||||
def timeLimit(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.confForDid(self.current_deck_id())
|
||||||
return conf["maxTaken"] * 1000
|
return conf["maxTaken"] * 1000
|
||||||
|
|
||||||
def shouldShowTimer(self) -> bool:
|
def should_show_timer(self) -> bool:
|
||||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||||
return conf["timer"]
|
return conf["timer"]
|
||||||
|
|
||||||
|
@ -192,23 +184,19 @@ class Card:
|
||||||
def autoplay(self) -> bool:
|
def autoplay(self) -> bool:
|
||||||
return self.col.decks.confForDid(self.current_deck_id())["autoplay"]
|
return self.col.decks.confForDid(self.current_deck_id())["autoplay"]
|
||||||
|
|
||||||
def timeTaken(self) -> int:
|
def time_taken(self) -> int:
|
||||||
"Time taken to answer card, in integer MS."
|
"Time taken to answer card, in integer MS."
|
||||||
total = int((time.time() - self.timerStarted) * 1000)
|
total = int((time.time() - self.timer_started) * 1000)
|
||||||
return min(total, self.timeLimit())
|
return min(total, self.time_limit())
|
||||||
|
|
||||||
# legacy
|
def description(self) -> str:
|
||||||
def isEmpty(self) -> bool:
|
dict_copy = dict(self.__dict__)
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
d = dict(self.__dict__)
|
|
||||||
# remove non-useful elements
|
# remove non-useful elements
|
||||||
del d["_note"]
|
del dict_copy["_note"]
|
||||||
del d["_render_output"]
|
del dict_copy["_render_output"]
|
||||||
del d["col"]
|
del dict_copy["col"]
|
||||||
del d["timerStarted"]
|
del dict_copy["timerStarted"]
|
||||||
return f"{super().__repr__()} {pprint.pformat(d, width=300)}"
|
return f"{super().__repr__()} {pprint.pformat(dict_copy, width=300)}"
|
||||||
|
|
||||||
def user_flag(self) -> int:
|
def user_flag(self) -> int:
|
||||||
return self.flags & 0b111
|
return self.flags & 0b111
|
||||||
|
@ -218,7 +206,18 @@ class Card:
|
||||||
assert 0 <= flag <= 7
|
assert 0 <= flag <= 7
|
||||||
self.flags = (self.flags & ~0b111) | flag
|
self.flags = (self.flags & ~0b111) | flag
|
||||||
|
|
||||||
# legacy
|
@deprecated(info="use card.render_output() directly")
|
||||||
|
def css(self) -> str:
|
||||||
|
return f"<style>{self.render_output().css}</style>"
|
||||||
|
|
||||||
userFlag = user_flag
|
@deprecated(info="handled by template rendering")
|
||||||
setUserFlag = set_user_flag
|
def is_empty(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
Card.register_deprecated_aliases(
|
||||||
|
flushSched=Card.flush,
|
||||||
|
q=Card.question,
|
||||||
|
a=Card.answer,
|
||||||
|
model=Card.note_type,
|
||||||
|
)
|
||||||
|
|
|
@ -429,7 +429,7 @@ class Collection:
|
||||||
return Note(self, self.models.current(forDeck))
|
return Note(self, self.models.current(forDeck))
|
||||||
|
|
||||||
def addNote(self, note: Note) -> int:
|
def addNote(self, note: Note) -> int:
|
||||||
self.add_note(note, note.model()["did"])
|
self.add_note(note, note.note_type()["did"])
|
||||||
return len(note.cards())
|
return len(note.cards())
|
||||||
|
|
||||||
def remNotes(self, ids: Sequence[NoteId]) -> None:
|
def remNotes(self, ids: Sequence[NoteId]) -> None:
|
||||||
|
|
|
@ -118,8 +118,8 @@ class TextCardExporter(Exporter):
|
||||||
out = ""
|
out = ""
|
||||||
for cid in ids:
|
for cid in ids:
|
||||||
c = self.col.getCard(cid)
|
c = self.col.getCard(cid)
|
||||||
out += esc(c.q())
|
out += esc(c.question())
|
||||||
out += "\t" + esc(c.a()) + "\n"
|
out += "\t" + esc(c.answer()) + "\n"
|
||||||
file.write(out.encode("utf-8"))
|
file.write(out.encode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Note(DeprecatedNamesMixin):
|
||||||
self.usn = note.usn
|
self.usn = note.usn
|
||||||
self.tags = list(note.tags)
|
self.tags = list(note.tags)
|
||||||
self.fields = list(note.fields)
|
self.fields = list(note.fields)
|
||||||
self._fmap = self.col.models.fieldMap(self.model())
|
self._fmap = self.col.models.fieldMap(self.note_type())
|
||||||
|
|
||||||
def _to_backend_note(self) -> _pb.Note:
|
def _to_backend_note(self) -> _pb.Note:
|
||||||
hooks.note_will_flush(self)
|
hooks.note_will_flush(self)
|
||||||
|
@ -98,7 +98,7 @@ class Note(DeprecatedNamesMixin):
|
||||||
card.ord = ord
|
card.ord = ord
|
||||||
card.did = anki.decks.DEFAULT_DECK_ID
|
card.did = anki.decks.DEFAULT_DECK_ID
|
||||||
|
|
||||||
model = custom_note_type or self.model()
|
model = custom_note_type or self.note_type()
|
||||||
template = copy.copy(
|
template = copy.copy(
|
||||||
custom_template
|
custom_template
|
||||||
or (
|
or (
|
||||||
|
@ -125,10 +125,10 @@ class Note(DeprecatedNamesMixin):
|
||||||
def card_ids(self) -> Sequence[anki.cards.CardId]:
|
def card_ids(self) -> Sequence[anki.cards.CardId]:
|
||||||
return self.col.card_ids_of_note(self.id)
|
return self.col.card_ids_of_note(self.id)
|
||||||
|
|
||||||
def model(self) -> Optional[NotetypeDict]:
|
def note_type(self) -> Optional[NotetypeDict]:
|
||||||
return self.col.models.get(self.mid)
|
return self.col.models.get(self.mid)
|
||||||
|
|
||||||
_model = property(model)
|
_note_type = property(note_type)
|
||||||
|
|
||||||
def cloze_numbers_in_fields(self) -> Sequence[int]:
|
def cloze_numbers_in_fields(self) -> Sequence[int]:
|
||||||
return self.col._backend.cloze_numbers_in_note(self._to_backend_note())
|
return self.col._backend.cloze_numbers_in_note(self._to_backend_note())
|
||||||
|
@ -193,4 +193,6 @@ class Note(DeprecatedNamesMixin):
|
||||||
dupeOrEmpty = duplicate_or_empty = fields_check
|
dupeOrEmpty = duplicate_or_empty = fields_check
|
||||||
|
|
||||||
|
|
||||||
Note.register_deprecated_aliases(delTag=Note.remove_tag, _fieldOrd=Note._field_index)
|
Note.register_deprecated_aliases(
|
||||||
|
delTag=Note.remove_tag, _fieldOrd=Note._field_index, model=Note.note_type
|
||||||
|
)
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Scheduler(V2):
|
||||||
card.did,
|
card.did,
|
||||||
new_delta=new_delta,
|
new_delta=new_delta,
|
||||||
review_delta=review_delta,
|
review_delta=review_delta,
|
||||||
milliseconds_delta=+card.timeTaken(),
|
milliseconds_delta=+card.time_taken(),
|
||||||
)
|
)
|
||||||
|
|
||||||
card.mod = intTime()
|
card.mod = intTime()
|
||||||
|
@ -363,7 +363,7 @@ limit %d"""
|
||||||
ivl,
|
ivl,
|
||||||
lastIvl,
|
lastIvl,
|
||||||
card.factor,
|
card.factor,
|
||||||
card.timeTaken(),
|
card.time_taken(),
|
||||||
type,
|
type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
self.col.log(card)
|
self.col.log(card)
|
||||||
if not self._burySiblingsOnAnswer:
|
if not self._burySiblingsOnAnswer:
|
||||||
self._burySiblings(card)
|
self._burySiblings(card)
|
||||||
card.startTimer()
|
card.start_timer()
|
||||||
return card
|
return card
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -494,7 +494,7 @@ limit ?"""
|
||||||
card.did,
|
card.did,
|
||||||
new_delta=new_delta,
|
new_delta=new_delta,
|
||||||
review_delta=review_delta,
|
review_delta=review_delta,
|
||||||
milliseconds_delta=+card.timeTaken(),
|
milliseconds_delta=+card.time_taken(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# once a card has been answered once, the original due date
|
# once a card has been answered once, the original due date
|
||||||
|
@ -760,7 +760,7 @@ limit ?"""
|
||||||
ivl,
|
ivl,
|
||||||
lastIvl,
|
lastIvl,
|
||||||
card.factor,
|
card.factor,
|
||||||
card.timeTaken(),
|
card.time_taken(),
|
||||||
type,
|
type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -891,7 +891,7 @@ limit ?"""
|
||||||
-delay or card.ivl,
|
-delay or card.ivl,
|
||||||
card.lastIvl,
|
card.lastIvl,
|
||||||
card.factor,
|
card.factor,
|
||||||
card.timeTaken(),
|
card.time_taken(),
|
||||||
type,
|
type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
new_state=new_state,
|
new_state=new_state,
|
||||||
rating=rating,
|
rating=rating,
|
||||||
answered_at_millis=intTime(1000),
|
answered_at_millis=intTime(1000),
|
||||||
milliseconds_taken=card.timeTaken(),
|
milliseconds_taken=card.time_taken(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def answer_card(self, input: CardAnswer) -> OpChanges:
|
def answer_card(self, input: CardAnswer) -> OpChanges:
|
||||||
|
@ -106,7 +106,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
|
|
||||||
card = Card(self.col)
|
card = Card(self.col)
|
||||||
card._load_from_backend_card(queued_card.card)
|
card._load_from_backend_card(queued_card.card)
|
||||||
card.startTimer()
|
card.start_timer()
|
||||||
return card
|
return card
|
||||||
|
|
||||||
def _is_finished(self) -> bool:
|
def _is_finished(self) -> bool:
|
||||||
|
|
|
@ -155,7 +155,7 @@ class TemplateRenderContext:
|
||||||
self._fields: Optional[Dict] = None
|
self._fields: Optional[Dict] = None
|
||||||
self._latex_svg = False
|
self._latex_svg = False
|
||||||
if not notetype:
|
if not notetype:
|
||||||
self._note_type = note.model()
|
self._note_type = note.note_type()
|
||||||
else:
|
else:
|
||||||
self._note_type = notetype
|
self._note_type = notetype
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ class TemplateRenderContext:
|
||||||
def card(self) -> Card:
|
def card(self) -> Card:
|
||||||
"""Returns the card being rendered.
|
"""Returns the card being rendered.
|
||||||
|
|
||||||
Be careful not to call .q() or .a() on the card, or you'll create an
|
Be careful not to call .question() or .answer() on the card, or you'll create an
|
||||||
infinite loop."""
|
infinite loop."""
|
||||||
return self._card
|
return self._card
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ def test_noteAddDelete():
|
||||||
assert col.cardCount() == 4
|
assert col.cardCount() == 4
|
||||||
# check q/a generation
|
# check q/a generation
|
||||||
c0 = note.cards()[0]
|
c0 = note.cards()[0]
|
||||||
assert "three" in c0.q()
|
assert "three" in c0.question()
|
||||||
# it should not be a duplicate
|
# it should not be a duplicate
|
||||||
assert not note.fields_check()
|
assert not note.fields_check()
|
||||||
# now let's make a duplicate
|
# now let's make a duplicate
|
||||||
|
@ -138,15 +138,15 @@ def test_furigana():
|
||||||
n["Front"] = "foo[abc]"
|
n["Front"] = "foo[abc]"
|
||||||
col.addNote(n)
|
col.addNote(n)
|
||||||
c = n.cards()[0]
|
c = n.cards()[0]
|
||||||
assert c.q().endswith("abc")
|
assert c.question().endswith("abc")
|
||||||
# and should avoid sound
|
# and should avoid sound
|
||||||
n["Front"] = "foo[sound:abc.mp3]"
|
n["Front"] = "foo[sound:abc.mp3]"
|
||||||
n.flush()
|
n.flush()
|
||||||
assert "anki:play" in c.q(reload=True)
|
assert "anki:play" in c.question(reload=True)
|
||||||
# it shouldn't throw an error while people are editing
|
# it shouldn't throw an error while people are editing
|
||||||
m["tmpls"][0]["qfmt"] = "{{kana:}}"
|
m["tmpls"][0]["qfmt"] = "{{kana:}}"
|
||||||
mm.save(m)
|
mm.save(m)
|
||||||
c.q(reload=True)
|
c.question(reload=True)
|
||||||
|
|
||||||
|
|
||||||
def test_translate():
|
def test_translate():
|
||||||
|
|
|
@ -53,12 +53,12 @@ def test_remove():
|
||||||
deck1 = col.decks.id("deck1")
|
deck1 = col.decks.id("deck1")
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "1"
|
note["Front"] = "1"
|
||||||
note.model()["did"] = deck1
|
note.note_type()["did"] = deck1
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
c = note.cards()[0]
|
c = note.cards()[0]
|
||||||
assert c.did == deck1
|
assert c.did == deck1
|
||||||
assert col.cardCount() == 1
|
assert col.cardCount() == 1
|
||||||
col.decks.rem(deck1)
|
col.decks.remove([deck1])
|
||||||
assert col.cardCount() == 0
|
assert col.cardCount() == 0
|
||||||
# if we try to get it, we get the default
|
# if we try to get it, we get the default
|
||||||
assert col.decks.name(c.did) == "[no deck]"
|
assert col.decks.name(c.did) == "[no deck]"
|
||||||
|
@ -142,7 +142,7 @@ def test_renameForDragAndDrop():
|
||||||
new_hsk_did = col.decks.id("hsk")
|
new_hsk_did = col.decks.id("hsk")
|
||||||
col.decks.renameForDragAndDrop(new_hsk_did, chinese_did)
|
col.decks.renameForDragAndDrop(new_hsk_did, chinese_did)
|
||||||
assert deckNames() == ["Chinese", "Chinese::HSK", "Chinese::hsk+", "Languages"]
|
assert deckNames() == ["Chinese", "Chinese::HSK", "Chinese::hsk+", "Languages"]
|
||||||
col.decks.rem(new_hsk_did)
|
col.decks.remove([new_hsk_did])
|
||||||
|
|
||||||
# '' is a convenient alias for the top level DID
|
# '' is a convenient alias for the top level DID
|
||||||
col.decks.renameForDragAndDrop(hsk_did, "")
|
col.decks.renameForDragAndDrop(hsk_did, "")
|
||||||
|
|
|
@ -36,7 +36,7 @@ def setup1():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "baz"
|
note["Front"] = "baz"
|
||||||
note["Back"] = "qux"
|
note["Back"] = "qux"
|
||||||
note.model()["did"] = col.decks.id("new col")
|
note.note_type()["did"] = col.decks.id("new col")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,3 @@ def test_flags():
|
||||||
col.set_user_flag_for_cards(0, [c.id])
|
col.set_user_flag_for_cards(0, [c.id])
|
||||||
c.load()
|
c.load()
|
||||||
assert c.user_flag() == 0
|
assert c.user_flag() == 0
|
||||||
|
|
||||||
# should work with Cards method as well
|
|
||||||
c.set_user_flag(2)
|
|
||||||
assert c.user_flag() == 2
|
|
||||||
c.set_user_flag(3)
|
|
||||||
assert c.user_flag() == 3
|
|
||||||
c.set_user_flag(0)
|
|
||||||
assert c.user_flag() == 0
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ def test_anki2_mediadupes():
|
||||||
# add a note that references a sound
|
# add a note that references a sound
|
||||||
n = col.newNote()
|
n = col.newNote()
|
||||||
n["Front"] = "[sound:foo.mp3]"
|
n["Front"] = "[sound:foo.mp3]"
|
||||||
mid = n.model()["id"]
|
mid = n.note_type()["id"]
|
||||||
col.addNote(n)
|
col.addNote(n)
|
||||||
# add that sound to media folder
|
# add that sound to media folder
|
||||||
with open(os.path.join(col.media.dir(), "foo.mp3"), "w") as note:
|
with open(os.path.join(col.media.dir(), "foo.mp3"), "w") as note:
|
||||||
|
|
|
@ -23,7 +23,7 @@ def test_latex():
|
||||||
# but since latex couldn't run, there's nothing there
|
# but since latex couldn't run, there's nothing there
|
||||||
assert len(os.listdir(col.media.dir())) == 0
|
assert len(os.listdir(col.media.dir())) == 0
|
||||||
# check the error message
|
# check the error message
|
||||||
msg = note.cards()[0].q()
|
msg = note.cards()[0].question()
|
||||||
assert "executing nolatex" in without_unicode_isolation(msg)
|
assert "executing nolatex" in without_unicode_isolation(msg)
|
||||||
assert "installed" in msg
|
assert "installed" in msg
|
||||||
# check if we have latex installed, and abort test if we don't
|
# check if we have latex installed, and abort test if we don't
|
||||||
|
@ -35,12 +35,12 @@ def test_latex():
|
||||||
# check media db should cause latex to be generated
|
# check media db should cause latex to be generated
|
||||||
col.media.render_all_latex()
|
col.media.render_all_latex()
|
||||||
assert len(os.listdir(col.media.dir())) == 1
|
assert len(os.listdir(col.media.dir())) == 1
|
||||||
assert ".png" in note.cards()[0].q()
|
assert ".png" in note.cards()[0].question()
|
||||||
# adding new notes should cause generation on question display
|
# adding new notes should cause generation on question display
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "[latex]world[/latex]"
|
note["Front"] = "[latex]world[/latex]"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
note.cards()[0].q()
|
note.cards()[0].question()
|
||||||
assert len(os.listdir(col.media.dir())) == 2
|
assert len(os.listdir(col.media.dir())) == 2
|
||||||
# another note with the same media should reuse
|
# another note with the same media should reuse
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
|
@ -48,7 +48,7 @@ def test_latex():
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
assert len(os.listdir(col.media.dir())) == 2
|
assert len(os.listdir(col.media.dir())) == 2
|
||||||
oldcard = note.cards()[0]
|
oldcard = note.cards()[0]
|
||||||
assert ".png" in oldcard.q()
|
assert ".png" in oldcard.question()
|
||||||
# if we turn off building, then previous cards should work, but cards with
|
# if we turn off building, then previous cards should work, but cards with
|
||||||
# missing media will show a broken image
|
# missing media will show a broken image
|
||||||
anki.latex.build = False
|
anki.latex.build = False
|
||||||
|
@ -56,7 +56,7 @@ def test_latex():
|
||||||
note["Front"] = "[latex]foo[/latex]"
|
note["Front"] = "[latex]foo[/latex]"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
assert len(os.listdir(col.media.dir())) == 2
|
assert len(os.listdir(col.media.dir())) == 2
|
||||||
assert ".png" in oldcard.q()
|
assert ".png" in oldcard.question()
|
||||||
# turn it on again so other test don't suffer
|
# turn it on again so other test don't suffer
|
||||||
anki.latex.build = True
|
anki.latex.build = True
|
||||||
|
|
||||||
|
@ -95,5 +95,5 @@ def _test_includes_bad_command(bad):
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "[latex]%s[/latex]" % bad
|
note["Front"] = "[latex]%s[/latex]" % bad
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
q = without_unicode_isolation(note.cards()[0].q())
|
q = without_unicode_isolation(note.cards()[0].question())
|
||||||
return ("'%s' is not allowed on cards" % bad in q, "Card content: %s" % q)
|
return ("'%s' is not allowed on cards" % bad in q, "Card content: %s" % q)
|
||||||
|
|
|
@ -112,7 +112,7 @@ def test_templates():
|
||||||
# and should have updated the other cards' ordinals
|
# and should have updated the other cards' ordinals
|
||||||
c = note.cards()[0]
|
c = note.cards()[0]
|
||||||
assert c.ord == 0
|
assert c.ord == 0
|
||||||
assert stripHTML(c.q()) == "1"
|
assert stripHTML(c.question()) == "1"
|
||||||
# it shouldn't be possible to orphan notes by removing templates
|
# it shouldn't be possible to orphan notes by removing templates
|
||||||
t = mm.newTemplate("template name")
|
t = mm.newTemplate("template name")
|
||||||
t["qfmt"] = "{{Front}}2"
|
t["qfmt"] = "{{Front}}2"
|
||||||
|
@ -158,14 +158,14 @@ def test_text():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "hello<b>world"
|
note["Front"] = "hello<b>world"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
assert "helloworld" in note.cards()[0].q()
|
assert "helloworld" in note.cards()[0].question()
|
||||||
|
|
||||||
|
|
||||||
def test_cloze():
|
def test_cloze():
|
||||||
col = getEmptyCol()
|
col = getEmptyCol()
|
||||||
col.models.setCurrent(col.models.byName("Cloze"))
|
col.models.setCurrent(col.models.byName("Cloze"))
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
assert note.model()["name"] == "Cloze"
|
assert note.note_type()["name"] == "Cloze"
|
||||||
# a cloze model with no clozes is not empty
|
# a cloze model with no clozes is not empty
|
||||||
note["Text"] = "nothing"
|
note["Text"] = "nothing"
|
||||||
assert col.addNote(note)
|
assert col.addNote(note)
|
||||||
|
@ -173,30 +173,30 @@ def test_cloze():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = "hello {{c1::world}}"
|
note["Text"] = "hello {{c1::world}}"
|
||||||
assert col.addNote(note) == 1
|
assert col.addNote(note) == 1
|
||||||
assert "hello <span class=cloze>[...]</span>" in note.cards()[0].q()
|
assert "hello <span class=cloze>[...]</span>" in note.cards()[0].question()
|
||||||
assert "hello <span class=cloze>world</span>" in note.cards()[0].a()
|
assert "hello <span class=cloze>world</span>" in note.cards()[0].answer()
|
||||||
# and with a comment
|
# and with a comment
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = "hello {{c1::world::typical}}"
|
note["Text"] = "hello {{c1::world::typical}}"
|
||||||
assert col.addNote(note) == 1
|
assert col.addNote(note) == 1
|
||||||
assert "<span class=cloze>[typical]</span>" in note.cards()[0].q()
|
assert "<span class=cloze>[typical]</span>" in note.cards()[0].question()
|
||||||
assert "<span class=cloze>world</span>" in note.cards()[0].a()
|
assert "<span class=cloze>world</span>" in note.cards()[0].answer()
|
||||||
# and with 2 clozes
|
# and with 2 clozes
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = "hello {{c1::world}} {{c2::bar}}"
|
note["Text"] = "hello {{c1::world}} {{c2::bar}}"
|
||||||
assert col.addNote(note) == 2
|
assert col.addNote(note) == 2
|
||||||
(c1, c2) = note.cards()
|
(c1, c2) = note.cards()
|
||||||
assert "<span class=cloze>[...]</span> bar" in c1.q()
|
assert "<span class=cloze>[...]</span> bar" in c1.question()
|
||||||
assert "<span class=cloze>world</span> bar" in c1.a()
|
assert "<span class=cloze>world</span> bar" in c1.answer()
|
||||||
assert "world <span class=cloze>[...]</span>" in c2.q()
|
assert "world <span class=cloze>[...]</span>" in c2.question()
|
||||||
assert "world <span class=cloze>bar</span>" in c2.a()
|
assert "world <span class=cloze>bar</span>" in c2.answer()
|
||||||
# if there are multiple answers for a single cloze, they are given in a
|
# if there are multiple answers for a single cloze, they are given in a
|
||||||
# list
|
# list
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = "a {{c1::b}} {{c1::c}}"
|
note["Text"] = "a {{c1::b}} {{c1::c}}"
|
||||||
assert col.addNote(note) == 1
|
assert col.addNote(note) == 1
|
||||||
assert "<span class=cloze>b</span> <span class=cloze>c</span>" in (
|
assert "<span class=cloze>b</span> <span class=cloze>c</span>" in (
|
||||||
note.cards()[0].a()
|
note.cards()[0].answer()
|
||||||
)
|
)
|
||||||
# if we add another cloze, a card should be generated
|
# if we add another cloze, a card should be generated
|
||||||
cnt = col.cardCount()
|
cnt = col.cardCount()
|
||||||
|
@ -218,11 +218,11 @@ def test_cloze_mathjax():
|
||||||
] = r"{{c1::ok}} \(2^2\) {{c2::not ok}} \(2^{{c3::2}}\) \(x^3\) {{c4::blah}} {{c5::text with \(x^2\) jax}}"
|
] = r"{{c1::ok}} \(2^2\) {{c2::not ok}} \(2^{{c3::2}}\) \(x^3\) {{c4::blah}} {{c5::text with \(x^2\) jax}}"
|
||||||
assert col.addNote(note)
|
assert col.addNote(note)
|
||||||
assert len(note.cards()) == 5
|
assert len(note.cards()) == 5
|
||||||
assert "class=cloze" in note.cards()[0].q()
|
assert "class=cloze" in note.cards()[0].question()
|
||||||
assert "class=cloze" in note.cards()[1].q()
|
assert "class=cloze" in note.cards()[1].question()
|
||||||
assert "class=cloze" not in note.cards()[2].q()
|
assert "class=cloze" not in note.cards()[2].question()
|
||||||
assert "class=cloze" in note.cards()[3].q()
|
assert "class=cloze" in note.cards()[3].question()
|
||||||
assert "class=cloze" in note.cards()[4].q()
|
assert "class=cloze" in note.cards()[4].question()
|
||||||
|
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = r"\(a\) {{c1::b}} \[ {{c1::c}} \]"
|
note["Text"] = r"\(a\) {{c1::b}} \[ {{c1::c}} \]"
|
||||||
|
@ -230,7 +230,7 @@ def test_cloze_mathjax():
|
||||||
assert len(note.cards()) == 1
|
assert len(note.cards()) == 1
|
||||||
assert (
|
assert (
|
||||||
note.cards()[0]
|
note.cards()[0]
|
||||||
.q()
|
.question()
|
||||||
.endswith(r"\(a\) <span class=cloze>[...]</span> \[ [...] \]")
|
.endswith(r"\(a\) <span class=cloze>[...]</span> \[ [...] \]")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ def test_typecloze():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Text"] = "hello {{c1::world}}"
|
note["Text"] = "hello {{c1::world}}"
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
assert "[[type:cloze:Text]]" in note.cards()[0].q()
|
assert "[[type:cloze:Text]]" in note.cards()[0].question()
|
||||||
|
|
||||||
|
|
||||||
def test_chained_mods():
|
def test_chained_mods():
|
||||||
|
@ -275,11 +275,11 @@ def test_chained_mods():
|
||||||
assert col.addNote(note) == 1
|
assert col.addNote(note) == 1
|
||||||
assert (
|
assert (
|
||||||
"This <span class=cloze>[sentence]</span> demonstrates <span class=cloze>[chained]</span> clozes."
|
"This <span class=cloze>[sentence]</span> demonstrates <span class=cloze>[chained]</span> clozes."
|
||||||
in note.cards()[0].q()
|
in note.cards()[0].question()
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
"This <span class=cloze>phrase</span> demonstrates <span class=cloze>en chaine</span> clozes."
|
"This <span class=cloze>phrase</span> demonstrates <span class=cloze>en chaine</span> clozes."
|
||||||
in note.cards()[0].a()
|
in note.cards()[0].answer()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,16 +309,16 @@ def test_modelChange():
|
||||||
# switch cards
|
# switch cards
|
||||||
c0 = note.cards()[0]
|
c0 = note.cards()[0]
|
||||||
c1 = note.cards()[1]
|
c1 = note.cards()[1]
|
||||||
assert "b123" in c0.q()
|
assert "b123" in c0.question()
|
||||||
assert "note" in c1.q()
|
assert "note" in c1.question()
|
||||||
assert c0.ord == 0
|
assert c0.ord == 0
|
||||||
assert c1.ord == 1
|
assert c1.ord == 1
|
||||||
col.models.change(basic, [note.id], basic, noop, map)
|
col.models.change(basic, [note.id], basic, noop, map)
|
||||||
note.load()
|
note.load()
|
||||||
c0.load()
|
c0.load()
|
||||||
c1.load()
|
c1.load()
|
||||||
assert "note" in c0.q()
|
assert "note" in c0.question()
|
||||||
assert "b123" in c1.q()
|
assert "b123" in c1.question()
|
||||||
assert c0.ord == 1
|
assert c0.ord == 1
|
||||||
assert c1.ord == 0
|
assert c1.ord == 0
|
||||||
# .cards() returns cards in order
|
# .cards() returns cards in order
|
||||||
|
|
|
@ -78,7 +78,7 @@ def test_new():
|
||||||
# qs = ("2", "3", "2", "3")
|
# qs = ("2", "3", "2", "3")
|
||||||
# for n in range(4):
|
# for n in range(4):
|
||||||
# c = col.sched.getCard()
|
# c = col.sched.getCard()
|
||||||
# assert qs[n] in c.q()
|
# assert qs[n] in c.question()
|
||||||
# col.sched.answerCard(c, 2)
|
# col.sched.answerCard(c, 2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ def test_newLimits():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = str(i)
|
note["Front"] = str(i)
|
||||||
if i > 4:
|
if i > 4:
|
||||||
note.model()["did"] = deck2
|
note.note_type()["did"] = deck2
|
||||||
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")
|
||||||
|
@ -224,17 +224,17 @@ def test_learn_collapsed():
|
||||||
col.reset()
|
col.reset()
|
||||||
# should get '1' first
|
# should get '1' first
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.q().endswith("1")
|
assert c.question().endswith("1")
|
||||||
# pass it so it's due in 10 minutes
|
# pass it so it's due in 10 minutes
|
||||||
col.sched.answerCard(c, 2)
|
col.sched.answerCard(c, 2)
|
||||||
# get the other card
|
# get the other card
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.q().endswith("2")
|
assert c.question().endswith("2")
|
||||||
# fail it so it's due in 1 minute
|
# fail it so it's due in 1 minute
|
||||||
col.sched.answerCard(c, 1)
|
col.sched.answerCard(c, 1)
|
||||||
# we shouldn't get the same card again
|
# we shouldn't get the same card again
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert not c.q().endswith("2")
|
assert not c.question().endswith("2")
|
||||||
|
|
||||||
|
|
||||||
def test_learn_day():
|
def test_learn_day():
|
||||||
|
@ -316,7 +316,7 @@ def test_reviews():
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.ivl = 100
|
c.ivl = 100
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
# save it for later use as well
|
# save it for later use as well
|
||||||
cardcopy = copy.copy(c)
|
cardcopy = copy.copy(c)
|
||||||
|
@ -393,7 +393,7 @@ def test_button_spacing():
|
||||||
c.due = col.sched.today
|
c.due = col.sched.today
|
||||||
c.reps = 1
|
c.reps = 1
|
||||||
c.ivl = 1
|
c.ivl = 1
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
ni = col.sched.nextIvlStr
|
ni = col.sched.nextIvlStr
|
||||||
|
@ -575,7 +575,7 @@ def test_cram():
|
||||||
c.due = col.sched.today + 25
|
c.due = col.sched.today + 25
|
||||||
c.mod = 1
|
c.mod = 1
|
||||||
c.factor = STARTING_FACTOR
|
c.factor = STARTING_FACTOR
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
assert col.sched.counts() == (0, 0, 0)
|
assert col.sched.counts() == (0, 0, 0)
|
||||||
|
@ -638,7 +638,7 @@ def test_cram():
|
||||||
assert col.sched.nextIvl(c, 2) == 600
|
assert col.sched.nextIvl(c, 2) == 600
|
||||||
assert col.sched.nextIvl(c, 3) == 86400
|
assert col.sched.nextIvl(c, 3) == 86400
|
||||||
# delete the deck, returning the card mid-study
|
# delete the deck, returning the card mid-study
|
||||||
col.decks.rem(col.decks.selected())
|
col.decks.remove([col.decks.selected()])
|
||||||
assert len(col.sched.deck_due_tree().children) == 1
|
assert len(col.sched.deck_due_tree().children) == 1
|
||||||
c.load()
|
c.load()
|
||||||
assert c.ivl == 1
|
assert c.ivl == 1
|
||||||
|
@ -964,7 +964,7 @@ def test_deckDue():
|
||||||
# and one that's a child
|
# and one that's a child
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
default1 = note.model()["did"] = col.decks.id("Default::1")
|
default1 = note.note_type()["did"] = col.decks.id("Default::1")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# make it a review card
|
# make it a review card
|
||||||
c = note.cards()[0]
|
c = note.cards()[0]
|
||||||
|
@ -974,12 +974,12 @@ def test_deckDue():
|
||||||
# add one more with a new deck
|
# add one more with a new deck
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
note.model()["did"] = col.decks.id("foo::bar")
|
note.note_type()["did"] = col.decks.id("foo::bar")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# and one that's a sibling
|
# and one that's a sibling
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "three"
|
note["Front"] = "three"
|
||||||
note.model()["did"] = col.decks.id("foo::baz")
|
note.note_type()["did"] = col.decks.id("foo::baz")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
col.reset()
|
col.reset()
|
||||||
assert len(col.decks.all_names_and_ids()) == 5
|
assert len(col.decks.all_names_and_ids()) == 5
|
||||||
|
@ -1010,12 +1010,12 @@ def test_deckFlow():
|
||||||
# and one that's a child
|
# and one that's a child
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
note.model()["did"] = col.decks.id("Default::2")
|
note.note_type()["did"] = col.decks.id("Default::2")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# and another that's higher up
|
# and another that's higher up
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "three"
|
note["Front"] = "three"
|
||||||
default1 = note.model()["did"] = col.decks.id("Default::1")
|
default1 = note.note_type()["did"] = col.decks.id("Default::1")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# should get top level one first, then ::1, then ::2
|
# should get top level one first, then ::1, then ::2
|
||||||
col.reset()
|
col.reset()
|
||||||
|
@ -1040,7 +1040,7 @@ def test_norelearn():
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.ivl = 100
|
c.ivl = 100
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
col.sched.answerCard(c, 1)
|
col.sched.answerCard(c, 1)
|
||||||
|
@ -1062,7 +1062,7 @@ def test_failmult():
|
||||||
c.factor = STARTING_FACTOR
|
c.factor = STARTING_FACTOR
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
conf = col.sched._cardConf(c)
|
conf = col.sched._cardConf(c)
|
||||||
conf["lapse"]["mult"] = 0.5
|
conf["lapse"]["mult"] = 0.5
|
||||||
|
|
|
@ -90,7 +90,7 @@ def test_new():
|
||||||
# qs = ("2", "3", "2", "3")
|
# qs = ("2", "3", "2", "3")
|
||||||
# for n in range(4):
|
# for n in range(4):
|
||||||
# c = col.sched.getCard()
|
# c = col.sched.getCard()
|
||||||
# assert qs[n] in c.q()
|
# assert qs[n] in c.question()
|
||||||
# col.sched.answerCard(c, 2)
|
# col.sched.answerCard(c, 2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ def test_newLimits():
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = str(i)
|
note["Front"] = str(i)
|
||||||
if i > 4:
|
if i > 4:
|
||||||
note.model()["did"] = deck2
|
note.note_type()["did"] = deck2
|
||||||
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")
|
||||||
|
@ -270,17 +270,17 @@ def test_learn_collapsed():
|
||||||
col.reset()
|
col.reset()
|
||||||
# should get '1' first
|
# should get '1' first
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.q().endswith("1")
|
assert c.question().endswith("1")
|
||||||
# pass it so it's due in 10 minutes
|
# pass it so it's due in 10 minutes
|
||||||
col.sched.answerCard(c, 3)
|
col.sched.answerCard(c, 3)
|
||||||
# get the other card
|
# get the other card
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert c.q().endswith("2")
|
assert c.question().endswith("2")
|
||||||
# fail it so it's due in 1 minute
|
# fail it so it's due in 1 minute
|
||||||
col.sched.answerCard(c, 1)
|
col.sched.answerCard(c, 1)
|
||||||
# we shouldn't get the same card again
|
# we shouldn't get the same card again
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
assert not c.q().endswith("2")
|
assert not c.question().endswith("2")
|
||||||
|
|
||||||
|
|
||||||
def test_learn_day():
|
def test_learn_day():
|
||||||
|
@ -374,7 +374,7 @@ def test_reviews():
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.ivl = 100
|
c.ivl = 100
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
# save it for later use as well
|
# save it for later use as well
|
||||||
cardcopy = copy.copy(c)
|
cardcopy = copy.copy(c)
|
||||||
|
@ -509,7 +509,7 @@ def test_button_spacing():
|
||||||
c.due = col.sched.today
|
c.due = col.sched.today
|
||||||
c.reps = 1
|
c.reps = 1
|
||||||
c.ivl = 1
|
c.ivl = 1
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
ni = col.sched.nextIvlStr
|
ni = col.sched.nextIvlStr
|
||||||
|
@ -731,7 +731,7 @@ def test_filt_reviewing_early_normal():
|
||||||
c.due = col.sched.today + 25
|
c.due = col.sched.today + 25
|
||||||
c.mod = 1
|
c.mod = 1
|
||||||
c.factor = STARTING_FACTOR
|
c.factor = STARTING_FACTOR
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
assert col.sched.counts() == (0, 0, 0)
|
assert col.sched.counts() == (0, 0, 0)
|
||||||
|
@ -1082,7 +1082,7 @@ def test_deckDue():
|
||||||
# and one that's a child
|
# and one that's a child
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
default1 = note.model()["did"] = col.decks.id("Default::1")
|
default1 = note.note_type()["did"] = col.decks.id("Default::1")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# make it a review card
|
# make it a review card
|
||||||
c = note.cards()[0]
|
c = note.cards()[0]
|
||||||
|
@ -1092,12 +1092,12 @@ def test_deckDue():
|
||||||
# add one more with a new deck
|
# add one more with a new deck
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
note.model()["did"] = col.decks.id("foo::bar")
|
note.note_type()["did"] = col.decks.id("foo::bar")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# and one that's a sibling
|
# and one that's a sibling
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "three"
|
note["Front"] = "three"
|
||||||
note.model()["did"] = col.decks.id("foo::baz")
|
note.note_type()["did"] = col.decks.id("foo::baz")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
col.reset()
|
col.reset()
|
||||||
assert len(col.decks.all_names_and_ids()) == 5
|
assert len(col.decks.all_names_and_ids()) == 5
|
||||||
|
@ -1138,12 +1138,12 @@ def test_deckFlow():
|
||||||
# and one that's a child
|
# and one that's a child
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "two"
|
note["Front"] = "two"
|
||||||
note.model()["did"] = col.decks.id("Default::2")
|
note.note_type()["did"] = col.decks.id("Default::2")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
# and another that's higher up
|
# and another that's higher up
|
||||||
note = col.newNote()
|
note = col.newNote()
|
||||||
note["Front"] = "three"
|
note["Front"] = "three"
|
||||||
default1 = note.model()["did"] = col.decks.id("Default::1")
|
default1 = note.note_type()["did"] = col.decks.id("Default::1")
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
col.reset()
|
col.reset()
|
||||||
assert col.sched.counts() == (3, 0, 0)
|
assert col.sched.counts() == (3, 0, 0)
|
||||||
|
@ -1255,7 +1255,7 @@ def test_norelearn():
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.ivl = 100
|
c.ivl = 100
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
col.sched.answerCard(c, 1)
|
col.sched.answerCard(c, 1)
|
||||||
|
@ -1277,7 +1277,7 @@ def test_failmult():
|
||||||
c.factor = STARTING_FACTOR
|
c.factor = STARTING_FACTOR
|
||||||
c.reps = 3
|
c.reps = 3
|
||||||
c.lapses = 1
|
c.lapses = 1
|
||||||
c.startTimer()
|
c.start_timer()
|
||||||
c.flush()
|
c.flush()
|
||||||
conf = col.sched._cardConf(c)
|
conf = col.sched._cardConf(c)
|
||||||
conf["lapse"]["mult"] = 0.5
|
conf["lapse"]["mult"] = 0.5
|
||||||
|
|
|
@ -15,4 +15,4 @@ def test_deferred_frontside():
|
||||||
note["Back"] = ""
|
note["Back"] = ""
|
||||||
col.addNote(note)
|
col.addNote(note)
|
||||||
|
|
||||||
assert "xxtest" in note.cards()[0].a()
|
assert "xxtest" in note.cards()[0].answer()
|
||||||
|
|
|
@ -128,14 +128,14 @@ class AddCards(QDialog):
|
||||||
if old:
|
if old:
|
||||||
old_fields = list(old.keys())
|
old_fields = list(old.keys())
|
||||||
new_fields = list(new.keys())
|
new_fields = list(new.keys())
|
||||||
for n, f in enumerate(new.model()["flds"]):
|
for n, f in enumerate(new.note_type()["flds"]):
|
||||||
field_name = f["name"]
|
field_name = f["name"]
|
||||||
# copy identical fields
|
# copy identical fields
|
||||||
if field_name in old_fields:
|
if field_name in old_fields:
|
||||||
new[field_name] = old[field_name]
|
new[field_name] = old[field_name]
|
||||||
elif n < len(old.model()["flds"]):
|
elif n < len(old.note_type()["flds"]):
|
||||||
# set non-identical fields by field index
|
# set non-identical fields by field index
|
||||||
old_field_name = old.model()["flds"][n]["name"]
|
old_field_name = old.note_type()["flds"][n]["name"]
|
||||||
if old_field_name not in new_fields:
|
if old_field_name not in new_fields:
|
||||||
new.fields[n] = old.fields[n]
|
new.fields[n] = old.fields[n]
|
||||||
new.tags = old.tags
|
new.tags = old.tags
|
||||||
|
@ -147,7 +147,7 @@ class AddCards(QDialog):
|
||||||
def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
|
def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
|
||||||
note = self._new_note()
|
note = self._new_note()
|
||||||
if old_note := sticky_fields_from:
|
if old_note := sticky_fields_from:
|
||||||
flds = note.model()["flds"]
|
flds = note.note_type()["flds"]
|
||||||
# copy fields from old note
|
# copy fields from old note
|
||||||
if old_note:
|
if old_note:
|
||||||
for n in range(min(len(note.fields), len(old_note.fields))):
|
for n in range(min(len(note.fields), len(old_note.fields))):
|
||||||
|
|
|
@ -187,11 +187,11 @@ class Previewer(QDialog):
|
||||||
return
|
return
|
||||||
|
|
||||||
# need to force reload even if answer
|
# need to force reload even if answer
|
||||||
txt = c.q(reload=True)
|
txt = c.question(reload=True)
|
||||||
|
|
||||||
if self._state == "answer":
|
if self._state == "answer":
|
||||||
func = "_showAnswer"
|
func = "_showAnswer"
|
||||||
txt = c.a()
|
txt = c.answer()
|
||||||
txt = re.sub(r"\[\[type:[^]]+\]\]", "", txt)
|
txt = re.sub(r"\[\[type:[^]]+\]\]", "", txt)
|
||||||
|
|
||||||
bodyclass = theme_manager.body_classes_for_card_ord(c.ord)
|
bodyclass = theme_manager.body_classes_for_card_ord(c.ord)
|
||||||
|
|
|
@ -52,7 +52,7 @@ class CardLayout(QDialog):
|
||||||
self.ord = ord
|
self.ord = ord
|
||||||
self.col = self.mw.col.weakref()
|
self.col = self.mw.col.weakref()
|
||||||
self.mm = self.mw.col.models
|
self.mm = self.mw.col.models
|
||||||
self.model = note.model()
|
self.model = note.note_type()
|
||||||
self.templates = self.model["tmpls"]
|
self.templates = self.model["tmpls"]
|
||||||
self.fill_empty_action_toggled = fill_empty
|
self.fill_empty_action_toggled = fill_empty
|
||||||
self.night_mode_is_enabled = self.mw.pm.night_mode()
|
self.night_mode_is_enabled = self.mw.pm.night_mode()
|
||||||
|
@ -493,11 +493,11 @@ class CardLayout(QDialog):
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.pform.preview_front.isChecked():
|
if self.pform.preview_front.isChecked():
|
||||||
q = ti(self.mw.prepare_card_text_for_display(c.q()))
|
q = ti(self.mw.prepare_card_text_for_display(c.question()))
|
||||||
q = gui_hooks.card_will_show(q, c, "clayoutQuestion")
|
q = gui_hooks.card_will_show(q, c, "clayoutQuestion")
|
||||||
text = q
|
text = q
|
||||||
else:
|
else:
|
||||||
a = ti(self.mw.prepare_card_text_for_display(c.a()), type="a")
|
a = ti(self.mw.prepare_card_text_for_display(c.answer()), type="a")
|
||||||
a = gui_hooks.card_will_show(a, c, "clayoutAnswer")
|
a = gui_hooks.card_will_show(a, c, "clayoutAnswer")
|
||||||
text = a
|
text = a
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
def _onFields(self) -> None:
|
def _onFields(self) -> None:
|
||||||
from aqt.fields import FieldDialog
|
from aqt.fields import FieldDialog
|
||||||
|
|
||||||
FieldDialog(self.mw, self.note.model(), parent=self.parentWindow)
|
FieldDialog(self.mw, self.note.note_type(), parent=self.parentWindow)
|
||||||
|
|
||||||
def onCardLayout(self) -> None:
|
def onCardLayout(self) -> None:
|
||||||
self.call_after_note_saved(self._onCardLayout)
|
self.call_after_note_saved(self._onCardLayout)
|
||||||
|
@ -394,7 +394,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
(type, num) = cmd.split(":", 1)
|
(type, num) = cmd.split(":", 1)
|
||||||
ord = int(num)
|
ord = int(num)
|
||||||
|
|
||||||
model = self.note.model()
|
model = self.note.note_type()
|
||||||
fld = model["flds"][ord]
|
fld = model["flds"][ord]
|
||||||
new_state = not fld["sticky"]
|
new_state = not fld["sticky"]
|
||||||
fld["sticky"] = new_state
|
fld["sticky"] = new_state
|
||||||
|
@ -463,7 +463,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.addMode:
|
if self.addMode:
|
||||||
sticky = [field["sticky"] for field in self.note.model()["flds"]]
|
sticky = [field["sticky"] for field in self.note.note_type()["flds"]]
|
||||||
js += " setSticky(%s);" % json.dumps(sticky)
|
js += " setSticky(%s);" % json.dumps(sticky)
|
||||||
|
|
||||||
js = gui_hooks.editor_will_load_note(js, self.note, self)
|
js = gui_hooks.editor_will_load_note(js, self.note, self)
|
||||||
|
@ -478,7 +478,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
def fonts(self) -> List[Tuple[str, int, bool]]:
|
def fonts(self) -> List[Tuple[str, int, bool]]:
|
||||||
return [
|
return [
|
||||||
(gui_hooks.editor_will_use_font_for_field(f["font"]), f["size"], f["rtl"])
|
(gui_hooks.editor_will_use_font_for_field(f["font"]), f["size"], f["rtl"])
|
||||||
for f in self.note.model()["flds"]
|
for f in self.note.note_type()["flds"]
|
||||||
]
|
]
|
||||||
|
|
||||||
def call_after_note_saved(
|
def call_after_note_saved(
|
||||||
|
@ -532,7 +532,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
search=(
|
search=(
|
||||||
SearchNode(
|
SearchNode(
|
||||||
dupe=SearchNode.Dupe(
|
dupe=SearchNode.Dupe(
|
||||||
notetype_id=self.note.model()["id"],
|
notetype_id=self.note.note_type()["id"],
|
||||||
first_field=self.note.fields[0],
|
first_field=self.note.fields[0],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -542,7 +542,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
def fieldsAreBlank(self, previousNote: Optional[Note] = None) -> bool:
|
def fieldsAreBlank(self, previousNote: Optional[Note] = None) -> bool:
|
||||||
if not self.note:
|
if not self.note:
|
||||||
return True
|
return True
|
||||||
m = self.note.model()
|
m = self.note.note_type()
|
||||||
for c, f in enumerate(self.note.fields):
|
for c, f in enumerate(self.note.fields):
|
||||||
f = f.replace("<br>", "").strip()
|
f = f.replace("<br>", "").strip()
|
||||||
notChangedvalues = {"", "<br>"}
|
notChangedvalues = {"", "<br>"}
|
||||||
|
@ -681,7 +681,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
||||||
|
|
||||||
def _onCloze(self) -> None:
|
def _onCloze(self) -> None:
|
||||||
# check that the model is set up for cloze deletion
|
# check that the model is set up for cloze deletion
|
||||||
if self.note.model()["type"] != MODEL_CLOZE:
|
if self.note.note_type()["type"] != MODEL_CLOZE:
|
||||||
if self.addMode:
|
if self.addMode:
|
||||||
tooltip(tr.editing_warning_cloze_deletions_will_not_work())
|
tooltip(tr.editing_warning_cloze_deletions_will_not_work())
|
||||||
else:
|
else:
|
||||||
|
@ -1280,7 +1280,7 @@ gui_hooks.editor_will_munge_html.append(reverse_url_quoting)
|
||||||
|
|
||||||
|
|
||||||
def set_cloze_button(editor: Editor) -> None:
|
def set_cloze_button(editor: Editor) -> None:
|
||||||
if editor.note.model()["type"] == MODEL_CLOZE:
|
if editor.note.note_type()["type"] == MODEL_CLOZE:
|
||||||
editor.web.eval(
|
editor.web.eval(
|
||||||
'$editorToolbar.then(({ templateButtons }) => templateButtons.showButton("cloze")); '
|
'$editorToolbar.then(({ templateButtons }) => templateButtons.showButton("cloze")); '
|
||||||
)
|
)
|
||||||
|
|
|
@ -118,7 +118,7 @@ class ImportDialog(QDialog):
|
||||||
self.deck = aqt.deckchooser.DeckChooser(self.mw, self.frm.deckArea, label=False)
|
self.deck = aqt.deckchooser.DeckChooser(self.mw, self.frm.deckArea, label=False)
|
||||||
|
|
||||||
def modelChanged(self, unused: Any = None) -> None:
|
def modelChanged(self, unused: Any = None) -> None:
|
||||||
self.importer.model = self.mw.col.models.current()
|
self.importer.note_type = self.mw.col.models.current()
|
||||||
self.importer.initMapping()
|
self.importer.initMapping()
|
||||||
self.showMapping()
|
self.showMapping()
|
||||||
|
|
||||||
|
@ -191,9 +191,9 @@ class ImportDialog(QDialog):
|
||||||
self.importer.tagModified = self.frm.tagModified.text()
|
self.importer.tagModified = self.frm.tagModified.text()
|
||||||
self.mw.pm.profile["tagModified"] = self.importer.tagModified
|
self.mw.pm.profile["tagModified"] = self.importer.tagModified
|
||||||
self.mw.col.set_aux_notetype_config(
|
self.mw.col.set_aux_notetype_config(
|
||||||
self.importer.model["id"], "lastDeck", self.deck.selected_deck_id
|
self.importer.note_type["id"], "lastDeck", self.deck.selected_deck_id
|
||||||
)
|
)
|
||||||
self.mw.col.models.save(self.importer.model, updateReqs=False)
|
self.mw.col.models.save(self.importer.note_type, updateReqs=False)
|
||||||
self.mw.progress.start()
|
self.mw.progress.start()
|
||||||
self.mw.checkpoint(tr.actions_import())
|
self.mw.checkpoint(tr.actions_import())
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ class ImportDialog(QDialog):
|
||||||
qconnect(button.clicked, lambda _, s=self, n=num: s.changeMappingNum(n))
|
qconnect(button.clicked, lambda _, s=self, n=num: s.changeMappingNum(n))
|
||||||
|
|
||||||
def changeMappingNum(self, n: int) -> None:
|
def changeMappingNum(self, n: int) -> None:
|
||||||
f = ChangeMap(self.mw, self.importer.model, self.mapping[n]).getField()
|
f = ChangeMap(self.mw, self.importer.note_type, self.mapping[n]).getField()
|
||||||
try:
|
try:
|
||||||
# make sure we don't have it twice
|
# make sure we don't have it twice
|
||||||
index = self.mapping.index(f)
|
index = self.mapping.index(f)
|
||||||
|
|
|
@ -218,7 +218,7 @@ class Reviewer:
|
||||||
if self.cardQueue:
|
if self.cardQueue:
|
||||||
# undone/edited cards to show
|
# undone/edited cards to show
|
||||||
card = self.cardQueue.pop()
|
card = self.cardQueue.pop()
|
||||||
card.startTimer()
|
card.start_timer()
|
||||||
self.hadCardQueue = True
|
self.hadCardQueue = True
|
||||||
else:
|
else:
|
||||||
if self.hadCardQueue:
|
if self.hadCardQueue:
|
||||||
|
@ -236,7 +236,7 @@ class Reviewer:
|
||||||
return
|
return
|
||||||
self._v3 = V3CardInfo.from_queue(output)
|
self._v3 = V3CardInfo.from_queue(output)
|
||||||
self.card = Card(self.mw.col, backend_card=self._v3.top_card().card)
|
self.card = Card(self.mw.col, backend_card=self._v3.top_card().card)
|
||||||
self.card.startTimer()
|
self.card.start_timer()
|
||||||
|
|
||||||
def get_next_states(self) -> Optional[NextStates]:
|
def get_next_states(self) -> Optional[NextStates]:
|
||||||
if v3 := self._v3:
|
if v3 := self._v3:
|
||||||
|
@ -320,7 +320,7 @@ class Reviewer:
|
||||||
self.typedAnswer: str = None
|
self.typedAnswer: str = None
|
||||||
c = self.card
|
c = self.card
|
||||||
# grab the question and play audio
|
# grab the question and play audio
|
||||||
q = c.q()
|
q = c.question()
|
||||||
# play audio?
|
# play audio?
|
||||||
if c.autoplay():
|
if c.autoplay():
|
||||||
AnkiWebView.setPlaybackRequiresGesture(False)
|
AnkiWebView.setPlaybackRequiresGesture(False)
|
||||||
|
@ -370,7 +370,7 @@ class Reviewer:
|
||||||
return
|
return
|
||||||
self.state = "answer"
|
self.state = "answer"
|
||||||
c = self.card
|
c = self.card
|
||||||
a = c.a()
|
a = c.answer()
|
||||||
# play audio?
|
# play audio?
|
||||||
if c.autoplay():
|
if c.autoplay():
|
||||||
sounds = c.answer_av_tags()
|
sounds = c.answer_av_tags()
|
||||||
|
@ -535,7 +535,7 @@ class Reviewer:
|
||||||
clozeIdx = self.card.ord + 1
|
clozeIdx = self.card.ord + 1
|
||||||
fld = fld.split(":")[1]
|
fld = fld.split(":")[1]
|
||||||
# loop through fields for a match
|
# loop through fields for a match
|
||||||
for f in self.card.model()["flds"]:
|
for f in self.card.note_type()["flds"]:
|
||||||
if f["name"] == fld:
|
if f["name"] == fld:
|
||||||
self.typeCorrect = self.card.note()[f["name"]]
|
self.typeCorrect = self.card.note()[f["name"]]
|
||||||
if clozeIdx:
|
if clozeIdx:
|
||||||
|
@ -733,7 +733,7 @@ time = %(time)d;
|
||||||
editkey=tr.actions_shortcut_key(val="E"),
|
editkey=tr.actions_shortcut_key(val="E"),
|
||||||
more=tr.studying_more(),
|
more=tr.studying_more(),
|
||||||
downArrow=downArrow(),
|
downArrow=downArrow(),
|
||||||
time=self.card.timeTaken() // 1000,
|
time=self.card.time_taken() // 1000,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _showAnswerButton(self) -> None:
|
def _showAnswerButton(self) -> None:
|
||||||
|
@ -749,8 +749,8 @@ time = %(time)d;
|
||||||
"<table cellpadding=0><tr><td class=stat2 align=center>%s</td></tr></table>"
|
"<table cellpadding=0><tr><td class=stat2 align=center>%s</td></tr></table>"
|
||||||
% middle
|
% middle
|
||||||
)
|
)
|
||||||
if self.card.shouldShowTimer():
|
if self.card.should_show_timer():
|
||||||
maxTime = self.card.timeLimit() / 1000
|
maxTime = self.card.time_limit() / 1000
|
||||||
else:
|
else:
|
||||||
maxTime = 0
|
maxTime = 0
|
||||||
self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime))
|
self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime))
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod learning;
|
||||||
mod main;
|
mod main;
|
||||||
pub(crate) mod undo;
|
pub(crate) mod undo;
|
||||||
|
|
||||||
use std::{collections::VecDeque, time::Instant};
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub(crate) use builder::{DueCard, NewCard};
|
pub(crate) use builder::{DueCard, NewCard};
|
||||||
pub(crate) use entry::{QueueEntry, QueueEntryKind};
|
pub(crate) use entry::{QueueEntry, QueueEntryKind};
|
||||||
|
@ -205,9 +205,7 @@ impl Collection {
|
||||||
self.discard_undo_and_study_queues();
|
self.discard_undo_and_study_queues();
|
||||||
}
|
}
|
||||||
if self.state.card_queues.is_none() {
|
if self.state.card_queues.is_none() {
|
||||||
let now = Instant::now();
|
|
||||||
self.state.card_queues = Some(self.build_queues(deck)?);
|
self.state.card_queues = Some(self.build_queues(deck)?);
|
||||||
println!("queue build in {:?}", now.elapsed());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.state.card_queues.as_mut().unwrap())
|
Ok(self.state.card_queues.as_mut().unwrap())
|
||||||
|
|
Loading…
Reference in a new issue