mirror of
https://github.com/ankitects/anki.git
synced 2025-11-09 14:17:13 -05:00
centralize all tmp dir access
This commit is contained in:
parent
d96a0eaf08
commit
344b111b80
5 changed files with 72 additions and 44 deletions
|
|
@ -2,8 +2,8 @@
|
||||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import re, tempfile, os, sys, shutil, cgi, subprocess
|
import re, os, sys, shutil, cgi, subprocess
|
||||||
from anki.utils import checksum, call
|
from anki.utils import checksum, call, namedtmp, tmpdir, isMac
|
||||||
from anki.hooks import addHook
|
from anki.hooks import addHook
|
||||||
from htmlentitydefs import entitydefs
|
from htmlentitydefs import entitydefs
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
|
|
@ -17,10 +17,8 @@ regexps = {
|
||||||
"math": re.compile(r"\[\$\$\](.+?)\[/\$\$\]", re.DOTALL | re.IGNORECASE),
|
"math": re.compile(r"\[\$\$\](.+?)\[/\$\$\]", re.DOTALL | re.IGNORECASE),
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpdir = tempfile.mkdtemp(prefix="anki")
|
|
||||||
|
|
||||||
# add standard tex install location to osx
|
# add standard tex install location to osx
|
||||||
if sys.platform == "darwin":
|
if isMac:
|
||||||
os.environ['PATH'] += ":/usr/texbin"
|
os.environ['PATH'] += ":/usr/texbin"
|
||||||
|
|
||||||
def stripLatex(text):
|
def stripLatex(text):
|
||||||
|
|
@ -76,17 +74,17 @@ def _buildImg(deck, latex, fname):
|
||||||
latex + "\n" +
|
latex + "\n" +
|
||||||
deck.conf["latexPost"])
|
deck.conf["latexPost"])
|
||||||
# write into a temp file
|
# write into a temp file
|
||||||
log = open(os.path.join(tmpdir, "latex_log.txt"), "w+")
|
log = open(namedtmp("latex_log.txt"), "w")
|
||||||
texpath = os.path.join(tmpdir, "tmp.tex")
|
texfile = file(namedtmp("tmp.tex"), "w")
|
||||||
texfile = file(texpath, "w")
|
|
||||||
texfile.write(latex)
|
texfile.write(latex)
|
||||||
texfile.close()
|
texfile.close()
|
||||||
# make sure we have a valid mediaDir
|
# make sure we have a valid mediaDir
|
||||||
mdir = deck.media.dir(create=True)
|
mdir = deck.media.dir(create=True)
|
||||||
oldcwd = os.getcwd()
|
oldcwd = os.getcwd()
|
||||||
|
png = namedtmp("tmp.png")
|
||||||
try:
|
try:
|
||||||
# generate dvi
|
# generate dvi
|
||||||
os.chdir(tmpdir)
|
os.chdir(tmpdir())
|
||||||
if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
|
if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
|
||||||
return _errMsg("latex")
|
return _errMsg("latex")
|
||||||
# and png
|
# and png
|
||||||
|
|
@ -94,7 +92,7 @@ def _buildImg(deck, latex, fname):
|
||||||
stdout=log, stderr=log):
|
stdout=log, stderr=log):
|
||||||
return _errMsg("dvipng")
|
return _errMsg("dvipng")
|
||||||
# add to media
|
# add to media
|
||||||
shutil.copy2(os.path.join(tmpdir, "tmp.png"),
|
shutil.copy2(png,
|
||||||
os.path.join(mdir, fname))
|
os.path.join(mdir, fname))
|
||||||
return
|
return
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -103,7 +101,7 @@ def _buildImg(deck, latex, fname):
|
||||||
def _errMsg(type):
|
def _errMsg(type):
|
||||||
msg = (_("Error executing %s.") % type) + "<br>"
|
msg = (_("Error executing %s.") % type) + "<br>"
|
||||||
try:
|
try:
|
||||||
log = open(os.path.join(tmpdir, "latex_log.txt")).read()
|
log = open(namedtmp("latex_log.txt")).read()
|
||||||
if not log:
|
if not log:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"
|
msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import os, shutil, re, urllib, urllib2, time, tempfile, unicodedata, \
|
import os, shutil, re, urllib, urllib2, time, unicodedata, \
|
||||||
urllib, sys
|
urllib, sys
|
||||||
from anki.utils import checksum, intTime
|
from anki.utils import checksum, intTime, namedtmp, isWin
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
|
|
||||||
class MediaRegistry(object):
|
class MediaRegistry(object):
|
||||||
|
|
@ -111,7 +111,7 @@ If the same name exists, compare checksums."""
|
||||||
# problem is more complicated - if we percent-escape as utf8 it fixes
|
# problem is more complicated - if we percent-escape as utf8 it fixes
|
||||||
# some images but breaks others. When filenames are normalized by
|
# some images but breaks others. When filenames are normalized by
|
||||||
# dropbox they become unreadable if we escape them.
|
# dropbox they become unreadable if we escape them.
|
||||||
if sys.platform.startswith("win32"):
|
if isWin:
|
||||||
return string
|
return string
|
||||||
def repl(match):
|
def repl(match):
|
||||||
tag = match.group(1)
|
tag = match.group(1)
|
||||||
|
|
@ -212,12 +212,11 @@ If the same name exists, compare checksums."""
|
||||||
for f in mediaFiles(txt, remote=True):
|
for f in mediaFiles(txt, remote=True):
|
||||||
refs[f] = True
|
refs[f] = True
|
||||||
|
|
||||||
tmpdir = tempfile.mkdtemp(prefix="anki")
|
|
||||||
failed = []
|
failed = []
|
||||||
passed = []
|
passed = []
|
||||||
for c, link in enumerate(refs.keys()):
|
for c, link in enumerate(refs.keys()):
|
||||||
try:
|
try:
|
||||||
path = os.path.join(tmpdir, os.path.basename(link))
|
path = namedtmp(os.path.basename(link))
|
||||||
url = urllib2.urlopen(link)
|
url = urllib2.urlopen(link)
|
||||||
open(path, "wb").write(url.read())
|
open(path, "wb").write(url.read())
|
||||||
newpath = copyToMedia(self.deck, path)
|
newpath = copyToMedia(self.deck, path)
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import re, sys, threading, time, subprocess, os, signal, errno, atexit
|
import re, sys, threading, time, subprocess, os, signal, errno, atexit
|
||||||
import tempfile, shutil
|
import shutil
|
||||||
from anki.hooks import addHook, runHook
|
from anki.hooks import addHook, runHook
|
||||||
|
from anki.utils import namedtmp, tmpdir, isWin, isMac
|
||||||
|
|
||||||
# Shared utils
|
# Shared utils
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
@ -30,23 +31,18 @@ processingChain = [
|
||||||
["lame", "rec.wav", processingDst, "--noreplaygain", "--quiet"],
|
["lame", "rec.wav", processingDst, "--noreplaygain", "--quiet"],
|
||||||
]
|
]
|
||||||
|
|
||||||
tmpdir = None
|
|
||||||
|
|
||||||
# don't show box on windows
|
# don't show box on windows
|
||||||
if sys.platform == "win32":
|
if isWin:
|
||||||
si = subprocess.STARTUPINFO()
|
si = subprocess.STARTUPINFO()
|
||||||
try:
|
try:
|
||||||
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
except:
|
except:
|
||||||
# python2.7+
|
# python2.7+
|
||||||
si.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
|
si.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
|
||||||
# tmp dir for non-hashed media
|
|
||||||
tmpdir = unicode(
|
|
||||||
tempfile.mkdtemp(prefix="anki"), sys.getfilesystemencoding())
|
|
||||||
else:
|
else:
|
||||||
si = None
|
si = None
|
||||||
|
|
||||||
if sys.platform.startswith("darwin"):
|
if isMac:
|
||||||
# make sure lame, which is installed in /usr/local/bin, is in the path
|
# make sure lame, which is installed in /usr/local/bin, is in the path
|
||||||
os.environ['PATH'] += ":" + "/usr/local/bin"
|
os.environ['PATH'] += ":" + "/usr/local/bin"
|
||||||
dir = os.path.dirname(os.path.abspath(__file__))
|
dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
@ -64,7 +60,7 @@ def retryWait(proc):
|
||||||
# Mplayer settings
|
# Mplayer settings
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
if sys.platform.startswith("win32"):
|
if isWin:
|
||||||
mplayerCmd = ["mplayer.exe", "-ao", "win32"]
|
mplayerCmd = ["mplayer.exe", "-ao", "win32"]
|
||||||
dir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
dir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||||
os.environ['PATH'] += ";" + dir
|
os.environ['PATH'] += ";" + dir
|
||||||
|
|
@ -157,13 +153,13 @@ def queueMplayer(path):
|
||||||
ensureMplayerThreads()
|
ensureMplayerThreads()
|
||||||
while mplayerEvt.isSet():
|
while mplayerEvt.isSet():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
if tmpdir and os.path.exists(path):
|
if isWin and os.path.exists(path):
|
||||||
# mplayer on windows doesn't like the encoding, so we create a
|
# mplayer on windows doesn't like the encoding, so we create a
|
||||||
# temporary file instead. oddly, foreign characters in the dirname
|
# temporary file instead. oddly, foreign characters in the dirname
|
||||||
# don't seem to matter.
|
# don't seem to matter.
|
||||||
(fd, name) = tempfile.mkstemp(suffix=os.path.splitext(path)[1],
|
dir = tmpdir().encode(sys.getfilesystemencoding())
|
||||||
dir=tmpdir)
|
name = os.path.join(dir, "audio"+os.path.splitext(path)[1])
|
||||||
f = os.fdopen(fd, "wb")
|
f = open(name, "wb")
|
||||||
f.write(open(path, "rb").read())
|
f.write(open(path, "rb").read())
|
||||||
f.close()
|
f.close()
|
||||||
# it wants unix paths, too!
|
# it wants unix paths, too!
|
||||||
|
|
@ -194,12 +190,7 @@ def stopMplayer(*args):
|
||||||
return
|
return
|
||||||
mplayerManager.kill()
|
mplayerManager.kill()
|
||||||
|
|
||||||
def onExit():
|
|
||||||
if tmpdir:
|
|
||||||
shutil.rmtree(tmpdir)
|
|
||||||
|
|
||||||
addHook("deckClosed", stopMplayer)
|
addHook("deckClosed", stopMplayer)
|
||||||
atexit.register(onExit)
|
|
||||||
|
|
||||||
# PyAudio recording
|
# PyAudio recording
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
||||||
11
anki/sync.py
11
anki/sync.py
|
|
@ -3,7 +3,7 @@
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import zlib, re, urllib, urllib2, socket, simplejson, time, shutil
|
import zlib, re, urllib, urllib2, socket, simplejson, time, shutil
|
||||||
import os, base64, httplib, sys, tempfile, httplib, types
|
import os, base64, httplib, sys, httplib, types
|
||||||
from datetime import date
|
from datetime import date
|
||||||
import anki, anki.deck, anki.cards
|
import anki, anki.deck, anki.cards
|
||||||
from anki.errors import *
|
from anki.errors import *
|
||||||
|
|
@ -851,8 +851,8 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
|
||||||
try:
|
try:
|
||||||
# write into a temporary file, since POST needs content-length
|
# write into a temporary file, since POST needs content-length
|
||||||
src = open(path, "rb")
|
src = open(path, "rb")
|
||||||
(fd, name) = tempfile.mkstemp(prefix="anki")
|
name = namedtmp("fullsync.anki")
|
||||||
tmp = open(name, "w+b")
|
tmp = open(name, "wb")
|
||||||
# post vars
|
# post vars
|
||||||
for (key, value) in fields.items():
|
for (key, value) in fields.items():
|
||||||
tmp.write('--' + MIME_BOUNDARY + "\r\n")
|
tmp.write('--' + MIME_BOUNDARY + "\r\n")
|
||||||
|
|
@ -900,8 +900,6 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
|
||||||
finally:
|
finally:
|
||||||
sendProgressHook = None
|
sendProgressHook = None
|
||||||
tmp.close()
|
tmp.close()
|
||||||
os.close(fd)
|
|
||||||
os.unlink(name)
|
|
||||||
finally:
|
finally:
|
||||||
runHook("fullSyncFinished")
|
runHook("fullSyncFinished")
|
||||||
|
|
||||||
|
|
@ -910,8 +908,7 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
|
||||||
runHook("fullSyncStarted", 0)
|
runHook("fullSyncStarted", 0)
|
||||||
fields = urllib.urlencode(fields)
|
fields = urllib.urlencode(fields)
|
||||||
src = urllib.urlopen(SYNC_URL + "fulldown", fields)
|
src = urllib.urlopen(SYNC_URL + "fulldown", fields)
|
||||||
(fd, tmpname) = tempfile.mkstemp(dir=os.path.dirname(path),
|
tmpname = namedtmp("fullsync.anki")
|
||||||
prefix="fullsync")
|
|
||||||
tmp = open(tmpname, "wb")
|
tmp = open(tmpname, "wb")
|
||||||
decomp = zlib.decompressobj()
|
decomp = zlib.decompressobj()
|
||||||
cnt = 0
|
cnt = 0
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import re, os, random, time, types, math, htmlentitydefs, subprocess
|
import re, os, random, time, types, math, htmlentitydefs, subprocess, \
|
||||||
|
tempfile, shutil
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
@ -231,7 +232,7 @@ def joinFields(list):
|
||||||
def splitFields(string):
|
def splitFields(string):
|
||||||
return string.split("\x1f")
|
return string.split("\x1f")
|
||||||
|
|
||||||
# Misc
|
# Checksums
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
def checksum(data):
|
def checksum(data):
|
||||||
|
|
@ -241,10 +242,46 @@ def fieldChecksum(data):
|
||||||
# 32 bit unsigned number from first 8 digits of md5 hash
|
# 32 bit unsigned number from first 8 digits of md5 hash
|
||||||
return int(checksum(data.encode("utf-8"))[:8], 16)
|
return int(checksum(data.encode("utf-8"))[:8], 16)
|
||||||
|
|
||||||
|
# Temp files
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
_tmpdir = None
|
||||||
|
|
||||||
|
def tmpdir():
|
||||||
|
"A reusable temp folder which we clean out on each program invocation."
|
||||||
|
global _tmpdir
|
||||||
|
if not _tmpdir:
|
||||||
|
def cleanup():
|
||||||
|
shutil.rmtree(_tmpdir)
|
||||||
|
import atexit
|
||||||
|
atexit.register(cleanup)
|
||||||
|
_tmpdir = os.path.join(tempfile.gettempdir(), "anki_temp")
|
||||||
|
try:
|
||||||
|
shutil.rmtree(_tmpdir)
|
||||||
|
except (IOError, OSError):
|
||||||
|
pass
|
||||||
|
os.mkdir(_tmpdir)
|
||||||
|
return _tmpdir
|
||||||
|
|
||||||
|
def tmpfile(prefix=None, suffix=None):
|
||||||
|
return tempfile.mkstemp(dir=tmpdir(), prefix=prefix, suffix=suffix)
|
||||||
|
|
||||||
|
def namedtmp(name):
|
||||||
|
"Return tmpdir+name. Deletes any existing file."
|
||||||
|
path = os.path.join(tmpdir(), name)
|
||||||
|
try:
|
||||||
|
os.unlink(path)
|
||||||
|
except (OSError, IOError):
|
||||||
|
pass
|
||||||
|
return path
|
||||||
|
|
||||||
|
# Cmd invocation
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
def call(argv, wait=True, **kwargs):
|
def call(argv, wait=True, **kwargs):
|
||||||
"Execute a command. If WAIT, return exit code."
|
"Execute a command. If WAIT, return exit code."
|
||||||
# ensure we don't open a separate window for forking process on windows
|
# ensure we don't open a separate window for forking process on windows
|
||||||
if sys.platform == "win32":
|
if isWin:
|
||||||
si = subprocess.STARTUPINFO()
|
si = subprocess.STARTUPINFO()
|
||||||
try:
|
try:
|
||||||
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
|
|
@ -270,3 +307,9 @@ def call(argv, wait=True, **kwargs):
|
||||||
else:
|
else:
|
||||||
ret = 0
|
ret = 0
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
# OS helpers
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
isMac = sys.platform.startswith("darwin")
|
||||||
|
isWin = sys.platform.startswith("win32")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue