source: titan/mediathek/localhoster/lib/python2.7/tempfile.py @ 40523

Last change on this file since 40523 was 40094, checked in by obi, 7 years ago

tithek add yoztube-dl support

File size: 19.0 KB
Line 
1"""Temporary files.
2
3This module provides generic, low- and high-level interfaces for
4creating temporary files and directories.  All of the interfaces
5provided by this module can be used without fear of race conditions
6except for 'mktemp'.  'mktemp' is subject to race conditions and
7should not be used; it is provided for backward compatibility 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                    continue
210                if (_os.name == 'nt' and e.args[0] == _errno.EACCES and
211                    _os.path.isdir(dir) and _os.access(dir, _os.W_OK)):
212                    # On windows, when a directory with the chosen name already
213                    # exists, EACCES error code is returned instead of EEXIST.
214                    continue
215                break # no point trying more names in this directory
216    raise IOError, (_errno.ENOENT,
217                    ("No usable temporary directory found in %s" % dirlist))
218
219_name_sequence = None
220
221def _get_candidate_names():
222    """Common setup sequence for all user-callable interfaces."""
223
224    global _name_sequence
225    if _name_sequence is None:
226        _once_lock.acquire()
227        try:
228            if _name_sequence is None:
229                _name_sequence = _RandomNameSequence()
230        finally:
231            _once_lock.release()
232    return _name_sequence
233
234
235def _mkstemp_inner(dir, pre, suf, flags):
236    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
237
238    names = _get_candidate_names()
239
240    for seq in xrange(TMP_MAX):
241        name = names.next()
242        file = _os.path.join(dir, pre + name + suf)
243        try:
244            fd = _os.open(file, flags, 0600)
245            _set_cloexec(fd)
246            return (fd, _os.path.abspath(file))
247        except OSError, e:
248            if e.errno == _errno.EEXIST:
249                continue # try again
250            if (_os.name == 'nt' and e.errno == _errno.EACCES and
251                _os.path.isdir(dir) and _os.access(dir, _os.W_OK)):
252                # On windows, when a directory with the chosen name already
253                # exists, EACCES error code is returned instead of EEXIST.
254                continue
255            raise
256
257    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
258
259
260# User visible interfaces.
261
262def gettempprefix():
263    """Accessor for tempdir.template."""
264    return template
265
266tempdir = None
267
268def gettempdir():
269    """Accessor for tempfile.tempdir."""
270    global tempdir
271    if tempdir is None:
272        _once_lock.acquire()
273        try:
274            if tempdir is None:
275                tempdir = _get_default_tempdir()
276        finally:
277            _once_lock.release()
278    return tempdir
279
280def mkstemp(suffix="", prefix=template, dir=None, text=False):
281    """User-callable function to create and return a unique temporary
282    file.  The return value is a pair (fd, name) where fd is the
283    file descriptor returned by os.open, and name is the filename.
284
285    If 'suffix' is specified, the file name will end with that suffix,
286    otherwise there will be no suffix.
287
288    If 'prefix' is specified, the file name will begin with that prefix,
289    otherwise a default prefix is used.
290
291    If 'dir' is specified, the file will be created in that directory,
292    otherwise a default directory is used.
293
294    If 'text' is specified and true, the file is opened in text
295    mode.  Else (the default) the file is opened in binary mode.  On
296    some operating systems, this makes no difference.
297
298    The file is readable and writable only by the creating user ID.
299    If the operating system uses permission bits to indicate whether a
300    file is executable, the file is executable by no one. The file
301    descriptor is not inherited by children of this process.
302
303    Caller is responsible for deleting the file when done with it.
304    """
305
306    if dir is None:
307        dir = gettempdir()
308
309    if text:
310        flags = _text_openflags
311    else:
312        flags = _bin_openflags
313
314    return _mkstemp_inner(dir, prefix, suffix, flags)
315
316
317def mkdtemp(suffix="", prefix=template, dir=None):
318    """User-callable function to create and return a unique temporary
319    directory.  The return value is the pathname of the directory.
320
321    Arguments are as for mkstemp, except that the 'text' argument is
322    not accepted.
323
324    The directory is readable, writable, and searchable only by the
325    creating user.
326
327    Caller is responsible for deleting the directory when done with it.
328    """
329
330    if dir is None:
331        dir = gettempdir()
332
333    names = _get_candidate_names()
334
335    for seq in xrange(TMP_MAX):
336        name = names.next()
337        file = _os.path.join(dir, prefix + name + suffix)
338        try:
339            _os.mkdir(file, 0700)
340            return file
341        except OSError, e:
342            if e.errno == _errno.EEXIST:
343                continue # try again
344            if (_os.name == 'nt' and e.errno == _errno.EACCES and
345                _os.path.isdir(dir) and _os.access(dir, _os.W_OK)):
346                # On windows, when a directory with the chosen name already
347                # exists, EACCES error code is returned instead of EEXIST.
348                continue
349            raise
350
351    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
352
353def mktemp(suffix="", prefix=template, dir=None):
354    """User-callable function to return a unique temporary file name.  The
355    file is not created.
356
357    Arguments are as for mkstemp, except that the 'text' argument is
358    not accepted.
359
360    This function is unsafe and should not be used.  The file name
361    refers to a file that did not exist at some point, but by the time
362    you get around to creating it, someone else may have beaten you to
363    the punch.
364    """
365
366##    from warnings import warn as _warn
367##    _warn("mktemp is a potential security risk to your program",
368##          RuntimeWarning, stacklevel=2)
369
370    if dir is None:
371        dir = gettempdir()
372
373    names = _get_candidate_names()
374    for seq in xrange(TMP_MAX):
375        name = names.next()
376        file = _os.path.join(dir, prefix + name + suffix)
377        if not _exists(file):
378            return file
379
380    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
381
382
383class _TemporaryFileWrapper:
384    """Temporary file wrapper
385
386    This class provides a wrapper around files opened for
387    temporary use.  In particular, it seeks to automatically
388    remove the file when it is no longer needed.
389    """
390
391    def __init__(self, file, name, delete=True):
392        self.file = file
393        self.name = name
394        self.close_called = False
395        self.delete = delete
396
397    def __getattr__(self, name):
398        # Attribute lookups are delegated to the underlying file
399        # and cached for non-numeric results
400        # (i.e. methods are cached, closed and friends are not)
401        file = self.__dict__['file']
402        a = getattr(file, name)
403        if not issubclass(type(a), type(0)):
404            setattr(self, name, a)
405        return a
406
407    # The underlying __enter__ method returns the wrong object
408    # (self.file) so override it to return the wrapper
409    def __enter__(self):
410        self.file.__enter__()
411        return self
412
413    # NT provides delete-on-close as a primitive, so we don't need
414    # the wrapper to do anything special.  We still use it so that
415    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
416    if _os.name != 'nt':
417        # Cache the unlinker so we don't get spurious errors at
418        # shutdown when the module-level "os" is None'd out.  Note
419        # that this must be referenced as self.unlink, because the
420        # name TemporaryFileWrapper may also get None'd out before
421        # __del__ is called.
422        unlink = _os.unlink
423
424        def close(self):
425            if not self.close_called:
426                self.close_called = True
427                try:
428                    self.file.close()
429                finally:
430                    if self.delete:
431                        self.unlink(self.name)
432
433        def __del__(self):
434            self.close()
435
436        # Need to trap __exit__ as well to ensure the file gets
437        # deleted when used in a with statement
438        def __exit__(self, exc, value, tb):
439            result = self.file.__exit__(exc, value, tb)
440            self.close()
441            return result
442    else:
443        def __exit__(self, exc, value, tb):
444            self.file.__exit__(exc, value, tb)
445
446
447def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
448                       prefix=template, dir=None, delete=True):
449    """Create and return a temporary file.
450    Arguments:
451    'prefix', 'suffix', 'dir' -- as for mkstemp.
452    'mode' -- the mode argument to os.fdopen (default "w+b").
453    'bufsize' -- the buffer size argument to os.fdopen (default -1).
454    'delete' -- whether the file is deleted on close (default True).
455    The file is created as mkstemp() would do it.
456
457    Returns an object with a file-like interface; the name of the file
458    is accessible as file.name.  The file will be automatically deleted
459    when it is closed unless the 'delete' argument is set to False.
460    """
461
462    if dir is None:
463        dir = gettempdir()
464
465    if 'b' in mode:
466        flags = _bin_openflags
467    else:
468        flags = _text_openflags
469
470    # Setting O_TEMPORARY in the flags causes the OS to delete
471    # the file when it is closed.  This is only supported by Windows.
472    if _os.name == 'nt' and delete:
473        flags |= _os.O_TEMPORARY
474
475    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
476    try:
477        file = _os.fdopen(fd, mode, bufsize)
478        return _TemporaryFileWrapper(file, name, delete)
479    except:
480        _os.close(fd)
481        raise
482
483if _os.name != 'posix' or _os.sys.platform == 'cygwin':
484    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
485    # while it is open.
486    TemporaryFile = NamedTemporaryFile
487
488else:
489    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
490                      prefix=template, dir=None):
491        """Create and return a temporary file.
492        Arguments:
493        'prefix', 'suffix', 'dir' -- as for mkstemp.
494        'mode' -- the mode argument to os.fdopen (default "w+b").
495        'bufsize' -- the buffer size argument to os.fdopen (default -1).
496        The file is created as mkstemp() would do it.
497
498        Returns an object with a file-like interface.  The file has no
499        name, and will cease to exist when it is closed.
500        """
501
502        if dir is None:
503            dir = gettempdir()
504
505        if 'b' in mode:
506            flags = _bin_openflags
507        else:
508            flags = _text_openflags
509
510        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
511        try:
512            _os.unlink(name)
513            return _os.fdopen(fd, mode, bufsize)
514        except:
515            _os.close(fd)
516            raise
517
518class SpooledTemporaryFile:
519    """Temporary file wrapper, specialized to switch from
520    StringIO to a real file when it exceeds a certain size or
521    when a fileno is needed.
522    """
523    _rolled = False
524
525    def __init__(self, max_size=0, mode='w+b', bufsize=-1,
526                 suffix="", prefix=template, dir=None):
527        self._file = _StringIO()
528        self._max_size = max_size
529        self._rolled = False
530        self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir)
531
532    def _check(self, file):
533        if self._rolled: return
534        max_size = self._max_size
535        if max_size and file.tell() > max_size:
536            self.rollover()
537
538    def rollover(self):
539        if self._rolled: return
540        file = self._file
541        newfile = self._file = TemporaryFile(*self._TemporaryFileArgs)
542        del self._TemporaryFileArgs
543
544        newfile.write(file.getvalue())
545        newfile.seek(file.tell(), 0)
546
547        self._rolled = True
548
549    # The method caching trick from NamedTemporaryFile
550    # won't work here, because _file may change from a
551    # _StringIO instance to a real file. So we list
552    # all the methods directly.
553
554    # Context management protocol
555    def __enter__(self):
556        if self._file.closed:
557            raise ValueError("Cannot enter context with closed file")
558        return self
559
560    def __exit__(self, exc, value, tb):
561        self._file.close()
562
563    # file protocol
564    def __iter__(self):
565        return self._file.__iter__()
566
567    def close(self):
568        self._file.close()
569
570    @property
571    def closed(self):
572        return self._file.closed
573
574    def fileno(self):
575        self.rollover()
576        return self._file.fileno()
577
578    def flush(self):
579        self._file.flush()
580
581    def isatty(self):
582        return self._file.isatty()
583
584    @property
585    def mode(self):
586        try:
587            return self._file.mode
588        except AttributeError:
589            return self._TemporaryFileArgs[0]
590
591    @property
592    def name(self):
593        try:
594            return self._file.name
595        except AttributeError:
596            return None
597
598    def next(self):
599        return self._file.next
600
601    def read(self, *args):
602        return self._file.read(*args)
603
604    def readline(self, *args):
605        return self._file.readline(*args)
606
607    def readlines(self, *args):
608        return self._file.readlines(*args)
609
610    def seek(self, *args):
611        self._file.seek(*args)
612
613    @property
614    def softspace(self):
615        return self._file.softspace
616
617    def tell(self):
618        return self._file.tell()
619
620    def truncate(self):
621        self._file.truncate()
622
623    def write(self, s):
624        file = self._file
625        rv = file.write(s)
626        self._check(file)
627        return rv
628
629    def writelines(self, iterable):
630        file = self._file
631        rv = file.writelines(iterable)
632        self._check(file)
633        return rv
634
635    def xreadlines(self, *args):
636        if hasattr(self._file, 'xreadlines'):  # real file
637            return iter(self._file)
638        else:  # StringIO()
639            return iter(self._file.readlines(*args))
Note: See TracBrowser for help on using the repository browser.