centralize all tmp dir access

This commit is contained in:
Damien Elmes 2011-04-17 01:07:05 +09:00
parent d96a0eaf08
commit 344b111b80
5 changed files with 72 additions and 44 deletions

View file

@ -2,8 +2,8 @@
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import re, tempfile, os, sys, shutil, cgi, subprocess
from anki.utils import checksum, call
import re, os, sys, shutil, cgi, subprocess
from anki.utils import checksum, call, namedtmp, tmpdir, isMac
from anki.hooks import addHook
from htmlentitydefs import entitydefs
from anki.lang import _
@ -17,10 +17,8 @@ regexps = {
"math": re.compile(r"\[\$\$\](.+?)\[/\$\$\]", re.DOTALL | re.IGNORECASE),
}
tmpdir = tempfile.mkdtemp(prefix="anki")
# add standard tex install location to osx
if sys.platform == "darwin":
if isMac:
os.environ['PATH'] += ":/usr/texbin"
def stripLatex(text):
@ -76,17 +74,17 @@ def _buildImg(deck, latex, fname):
latex + "\n" +
deck.conf["latexPost"])
# write into a temp file
log = open(os.path.join(tmpdir, "latex_log.txt"), "w+")
texpath = os.path.join(tmpdir, "tmp.tex")
texfile = file(texpath, "w")
log = open(namedtmp("latex_log.txt"), "w")
texfile = file(namedtmp("tmp.tex"), "w")
texfile.write(latex)
texfile.close()
# make sure we have a valid mediaDir
mdir = deck.media.dir(create=True)
oldcwd = os.getcwd()
png = namedtmp("tmp.png")
try:
# generate dvi
os.chdir(tmpdir)
os.chdir(tmpdir())
if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
return _errMsg("latex")
# and png
@ -94,7 +92,7 @@ def _buildImg(deck, latex, fname):
stdout=log, stderr=log):
return _errMsg("dvipng")
# add to media
shutil.copy2(os.path.join(tmpdir, "tmp.png"),
shutil.copy2(png,
os.path.join(mdir, fname))
return
finally:
@ -103,7 +101,7 @@ def _buildImg(deck, latex, fname):
def _errMsg(type):
msg = (_("Error executing %s.") % type) + "<br>"
try:
log = open(os.path.join(tmpdir, "latex_log.txt")).read()
log = open(namedtmp("latex_log.txt")).read()
if not log:
raise Exception()
msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"

View file

@ -2,9 +2,9 @@
# Copyright: Damien Elmes <anki@ichi2.net>
# 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
from anki.utils import checksum, intTime
from anki.utils import checksum, intTime, namedtmp, isWin
from anki.lang import _
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
# some images but breaks others. When filenames are normalized by
# dropbox they become unreadable if we escape them.
if sys.platform.startswith("win32"):
if isWin:
return string
def repl(match):
tag = match.group(1)
@ -212,12 +212,11 @@ If the same name exists, compare checksums."""
for f in mediaFiles(txt, remote=True):
refs[f] = True
tmpdir = tempfile.mkdtemp(prefix="anki")
failed = []
passed = []
for c, link in enumerate(refs.keys()):
try:
path = os.path.join(tmpdir, os.path.basename(link))
path = namedtmp(os.path.basename(link))
url = urllib2.urlopen(link)
open(path, "wb").write(url.read())
newpath = copyToMedia(self.deck, path)

View file

@ -3,8 +3,9 @@
# 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 tempfile, shutil
import shutil
from anki.hooks import addHook, runHook
from anki.utils import namedtmp, tmpdir, isWin, isMac
# Shared utils
##########################################################################
@ -30,23 +31,18 @@ processingChain = [
["lame", "rec.wav", processingDst, "--noreplaygain", "--quiet"],
]
tmpdir = None
# don't show box on windows
if sys.platform == "win32":
if isWin:
si = subprocess.STARTUPINFO()
try:
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
except:
# python2.7+
si.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
# tmp dir for non-hashed media
tmpdir = unicode(
tempfile.mkdtemp(prefix="anki"), sys.getfilesystemencoding())
else:
si = None
if sys.platform.startswith("darwin"):
if isMac:
# make sure lame, which is installed in /usr/local/bin, is in the path
os.environ['PATH'] += ":" + "/usr/local/bin"
dir = os.path.dirname(os.path.abspath(__file__))
@ -64,7 +60,7 @@ def retryWait(proc):
# Mplayer settings
##########################################################################
if sys.platform.startswith("win32"):
if isWin:
mplayerCmd = ["mplayer.exe", "-ao", "win32"]
dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.environ['PATH'] += ";" + dir
@ -157,13 +153,13 @@ def queueMplayer(path):
ensureMplayerThreads()
while mplayerEvt.isSet():
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
# temporary file instead. oddly, foreign characters in the dirname
# don't seem to matter.
(fd, name) = tempfile.mkstemp(suffix=os.path.splitext(path)[1],
dir=tmpdir)
f = os.fdopen(fd, "wb")
dir = tmpdir().encode(sys.getfilesystemencoding())
name = os.path.join(dir, "audio"+os.path.splitext(path)[1])
f = open(name, "wb")
f.write(open(path, "rb").read())
f.close()
# it wants unix paths, too!
@ -194,12 +190,7 @@ def stopMplayer(*args):
return
mplayerManager.kill()
def onExit():
if tmpdir:
shutil.rmtree(tmpdir)
addHook("deckClosed", stopMplayer)
atexit.register(onExit)
# PyAudio recording
##########################################################################

View file

@ -3,7 +3,7 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
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
import anki, anki.deck, anki.cards
from anki.errors import *
@ -851,8 +851,8 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
try:
# write into a temporary file, since POST needs content-length
src = open(path, "rb")
(fd, name) = tempfile.mkstemp(prefix="anki")
tmp = open(name, "w+b")
name = namedtmp("fullsync.anki")
tmp = open(name, "wb")
# post vars
for (key, value) in fields.items():
tmp.write('--' + MIME_BOUNDARY + "\r\n")
@ -900,8 +900,6 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
finally:
sendProgressHook = None
tmp.close()
os.close(fd)
os.unlink(name)
finally:
runHook("fullSyncFinished")
@ -910,8 +908,7 @@ and cards.id in %s""" % ids2str([c[0] for c in cards])))
runHook("fullSyncStarted", 0)
fields = urllib.urlencode(fields)
src = urllib.urlopen(SYNC_URL + "fulldown", fields)
(fd, tmpname) = tempfile.mkstemp(dir=os.path.dirname(path),
prefix="fullsync")
tmpname = namedtmp("fullsync.anki")
tmp = open(tmpname, "wb")
decomp = zlib.decompressobj()
cnt = 0

View file

@ -2,7 +2,8 @@
# Copyright: Damien Elmes <anki@ichi2.net>
# 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:
import hashlib
@ -231,7 +232,7 @@ def joinFields(list):
def splitFields(string):
return string.split("\x1f")
# Misc
# Checksums
##############################################################################
def checksum(data):
@ -241,10 +242,46 @@ def fieldChecksum(data):
# 32 bit unsigned number from first 8 digits of md5 hash
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):
"Execute a command. If WAIT, return exit code."
# ensure we don't open a separate window for forking process on windows
if sys.platform == "win32":
if isWin:
si = subprocess.STARTUPINFO()
try:
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
@ -270,3 +307,9 @@ def call(argv, wait=True, **kwargs):
else:
ret = 0
return ret
# OS helpers
##############################################################################
isMac = sys.platform.startswith("darwin")
isWin = sys.platform.startswith("win32")