allow updates to existing notes in .apkg import

This commit is contained in:
Damien Elmes 2013-08-08 13:01:47 +09:00
parent f6c19ca0b4
commit 914f56dbc0
4 changed files with 53 additions and 12 deletions

View File

@ -9,8 +9,9 @@ from anki.importing.base import Importer
from anki.lang import _
from anki.lang import ngettext
MID = 2
GUID = 1
MID = 2
MOD = 3
class Anki2Importer(Importer):
@ -63,6 +64,7 @@ class Anki2Importer(Importer):
self._changedGuids = {}
# iterate over source collection
add = []
update = []
dirty = []
usn = self.dst.usn()
dupes = 0
@ -85,22 +87,35 @@ class Anki2Importer(Importer):
# note we have the added the guid
self._notes[note[GUID]] = (note[0], note[3], note[MID])
else:
# a duplicate or changed schema - safe to update?
dupes += 1
## update existing note - not yet tested; for post 2.0
# newer = note[3] > mod
# if self.allowUpdate and self._mid(mid) == mid and newer:
# localNid = self._notes[guid][0]
# note[0] = localNid
# note[4] = usn
# add.append(note)
# dirty.append(note[0])
if self.allowUpdate and note[GUID] in self._notes:
oldNid, oldMod, oldMid = self._notes[note[GUID]]
# safe if note types identical
if oldMid == note[MID]:
# will update if incoming note more recent
if oldMod < note[MOD]:
# incoming note should use existing id
note[0] = oldNid
note[4] = usn
note[6] = self._mungeMedia(note[MID], note[6])
update.append(note)
dirty.append(note[0])
if dupes:
self.log.append(_("Already in collection: %s.") % (ngettext(
"%d note", "%d notes", dupes) % dupes))
up = len(update)
self.log.append(_("Updated %(a)d of %(b)d existing notes.") % dict(
a=len(update), b=dupes))
# export info for calling code
self.dupes = dupes
self.added = len(add)
self.updated = len(update)
# add to col
self.dst.db.executemany(
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
add)
self.dst.db.executemany(
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
update)
self.dst.updateFieldCache(dirty)
self.dst.tags.registerNotes(dirty)

BIN
tests/support/update1.apkg Normal file

Binary file not shown.

BIN
tests/support/update2.apkg Normal file

Binary file not shown.

View File

@ -163,7 +163,6 @@ def test_anki1_diffmodels():
assert after == before + 1
assert beforeModels == len(dst.models.all())
def test_suspended():
# create a new empty deck
dst = getEmptyDeck()
@ -205,6 +204,33 @@ def test_anki2_diffmodels():
assert after == before + 1
assert dst.cardCount() == 3
def test_anki2_updates():
# create a new empty deck
dst = getEmptyDeck()
tmp = getUpgradeDeckPath("update1.apkg")
imp = AnkiPackageImporter(dst, tmp)
imp.run()
assert imp.dupes == 0
assert imp.added == 1
assert imp.updated == 0
# importing again should be idempotent
imp = AnkiPackageImporter(dst, tmp)
imp.run()
assert imp.dupes == 1
assert imp.added == 0
assert imp.updated == 0
# importing a newer note should update
assert dst.noteCount() == 1
assert dst.db.scalar("select flds from notes").startswith("hello")
tmp = getUpgradeDeckPath("update2.apkg")
imp = AnkiPackageImporter(dst, tmp)
imp.run()
assert imp.dupes == 1
assert imp.added == 0
assert imp.updated == 1
assert dst.noteCount() == 1
assert dst.db.scalar("select flds from notes").startswith("goodbye")
def test_csv():
deck = getEmptyDeck()
file = unicode(os.path.join(testDir, "support/text-2fields.txt"))