mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02: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 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
|
||||
|
||||
|
@ -18,20 +22,37 @@ def _target_to_string(target: DeprecatedAliasTarget) -> str:
|
|||
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:
|
||||
"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] = {}
|
||||
|
||||
@no_type_check
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
remapped = self._deprecated_aliases.get(name) or stringcase.snakecase(name)
|
||||
if remapped == name:
|
||||
raise AttributeError
|
||||
|
||||
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
|
||||
|
||||
@no_type_check
|
||||
@classmethod
|
||||
def register_deprecated_aliases(cls, **kwargs: DeprecatedAliasTarget) -> None:
|
||||
"""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`."""
|
||||
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@functools.wraps(func)
|
||||
def decorated_func(*args: Any, **kwargs: Any) -> Any:
|
||||
if replaced_by:
|
||||
doc = f"please use {replaced_by.__name__} instead."
|
||||
else:
|
||||
doc = info
|
||||
print(
|
||||
f"'{func.__name__}' is deprecated, and will be removed in the future: ",
|
||||
doc,
|
||||
)
|
||||
|
||||
_print_deprecation_warning(f"{func.__name__}()", doc)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return decorated_func
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pprint
|
||||
|
@ -10,6 +12,7 @@ from typing import List, NewType, Optional
|
|||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||
from anki.consts import *
|
||||
from anki.models import NotetypeDict, TemplateDict
|
||||
from anki.notes import Note
|
||||
|
@ -22,7 +25,7 @@ from anki.sound import AVTag
|
|||
# Queue: same as above, and:
|
||||
# -1=suspended, -2=user buried, -3=sched buried
|
||||
# Due is used differently for different queues.
|
||||
# - new queue: note id or random int
|
||||
# - new queue: position
|
||||
# - rev queue: integer day
|
||||
# - lrn queue: integer timestamp
|
||||
|
||||
|
@ -31,9 +34,8 @@ CardId = NewType("CardId", int)
|
|||
BackendCard = _pb.Card
|
||||
|
||||
|
||||
class Card:
|
||||
class Card(DeprecatedNamesMixin):
|
||||
_note: Optional[Note]
|
||||
timerStarted: Optional[float]
|
||||
lastIvl: int
|
||||
ord: int
|
||||
nid: anki.notes.NoteId
|
||||
|
@ -50,7 +52,7 @@ class Card:
|
|||
backend_card: Optional[BackendCard] = None,
|
||||
) -> None:
|
||||
self.col = col.weakref()
|
||||
self.timerStarted = None
|
||||
self.timer_started: Optional[float] = None
|
||||
self._render_output: Optional[anki.template.TemplateRenderOutput] = None
|
||||
if id:
|
||||
# existing card
|
||||
|
@ -63,31 +65,31 @@ class Card:
|
|||
self._load_from_backend_card(_pb.Card())
|
||||
|
||||
def load(self) -> None:
|
||||
c = self.col._backend.get_card(self.id)
|
||||
assert c
|
||||
self._load_from_backend_card(c)
|
||||
card = self.col._backend.get_card(self.id)
|
||||
assert card
|
||||
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._note = None
|
||||
self.id = CardId(c.id)
|
||||
self.nid = anki.notes.NoteId(c.note_id)
|
||||
self.did = anki.decks.DeckId(c.deck_id)
|
||||
self.ord = c.template_idx
|
||||
self.mod = c.mtime_secs
|
||||
self.usn = c.usn
|
||||
self.type = CardType(c.ctype)
|
||||
self.queue = CardQueue(c.queue)
|
||||
self.due = c.due
|
||||
self.ivl = c.interval
|
||||
self.factor = c.ease_factor
|
||||
self.reps = c.reps
|
||||
self.lapses = c.lapses
|
||||
self.left = c.remaining_steps
|
||||
self.odue = c.original_due
|
||||
self.odid = anki.decks.DeckId(c.original_deck_id)
|
||||
self.flags = c.flags
|
||||
self.data = c.data
|
||||
self.id = CardId(card.id)
|
||||
self.nid = anki.notes.NoteId(card.note_id)
|
||||
self.did = anki.decks.DeckId(card.deck_id)
|
||||
self.ord = card.template_idx
|
||||
self.mod = card.mtime_secs
|
||||
self.usn = card.usn
|
||||
self.type = CardType(card.ctype)
|
||||
self.queue = CardQueue(card.queue)
|
||||
self.due = card.due
|
||||
self.ivl = card.interval
|
||||
self.factor = card.ease_factor
|
||||
self.reps = card.reps
|
||||
self.lapses = card.lapses
|
||||
self.left = card.remaining_steps
|
||||
self.odue = card.original_due
|
||||
self.odid = anki.decks.DeckId(card.original_deck_id)
|
||||
self.flags = card.flags
|
||||
self.data = card.data
|
||||
|
||||
def _to_backend_card(self) -> _pb.Card:
|
||||
# mtime & usn are set by backend
|
||||
|
@ -131,10 +133,6 @@ class Card:
|
|||
def answer_av_tags(self) -> List[AVTag]:
|
||||
return self.render_output().answer_av_tags
|
||||
|
||||
# legacy
|
||||
def css(self) -> str:
|
||||
return f"<style>{self.render_output().css}</style>"
|
||||
|
||||
def render_output(
|
||||
self, reload: bool = False, browser: bool = False
|
||||
) -> anki.template.TemplateRenderOutput:
|
||||
|
@ -157,31 +155,25 @@ class Card:
|
|||
def note_type(self) -> NotetypeDict:
|
||||
return self.col.models.get(self.note().mid)
|
||||
|
||||
# legacy aliases
|
||||
flushSched = flush
|
||||
q = question
|
||||
a = answer
|
||||
model = note_type
|
||||
|
||||
def template(self) -> TemplateDict:
|
||||
m = self.model()
|
||||
if m["type"] == MODEL_STD:
|
||||
return self.model()["tmpls"][self.ord]
|
||||
notetype = self.note_type()
|
||||
if notetype["type"] == MODEL_STD:
|
||||
return self.note_type()["tmpls"][self.ord]
|
||||
else:
|
||||
return self.model()["tmpls"][0]
|
||||
return self.note_type()["tmpls"][0]
|
||||
|
||||
def startTimer(self) -> None:
|
||||
self.timerStarted = time.time()
|
||||
def start_timer(self) -> None:
|
||||
self.timer_started = time.time()
|
||||
|
||||
def current_deck_id(self) -> anki.decks.DeckId:
|
||||
return anki.decks.DeckId(self.odid or self.did)
|
||||
|
||||
def timeLimit(self) -> int:
|
||||
def time_limit(self) -> int:
|
||||
"Time limit for answering in milliseconds."
|
||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||
return conf["maxTaken"] * 1000
|
||||
|
||||
def shouldShowTimer(self) -> bool:
|
||||
def should_show_timer(self) -> bool:
|
||||
conf = self.col.decks.confForDid(self.current_deck_id())
|
||||
return conf["timer"]
|
||||
|
||||
|
@ -192,23 +184,19 @@ class Card:
|
|||
def autoplay(self) -> bool:
|
||||
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."
|
||||
total = int((time.time() - self.timerStarted) * 1000)
|
||||
return min(total, self.timeLimit())
|
||||
total = int((time.time() - self.timer_started) * 1000)
|
||||
return min(total, self.time_limit())
|
||||
|
||||
# legacy
|
||||
def isEmpty(self) -> bool:
|
||||
return False
|
||||
|
||||
def __repr__(self) -> str:
|
||||
d = dict(self.__dict__)
|
||||
def description(self) -> str:
|
||||
dict_copy = dict(self.__dict__)
|
||||
# remove non-useful elements
|
||||
del d["_note"]
|
||||
del d["_render_output"]
|
||||
del d["col"]
|
||||
del d["timerStarted"]
|
||||
return f"{super().__repr__()} {pprint.pformat(d, width=300)}"
|
||||
del dict_copy["_note"]
|
||||
del dict_copy["_render_output"]
|
||||
del dict_copy["col"]
|
||||
del dict_copy["timerStarted"]
|
||||
return f"{super().__repr__()} {pprint.pformat(dict_copy, width=300)}"
|
||||
|
||||
def user_flag(self) -> int:
|
||||
return self.flags & 0b111
|
||||
|
@ -218,7 +206,18 @@ class Card:
|
|||
assert 0 <= flag <= 7
|
||||
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
|
||||
setUserFlag = set_user_flag
|
||||
@deprecated(info="handled by template rendering")
|
||||
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))
|
||||
|
||||
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())
|
||||
|
||||
def remNotes(self, ids: Sequence[NoteId]) -> None:
|
||||
|
|
|
@ -118,8 +118,8 @@ class TextCardExporter(Exporter):
|
|||
out = ""
|
||||
for cid in ids:
|
||||
c = self.col.getCard(cid)
|
||||
out += esc(c.q())
|
||||
out += "\t" + esc(c.a()) + "\n"
|
||||
out += esc(c.question())
|
||||
out += "\t" + esc(c.answer()) + "\n"
|
||||
file.write(out.encode("utf-8"))
|
||||
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ class Note(DeprecatedNamesMixin):
|
|||
self.usn = note.usn
|
||||
self.tags = list(note.tags)
|
||||
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:
|
||||
hooks.note_will_flush(self)
|
||||
|
@ -98,7 +98,7 @@ class Note(DeprecatedNamesMixin):
|
|||
card.ord = ord
|
||||
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(
|
||||
custom_template
|
||||
or (
|
||||
|
@ -125,10 +125,10 @@ class Note(DeprecatedNamesMixin):
|
|||
def card_ids(self) -> Sequence[anki.cards.CardId]:
|
||||
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)
|
||||
|
||||
_model = property(model)
|
||||
_note_type = property(note_type)
|
||||
|
||||
def cloze_numbers_in_fields(self) -> Sequence[int]:
|
||||
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
|
||||
|
||||
|
||||
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,
|
||||
new_delta=new_delta,
|
||||
review_delta=review_delta,
|
||||
milliseconds_delta=+card.timeTaken(),
|
||||
milliseconds_delta=+card.time_taken(),
|
||||
)
|
||||
|
||||
card.mod = intTime()
|
||||
|
@ -363,7 +363,7 @@ limit %d"""
|
|||
ivl,
|
||||
lastIvl,
|
||||
card.factor,
|
||||
card.timeTaken(),
|
||||
card.time_taken(),
|
||||
type,
|
||||
)
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
self.col.log(card)
|
||||
if not self._burySiblingsOnAnswer:
|
||||
self._burySiblings(card)
|
||||
card.startTimer()
|
||||
card.start_timer()
|
||||
return card
|
||||
return None
|
||||
|
||||
|
@ -494,7 +494,7 @@ limit ?"""
|
|||
card.did,
|
||||
new_delta=new_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
|
||||
|
@ -760,7 +760,7 @@ limit ?"""
|
|||
ivl,
|
||||
lastIvl,
|
||||
card.factor,
|
||||
card.timeTaken(),
|
||||
card.time_taken(),
|
||||
type,
|
||||
)
|
||||
|
||||
|
@ -891,7 +891,7 @@ limit ?"""
|
|||
-delay or card.ivl,
|
||||
card.lastIvl,
|
||||
card.factor,
|
||||
card.timeTaken(),
|
||||
card.time_taken(),
|
||||
type,
|
||||
)
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
new_state=new_state,
|
||||
rating=rating,
|
||||
answered_at_millis=intTime(1000),
|
||||
milliseconds_taken=card.timeTaken(),
|
||||
milliseconds_taken=card.time_taken(),
|
||||
)
|
||||
|
||||
def answer_card(self, input: CardAnswer) -> OpChanges:
|
||||
|
@ -106,7 +106,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
|
||||
card = Card(self.col)
|
||||
card._load_from_backend_card(queued_card.card)
|
||||
card.startTimer()
|
||||
card.start_timer()
|
||||
return card
|
||||
|
||||
def _is_finished(self) -> bool:
|
||||
|
|
|
@ -155,7 +155,7 @@ class TemplateRenderContext:
|
|||
self._fields: Optional[Dict] = None
|
||||
self._latex_svg = False
|
||||
if not notetype:
|
||||
self._note_type = note.model()
|
||||
self._note_type = note.note_type()
|
||||
else:
|
||||
self._note_type = notetype
|
||||
|
||||
|
@ -190,7 +190,7 @@ class TemplateRenderContext:
|
|||
def card(self) -> Card:
|
||||
"""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."""
|
||||
return self._card
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ def test_noteAddDelete():
|
|||
assert col.cardCount() == 4
|
||||
# check q/a generation
|
||||
c0 = note.cards()[0]
|
||||
assert "three" in c0.q()
|
||||
assert "three" in c0.question()
|
||||
# it should not be a duplicate
|
||||
assert not note.fields_check()
|
||||
# now let's make a duplicate
|
||||
|
@ -138,15 +138,15 @@ def test_furigana():
|
|||
n["Front"] = "foo[abc]"
|
||||
col.addNote(n)
|
||||
c = n.cards()[0]
|
||||
assert c.q().endswith("abc")
|
||||
assert c.question().endswith("abc")
|
||||
# and should avoid sound
|
||||
n["Front"] = "foo[sound:abc.mp3]"
|
||||
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
|
||||
m["tmpls"][0]["qfmt"] = "{{kana:}}"
|
||||
mm.save(m)
|
||||
c.q(reload=True)
|
||||
c.question(reload=True)
|
||||
|
||||
|
||||
def test_translate():
|
||||
|
|
|
@ -53,12 +53,12 @@ def test_remove():
|
|||
deck1 = col.decks.id("deck1")
|
||||
note = col.newNote()
|
||||
note["Front"] = "1"
|
||||
note.model()["did"] = deck1
|
||||
note.note_type()["did"] = deck1
|
||||
col.addNote(note)
|
||||
c = note.cards()[0]
|
||||
assert c.did == deck1
|
||||
assert col.cardCount() == 1
|
||||
col.decks.rem(deck1)
|
||||
col.decks.remove([deck1])
|
||||
assert col.cardCount() == 0
|
||||
# if we try to get it, we get the default
|
||||
assert col.decks.name(c.did) == "[no deck]"
|
||||
|
@ -142,7 +142,7 @@ def test_renameForDragAndDrop():
|
|||
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.rem(new_hsk_did)
|
||||
col.decks.remove([new_hsk_did])
|
||||
|
||||
# '' is a convenient alias for the top level DID
|
||||
col.decks.renameForDragAndDrop(hsk_did, "")
|
||||
|
|
|
@ -36,7 +36,7 @@ def setup1():
|
|||
note = col.newNote()
|
||||
note["Front"] = "baz"
|
||||
note["Back"] = "qux"
|
||||
note.model()["did"] = col.decks.id("new col")
|
||||
note.note_type()["did"] = col.decks.id("new col")
|
||||
col.addNote(note)
|
||||
|
||||
|
||||
|
|
|
@ -35,11 +35,3 @@ def test_flags():
|
|||
col.set_user_flag_for_cards(0, [c.id])
|
||||
c.load()
|
||||
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
|
||||
n = col.newNote()
|
||||
n["Front"] = "[sound:foo.mp3]"
|
||||
mid = n.model()["id"]
|
||||
mid = n.note_type()["id"]
|
||||
col.addNote(n)
|
||||
# add that sound to media folder
|
||||
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
|
||||
assert len(os.listdir(col.media.dir())) == 0
|
||||
# check the error message
|
||||
msg = note.cards()[0].q()
|
||||
msg = note.cards()[0].question()
|
||||
assert "executing nolatex" in without_unicode_isolation(msg)
|
||||
assert "installed" in msg
|
||||
# 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
|
||||
col.media.render_all_latex()
|
||||
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
|
||||
note = col.newNote()
|
||||
note["Front"] = "[latex]world[/latex]"
|
||||
col.addNote(note)
|
||||
note.cards()[0].q()
|
||||
note.cards()[0].question()
|
||||
assert len(os.listdir(col.media.dir())) == 2
|
||||
# another note with the same media should reuse
|
||||
note = col.newNote()
|
||||
|
@ -48,7 +48,7 @@ def test_latex():
|
|||
col.addNote(note)
|
||||
assert len(os.listdir(col.media.dir())) == 2
|
||||
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
|
||||
# missing media will show a broken image
|
||||
anki.latex.build = False
|
||||
|
@ -56,7 +56,7 @@ def test_latex():
|
|||
note["Front"] = "[latex]foo[/latex]"
|
||||
col.addNote(note)
|
||||
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
|
||||
anki.latex.build = True
|
||||
|
||||
|
@ -95,5 +95,5 @@ def _test_includes_bad_command(bad):
|
|||
note = col.newNote()
|
||||
note["Front"] = "[latex]%s[/latex]" % bad
|
||||
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)
|
||||
|
|
|
@ -112,7 +112,7 @@ def test_templates():
|
|||
# and should have updated the other cards' ordinals
|
||||
c = note.cards()[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
|
||||
t = mm.newTemplate("template name")
|
||||
t["qfmt"] = "{{Front}}2"
|
||||
|
@ -158,14 +158,14 @@ def test_text():
|
|||
note = col.newNote()
|
||||
note["Front"] = "hello<b>world"
|
||||
col.addNote(note)
|
||||
assert "helloworld" in note.cards()[0].q()
|
||||
assert "helloworld" in note.cards()[0].question()
|
||||
|
||||
|
||||
def test_cloze():
|
||||
col = getEmptyCol()
|
||||
col.models.setCurrent(col.models.byName("Cloze"))
|
||||
note = col.newNote()
|
||||
assert note.model()["name"] == "Cloze"
|
||||
assert note.note_type()["name"] == "Cloze"
|
||||
# a cloze model with no clozes is not empty
|
||||
note["Text"] = "nothing"
|
||||
assert col.addNote(note)
|
||||
|
@ -173,30 +173,30 @@ def test_cloze():
|
|||
note = col.newNote()
|
||||
note["Text"] = "hello {{c1::world}}"
|
||||
assert col.addNote(note) == 1
|
||||
assert "hello <span class=cloze>[...]</span>" in note.cards()[0].q()
|
||||
assert "hello <span class=cloze>world</span>" in note.cards()[0].a()
|
||||
assert "hello <span class=cloze>[...]</span>" in note.cards()[0].question()
|
||||
assert "hello <span class=cloze>world</span>" in note.cards()[0].answer()
|
||||
# and with a comment
|
||||
note = col.newNote()
|
||||
note["Text"] = "hello {{c1::world::typical}}"
|
||||
assert col.addNote(note) == 1
|
||||
assert "<span class=cloze>[typical]</span>" in note.cards()[0].q()
|
||||
assert "<span class=cloze>world</span>" in note.cards()[0].a()
|
||||
assert "<span class=cloze>[typical]</span>" in note.cards()[0].question()
|
||||
assert "<span class=cloze>world</span>" in note.cards()[0].answer()
|
||||
# and with 2 clozes
|
||||
note = col.newNote()
|
||||
note["Text"] = "hello {{c1::world}} {{c2::bar}}"
|
||||
assert col.addNote(note) == 2
|
||||
(c1, c2) = note.cards()
|
||||
assert "<span class=cloze>[...]</span> bar" in c1.q()
|
||||
assert "<span class=cloze>world</span> bar" in c1.a()
|
||||
assert "world <span class=cloze>[...]</span>" in c2.q()
|
||||
assert "world <span class=cloze>bar</span>" in c2.a()
|
||||
assert "<span class=cloze>[...]</span> bar" in c1.question()
|
||||
assert "<span class=cloze>world</span> bar" in c1.answer()
|
||||
assert "world <span class=cloze>[...]</span>" in c2.question()
|
||||
assert "world <span class=cloze>bar</span>" in c2.answer()
|
||||
# if there are multiple answers for a single cloze, they are given in a
|
||||
# list
|
||||
note = col.newNote()
|
||||
note["Text"] = "a {{c1::b}} {{c1::c}}"
|
||||
assert col.addNote(note) == 1
|
||||
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
|
||||
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}}"
|
||||
assert col.addNote(note)
|
||||
assert len(note.cards()) == 5
|
||||
assert "class=cloze" in note.cards()[0].q()
|
||||
assert "class=cloze" in note.cards()[1].q()
|
||||
assert "class=cloze" not in note.cards()[2].q()
|
||||
assert "class=cloze" in note.cards()[3].q()
|
||||
assert "class=cloze" in note.cards()[4].q()
|
||||
assert "class=cloze" in note.cards()[0].question()
|
||||
assert "class=cloze" in note.cards()[1].question()
|
||||
assert "class=cloze" not in note.cards()[2].question()
|
||||
assert "class=cloze" in note.cards()[3].question()
|
||||
assert "class=cloze" in note.cards()[4].question()
|
||||
|
||||
note = col.newNote()
|
||||
note["Text"] = r"\(a\) {{c1::b}} \[ {{c1::c}} \]"
|
||||
|
@ -230,7 +230,7 @@ def test_cloze_mathjax():
|
|||
assert len(note.cards()) == 1
|
||||
assert (
|
||||
note.cards()[0]
|
||||
.q()
|
||||
.question()
|
||||
.endswith(r"\(a\) <span class=cloze>[...]</span> \[ [...] \]")
|
||||
)
|
||||
|
||||
|
@ -244,7 +244,7 @@ def test_typecloze():
|
|||
note = col.newNote()
|
||||
note["Text"] = "hello {{c1::world}}"
|
||||
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():
|
||||
|
@ -275,11 +275,11 @@ def test_chained_mods():
|
|||
assert col.addNote(note) == 1
|
||||
assert (
|
||||
"This <span class=cloze>[sentence]</span> demonstrates <span class=cloze>[chained]</span> clozes."
|
||||
in note.cards()[0].q()
|
||||
in note.cards()[0].question()
|
||||
)
|
||||
assert (
|
||||
"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
|
||||
c0 = note.cards()[0]
|
||||
c1 = note.cards()[1]
|
||||
assert "b123" in c0.q()
|
||||
assert "note" in c1.q()
|
||||
assert "b123" in c0.question()
|
||||
assert "note" in c1.question()
|
||||
assert c0.ord == 0
|
||||
assert c1.ord == 1
|
||||
col.models.change(basic, [note.id], basic, noop, map)
|
||||
note.load()
|
||||
c0.load()
|
||||
c1.load()
|
||||
assert "note" in c0.q()
|
||||
assert "b123" in c1.q()
|
||||
assert "note" in c0.question()
|
||||
assert "b123" in c1.question()
|
||||
assert c0.ord == 1
|
||||
assert c1.ord == 0
|
||||
# .cards() returns cards in order
|
||||
|
|
|
@ -78,7 +78,7 @@ def test_new():
|
|||
# qs = ("2", "3", "2", "3")
|
||||
# for n in range(4):
|
||||
# c = col.sched.getCard()
|
||||
# assert qs[n] in c.q()
|
||||
# assert qs[n] in c.question()
|
||||
# col.sched.answerCard(c, 2)
|
||||
|
||||
|
||||
|
@ -90,7 +90,7 @@ def test_newLimits():
|
|||
note = col.newNote()
|
||||
note["Front"] = str(i)
|
||||
if i > 4:
|
||||
note.model()["did"] = deck2
|
||||
note.note_type()["did"] = deck2
|
||||
col.addNote(note)
|
||||
# give the child deck a different configuration
|
||||
c2 = col.decks.add_config_returning_id("new conf")
|
||||
|
@ -224,17 +224,17 @@ def test_learn_collapsed():
|
|||
col.reset()
|
||||
# should get '1' first
|
||||
c = col.sched.getCard()
|
||||
assert c.q().endswith("1")
|
||||
assert c.question().endswith("1")
|
||||
# pass it so it's due in 10 minutes
|
||||
col.sched.answerCard(c, 2)
|
||||
# get the other card
|
||||
c = col.sched.getCard()
|
||||
assert c.q().endswith("2")
|
||||
assert c.question().endswith("2")
|
||||
# fail it so it's due in 1 minute
|
||||
col.sched.answerCard(c, 1)
|
||||
# we shouldn't get the same card again
|
||||
c = col.sched.getCard()
|
||||
assert not c.q().endswith("2")
|
||||
assert not c.question().endswith("2")
|
||||
|
||||
|
||||
def test_learn_day():
|
||||
|
@ -316,7 +316,7 @@ def test_reviews():
|
|||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.ivl = 100
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
# save it for later use as well
|
||||
cardcopy = copy.copy(c)
|
||||
|
@ -393,7 +393,7 @@ def test_button_spacing():
|
|||
c.due = col.sched.today
|
||||
c.reps = 1
|
||||
c.ivl = 1
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
ni = col.sched.nextIvlStr
|
||||
|
@ -575,7 +575,7 @@ def test_cram():
|
|||
c.due = col.sched.today + 25
|
||||
c.mod = 1
|
||||
c.factor = STARTING_FACTOR
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
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, 3) == 86400
|
||||
# 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
|
||||
c.load()
|
||||
assert c.ivl == 1
|
||||
|
@ -964,7 +964,7 @@ def test_deckDue():
|
|||
# and one that's a child
|
||||
note = col.newNote()
|
||||
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)
|
||||
# make it a review card
|
||||
c = note.cards()[0]
|
||||
|
@ -974,12 +974,12 @@ def test_deckDue():
|
|||
# add one more with a new deck
|
||||
note = col.newNote()
|
||||
note["Front"] = "two"
|
||||
note.model()["did"] = col.decks.id("foo::bar")
|
||||
note.note_type()["did"] = col.decks.id("foo::bar")
|
||||
col.addNote(note)
|
||||
# and one that's a sibling
|
||||
note = col.newNote()
|
||||
note["Front"] = "three"
|
||||
note.model()["did"] = col.decks.id("foo::baz")
|
||||
note.note_type()["did"] = col.decks.id("foo::baz")
|
||||
col.addNote(note)
|
||||
col.reset()
|
||||
assert len(col.decks.all_names_and_ids()) == 5
|
||||
|
@ -1010,12 +1010,12 @@ def test_deckFlow():
|
|||
# and one that's a child
|
||||
note = col.newNote()
|
||||
note["Front"] = "two"
|
||||
note.model()["did"] = col.decks.id("Default::2")
|
||||
note.note_type()["did"] = col.decks.id("Default::2")
|
||||
col.addNote(note)
|
||||
# and another that's higher up
|
||||
note = col.newNote()
|
||||
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)
|
||||
# should get top level one first, then ::1, then ::2
|
||||
col.reset()
|
||||
|
@ -1040,7 +1040,7 @@ def test_norelearn():
|
|||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.ivl = 100
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
col.sched.answerCard(c, 1)
|
||||
|
@ -1062,7 +1062,7 @@ def test_failmult():
|
|||
c.factor = STARTING_FACTOR
|
||||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
conf = col.sched._cardConf(c)
|
||||
conf["lapse"]["mult"] = 0.5
|
||||
|
|
|
@ -90,7 +90,7 @@ def test_new():
|
|||
# qs = ("2", "3", "2", "3")
|
||||
# for n in range(4):
|
||||
# c = col.sched.getCard()
|
||||
# assert qs[n] in c.q()
|
||||
# assert qs[n] in c.question()
|
||||
# col.sched.answerCard(c, 2)
|
||||
|
||||
|
||||
|
@ -102,7 +102,7 @@ def test_newLimits():
|
|||
note = col.newNote()
|
||||
note["Front"] = str(i)
|
||||
if i > 4:
|
||||
note.model()["did"] = deck2
|
||||
note.note_type()["did"] = deck2
|
||||
col.addNote(note)
|
||||
# give the child deck a different configuration
|
||||
c2 = col.decks.add_config_returning_id("new conf")
|
||||
|
@ -270,17 +270,17 @@ def test_learn_collapsed():
|
|||
col.reset()
|
||||
# should get '1' first
|
||||
c = col.sched.getCard()
|
||||
assert c.q().endswith("1")
|
||||
assert c.question().endswith("1")
|
||||
# pass it so it's due in 10 minutes
|
||||
col.sched.answerCard(c, 3)
|
||||
# get the other card
|
||||
c = col.sched.getCard()
|
||||
assert c.q().endswith("2")
|
||||
assert c.question().endswith("2")
|
||||
# fail it so it's due in 1 minute
|
||||
col.sched.answerCard(c, 1)
|
||||
# we shouldn't get the same card again
|
||||
c = col.sched.getCard()
|
||||
assert not c.q().endswith("2")
|
||||
assert not c.question().endswith("2")
|
||||
|
||||
|
||||
def test_learn_day():
|
||||
|
@ -374,7 +374,7 @@ def test_reviews():
|
|||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.ivl = 100
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
# save it for later use as well
|
||||
cardcopy = copy.copy(c)
|
||||
|
@ -509,7 +509,7 @@ def test_button_spacing():
|
|||
c.due = col.sched.today
|
||||
c.reps = 1
|
||||
c.ivl = 1
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
ni = col.sched.nextIvlStr
|
||||
|
@ -731,7 +731,7 @@ def test_filt_reviewing_early_normal():
|
|||
c.due = col.sched.today + 25
|
||||
c.mod = 1
|
||||
c.factor = STARTING_FACTOR
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
assert col.sched.counts() == (0, 0, 0)
|
||||
|
@ -1082,7 +1082,7 @@ def test_deckDue():
|
|||
# and one that's a child
|
||||
note = col.newNote()
|
||||
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)
|
||||
# make it a review card
|
||||
c = note.cards()[0]
|
||||
|
@ -1092,12 +1092,12 @@ def test_deckDue():
|
|||
# add one more with a new deck
|
||||
note = col.newNote()
|
||||
note["Front"] = "two"
|
||||
note.model()["did"] = col.decks.id("foo::bar")
|
||||
note.note_type()["did"] = col.decks.id("foo::bar")
|
||||
col.addNote(note)
|
||||
# and one that's a sibling
|
||||
note = col.newNote()
|
||||
note["Front"] = "three"
|
||||
note.model()["did"] = col.decks.id("foo::baz")
|
||||
note.note_type()["did"] = col.decks.id("foo::baz")
|
||||
col.addNote(note)
|
||||
col.reset()
|
||||
assert len(col.decks.all_names_and_ids()) == 5
|
||||
|
@ -1138,12 +1138,12 @@ def test_deckFlow():
|
|||
# and one that's a child
|
||||
note = col.newNote()
|
||||
note["Front"] = "two"
|
||||
note.model()["did"] = col.decks.id("Default::2")
|
||||
note.note_type()["did"] = col.decks.id("Default::2")
|
||||
col.addNote(note)
|
||||
# and another that's higher up
|
||||
note = col.newNote()
|
||||
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.reset()
|
||||
assert col.sched.counts() == (3, 0, 0)
|
||||
|
@ -1255,7 +1255,7 @@ def test_norelearn():
|
|||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.ivl = 100
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
col.reset()
|
||||
col.sched.answerCard(c, 1)
|
||||
|
@ -1277,7 +1277,7 @@ def test_failmult():
|
|||
c.factor = STARTING_FACTOR
|
||||
c.reps = 3
|
||||
c.lapses = 1
|
||||
c.startTimer()
|
||||
c.start_timer()
|
||||
c.flush()
|
||||
conf = col.sched._cardConf(c)
|
||||
conf["lapse"]["mult"] = 0.5
|
||||
|
|
|
@ -15,4 +15,4 @@ def test_deferred_frontside():
|
|||
note["Back"] = ""
|
||||
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:
|
||||
old_fields = list(old.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"]
|
||||
# copy identical fields
|
||||
if field_name in old_fields:
|
||||
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
|
||||
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:
|
||||
new.fields[n] = old.fields[n]
|
||||
new.tags = old.tags
|
||||
|
@ -147,7 +147,7 @@ class AddCards(QDialog):
|
|||
def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
|
||||
note = self._new_note()
|
||||
if old_note := sticky_fields_from:
|
||||
flds = note.model()["flds"]
|
||||
flds = note.note_type()["flds"]
|
||||
# copy fields from old note
|
||||
if old_note:
|
||||
for n in range(min(len(note.fields), len(old_note.fields))):
|
||||
|
|
|
@ -187,11 +187,11 @@ class Previewer(QDialog):
|
|||
return
|
||||
|
||||
# need to force reload even if answer
|
||||
txt = c.q(reload=True)
|
||||
txt = c.question(reload=True)
|
||||
|
||||
if self._state == "answer":
|
||||
func = "_showAnswer"
|
||||
txt = c.a()
|
||||
txt = c.answer()
|
||||
txt = re.sub(r"\[\[type:[^]]+\]\]", "", txt)
|
||||
|
||||
bodyclass = theme_manager.body_classes_for_card_ord(c.ord)
|
||||
|
|
|
@ -52,7 +52,7 @@ class CardLayout(QDialog):
|
|||
self.ord = ord
|
||||
self.col = self.mw.col.weakref()
|
||||
self.mm = self.mw.col.models
|
||||
self.model = note.model()
|
||||
self.model = note.note_type()
|
||||
self.templates = self.model["tmpls"]
|
||||
self.fill_empty_action_toggled = fill_empty
|
||||
self.night_mode_is_enabled = self.mw.pm.night_mode()
|
||||
|
@ -493,11 +493,11 @@ class CardLayout(QDialog):
|
|||
)
|
||||
|
||||
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")
|
||||
text = q
|
||||
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")
|
||||
text = a
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
def _onFields(self) -> None:
|
||||
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:
|
||||
self.call_after_note_saved(self._onCardLayout)
|
||||
|
@ -394,7 +394,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
(type, num) = cmd.split(":", 1)
|
||||
ord = int(num)
|
||||
|
||||
model = self.note.model()
|
||||
model = self.note.note_type()
|
||||
fld = model["flds"][ord]
|
||||
new_state = not fld["sticky"]
|
||||
fld["sticky"] = new_state
|
||||
|
@ -463,7 +463,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
)
|
||||
|
||||
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 = 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]]:
|
||||
return [
|
||||
(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(
|
||||
|
@ -532,7 +532,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
search=(
|
||||
SearchNode(
|
||||
dupe=SearchNode.Dupe(
|
||||
notetype_id=self.note.model()["id"],
|
||||
notetype_id=self.note.note_type()["id"],
|
||||
first_field=self.note.fields[0],
|
||||
)
|
||||
),
|
||||
|
@ -542,7 +542,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
def fieldsAreBlank(self, previousNote: Optional[Note] = None) -> bool:
|
||||
if not self.note:
|
||||
return True
|
||||
m = self.note.model()
|
||||
m = self.note.note_type()
|
||||
for c, f in enumerate(self.note.fields):
|
||||
f = f.replace("<br>", "").strip()
|
||||
notChangedvalues = {"", "<br>"}
|
||||
|
@ -681,7 +681,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
|
|||
|
||||
def _onCloze(self) -> None:
|
||||
# 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:
|
||||
tooltip(tr.editing_warning_cloze_deletions_will_not_work())
|
||||
else:
|
||||
|
@ -1280,7 +1280,7 @@ gui_hooks.editor_will_munge_html.append(reverse_url_quoting)
|
|||
|
||||
|
||||
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(
|
||||
'$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)
|
||||
|
||||
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.showMapping()
|
||||
|
||||
|
@ -191,9 +191,9 @@ class ImportDialog(QDialog):
|
|||
self.importer.tagModified = self.frm.tagModified.text()
|
||||
self.mw.pm.profile["tagModified"] = self.importer.tagModified
|
||||
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.checkpoint(tr.actions_import())
|
||||
|
||||
|
@ -273,7 +273,7 @@ class ImportDialog(QDialog):
|
|||
qconnect(button.clicked, lambda _, s=self, n=num: s.changeMappingNum(n))
|
||||
|
||||
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:
|
||||
# make sure we don't have it twice
|
||||
index = self.mapping.index(f)
|
||||
|
|
|
@ -218,7 +218,7 @@ class Reviewer:
|
|||
if self.cardQueue:
|
||||
# undone/edited cards to show
|
||||
card = self.cardQueue.pop()
|
||||
card.startTimer()
|
||||
card.start_timer()
|
||||
self.hadCardQueue = True
|
||||
else:
|
||||
if self.hadCardQueue:
|
||||
|
@ -236,7 +236,7 @@ class Reviewer:
|
|||
return
|
||||
self._v3 = V3CardInfo.from_queue(output)
|
||||
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]:
|
||||
if v3 := self._v3:
|
||||
|
@ -320,7 +320,7 @@ class Reviewer:
|
|||
self.typedAnswer: str = None
|
||||
c = self.card
|
||||
# grab the question and play audio
|
||||
q = c.q()
|
||||
q = c.question()
|
||||
# play audio?
|
||||
if c.autoplay():
|
||||
AnkiWebView.setPlaybackRequiresGesture(False)
|
||||
|
@ -370,7 +370,7 @@ class Reviewer:
|
|||
return
|
||||
self.state = "answer"
|
||||
c = self.card
|
||||
a = c.a()
|
||||
a = c.answer()
|
||||
# play audio?
|
||||
if c.autoplay():
|
||||
sounds = c.answer_av_tags()
|
||||
|
@ -535,7 +535,7 @@ class Reviewer:
|
|||
clozeIdx = self.card.ord + 1
|
||||
fld = fld.split(":")[1]
|
||||
# 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:
|
||||
self.typeCorrect = self.card.note()[f["name"]]
|
||||
if clozeIdx:
|
||||
|
@ -733,7 +733,7 @@ time = %(time)d;
|
|||
editkey=tr.actions_shortcut_key(val="E"),
|
||||
more=tr.studying_more(),
|
||||
downArrow=downArrow(),
|
||||
time=self.card.timeTaken() // 1000,
|
||||
time=self.card.time_taken() // 1000,
|
||||
)
|
||||
|
||||
def _showAnswerButton(self) -> None:
|
||||
|
@ -749,8 +749,8 @@ time = %(time)d;
|
|||
"<table cellpadding=0><tr><td class=stat2 align=center>%s</td></tr></table>"
|
||||
% middle
|
||||
)
|
||||
if self.card.shouldShowTimer():
|
||||
maxTime = self.card.timeLimit() / 1000
|
||||
if self.card.should_show_timer():
|
||||
maxTime = self.card.time_limit() / 1000
|
||||
else:
|
||||
maxTime = 0
|
||||
self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime))
|
||||
|
|
|
@ -7,7 +7,7 @@ mod learning;
|
|||
mod main;
|
||||
pub(crate) mod undo;
|
||||
|
||||
use std::{collections::VecDeque, time::Instant};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub(crate) use builder::{DueCard, NewCard};
|
||||
pub(crate) use entry::{QueueEntry, QueueEntryKind};
|
||||
|
@ -205,9 +205,7 @@ impl Collection {
|
|||
self.discard_undo_and_study_queues();
|
||||
}
|
||||
if self.state.card_queues.is_none() {
|
||||
let now = Instant::now();
|
||||
self.state.card_queues = Some(self.build_queues(deck)?);
|
||||
println!("queue build in {:?}", now.elapsed());
|
||||
}
|
||||
|
||||
Ok(self.state.card_queues.as_mut().unwrap())
|
||||
|
|
Loading…
Reference in a new issue