diff --git a/genanki/__init__.py b/genanki/__init__.py index 0f61df3..063cc0d 100644 --- a/genanki/__init__.py +++ b/genanki/__init__.py @@ -6,6 +6,7 @@ from .model import Model from .note import Note from .package import Package +from .deck_conf import DeckConf from .util import guid_for diff --git a/genanki/deck.py b/genanki/deck.py index 5e93a98..50d4715 100644 --- a/genanki/deck.py +++ b/genanki/deck.py @@ -1,10 +1,11 @@ import json class Deck: - def __init__(self, deck_id=None, name=None, description=''): + def __init__(self, deck_id=None, name=None, description='', conf=None): self.deck_id = deck_id self.name = name self.description = description + self.conf = conf self.notes = [] self.models = {} # map of model id to model @@ -15,9 +16,10 @@ def add_model(self, model): self.models[model.model_id] = model def to_json(self): + conf = 1 if self.conf is None else self.conf.deck_conf_id return { "collapsed": False, - "conf": 1, + "conf": conf, "desc": self.description, "dyn": 0, "extendNew": 0, @@ -55,6 +57,9 @@ def write_to_db(self, cursor, timestamp: float, id_gen): decks.update({str(self.deck_id): self.to_json()}) cursor.execute('UPDATE col SET decks = ?', (json.dumps(decks),)) + if self.conf is not None: + self.conf.write_to_db(cursor, timestamp) + models_json_str, = cursor.execute('SELECT models from col').fetchone() models = json.loads(models_json_str) for note in self.notes: diff --git a/genanki/deck_conf.py b/genanki/deck_conf.py new file mode 100644 index 0000000..9e3df96 --- /dev/null +++ b/genanki/deck_conf.py @@ -0,0 +1,68 @@ + +import copy +import json + + +DEFAULT_CONF = { + "autoplay": True, + "id": 1, + "lapse": { + "delays": [ + 10 + ], + "leechAction": 0, + "leechFails": 8, + "minInt": 1, + "mult": 0 + }, + "maxTaken": 60, + "mod": 0, + "name": "Default", + "new": { + "bury": True, + "delays": [ + 1, + 10 + ], + "initialFactor": 2500, + "ints": [ + 1, + 4, + 7 + ], + "order": 1, + "perDay": 20, + "separate": True + }, + "replayq": True, + "rev": { + "bury": True, + "ease4": 1.3, + "fuzz": 0.05, + "ivlFct": 1, + "maxIvl": 36500, + "minSpace": 1, + "perDay": 100 + }, + "timer": 0, + "usn": 0 +} + + +class DeckConf: + def __init__(self, deck_conf_id, name, conf=None): + self.deck_conf_id = deck_conf_id + self.name = name + conf = copy.deepcopy(DEFAULT_CONF) if conf is None else conf + conf["name"] = self.name + conf["id"] = self.deck_conf_id + self.conf = conf + + def to_json(self): + return self.conf + + def write_to_db(self, cursor, timestamp): + conf_json_str, = cursor.execute('SELECT dconf FROM col').fetchone() + confs = json.loads(conf_json_str) + confs.update({str(self.deck_conf_id): self.to_json()}) + cursor.execute('UPDATE col SET dconf = ?', (json.dumps(confs),)) diff --git a/tests/test_genanki.py b/tests/test_genanki.py index b0ab1d0..c161cdc 100644 --- a/tests/test_genanki.py +++ b/tests/test_genanki.py @@ -447,3 +447,44 @@ def test_notes_with_due2(self): # Next card changes to "Capital of Oregon", because it has lower # due value. assert next_note.fields == ['Capital of Oregon', 'Salem'] + + def test_deck_with_config(self): + conf = genanki.DeckConf(666, 'MyConf') + # Changing default initialFactor from 2500 to 4500 + conf.conf['new']['initialFactor'] = 4500 + deck = genanki.Deck(112233, 'foodeck', conf=conf) + # The Anki importer need at least one card to import the config. + # See related discussion: + # https://anki.tenderapp.com/discussions/ankidesktop/38114-importing-apkg-does-not-update-deck-config-fields + note = genanki.Note(TEST_MODEL, ['a', 'b']) + deck.add_note(note) + + self.import_package(genanki.Package(deck)) + + all_confs = self.col.decks.allConf() + assert len(all_confs) == 2 # default conf and MyConf + imported_deck = all_confs[1] + + assert imported_deck['new']['initialFactor'] == 4500 + + def test_deck_with_2_config(self): + conf = genanki.DeckConf(666, 'MyConf') + conf.conf['new']['initialFactor'] = 4500 + deck = genanki.Deck(112233, 'foodeck', conf=conf) + note = genanki.Note(TEST_MODEL, ['a', 'b']) + deck.add_note(note) + + self.import_package(genanki.Package(deck)) + conf = genanki.DeckConf(6666, 'MyConf2') + conf.conf['new']['initialFactor'] = 5500 + deck = genanki.Deck(11223344, 'boodeck', conf=conf) + note = genanki.Note(TEST_MODEL, ['a', 'b']) + deck.add_note(note) + + self.import_package(genanki.Package(deck)) + + all_confs = self.col.decks.allConf() + assert len(all_confs) == 2 # default conf and MyConf + imported_deck = all_confs[1] + + assert imported_deck['new']['initialFactor'] == 4500