diff --git a/anki/facts.py b/anki/facts.py index 8f7a93abf..4232cac73 100644 --- a/anki/facts.py +++ b/anki/facts.py @@ -45,6 +45,8 @@ from facts where id = ?""", self.id) self._fmap = self.deck.models.fieldMap(self._model) def flush(self, mod=None): + if self.model()['cloze']: + self._clozeFlush() self.mod = mod if mod else intTime() self.usn = self.deck.usn() sfld = stripHTML(self.fields[self.deck.models.sortIdx(self._model)]) @@ -177,3 +179,25 @@ insert or replace into facts values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", else: d.append((ord, None)) return [x[1] for x in sorted(d)] + + # Flushing cloze facts + ################################################## + + def _clozeFlush(self): + tmpls = self.deck.findTemplates(self) + ok = [] + for t in tmpls: + ok.append(t['ord']) + # check if there are cards referencing a deleted cloze + if self.deck.db.scalar( + "select 1 from cards where fid = ? and ord not in %s" % + ids2str(ok), self.id): + # there are; abort, as the UI should have handled this + raise Exception("UI should have deleted cloze") + # generate missing cards + # for t in tmpls: + # if not self.deck.db.scalar( + # "select 1 from cards where fid = ? and ord = ?", + # self.id, t['ord']): + # add.append(t) + # have = self.deck.db.scalar( diff --git a/anki/models.py b/anki/models.py index 32c79eb44..40e144bbe 100644 --- a/anki/models.py +++ b/anki/models.py @@ -437,10 +437,14 @@ select id from facts where mid = ?)""" % " ".join(map), def _updateRequired(self, m): req = [] flds = [f['name'] for f in m['flds']] + cloze = False for t in m['tmpls']: ret = self._reqForTemplate(m, flds, t) + if ret[1]: + cloze = True req.append((t['ord'], ret[0], ret[1])) m['req'] = req + m['cloze'] = cloze def _reqForTemplate(self, m, flds, t): a = [] diff --git a/tests/test_models.py b/tests/test_models.py index ab19b4ad0..a3412589f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,6 +1,6 @@ # coding: utf-8 -from tests.shared import getEmptyDeck +from tests.shared import getEmptyDeck, assertException from anki.utils import stripHTML def test_modelDelete(): @@ -164,6 +164,11 @@ def test_cloze(): assert d.addFact(f) == 0 f['Text'] = "hello {{c1::foo}}" assert d.addFact(f) == 1 + # deleting a cloze should fail; the ui should clean up invalid cards + f['Text'] = "hello" + assertException(Exception, lambda: f.flush()) + + def test_modelChange(): deck = getEmptyDeck()