mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 15:02:21 -04:00

- media is no longer hashed, and instead stored in the db using its original name - when adding media, its checksum is calculated and used to look for duplicates - duplicate filenames will result in a number tacked on the file - the size column is used to count card references to media. If media is referenced in a fact but not the question or answer, the count will be zero. - there is no guarantee media will be listed in the media db if it is unused on the question & answer - if rebuildMediaDir(delete=True), then entries with zero references are deleted, along with any unused files in the media dir. - rebuildMediaDir() will update the internal checksums, and set the checksum to "" if a file can't be found - rebuildMediaDir() is a lot less destructive now, and will leave alone directories it finds in the media folder (but not look in them either) - rebuildMediaDir() returns more information about the state of media now - the online and mobile clients will need to to make sure that when downloading media, entries with no checksum are non-fatal and should not abort the download process. - the ref count is updated every time the q/a is updated - so the db should be up to date after every add/edit/import - since we look for media on the q/a now, card templates like '<img src="{{{field}}}">' will work now - export original files as gone as it is not needed anymore - move from per-model media URL to deckVar. downloadMissingMedia() uses this now. Deck subscriptions will have to be updated to share media another way. - pass deck in formatQA, as latex support is going to change
106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
# coding: utf-8
|
|
|
|
import tempfile, os, time
|
|
import anki.media as m
|
|
from anki import DeckStorage
|
|
from anki.stdmodels import BasicModel
|
|
from anki.utils import checksum
|
|
|
|
# uniqueness check
|
|
def test_unique():
|
|
dir = tempfile.mkdtemp(prefix="anki")
|
|
# new file
|
|
n = "foo.jpg"
|
|
new = os.path.basename(m.uniquePath(dir, n))
|
|
assert new == n
|
|
# duplicate file
|
|
open(os.path.join(dir, n), "w").write("hello")
|
|
n = "foo.jpg"
|
|
new = os.path.basename(m.uniquePath(dir, n))
|
|
assert new == "foo (1).jpg"
|
|
# another duplicate
|
|
open(os.path.join(dir, "foo (1).jpg"), "w").write("hello")
|
|
n = "foo.jpg"
|
|
new = os.path.basename(m.uniquePath(dir, n))
|
|
assert new == "foo (2).jpg"
|
|
|
|
# copying files to media folder
|
|
def test_copy():
|
|
deck = DeckStorage.Deck()
|
|
dir = tempfile.mkdtemp(prefix="anki")
|
|
path = os.path.join(dir, "foo.jpg")
|
|
open(path, "w").write("hello")
|
|
# new file
|
|
assert m.copyToMedia(deck, path) == "foo.jpg"
|
|
# dupe md5
|
|
deck.s.statement("""
|
|
insert into media values (null, 'foo.jpg', 0, 0, :sum, '')""",
|
|
sum=checksum("hello"))
|
|
path = os.path.join(dir, "bar.jpg")
|
|
open(path, "w").write("hello")
|
|
assert m.copyToMedia(deck, path) == "foo.jpg"
|
|
|
|
# media db
|
|
def test_db():
|
|
deck = DeckStorage.Deck()
|
|
deck.addModel(BasicModel())
|
|
dir = tempfile.mkdtemp(prefix="anki")
|
|
path = os.path.join(dir, "foo.jpg")
|
|
open(path, "w").write("hello")
|
|
# add a new fact that references it twice
|
|
f = deck.newFact()
|
|
f['Front'] = u"<img src='foo.jpg'>"
|
|
f['Back'] = u"back [sound:foo.jpg]"
|
|
deck.addFact(f)
|
|
# 1 entry in the media db, with two references, and missing file
|
|
assert deck.s.scalar("select count() from media") == 1
|
|
assert deck.s.scalar("select size from media") == 2
|
|
assert deck.s.scalar("select not originalPath from media")
|
|
# copy to media folder & check db
|
|
path = m.copyToMedia(deck, path)
|
|
m.rebuildMediaDir(deck)
|
|
# md5 should be set now
|
|
assert deck.s.scalar("select count() from media") == 1
|
|
assert deck.s.scalar("select size from media") == 2
|
|
assert deck.s.scalar("select originalPath from media")
|
|
# edit the fact to remove a reference
|
|
f['Back'] = u""
|
|
f.setModified(True, deck)
|
|
deck.s.flush()
|
|
assert deck.s.scalar("select count() from media") == 1
|
|
assert deck.s.scalar("select size from media") == 1
|
|
# remove the front reference too
|
|
f['Front'] = u""
|
|
f.setModified(True, deck)
|
|
assert deck.s.scalar("select size from media") == 0
|
|
# add the reference back
|
|
f['Front'] = u"<img src='foo.jpg'>"
|
|
f.setModified(True, deck)
|
|
assert deck.s.scalar("select size from media") == 1
|
|
# detect file modifications
|
|
oldsum = deck.s.scalar("select originalPath from media")
|
|
open(path, "w").write("world")
|
|
m.rebuildMediaDir(deck)
|
|
newsum = deck.s.scalar("select originalPath from media")
|
|
assert newsum and newsum != oldsum
|
|
# delete underlying file and check db
|
|
os.unlink(path)
|
|
m.rebuildMediaDir(deck)
|
|
# md5 should be gone again
|
|
assert deck.s.scalar("select count() from media") == 1
|
|
assert deck.s.scalar("select not originalPath from media")
|
|
# media db should pick up media defined via templates & bulk update
|
|
f['Back'] = u"bar.jpg"
|
|
f.setModified(True, deck)
|
|
deck.s.flush()
|
|
# modify template & regenerate
|
|
assert deck.s.scalar("select count() from media") == 1
|
|
assert deck.s.scalar("select sum(size) from media") == 1
|
|
deck.currentModel.cardModels[0].aformat=u'<img src="{{{Back}}}">'
|
|
deck.updateCardsFromModel(deck.currentModel)
|
|
assert deck.s.scalar("select sum(size) from media") == 2
|
|
assert deck.s.scalar("select count() from media") == 2
|
|
deck.currentModel.cardModels[0].aformat=u'{{{Back}}}'
|
|
deck.updateCardsFromModel(deck.currentModel)
|
|
assert deck.s.scalar("select count() from media") == 2
|
|
assert deck.s.scalar("select sum(size) from media") == 1
|