more robust anki1 upgrading & anki2 importing

- base the 2.0 model id on the 1.2 one so we don't get new models each time we
  reimport the file
- when determining if we can reuse an existing note, it must have the same
  model id, and the model must have the same schema
- make sure we check templates when determining schema
- if schema has diverged, note needs new guid
This commit is contained in:
Damien Elmes 2012-10-27 20:55:08 +09:00
parent 6830ca99d9
commit bd1c6d4395
6 changed files with 47 additions and 9 deletions

View file

@ -4,7 +4,7 @@
import os
from anki import Collection
from anki.utils import intTime, splitFields, joinFields, checksum
from anki.utils import intTime, splitFields, joinFields, checksum, guid64
from anki.importing.base import Importer
from anki.lang import _
from anki.lang import ngettext
@ -96,8 +96,24 @@ class Anki2Importer(Importer):
# turn the db result into a mutable list
note = list(note)
guid, mid = note[1:3]
# missing from local col?
if guid not in self._notes:
duplicate = False
guidChange = False
# do we have the same guid?
if guid in self._notes:
# and do they share the same model id?
if self._notes[guid][2] == mid:
# and do they share the same schema?
srcM = self.src.models.get(mid)
dstM = self.dst.models.get(self._notes[guid][2])
if (self.src.models.scmhash(srcM) ==
self.src.models.scmhash(dstM)):
# then it's safe to treat as a duplicate
duplicate = True
if not duplicate:
# not identical models, so we need to change guid
guidChange = True
# missing from local col or divergent model?
if not duplicate:
# get corresponding local model
lmid = self._mid(mid)
# ensure id is unique
@ -111,11 +127,14 @@ class Anki2Importer(Importer):
note[6] = self._mungeMedia(mid, note[6])
add.append(note)
dirty.append(note[0])
# if it was originally the same as a note in this deck but the
# models have diverged, we need to change the guid
if guidChange:
guid = guid64()
# note we have the added note
self._notes[guid] = (note[0], note[3], note[2])
else:
dupes += 1
pass
## update existing note - not yet tested; for post 2.0
# newer = note[3] > mod
# if self.allowUpdate and self._mid(mid) == mid and newer:

View file

@ -452,6 +452,8 @@ select id from notes where mid = ?)""" % " ".join(map),
s = ""
for f in m['flds']:
s += f['name']
for t in m['tmpls']:
s += t['name']
return fieldChecksum(s)
# Required field/text cache

View file

@ -341,11 +341,8 @@ insert or replace into col select id, cast(created as int), :t,
mods = {}
for row in db.all(
"select id, name from models"):
while 1:
t = intTime(1000)
if t not in times:
times[t] = True
break
# use only first 31 bits
t = abs(row[0]) >> 32
m = anki.models.defaultModel.copy()
m['id'] = t
m['name'] = row[1]

Binary file not shown.

Binary file not shown.

View file

@ -138,6 +138,26 @@ def test_anki1():
imp.run()
check()
def test_anki1_diffmodels():
# create a new empty deck
dst = getEmptyDeck()
# import the 1 card version of the model
tmp = getUpgradeDeckPath("diffmodels1.anki")
imp = Anki1Importer(dst, tmp)
imp.run()
before = dst.noteCount()
# repeating the process should do nothing
imp = Anki1Importer(dst, tmp)
imp.run()
assert before == dst.noteCount()
# then the 2 card version
tmp = getUpgradeDeckPath("diffmodels2.anki")
imp = Anki1Importer(dst, tmp)
imp.run()
after = dst.noteCount()
# as the model schemas differ, should have been imported as new model
assert after == before + 1
def test_csv():
deck = getEmptyDeck()
file = unicode(os.path.join(testDir, "support/text-2fields.txt"))