refactor model copying

This commit is contained in:
Damien Elmes 2011-10-31 09:24:06 +09:00
parent b1bf50c677
commit cbdb283b20
3 changed files with 51 additions and 34 deletions

View file

@ -22,10 +22,10 @@ class Anki2Importer(Importer):
needMapper = False needMapper = False
groupPrefix = None groupPrefix = None
needCards = True needCards = True
flagModels = False
def run(self, media=None): def run(self, media=None):
self.dst = self.deck self._prepareDecks()
self.src = Deck(self.file, queue=False)
if media is not None: if media is not None:
# Anki1 importer has provided us with a custom media folder # Anki1 importer has provided us with a custom media folder
self.src.media._dir = media self.src.media._dir = media
@ -34,6 +34,10 @@ class Anki2Importer(Importer):
finally: finally:
self.src.close(save=False) self.src.close(save=False)
def _prepareDecks(self):
self.dst = self.deck
self.src = Deck(self.file, queue=False)
def _import(self): def _import(self):
self._groups = {} self._groups = {}
self._prepareTS() self._prepareTS()
@ -91,34 +95,44 @@ class Anki2Importer(Importer):
def _prepareModels(self): def _prepareModels(self):
"Prepare index of schema hashes." "Prepare index of schema hashes."
self._srcModels = {} self._modelMap = {}
self._dstModels = {}
self._dstHashes = {}
for m in self.dst.models.all():
h = self.dst.models.scmhash(m)
mid = int(m['id'])
self._dstHashes[h] = mid
self._dstModels[mid] = h
for m in self.src.models.all():
mid = int(m['id'])
self._srcModels[mid] = self.src.models.scmhash(m)
def _mid(self, mid): def _mid(self, mid):
"Return local id for remote MID." "Return local id for remote MID."
hash = self._srcModels[mid] # already processed this mid?
dmid = self._dstHashes.get(hash) if mid in self._modelMap:
if dmid: return self._modelMap[mid]
# dst deck already has this model src = self.src.models.get(mid).copy()
return dmid if self.flagModels:
# need to add to local and update index src['needWizard'] = True
m = self.dst.models._add(self.src.models.get(mid)) # if it doesn't exist, we'll copy it over, preserving id
# need to save so the css is updated if not self.dst.models.have(mid):
self.dst.models.save(m) self.dst.models.update(src)
h = self.dst.models.scmhash(m) # make sure to bump usn
mid = int(m['id']) self.dst.models.save(src)
self._dstModels[mid] = h self._modelMap[mid] = mid
self._dstHashes[h] = mid return mid
return mid # if it does exist, do the schema match?
dst = self.dst.models.get(mid)
dhash = self.src.models.scmhash(dst)
if self.src.models.scmhash(src) == dhash:
# reuse without modification
self._modelMap[mid] = mid
return mid
# try any alternative versions
vers = src.get("vers")
for v in vers:
m = self.src.models.get(v)
if self.src.models.scmhash(m) == dhash:
# valid alternate found; use that
self._modelMap[mid] = m['id']
return m['id']
# need to add a new alternate version, with new id
self.dst.models._add(src)
if vers:
dst['vers'].append(src['id'])
else:
dst['vers'] = [src['id']]
# Groups # Groups
###################################################################### ######################################################################
@ -158,19 +172,20 @@ class Anki2Importer(Importer):
# loop through src # loop through src
cards = [] cards = []
revlog = [] revlog = []
print "fixme: need to check schema issues in card import"
for card in self.src.db.execute( for card in self.src.db.execute(
"select f.guid, f.mid, c.* from cards c, facts f " "select f.guid, f.mid, c.* from cards c, facts f "
"where c.fid = f.id"): "where c.fid = f.id"):
guid = card[0] guid = card[0]
shash = self._srcModels[card[1]]
# does the card's fact exist in dst deck? # does the card's fact exist in dst deck?
if guid not in self._facts: if guid not in self._facts:
continue continue
dfid = self._facts[guid] dfid = self._facts[guid]
# does the fact share the same schema? # does the fact share the same schema?
mid = self._facts[guid][2] # shash = self._srcModels[card[1]]
if shash != self._dstModels[mid]: # mid = self._facts[guid][2]
continue # if shash != self._dstModels[mid]:
# continue
# does the card already exist in the dst deck? # does the card already exist in the dst deck?
ord = card[5] ord = card[5]
if (guid, ord) in self._cards: if (guid, ord) in self._cards:

View file

@ -31,6 +31,7 @@ defaultModel = {
'latexPost': "\\end{document}", 'latexPost': "\\end{document}",
'mod': 0, 'mod': 0,
'usn': 0, 'usn': 0,
'vers': [],
} }
defaultField = { defaultField = {
@ -166,6 +167,9 @@ select id from cards where fid in (select id from facts where mid = ?)""",
break break
m['id'] = id m['id'] = id
def have(self, id):
return str(id) in self.models
# Tools # Tools
################################################## ##################################################
@ -426,11 +430,8 @@ select id from facts where mid = ?)""" % " ".join(map),
def scmhash(self, m): def scmhash(self, m):
"Return a hash of the schema, to see if models are compatible." "Return a hash of the schema, to see if models are compatible."
s = m['name']
for f in m['flds']: for f in m['flds']:
s += f['name'] s += f['name']
for t in m['tmpls']:
s += t['name']
return fieldChecksum(s) return fieldChecksum(s)
# Required field/text cache # Required field/text cache

View file

@ -46,6 +46,7 @@ def test_anki2():
"select count() from cards where fid not in (select id from facts)") "select count() from cards where fid not in (select id from facts)")
assert not dst.db.scalar( assert not dst.db.scalar(
"select count() from revlog where cid not in (select id from cards)") "select count() from revlog where cid not in (select id from cards)")
assert dst.fixIntegrity().startswith("Database rebuilt")
check() check()
# importing should be idempotent # importing should be idempotent
imp.run() imp.run()