mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
allow updates to existing notes in .apkg import
This commit is contained in:
parent
f6c19ca0b4
commit
914f56dbc0
4 changed files with 53 additions and 12 deletions
|
@ -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
BIN
tests/support/update1.apkg
Normal file
Binary file not shown.
BIN
tests/support/update2.apkg
Normal file
BIN
tests/support/update2.apkg
Normal file
Binary file not shown.
|
@ -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"))
|
||||||
|
|
Loading…
Reference in a new issue