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 _
from anki.lang import ngettext from anki.lang import ngettext
MID = 2
GUID = 1 GUID = 1
MID = 2
MOD = 3
class Anki2Importer(Importer): class Anki2Importer(Importer):
@ -63,6 +64,7 @@ class Anki2Importer(Importer):
self._changedGuids = {} self._changedGuids = {}
# iterate over source collection # iterate over source collection
add = [] add = []
update = []
dirty = [] dirty = []
usn = self.dst.usn() usn = self.dst.usn()
dupes = 0 dupes = 0
@ -85,22 +87,35 @@ class Anki2Importer(Importer):
# note we have the added the guid # note we have the added the guid
self._notes[note[GUID]] = (note[0], note[3], note[MID]) self._notes[note[GUID]] = (note[0], note[3], note[MID])
else: else:
# a duplicate or changed schema - safe to update?
dupes += 1 dupes += 1
## update existing note - not yet tested; for post 2.0 if self.allowUpdate and note[GUID] in self._notes:
# newer = note[3] > mod oldNid, oldMod, oldMid = self._notes[note[GUID]]
# if self.allowUpdate and self._mid(mid) == mid and newer: # safe if note types identical
# localNid = self._notes[guid][0] if oldMid == note[MID]:
# note[0] = localNid # will update if incoming note more recent
# note[4] = usn if oldMod < note[MOD]:
# add.append(note) # incoming note should use existing id
# dirty.append(note[0]) note[0] = oldNid
note[4] = usn
note[6] = self._mungeMedia(note[MID], note[6])
update.append(note)
dirty.append(note[0])
if dupes: if dupes:
self.log.append(_("Already in collection: %s.") % (ngettext( up = len(update)
"%d note", "%d notes", dupes) % dupes)) 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 # add to col
self.dst.db.executemany( self.dst.db.executemany(
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)", "insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
add) add)
self.dst.db.executemany(
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
update)
self.dst.updateFieldCache(dirty) self.dst.updateFieldCache(dirty)
self.dst.tags.registerNotes(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 after == before + 1
assert beforeModels == len(dst.models.all()) assert beforeModels == len(dst.models.all())
def test_suspended(): def test_suspended():
# create a new empty deck # create a new empty deck
dst = getEmptyDeck() dst = getEmptyDeck()
@ -205,6 +204,33 @@ def test_anki2_diffmodels():
assert after == before + 1 assert after == before + 1
assert dst.cardCount() == 3 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(): def test_csv():
deck = getEmptyDeck() deck = getEmptyDeck()
file = unicode(os.path.join(testDir, "support/text-2fields.txt")) file = unicode(os.path.join(testDir, "support/text-2fields.txt"))