move group code into a registry like models

This commit is contained in:
Damien Elmes 2011-08-27 23:45:55 +09:00
parent d3a3edb707
commit 78600e8ed6
7 changed files with 89 additions and 65 deletions

View file

@ -11,12 +11,12 @@ from anki.hooks import runHook, runFilter
from anki.sched import Scheduler from anki.sched import Scheduler
from anki.models import ModelRegistry from anki.models import ModelRegistry
from anki.media import MediaRegistry from anki.media import MediaRegistry
from anki.groups import GroupRegistry
from anki.consts import * from anki.consts import *
from anki.errors import AnkiError from anki.errors import AnkiError
import anki.latex # sets up hook import anki.latex # sets up hook
import anki.cards, anki.facts, anki.template, anki.cram, \ import anki.cards, anki.facts, anki.template, anki.cram, anki.find
anki.groups, anki.find
# Settings related to queue building. These may be loaded without the rest of # Settings related to queue building. These may be loaded without the rest of
# the config to check due counts faster on mobile clients. # the config to check due counts faster on mobile clients.
@ -54,6 +54,7 @@ class _Deck(object):
self.clearUndo() self.clearUndo()
self.media = MediaRegistry(self) self.media = MediaRegistry(self)
self.models = ModelRegistry(self) self.models = ModelRegistry(self)
self.groups = GroupRegistry(self)
self.load() self.load()
if not self.crt: if not self.crt:
d = datetime.datetime.today() d = datetime.datetime.today()
@ -88,15 +89,14 @@ class _Deck(object):
self.qconf, self.qconf,
self.conf, self.conf,
models, models,
self.groups, groups,
self.gconf) = self.db.first(""" gconf) = self.db.first("""
select crt, mod, scm, dty, syncName, lastSync, select crt, mod, scm, dty, syncName, lastSync,
qconf, conf, models, groups, gconf from deck""") qconf, conf, models, groups, gconf from deck""")
self.qconf = simplejson.loads(self.qconf) self.qconf = simplejson.loads(self.qconf)
self.conf = simplejson.loads(self.conf) self.conf = simplejson.loads(self.conf)
self.groups = simplejson.loads(self.groups)
self.gconf = simplejson.loads(self.gconf)
self.models.load(models) self.models.load(models)
self.groups.load(groups, gconf)
def flush(self, mod=None): def flush(self, mod=None):
"Flush state to DB, updating mod time." "Flush state to DB, updating mod time."
@ -104,14 +104,13 @@ qconf, conf, models, groups, gconf from deck""")
self.db.execute( self.db.execute(
"""update deck set """update deck set
crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?, crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?,
qconf=?, conf=?, groups=?, gconf=?""", qconf=?, conf=?""",
self.crt, self.mod, self.scm, self.dty, self.crt, self.mod, self.scm, self.dty,
self.syncName, self.lastSync, self.syncName, self.lastSync,
simplejson.dumps(self.qconf), simplejson.dumps(self.qconf),
simplejson.dumps(self.conf), simplejson.dumps(self.conf))
simplejson.dumps(self.groups),
simplejson.dumps(self.gconf))
self.models.flush() self.models.flush()
self.groups.flush()
def save(self, name=None, mod=None): def save(self, name=None, mod=None):
"Flush, commit DB, and take out another write lock." "Flush, commit DB, and take out another write lock."
@ -420,7 +419,7 @@ select id from facts where id in %s and id not in (select fid from cards)""" %
fields[name] = "" fields[name] = ""
fields['Tags'] = data[5] fields['Tags'] = data[5]
fields['Model'] = model['name'] fields['Model'] = model['name']
fields['Group'] = self.groupName(data[3]) fields['Group'] = self.groups.name(data[3])
template = model['tmpls'][data[4]] template = model['tmpls'][data[4]]
fields['Template'] = template['name'] fields['Template'] = template['name']
# render q & a # render q & a
@ -504,43 +503,6 @@ update facts set tags = :t, mod = :n where id = :id""", [fix(row) for row in res
def delTags(self, ids, tags): def delTags(self, ids, tags):
self.addTags(ids, tags, False) self.addTags(ids, tags, False)
# Groups
##########################################################################
# the id keys are strings because that's the way they're stored in json,
# but the anki code passes around integers
def groupID(self, name, create=True):
"Add a group with NAME. Reuse group if already exists. Return id."
for id, g in self.groups.items():
if g['name'].lower() == name.lower():
return int(id)
if not create:
return None
g = dict(name=name, conf=1, mod=intTime())
while 1:
id = intTime(1000)
if str(id) in self.groups:
continue
self.groups[str(id)] = g
return id
def groupName(self, gid):
return self.groups[str(gid)]['name']
def groupConf(self, gid):
return self.gconf[str(self.groups[str(gid)]['conf'])]
def delGroup(self, gid):
self.modSchema()
self.db.execute("update cards set gid = 1 where gid = ?", gid)
self.db.execute("update facts set gid = 1 where gid = ?", gid)
self.db.execute("delete from groups where id = ?", gid)
print "fixme: loop through models and update stale gid references"
def setGroup(self, cids, gid):
self.db.execute(
"update cards set gid = ? where id in "+ids2str(cids), gid)
# Tag-based selective study # Tag-based selective study
########################################################################## ##########################################################################

View file

@ -192,8 +192,8 @@ order by %s""" % (lim, sort)
def _findGroup(self, val, isNeg): def _findGroup(self, val, isNeg):
extra = "!" if isNeg else "" extra = "!" if isNeg else ""
id = self.deck.groupID(val, create=False) or 0 id = self.deck.groups.id(val, create=False) or 0
self.lims['card'].append("c.gid %s= %d" % (extra, id)) self.lims['card'].append("c.gid %s= %s" % (extra, id))
def _findTemplate(self, val, isNeg): def _findTemplate(self, val, isNeg):
lims = [] lims = []

