forked from ankitects/anki
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_importing.py
209 lines (198 loc) · 6.92 KB
/
test_importing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# coding: utf-8
import os
from tests.shared import getUpgradeDeckPath, getEmptyCol
from anki.utils import ids2str
from anki.importing import Anki2Importer, TextImporter, \
SupermemoXmlImporter, MnemosyneImporter, AnkiPackageImporter
testDir = os.path.dirname(__file__)
srcNotes=None
srcCards=None
def test_anki2_mediadupes():
tmp = getEmptyCol()
# add a note that references a sound
n = tmp.newNote()
n['Front'] = "[sound:foo.mp3]"
mid = n.model()['id']
tmp.addNote(n)
# add that sound to media folder
with open(os.path.join(tmp.media.dir(), "foo.mp3"), "w") as f:
f.write("foo")
tmp.close()
# it should be imported correctly into an empty deck
empty = getEmptyCol()
imp = Anki2Importer(empty, tmp.path)
imp.run()
assert os.listdir(empty.media.dir()) == ["foo.mp3"]
# and importing again will not duplicate, as the file content matches
empty.remCards(empty.db.list("select id from cards"))
imp = Anki2Importer(empty, tmp.path)
imp.run()
assert os.listdir(empty.media.dir()) == ["foo.mp3"]
n = empty.getNote(empty.db.scalar("select id from notes"))
assert "foo.mp3" in n.fields[0]
# if the local file content is different, and import should trigger a
# rename
empty.remCards(empty.db.list("select id from cards"))
with open(os.path.join(empty.media.dir(), "foo.mp3"), "w") as f:
f.write("bar")
imp = Anki2Importer(empty, tmp.path)
imp.run()
assert sorted(os.listdir(empty.media.dir())) == [
"foo.mp3", "foo_%s.mp3" % mid]
n = empty.getNote(empty.db.scalar("select id from notes"))
assert "_" in n.fields[0]
# if the localized media file already exists, we rewrite the note and
# media
empty.remCards(empty.db.list("select id from cards"))
with open(os.path.join(empty.media.dir(), "foo.mp3"), "w") as f:
f.write("bar")
imp = Anki2Importer(empty, tmp.path)
imp.run()
assert sorted(os.listdir(empty.media.dir())) == [
"foo.mp3", "foo_%s.mp3" % mid]
assert sorted(os.listdir(empty.media.dir())) == [
"foo.mp3", "foo_%s.mp3" % mid]
n = empty.getNote(empty.db.scalar("select id from notes"))
assert "_" in n.fields[0]
def test_apkg():
tmp = getEmptyCol()
apkg = str(os.path.join(testDir, "support/media.apkg"))
imp = AnkiPackageImporter(tmp, apkg)
assert os.listdir(tmp.media.dir()) == []
imp.run()
assert os.listdir(tmp.media.dir()) == ['foo.wav']
# importing again should be idempotent in terms of media
tmp.remCards(tmp.db.list("select id from cards"))
imp = AnkiPackageImporter(tmp, apkg)
imp.run()
assert os.listdir(tmp.media.dir()) == ['foo.wav']
# but if the local file has different data, it will rename
tmp.remCards(tmp.db.list("select id from cards"))
with open(os.path.join(tmp.media.dir(), "foo.wav"), "w") as f:
f.write("xyz")
imp = AnkiPackageImporter(tmp, apkg)
imp.run()
assert len(os.listdir(tmp.media.dir())) == 2
def test_anki2_diffmodel_templates():
# different from the above as this one tests only the template text being
# changed, not the number of cards/fields
dst = getEmptyCol()
# import the first version of the model
tmp = getUpgradeDeckPath("diffmodeltemplates-1.apkg")
imp = AnkiPackageImporter(dst, tmp)
imp.dupeOnSchemaChange = True
imp.run()
# then the version with updated template
tmp = getUpgradeDeckPath("diffmodeltemplates-2.apkg")
imp = AnkiPackageImporter(dst, tmp)
imp.dupeOnSchemaChange = True
imp.run()
# collection should contain the note we imported
assert(dst.noteCount() == 1)
# the front template should contain the text added in the 2nd package
tcid = dst.findCards("")[0] # only 1 note in collection
tnote = dst.getCard(tcid).note()
assert("Changed Front Template" in dst.findTemplates(tnote)[0]['qfmt'])
def test_anki2_updates():
# create a new empty deck
dst = getEmptyCol()
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():
deck = getEmptyCol()
file = str(os.path.join(testDir, "support/text-2fields.txt"))
i = TextImporter(deck, file)
i.initMapping()
i.run()
# four problems - too many & too few fields, a missing front, and a
# duplicate entry
assert len(i.log) == 5
assert i.total == 5
# if we run the import again, it should update instead
i.run()
assert len(i.log) == 10
assert i.total == 5
# but importing should not clobber tags if they're unmapped
n = deck.getNote(deck.db.scalar("select id from notes"))
n.addTag("test")
n.flush()
i.run()
n.load()
assert n.tags == ['test']
# if add-only mode, count will be 0
i.importMode = 1
i.run()
assert i.total == 0
# and if dupes mode, will reimport everything
assert deck.cardCount() == 5
i.importMode = 2
i.run()
# includes repeated field
assert i.total == 6
assert deck.cardCount() == 11
deck.close()
def test_csv2():
deck = getEmptyCol()
mm = deck.models
m = mm.current()
f = mm.newField("Three")
mm.addField(m, f)
mm.save(m)
n = deck.newNote()
n['Front'] = "1"
n['Back'] = "2"
n['Three'] = "3"
deck.addNote(n)
# an update with unmapped fields should not clobber those fields
file = str(os.path.join(testDir, "support/text-update.txt"))
i = TextImporter(deck, file)
i.initMapping()
i.run()
n.load()
assert n['Front'] == "1"
assert n['Back'] == "x"
assert n['Three'] == "3"
deck.close()
def test_supermemo_xml_01_unicode():
deck = getEmptyCol()
file = str(os.path.join(testDir, "support/supermemo1.xml"))
i = SupermemoXmlImporter(deck, file)
#i.META.logToStdOutput = True
i.run()
assert i.total == 1
cid = deck.db.scalar("select id from cards")
c = deck.getCard(cid)
# Applies A Factor-to-E Factor conversion
assert c.factor == 2879
assert c.reps == 7
deck.close()
def test_mnemo():
deck = getEmptyCol()
file = str(os.path.join(testDir, "support/mnemo.db"))
i = MnemosyneImporter(deck, file)
i.run()
assert deck.cardCount() == 7
assert "a_longer_tag" in deck.tags.all()
assert deck.db.scalar("select count() from cards where type = 0") == 1
deck.close()