1"""Temporary files.
2
3This module provides generic, low- and high-level interfaces for
4creating temporary files and directories.  The interfaces listed
5as "safe" just below can be used without fear of race conditions.
6Those listed as "unsafe" cannot, and are provided for backward
7compatibility only.
8
9This module also provides some data items to the user:
10
11  TMP_MAX  - maximum number of names that will be tried before
12             giving up.
13  template - the default prefix for all temporary names.
14             You may change this to control the default prefix.
15  tempdir  - If this is set to a string before the first use of
16             any routine from this module, it will be considered as
17             another candidate location to store temporary files.
18"""
19
20__all__ = [
21    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
22    "SpooledTemporaryFile",
23    "mkstemp", "mkdtemp",                  # low level safe interfaces
24    "mktemp",                              # deprecated unsafe interface
25    "TMP_MAX", "gettempprefix",            # constants
26    "tempdir", "gettempdir"
27   ]
28
29
30# Imports.
31
32import io as _io
33import os as _os
34import errno as _errno
35from random import Random as _Random
36
37try:
38    from cStringIO import StringIO as _StringIO
39except ImportError:
40    from StringIO import StringIO as _StringIO
41
42try:
43    import fcntl as _fcntl
44except ImportError:
45    def _set_cloexec(fd):
46        pass
47else:
48    def _set_cloexec(fd):
49        try:
50            flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
51        except IOError:
52            pass
53        else:
54            # flags read successfully, modify
55            flags |= _fcntl.FD_CLOEXEC
56            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
57
58
59try:
60    import thread as _thread
61except ImportError:
62    import dummy_thread as _thread
63_allocate_lock = _thread.allocate_lock
64
65_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
66if hasattr(_os, 'O_NOINHERIT'):
67    _text_openflags |= _os.O_NOINHERIT
68if hasattr(_os, 'O_NOFOLLOW'):
69    _text_openflags |= _os.O_NOFOLLOW
70
71_bin_openflags = _text_openflags
72if hasattr(_os, 'O_BINARY'):
73    _bin_openflags |= _os.O_BINARY
74
75if hasattr(_os, 'TMP_MAX'):
76    TMP_MAX = _os.TMP_MAX
77else:
78    TMP_MAX = 10000
79
80template = "tmp"
81
82# Internal routines.
83
84_once_lock = _allocate_lock()
85
86if hasattr(_os, "lstat"):
87    _stat = _os.lstat
88elif hasattr(_os, "stat"):
89    _stat = _os.stat
90else:
91    # Fallback.  All we need is something that raises os.error if the
92    # file doesn't exist.
93    def _stat(fn):
94        try:
95            f = open(fn)
96        except IOError:
97            raise _os.error
98        f.close()
99
100def _exists(fn):
101    try:
102        _stat(fn)
103    except _os.error:
104        return False
105    else:
106        return True
107
108class _RandomNameSequence:
109    """An instance of _RandomNameSequence generates an endless
110    sequence of unpredictable strings which can safely be incorporated
111    into file names.  Each string is six characters long.  Multiple
112    threads can safely use the same instance at the same time.
113
114    _RandomNameSequence is an iterator."""
115
116    characters = ("abcdefghijklmnopqrstuvwxyz" +
117                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
118                  "0123456789_")
119
120    def __init__(self):
121        self.mutex = _allocate_lock()
122        self.normcase = _os.path.normcase
123
124    @property
125    def rng(self):
126        cur_pid = _os.getpid()
127        if cur_pid != getattr(self, '_rng_pid', None):
128            self._rng = _Random()
129            self._rng_pid = cur_pid
130        return self._rng
131
132    def __iter__(self):
133        return self
134
135    def next(self):
136        m = self.mutex
137        c = self.characters
138        choose = self.rng.choice
139
140        m.acquire()
141        try:
142            letters = [choose(c) for dummy in "123456"]
143        finally:
144            m.release()
145
146        return self.normcase(''.join(letters))
147
148def _candidate_tempdir_list():
149    """Generate a list of candidate temporary directories which
150    _get_default_tempdir will try."""
151
152    dirlist = []
153
154    # First, try the environment.
155    for envname in 'TMPDIR', 'TEMP', 'TMP':
156        dirname = _os.getenv(envname)
157        if dirname: dirlist.append(dirname)
158
159    # Failing that, try OS-specific locations.
160    if _os.name == 'riscos':
161        dirname = _os.getenv('Wimp$ScrapDir')
162        if dirname: dirlist.append(dirname)
163    elif _os.name == 'nt':
164        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
165    else:
166        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
167
168    # As a last resort, the current directory.
169    try:
170        dirlist.append(_os.getcwd())
171    except (AttributeError, _os.error):
172        dirlist.append(_os.curdir)
173
174    return dirlist
175
176def _get_default_tempdir():
177    """Calculate the default directory to use for temporary files.
178    This routine should be called exactly once.
179
180    We determine whether or not a candidate temp dir is usable by
181    trying to create and write to a file in that directory.  If this
182    is successful, the test file is deleted.  To prevent denial of
183    service, the name of the test file must be randomized."""
184
185    namer = _RandomNameSequence()
186    dirlist = _candidate_tempdir_list()
187    flags = _text_openflags
188
189    for dir in dirlist:
190        if dir != _os.curdir:
191            dir = _os.path.normcase(_os.path.abspath(dir))
192        # Try only a few names per directory.
193        for seq in xrange(100):
194            name = namer.next()
195            filename = _os.path.join(dir, name)
196            try:
197                fd = _os.open(filename, flags, 0o600)
198                try:
199                    try:
200                        with _io.open(fd, 'wb', closefd=False) as fp:
201                            fp.write(b'blat')
202                    finally:
203                        _os.close(fd)
204                finally:
205                    _os.unlink(filename)
206                return dir
207            except (OSError, IOError) as e:
208                if e.args[0] != _errno.EEXIST:
209                    break # no point trying more names in this directory
210                pass
211    raise IOError, (_errno.ENOENT,
212                    ("No usable temporary directory found in %s" % dirlist))
213
214_name_sequence = None
215
216def _get_candidate_names():
217    """Common setup sequence for all user-callable interfaces."""
218
219    global _name_sequence
220    if _name_sequence is None:
221        _once_lock.acquire()
222        try:
223            if _name_sequence is None:
224                _name_sequence = _RandomNameSequence()
225        finally:
226            _once_lock.release()
227    return _name_sequence
228
229
230def _mkstemp_inner(dir, pre, suf, flags):
231    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
232
233    names = _get_candidate_names()
234
235    for seq in xrange(TMP_MAX):
236        name = names.next()
237        file = _os.path.join(dir, pre + name + suf)
238        try:
239            fd = _os.open(file, flags, 0600)
240            _set_cloexec(fd)
241            return (fd, _os.path.abspath(file))
242        except OSError, e:
243            if e.errno == _errno.EEXIST:
244                continue # try again
245            raise
246
247    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
248
249
250# User visible interfaces.
251
252def gettempprefix():
253    """Accessor for tempdir.template."""
254    return template
255
256tempdir = None
257
258def gettempdir():
259    """Accessor for tempfile.tempdir."""
260    global tempdir
261    if tempdir is None:
262        _once_lock.acquire()
263        try:
264            if tempdir is None:
265                tempdir = _get_default_tempdir()
266        finally:
267            _once_lock.release()
268    return tempdir
269
270def mkstemp(suffix="", prefix=template, dir=None, text=False):
271    """User-callable function to create and return a unique temporary
272    file.  The return value is a pair (fd, name) where fd is the
273    file descriptor returned by os.open, and name is the filename.
274
275    If 'suffix' is specified, the file name will end with that suffix,
276    otherwise there will be no suffix.
277
278    If 'prefix' is specified, the file name will begin with that prefix,
279    otherwise a default prefix is used.
280
281    If 'dir' is specified, the file will be created in that directory,
282    otherwise a default directory is used.
283
284    If 'text' is specified and true, the file is opened in text
285    mode.  Else (the default) the file is opened in binary mode.  On
286    some operating systems, this makes no difference.
287
288    The file is readable and writable only by the creating user ID.
289    If the operating system uses permission bits to indicate whether a
290    file is executable, the file is executable by no one. The file
291    descriptor is not inherited by children of this process.
292
293    Caller is responsible for deleting the file when done with it.
294    """
295
296    if dir is None:
297        dir = gettempdir()
298
299    if text:
300        flags = _text_openflags
301    else:
302        flags = _bin_openflags
303
304    return _mkstemp_inner(dir, prefix, suffix, flags)
305
306
307def mkdtemp(suffix="", prefix=template, dir=None):
308    """User-callable function to create and return a unique temporary
309    directory.  The return value is the pathname of the directory.
310
311    Arguments are as for mkstemp, except that the 'text' argument is
312    not accepted.
313
314    The directory is readable, writable, and searchable only by the
315    creating user.
316
317    Caller is responsible for deleting the directory when done with it.
318    """
319
320    if dir is None:
321        dir = gettempdir()
322
323    names = _get_candidate_names()
324
325    for seq in xrange(TMP_MAX):
326        name = names.next()
327        file = _os.path.join(dir, prefix + name + suffix)
328        try:
329            _os.mkdir(file, 0700)
330            return file
331        except OSError, e:
332            if e.errno == _errno.EEXIST:
333                continue # try again
334            raise
335
336    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
337
338def mktemp(suffix="", prefix=template, dir=None):
339    """User-callable function to return a unique temporary file name.  The
340    file is not created.
341
342    Arguments are as for mkstemp, except that the 'text' argument is
343    not accepted.
344
345    This function is unsafe and should not be used.  The file name
346    refers to a file that did not exist at some point, but by the time
347    you get around to creating it, someone else may have beaten you to
348    the punch.
349    """
350
351##    from warnings import warn as _warn
352##    _warn("mktemp is a potential security risk to your program",
353##          RuntimeWarning, stacklevel=2)
354
355    if dir is None:
356        dir = gettempdir()
357
358    names = _get_candidate_names()
359    for seq in xrange(TMP_MAX):
360        name = names.next()
361        file = _os.path.join(dir, prefix + name + suffix)
362        if not _exists(file):
363            return file
364
365    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
366
367
368class _TemporaryFileWrapper:
369    """Temporary file wrapper
370
371    This class provides a wrapper around files opened for
372    temporary use.  In particular, it seeks to automatically
373    remove the file when it is no longer needed.
374    """
375
376    def __init__(self, file, name, delete=True):
377        self.file = file
378        self.name = name
379        self.close_called = False
380        self.delete = delete
381
382    def __getattr__(self, name):
383        # Attribute lookups are delegated to the underlying file
384        # and cached for non-numeric results
385        # (i.e. methods are cached, closed and friends are not)
386        file = self.__dict__['file']
387        a = getattr(file, name)
388        if not issubclass(type(a), type(0)):
389            setattr(self, name, a)
390        return a
391
392    # The underlying __enter__ method returns the wrong object
393    # (self.file) so override it to return the wrapper
394    def __enter__(self):
395        self.file.__enter__()
396        return self
397
398    # NT provides delete-on-close as a primitive, so we don't need
399    # the wrapper to do anything special.  We still use it so that
400    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
401    if _os.name != 'nt':
402        # Cache the unlinker so we don't get spurious errors at
403        # shutdown when the module-level "os" is None'd out.  Note
404        # that this must be referenced as self.unlink, because the
405        # name TemporaryFileWrapper may also get None'd out before
406        # __del__ is called.
407        unlink = _os.unlink
408
409        def close(self):
410            if not self.close_called:
411                self.close_called = True
412                self.file.close()
413                if self.delete:
414                    self.unlink(self.name)
415
416        def __del__(self):
417            self.close()
418
419        # Need to trap __exit__ as well to ensure the file gets
420        # deleted when used in a with statement
421        def __exit__(self, exc, value, tb):
422            result = self.file.__exit__(exc, value, tb)
423            self.close()
424            return result
425    else:
426        def __exit__(self, exc, value, tb):
427            self.file.__exit__(exc, value, tb)
428
429
430def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
431                       prefix=template, dir=None, delete=True):
432    """Create and return a temporary file.
433    Arguments:
434    'prefix', 'suffix', 'dir' -- as for mkstemp.
435    'mode' -- the mode argument to os.fdopen (default "w+b").
436    'bufsize' -- the buffer size argument to os.fdopen (default -1).
437    'delete' -- whether the file is deleted on close (default True).
438    The file is created as mkstemp() would do it.
439
440    Returns an object with a file-like interface; the name of the file
441    is accessible as file.name.  The file will be automatically deleted
442    when it is closed unless the 'delete' argument is set to False.
443    """
444
445    if dir is None:
446        dir = gettempdir()
447
448    if 'b' in mode:
449        flags = _bin_openflags
450    else:
451        flags = _text_openflags
452
453    # Setting O_TEMPORARY in the flags causes the OS to delete
454    # the file when it is closed.  This is only supported by Windows.
455    if _os.name == 'nt' and delete:
456        flags |= _os.O_TEMPORARY
457
458    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
459    file = _os.fdopen(fd, mode, bufsize)
460    return _TemporaryFileWrapper(file, name, delete)
461
462if _os.name != 'posix' or _os.sys.platform == 'cygwin':
463    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
464    # while it is open.
465    TemporaryFile = NamedTemporaryFile
466
467else:
468    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
469                      prefix=template, dir=None):
470        """Create and return a temporary file.
471        Arguments:
472        'prefix', 'suffix', 'dir' -- as for mkstemp.
473        'mode' -- the mode argument to os.fdopen (default "w+b").
474        'bufsize' -- the buffer size argument to os.fdopen (default -1).
475        The file is created as mkstemp() would do it.
476
477        Returns an object with a file-like interface.  The file has no
478        name, and will cease to exist when it is closed.
479        """
480
481        if dir is None:
482            dir = gettempdir()
483
484        if 'b' in mode:
485            flags = _bin_openflags
486        else:
487            flags = _text_openflags
488
489        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
490        try:
491            _os.unlink(name)
492            return _os.fdopen(fd, mode, bufsize)
493        except:
494            _os.close(fd)
495            raise
496
497class SpooledTemporaryFile:
498    """Temporary file wrapper, specialized to switch from
499    StringIO to a real file when it exceeds a certain size or
500    when a fileno is needed.
501    """
502    _rolled = False
503
504    def __init__(self, max_size=0, mode='w+b', bufsize=-1,
505                 suffix="", prefix=template, dir=None):
506        self._file = _StringIO()
507        self._max_size = max_size
508        self._rolled = False
509        self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir)
510
511    def _check(self, file):
512        if self._rolled: return
513        max_size = self._max_size
514        if max_size and file.tell() > max_size:
515            self.rollover()
516
517    def rollover(self):
518        if self._rolled: return
519        file = self._file
520        newfile = self._file = TemporaryFile(*self._TemporaryFileArgs)
521        del self._TemporaryFileArgs
522
523        newfile.write(file.getvalue())
524        newfile.seek(file.tell(), 0)
525
526        self._rolled = True
527
528    # The method caching trick from NamedTemporaryFile
529    # won't work here, because _file may change from a
530    # _StringIO instance to a real file. So we list
531    # all the methods directly.
532
533    # Context management protocol
534    def __enter__(self):
535        if self._file.closed:
536            raise ValueError("Cannot enter context with closed file")
537        return self
538
539    def __exit__(self, exc, value, tb):
540        self._file.close()
541
542    # file protocol
543    def __iter__(self):
544        return self._file.__iter__()
545
546    def close(self):
547        self._file.close()
548
549    @property
550    def closed(self):
551        return self._file.closed
552
553    def fileno(self):
554        self.rollover()
555        return self._file.fileno()
556
557    def flush(self):
558        self._file.flush()
559
560    def isatty(self):
561        return self._file.isatty()
562
563    @property
564    def mode(self):
565        try:
566            return self._file.mode
567        except AttributeError:
568            return self._TemporaryFileArgs[0]
569
570    @property
571    def name(self):
572        try:
573            return self._file.name
574        except AttributeError:
575            return None
576
577    def next(self):
578        return self._file.next
579
580    def read(self, *args):
581        return self._file.read(*args)
582
583    def readline(self, *args):
584        return self._file.readline(*args)
585
586    def readlines(self, *args):
587        return self._file.readlines(*args)
588
589    def seek(self, *args):
590        self._file.seek(*args)
591
592    @property
593    def softspace(self):
594        return self._file.softspace
595
596    def tell(self):
597        return self._file.tell()
598
599    def truncate(self):
600        self._file.truncate()
601
602    def write(self, s):
603        file = self._file
604        rv = file.write(s)
605        self._check(file)
606        return rv
607
608    def writelines(self, iterable):
609        file = self._file
610        rv = file.writelines(iterable)
611        self._check(file)
612        return rv
613
614    def xreadlines(self, *args):
615        try:
616            return self._file.xreadlines(*args)
617        except AttributeError:
618            return iter(self._file.readlines(*args))
619