View file

@ -39,3 +39,65 @@ defaultData = {
'activeTags': None, 'activeTags': None,
'inactiveTags': None, 'inactiveTags': None,
} }
class GroupRegistry(object):
# Registry save/load
#############################################################
def __init__(self, deck):
self.deck = deck
def load(self, groups, gconf):
self.groups = simplejson.loads(groups)
self.gconf = simplejson.loads(gconf)
self.changed = False
def save(self, g):
g['mod'] = intTime()
self.changed = True
def flush(self):
if self.changed:
self.deck.db.execute("update deck set groups=?, gconf=?",
simplejson.dumps(self.groups),
simplejson.dumps(self.gconf))
# Group save/load
#############################################################
def id(self, name, create=True):
"Add a group with NAME. Reuse group if already exists. Return id as int."
for id, g in self.groups.items():
if g['name'].lower() == name.lower():
return int(id)
if not create:
return None
g = dict(name=name, conf=1, mod=intTime())
while 1:
id = str(intTime(1000))
if id in self.groups:
continue
self.groups[id] = g
self.save(g)
return int(id)
def del_(self, gid):
self.deck.modSchema()
self.deck.db.execute("update cards set gid = 1 where gid = ?", gid)
self.deck.db.execute("update facts set gid = 1 where gid = ?", gid)
self.deck.db.execute("delete from groups where id = ?", gid)
print "fixme: loop through models and update stale gid references"
# Utils
#############################################################
def name(self, gid):
return self.groups[str(gid)]['name']
def conf(self, gid):
return self.gconf[str(self.groups[str(gid)]['conf'])]
def setGroup(self, cids, gid):
self.db.execute(
"update cards set gid = ? where id in "+ids2str(cids), gid)

View file

