anki/pylib/tests/test_collection.py

195 lines
5.2 KiB
Python
Raw Normal View History

# coding: utf-8
import os
import tempfile
2019-12-24 10:14:48 +01:00
from anki import Collection as aopen
2020-02-16 12:07:40 +01:00
from anki.rsbackend import StringsGroup
from anki.stdmodels import addBasicModel, models
2019-12-24 10:14:48 +01:00
from anki.utils import isWin
2014-06-03 10:38:47 +02:00
from tests.shared import assertException, getEmptyCol
2019-12-25 05:18:34 +01:00
2017-10-05 06:14:56 +02:00
def test_create_open():
(fd, path) = tempfile.mkstemp(suffix=".anki2", prefix="test_attachNew")
try:
os.close(fd)
os.unlink(path)
except OSError:
pass
deck = aopen(path)
# for open()
newPath = deck.path
deck.close()
newMod = deck.mod
del deck
2017-10-05 06:14:56 +02:00
# reopen
deck = aopen(newPath)
assert deck.mod == newMod
deck.close()
# non-writeable dir
2019-12-24 10:14:48 +01:00
if isWin:
dir = "c:\root.anki2"
else:
dir = "/attachroot.anki2"
2019-12-25 05:18:34 +01:00
assertException(Exception, lambda: aopen(dir))
# reuse tmp file from before, test non-writeable file
os.chmod(newPath, 0)
2019-12-25 05:18:34 +01:00
assertException(Exception, lambda: aopen(newPath))
os.chmod(newPath, 0o666)
os.unlink(newPath)
2019-12-25 05:18:34 +01:00
def test_noteAddDelete():
2014-06-03 10:38:47 +02:00
deck = getEmptyCol()
# add a note
f = deck.newNote()
2019-12-25 05:18:34 +01:00
f["Front"] = "one"
f["Back"] = "two"
n = deck.addNote(f)
assert n == 1
# test multiple cards - add another template
2019-12-25 05:18:34 +01:00
m = deck.models.current()
mm = deck.models
t = mm.newTemplate("Reverse")
2019-12-25 05:18:34 +01:00
t["qfmt"] = "{{Back}}"
t["afmt"] = "{{Front}}"
mm.addTemplate(m, t)
mm.save(m)
# the default save doesn't generate cards
assert deck.cardCount() == 1
# but when templates are edited such as in the card layout screen, it
# should generate cards on close
2019-12-20 22:25:30 +01:00
mm.save(m, templates=True, updateReqs=False)
assert deck.cardCount() == 2
# creating new notes should use both cards
f = deck.newNote()
2019-12-25 05:18:34 +01:00
f["Front"] = "three"
f["Back"] = "four"
n = deck.addNote(f)
assert n == 2
assert deck.cardCount() == 4
# check q/a generation
c0 = f.cards()[0]
assert "three" in c0.q()
# it should not be a duplicate
assert not f.dupeOrEmpty()
# now let's make a duplicate
f2 = deck.newNote()
2019-12-25 05:18:34 +01:00
f2["Front"] = "one"
f2["Back"] = ""
assert f2.dupeOrEmpty()
# empty first field should not be permitted either
2019-12-25 05:18:34 +01:00
f2["Front"] = " "
assert f2.dupeOrEmpty()
2019-12-25 05:18:34 +01:00
def test_fieldChecksum():
2014-06-03 10:38:47 +02:00
deck = getEmptyCol()
f = deck.newNote()
2019-12-25 05:18:34 +01:00
f["Front"] = "new"
f["Back"] = "new2"
deck.addNote(f)
2019-12-25 05:18:34 +01:00
assert deck.db.scalar("select csum from notes") == int("c2a6b03f", 16)
# changing the val should change the checksum
2019-12-25 05:18:34 +01:00
f["Front"] = "newx"
f.flush()
2019-12-25 05:18:34 +01:00
assert deck.db.scalar("select csum from notes") == int("302811ae", 16)
def test_addDelTags():
2014-06-03 10:38:47 +02:00
deck = getEmptyCol()
f = deck.newNote()
2019-12-25 05:18:34 +01:00
f["Front"] = "1"
deck.addNote(f)
f2 = deck.newNote()
2019-12-25 05:18:34 +01:00
f2["Front"] = "2"
deck.addNote(f2)
# adding for a given id
deck.tags.bulkAdd([f.id], "foo")
2019-12-25 05:18:34 +01:00
f.load()
f2.load()
assert "foo" in f.tags
assert "foo" not in f2.tags
# should be canonified
deck.tags.bulkAdd([f.id], "foo aaa")
f.load()
assert f.tags[0] == "aaa"
assert len(f.tags) == 2
2019-12-25 05:18:34 +01:00
def test_timestamps():
2014-06-03 10:38:47 +02:00
deck = getEmptyCol()
2017-08-15 13:31:58 +02:00
assert len(deck.models.models) == len(models)
for i in range(100):
addBasicModel(deck)
2017-08-15 13:31:58 +02:00
assert len(deck.models.models) == 100 + len(models)
2019-12-25 05:18:34 +01:00
def test_furigana():
2014-06-03 10:38:47 +02:00
deck = getEmptyCol()
mm = deck.models
m = mm.current()
# filter should work
2019-12-25 05:18:34 +01:00
m["tmpls"][0]["qfmt"] = "{{kana:Front}}"
mm.save(m)
n = deck.newNote()
2019-12-25 05:18:34 +01:00
n["Front"] = "foo[abc]"
deck.addNote(n)
c = n.cards()[0]
assert c.q().endswith("abc")
# and should avoid sound
2019-12-25 05:18:34 +01:00
n["Front"] = "foo[sound:abc.mp3]"
n.flush()
assert "anki:play" in c.q(reload=True)
# it shouldn't throw an error while people are editing
2019-12-25 05:18:34 +01:00
m["tmpls"][0]["qfmt"] = "{{kana:}}"
mm.save(m)
c.q(reload=True)
2020-02-16 12:07:40 +01:00
def test_translate():
d = getEmptyCol()
tr = d.backend.translate
# strip off unicode separators
def no_uni(s: str) -> str:
return s.replace("\u2068", "").replace("\u2069", "")
def test_backend():
assert tr(StringsGroup.TEST, "valid-key") == "a valid key"
assert "invalid-key" in tr(StringsGroup.TEST, "invalid-key")
assert no_uni(tr(StringsGroup.TEST, "plural", hats=1)) == "You have 1 hat."
assert no_uni(tr(StringsGroup.TEST, "plural", hats=2)) == "You have 2 hats."
import time
t = time.time()
test_backend()
print(time.time() - t)
from fluent.runtime import FluentBundle, FluentResource
test_path = os.path.join(
os.path.dirname(__file__), "../../rslib/tests/support/test.ftl"
)
def python_render(bundle, key, **kwargs):
try:
return bundle.format_pattern(bundle.get_message(key).value, kwargs)[0]
except:
return f"Missing key: {key}"
def test_python():
bundle = FluentBundle(["en-US"])
bundle.add_resource(FluentResource(open(test_path).read()))
assert python_render(bundle, "valid-key") == "a valid key"
assert "invalid-key" in python_render(bundle, "invalid-key")
assert no_uni(python_render(bundle, "plural", hats=1)) == "You have 1 hat."
assert no_uni(python_render(bundle, "plural", hats=2)) == "You have 2 hats."
t = time.time()
test_python()
print(time.time() - t)