Use unicode temp paths on unix as well, for consistency.

This commit is contained in:
Kovid Goyal 2012-02-22 13:20:27 +05:30
parent eb98a1e66b
commit e8512141a1
2 changed files with 33 additions and 46 deletions

View File

@ -5,9 +5,10 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
Provides platform independent temporary files that persist even after Provides platform independent temporary files that persist even after
being closed. being closed.
""" """
import tempfile, os, atexit, binascii, cPickle import tempfile, os, atexit
from future_builtins import map
from calibre.constants import (__version__, __appname__, from calibre.constants import (__version__, __appname__, filesystem_encoding,
get_unicode_windows_env_var, iswindows, get_windows_temp_path) get_unicode_windows_env_var, iswindows, get_windows_temp_path)
def cleanup(path): def cleanup(path):
@ -40,6 +41,7 @@ def base_dir():
if _base_dir is None: if _base_dir is None:
td = os.environ.get('CALIBRE_WORKER_TEMP_DIR', None) td = os.environ.get('CALIBRE_WORKER_TEMP_DIR', None)
if td is not None: if td is not None:
import cPickle, binascii
try: try:
td = cPickle.loads(binascii.unhexlify(td)) td = cPickle.loads(binascii.unhexlify(td))
except: except:
@ -52,58 +54,38 @@ def base_dir():
base = get_unicode_windows_env_var('CALIBRE_TEMP_DIR') base = get_unicode_windows_env_var('CALIBRE_TEMP_DIR')
prefix = app_prefix(u'tmp_') prefix = app_prefix(u'tmp_')
if base is None and iswindows: if base is None and iswindows:
# On windows always use a unicode temp path, as for some # On windows, if the TMP env var points to a path that
# localized (east asian) windows builds, there's no reliable # cannot be encoded using the mbcs encoding, then the
# way to escalate to unicode only when needed. See # python 2 tempfile algorithm for getting the temporary
# https://bugs.launchpad.net/bugs/937389 Hopefully, by now, the # directory breaks. So we use the win32 api to get a
# rest of calibre can deal with unicode temp paths. We'll leave # unicode temp path instead. See
# temp paths as bytestring on Unix, as the temp dir on unix is # https://bugs.launchpad.net/bugs/937389
# very rarely non ascii anyway.
base = get_windows_temp_path() base = get_windows_temp_path()
try:
# First try an ascii path as that is what was done historically
# and we dont want to break working code
# _base_dir will be a bytestring
_base_dir = tempfile.mkdtemp(prefix=prefix.encode('ascii'), dir=base)
except:
# Failed to create tempdir (probably localized windows)
# Try unicode. This means that all temp paths created by this
# module will be unicode, this may cause problems elsewhere, if
# so, hopefully people will open tickets and they can be fixed.
_base_dir = tempfile.mkdtemp(prefix=prefix, dir=base)
_base_dir = tempfile.mkdtemp(prefix=prefix, dir=base)
atexit.register(remove_dir, _base_dir) atexit.register(remove_dir, _base_dir)
# Tell the tempfile module to in future always use our temp dir
# This also means that it will return unicode paths, instead of
# bytestrings
tempfile.tempdir = _base_dir
return _base_dir return _base_dir
def force_unicode(x):
# Cannot use the implementation in calibre.__init__ as it causes a circular
# dependency
if isinstance(x, bytes):
x = x.decode(filesystem_encoding)
return x
def _make_file(suffix, prefix, base): def _make_file(suffix, prefix, base):
try: suffix, prefix = map(force_unicode, (suffix, prefix))
fd, name = tempfile.mkstemp(suffix, prefix, dir=base) return tempfile.mkstemp(suffix, prefix, dir=base)
except (UnicodeDecodeError, OSError):
# On some windows systems, we get an OSError because base is not
# unicode and windows cannot find the path pointed to by base
global _base_dir
from calibre.constants import filesystem_encoding
base_dir()
if not isinstance(_base_dir, unicode):
_base_dir = _base_dir.decode(filesystem_encoding)
base = base.decode(filesystem_encoding)
fd, name = tempfile.mkstemp(suffix, prefix, dir=dir)
return fd, name
def _make_dir(suffix, prefix, base): def _make_dir(suffix, prefix, base):
try: suffix, prefix = map(force_unicode, (suffix, prefix))
tdir = tempfile.mkdtemp(suffix, prefix, base) return tempfile.mkdtemp(suffix, prefix, base)
except (ValueError, OSError):
# On some windows systems, we get an OSError because base is not
# unicode and windows cannot find the path pointed to by base
global _base_dir
from calibre.constants import filesystem_encoding
base_dir()
if not isinstance(_base_dir, unicode):
_base_dir = _base_dir.decode(filesystem_encoding)
base = base.decode(filesystem_encoding)
tdir = tempfile.mkdtemp(suffix, prefix, base)
return tdir
class PersistentTemporaryFile(object): class PersistentTemporaryFile(object):
""" """

View File

@ -33,6 +33,11 @@ if not _run_once:
if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode): if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode):
sys.argv[1:] = winutil.argv()[1-len(sys.argv):] sys.argv[1:] = winutil.argv()[1-len(sys.argv):]
################################################################################
# Ensure that all temp files/dirs are created under a calibre tmp dir
from calibre.ptempfile import base_dir
base_dir()
################################################################################ ################################################################################
# Convert command line arguments to unicode # Convert command line arguments to unicode
enc = preferred_encoding enc = preferred_encoding