@ -154,7 +154,7 @@ from cards group by gid""", self.today):
for (gid, grp) in self._orderedGroups()] for (gid, grp) in self._orderedGroups()]
def _orderedGroups(self): def _orderedGroups(self):
grps = self.deck.groups.items() grps = self.deck.groups.groups.items()
def key(grp): def key(grp):
return grp[1]['name'] return grp[1]['name']
grps.sort(key=key) grps.sort(key=key)
@ -595,7 +595,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
########################################################################## ##########################################################################
def _cardConf(self, card): def _cardConf(self, card):
return self.deck.groupConf(card.gid) return self.deck.groups.conf(card.gid)
def _groupLimit(self): def _groupLimit(self):
l = self.deck.qconf['groups'] l = self.deck.qconf['groups']

View file

@ -49,8 +49,8 @@ class CardStats(object):
self.addLine(_("Position"), c.due) self.addLine(_("Position"), c.due)
self.addLine(_("Model"), c.model()['name']) self.addLine(_("Model"), c.model()['name'])
self.addLine(_("Template"), c.template()['name']) self.addLine(_("Template"), c.template()['name'])
self.addLine(_("Current Group"), self.deck.groupName(c.gid)) self.addLine(_("Current Group"), self.deck.groups.name(c.gid))
self.addLine(_("Initial Group"), self.deck.groupName(c.fact().gid)) self.addLine(_("Home Group"), self.deck.groups.name(c.fact().gid))
self.txt += "</table>" self.txt += "</table>"
return self.txt return self.txt

View file

@ -133,15 +133,15 @@ def test_upgrade():
def test_groups(): def test_groups():
deck = getEmptyDeck() deck = getEmptyDeck()
# we start with a standard group # we start with a standard group
assert len(deck.groups) == 1 assert len(deck.groups.groups) == 1
# it should have an id of 1 # it should have an id of 1
assert deck.groups['1'] assert deck.groups.name(1)
# create a new group # create a new group
ts = deck.groupID("new group") g = deck.groups.id("new group")
assert ts assert g
assert len(deck.groups) == 2 assert len(deck.groups.groups) == 2
# should get the same id # should get the same id
assert deck.groupID("new group") == ts assert deck.groups.id("new group") == g
# by default, everything should be shown # by default, everything should be shown
assert not deck.qconf['groups'] assert not deck.qconf['groups']

View file

@ -581,7 +581,7 @@ def test_ordcycle():
def test_counts(): def test_counts():
d = getEmptyDeck() d = getEmptyDeck()
# add a second group # add a second group
assert d.groupID("new group") assert d.groups.id("new group")
# for each card type # for each card type
for type in range(3): for type in range(3):
# and each of the groups # and each of the groups
@ -680,7 +680,7 @@ def test_groupCounts():
# and one that's a child # and one that's a child
f = d.newFact() f = d.newFact()
f['Front'] = u"two" f['Front'] = u"two"
default1 = f.gid = d.groupID("Default::1") default1 = f.gid = d.groups.id("Default::1")
d.addFact(f) d.addFact(f)
# make it a review card # make it a review card
c = f.cards()[0] c = f.cards()[0]
@ -690,16 +690,16 @@ def test_groupCounts():
# add one more with a new group # add one more with a new group
f = d.newFact() f = d.newFact()
f['Front'] = u"two" f['Front'] = u"two"
foobar = f.gid = d.groupID("foo::bar") foobar = f.gid = d.groups.id("foo::bar")
d.addFact(f) d.addFact(f)
# and one that's a sibling # and one that's a sibling
f = d.newFact() f = d.newFact()
f['Front'] = u"three" f['Front'] = u"three"
foobaz = f.gid = d.groupID("foo::baz") foobaz = f.gid = d.groups.id("foo::baz")
d.addFact(f) d.addFact(f)
d.reset() d.reset()
assert d.sched.counts() == (3, 0, 1) assert d.sched.counts() == (3, 0, 1)
assert len(d.groups) == 4 assert len(d.groups.groups) == 4
cnts = d.sched.groupCounts() cnts = d.sched.groupCounts()
assert cnts[0] == ["Default", 1, 1, 0, 1] assert cnts[0] == ["Default", 1, 1, 0, 1]
assert cnts[1] == ["Default::1", default1, 1, 1, 0] assert cnts[1] == ["Default::1", default1, 1, 1, 0]