• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9The default path names are returned as str.  If you supply bytes as
10input, all return values will be in bytes.  Ex:
11
12    >>> tempfile.mkstemp()
13    (4, '/tmp/tmptpu9nin8')
14    >>> tempfile.mkdtemp(suffix=b'')
15    b'/tmp/tmppbi8f0hy'
16
17This module also provides some data items to the user:
18
19  TMP_MAX  - maximum number of names that will be tried before
20             giving up.
21  tempdir  - If this is set to a string before the first use of
22             any routine from this module, it will be considered as
23             another candidate location to store temporary files.
24"""
25
26__all__ = [
27    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
28    "SpooledTemporaryFile", "TemporaryDirectory",
29    "mkstemp", "mkdtemp",                  # low level safe interfaces
30    "mktemp",                              # deprecated unsafe interface
31    "TMP_MAX", "gettempprefix",            # constants
32    "tempdir", "gettempdir",
33    "gettempprefixb", "gettempdirb",
34   ]
35
36
37# Imports.
38
39import functools as _functools
40import warnings as _warnings
41import io as _io
42import os as _os
43import shutil as _shutil
44import errno as _errno
45from random import Random as _Random
46import sys as _sys
47import types as _types
48import weakref as _weakref
49import _thread
50_allocate_lock = _thread.allocate_lock
51
52_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
53if hasattr(_os, 'O_NOFOLLOW'):
54    _text_openflags |= _os.O_NOFOLLOW
55
56_bin_openflags = _text_openflags
57if hasattr(_os, 'O_BINARY'):
58    _bin_openflags |= _os.O_BINARY
59
60if hasattr(_os, 'TMP_MAX'):
61    TMP_MAX = _os.TMP_MAX
62else:
63    TMP_MAX = 10000
64
65# This variable _was_ unused for legacy reasons, see issue 10354.
66# But as of 3.5 we actually use it at runtime so changing it would
67# have a possibly desirable side effect...  But we do not want to support
68# that as an API.  It is undocumented on purpose.  Do not depend on this.
69template = "tmp"
70
71# Internal routines.
72
73_once_lock = _allocate_lock()
74
75
76def _exists(fn):
77    try:
78        _os.lstat(fn)
79    except OSError:
80        return False
81    else:
82        return True
83
84
85def _infer_return_type(*args):
86    """Look at the type of all args and divine their implied return type."""
87    return_type = None
88    for arg in args:
89        if arg is None:
90            continue
91
92        if isinstance(arg, _os.PathLike):
93            arg = _os.fspath(arg)
94
95        if isinstance(arg, bytes):
96            if return_type is str:
97                raise TypeError("Can't mix bytes and non-bytes in "
98                                "path components.")
99            return_type = bytes
100        else:
101            if return_type is bytes:
102                raise TypeError("Can't mix bytes and non-bytes in "
103                                "path components.")
104            return_type = str
105    if return_type is None:
106        if tempdir is None or isinstance(tempdir, str):
107            return str  # tempfile APIs return a str by default.
108        else:
109            # we could check for bytes but it'll fail later on anyway
110            return bytes
111    return return_type
112
113
114def _sanitize_params(prefix, suffix, dir):
115    """Common parameter processing for most APIs in this module."""
116    output_type = _infer_return_type(prefix, suffix, dir)
117    if suffix is None:
118        suffix = output_type()
119    if prefix is None:
120        if output_type is str:
121            prefix = template
122        else:
123            prefix = _os.fsencode(template)
124    if dir is None:
125        if output_type is str:
126            dir = gettempdir()
127        else:
128            dir = gettempdirb()
129    return prefix, suffix, dir, output_type
130
131
132class _RandomNameSequence:
133    """An instance of _RandomNameSequence generates an endless
134    sequence of unpredictable strings which can safely be incorporated
135    into file names.  Each string is eight characters long.  Multiple
136    threads can safely use the same instance at the same time.
137
138    _RandomNameSequence is an iterator."""
139
140    characters = "abcdefghijklmnopqrstuvwxyz0123456789_"
141
142    @property
143    def rng(self):
144        cur_pid = _os.getpid()
145        if cur_pid != getattr(self, '_rng_pid', None):
146            self._rng = _Random()
147            self._rng_pid = cur_pid
148        return self._rng
149
150    def __iter__(self):
151        return self
152
153    def __next__(self):
154        return ''.join(self.rng.choices(self.characters, k=8))
155
156def _candidate_tempdir_list():
157    """Generate a list of candidate temporary directories which
158    _get_default_tempdir will try."""
159
160    dirlist = []
161
162    # First, try the environment.
163    for envname in 'TMPDIR', 'TEMP', 'TMP':
164        dirname = _os.getenv(envname)
165        if dirname: dirlist.append(dirname)
166
167    # Failing that, try OS-specific locations.
168    if _os.name == 'nt':
169        dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'),
170                         _os.path.expandvars(r'%SYSTEMROOT%\Temp'),
171                         r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
172    else:
173        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
174
175    # As a last resort, the current directory.
176    try:
177        dirlist.append(_os.getcwd())
178    except (AttributeError, OSError):
179        dirlist.append(_os.curdir)
180
181    return dirlist
182
183def _get_default_tempdir():
184    """Calculate the default directory to use for temporary files.
185    This routine should be called exactly once.
186
187    We determine whether or not a candidate temp dir is usable by
188    trying to create and write to a file in that directory.  If this
189    is successful, the test file is deleted.  To prevent denial of
190    service, the name of the test file must be randomized."""
191
192    namer = _RandomNameSequence()
193    dirlist = _candidate_tempdir_list()
194
195    for dir in dirlist:
196        if dir != _os.curdir:
197            dir = _os.path.abspath(dir)
198        # Try only a few names per directory.
199        for seq in range(100):
200            name = next(namer)
201            filename = _os.path.join(dir, name)
202            try:
203                fd = _os.open(filename, _bin_openflags, 0o600)
204                try:
205                    try:
206                        with _io.open(fd, 'wb', closefd=False) as fp:
207                            fp.write(b'blat')
208                    finally:
209                        _os.close(fd)
210                finally:
211                    _os.unlink(filename)
212                return dir
213            except FileExistsError:
214                pass
215            except PermissionError:
216                # This exception is thrown when a directory with the chosen name
217                # already exists on windows.
218                if (_os.name == 'nt' and _os.path.isdir(dir) and
219                    _os.access(dir, _os.W_OK)):
220                    continue
221                break   # no point trying more names in this directory
222            except OSError:
223                break   # no point trying more names in this directory
224    raise FileNotFoundError(_errno.ENOENT,
225                            "No usable temporary directory found in %s" %
226                            dirlist)
227
228_name_sequence = None
229
230def _get_candidate_names():
231    """Common setup sequence for all user-callable interfaces."""
232
233    global _name_sequence
234    if _name_sequence is None:
235        _once_lock.acquire()
236        try:
237            if _name_sequence is None:
238                _name_sequence = _RandomNameSequence()
239        finally:
240            _once_lock.release()
241    return _name_sequence
242
243
244def _mkstemp_inner(dir, pre, suf, flags, output_type):
245    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
246
247    names = _get_candidate_names()
248    if output_type is bytes:
249        names = map(_os.fsencode, names)
250
251    for seq in range(TMP_MAX):
252        name = next(names)
253        file = _os.path.join(dir, pre + name + suf)
254        _sys.audit("tempfile.mkstemp", file)
255        try:
256            fd = _os.open(file, flags, 0o600)
257        except FileExistsError:
258            continue    # try again
259        except PermissionError:
260            # This exception is thrown when a directory with the chosen name
261            # already exists on windows.
262            if (_os.name == 'nt' and _os.path.isdir(dir) and
263                _os.access(dir, _os.W_OK)):
264                continue
265            else:
266                raise
267        return (fd, _os.path.abspath(file))
268
269    raise FileExistsError(_errno.EEXIST,
270                          "No usable temporary file name found")
271
272def _dont_follow_symlinks(func, path, *args):
273    # Pass follow_symlinks=False, unless not supported on this platform.
274    if func in _os.supports_follow_symlinks:
275        func(path, *args, follow_symlinks=False)
276    elif _os.name == 'nt' or not _os.path.islink(path):
277        func(path, *args)
278
279def _resetperms(path):
280    try:
281        chflags = _os.chflags
282    except AttributeError:
283        pass
284    else:
285        _dont_follow_symlinks(chflags, path, 0)
286    _dont_follow_symlinks(_os.chmod, path, 0o700)
287
288
289# User visible interfaces.
290
291def gettempprefix():
292    """The default prefix for temporary directories as string."""
293    return _os.fsdecode(template)
294
295def gettempprefixb():
296    """The default prefix for temporary directories as bytes."""
297    return _os.fsencode(template)
298
299tempdir = None
300
301def _gettempdir():
302    """Private accessor for tempfile.tempdir."""
303    global tempdir
304    if tempdir is None:
305        _once_lock.acquire()
306        try:
307            if tempdir is None:
308                tempdir = _get_default_tempdir()
309        finally:
310            _once_lock.release()
311    return tempdir
312
313def gettempdir():
314    """Returns tempfile.tempdir as str."""
315    return _os.fsdecode(_gettempdir())
316
317def gettempdirb():
318    """Returns tempfile.tempdir as bytes."""
319    return _os.fsencode(_gettempdir())
320
321def mkstemp(suffix=None, prefix=None, dir=None, text=False):
322    """User-callable function to create and return a unique temporary
323    file.  The return value is a pair (fd, name) where fd is the
324    file descriptor returned by os.open, and name is the filename.
325
326    If 'suffix' is not None, the file name will end with that suffix,
327    otherwise there will be no suffix.
328
329    If 'prefix' is not None, the file name will begin with that prefix,
330    otherwise a default prefix is used.
331
332    If 'dir' is not None, the file will be created in that directory,
333    otherwise a default directory is used.
334
335    If 'text' is specified and true, the file is opened in text
336    mode.  Else (the default) the file is opened in binary mode.
337
338    If any of 'suffix', 'prefix' and 'dir' are not None, they must be the
339    same type.  If they are bytes, the returned name will be bytes; str
340    otherwise.
341
342    The file is readable and writable only by the creating user ID.
343    If the operating system uses permission bits to indicate whether a
344    file is executable, the file is executable by no one. The file
345    descriptor is not inherited by children of this process.
346
347    Caller is responsible for deleting the file when done with it.
348    """
349
350    prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
351
352    if text:
353        flags = _text_openflags
354    else:
355        flags = _bin_openflags
356
357    return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
358
359
360def mkdtemp(suffix=None, prefix=None, dir=None):
361    """User-callable function to create and return a unique temporary
362    directory.  The return value is the pathname of the directory.
363
364    Arguments are as for mkstemp, except that the 'text' argument is
365    not accepted.
366
367    The directory is readable, writable, and searchable only by the
368    creating user.
369
370    Caller is responsible for deleting the directory when done with it.
371    """
372
373    prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
374
375    names = _get_candidate_names()
376    if output_type is bytes:
377        names = map(_os.fsencode, names)
378
379    for seq in range(TMP_MAX):
380        name = next(names)
381        file = _os.path.join(dir, prefix + name + suffix)
382        _sys.audit("tempfile.mkdtemp", file)
383        try:
384            _os.mkdir(file, 0o700)
385        except FileExistsError:
386            continue    # try again
387        except PermissionError:
388            # This exception is thrown when a directory with the chosen name
389            # already exists on windows.
390            if (_os.name == 'nt' and _os.path.isdir(dir) and
391                _os.access(dir, _os.W_OK)):
392                continue
393            else:
394                raise
395        return file
396
397    raise FileExistsError(_errno.EEXIST,
398                          "No usable temporary directory name found")
399
400def mktemp(suffix="", prefix=template, dir=None):
401    """User-callable function to return a unique temporary file name.  The
402    file is not created.
403
404    Arguments are similar to mkstemp, except that the 'text' argument is
405    not accepted, and suffix=None, prefix=None and bytes file names are not
406    supported.
407
408    THIS FUNCTION IS UNSAFE AND SHOULD NOT BE USED.  The file name may
409    refer to a file that did not exist at some point, but by the time
410    you get around to creating it, someone else may have beaten you to
411    the punch.
412    """
413
414##    from warnings import warn as _warn
415##    _warn("mktemp is a potential security risk to your program",
416##          RuntimeWarning, stacklevel=2)
417
418    if dir is None:
419        dir = gettempdir()
420
421    names = _get_candidate_names()
422    for seq in range(TMP_MAX):
423        name = next(names)
424        file = _os.path.join(dir, prefix + name + suffix)
425        if not _exists(file):
426            return file
427
428    raise FileExistsError(_errno.EEXIST,
429                          "No usable temporary filename found")
430
431
432class _TemporaryFileCloser:
433    """A separate object allowing proper closing of a temporary file's
434    underlying file object, without adding a __del__ method to the
435    temporary file."""
436
437    file = None  # Set here since __del__ checks it
438    close_called = False
439
440    def __init__(self, file, name, delete=True):
441        self.file = file
442        self.name = name
443        self.delete = delete
444
445    # NT provides delete-on-close as a primitive, so we don't need
446    # the wrapper to do anything special.  We still use it so that
447    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
448    if _os.name != 'nt':
449        # Cache the unlinker so we don't get spurious errors at
450        # shutdown when the module-level "os" is None'd out.  Note
451        # that this must be referenced as self.unlink, because the
452        # name TemporaryFileWrapper may also get None'd out before
453        # __del__ is called.
454
455        def close(self, unlink=_os.unlink):
456            if not self.close_called and self.file is not None:
457                self.close_called = True
458                try:
459                    self.file.close()
460                finally:
461                    if self.delete:
462                        unlink(self.name)
463
464        # Need to ensure the file is deleted on __del__
465        def __del__(self):
466            self.close()
467
468    else:
469        def close(self):
470            if not self.close_called:
471                self.close_called = True
472                self.file.close()
473
474
475class _TemporaryFileWrapper:
476    """Temporary file wrapper
477
478    This class provides a wrapper around files opened for
479    temporary use.  In particular, it seeks to automatically
480    remove the file when it is no longer needed.
481    """
482
483    def __init__(self, file, name, delete=True):
484        self.file = file
485        self.name = name
486        self.delete = delete
487        self._closer = _TemporaryFileCloser(file, name, delete)
488
489    def __getattr__(self, name):
490        # Attribute lookups are delegated to the underlying file
491        # and cached for non-numeric results
492        # (i.e. methods are cached, closed and friends are not)
493        file = self.__dict__['file']
494        a = getattr(file, name)
495        if hasattr(a, '__call__'):
496            func = a
497            @_functools.wraps(func)
498            def func_wrapper(*args, **kwargs):
499                return func(*args, **kwargs)
500            # Avoid closing the file as long as the wrapper is alive,
501            # see issue #18879.
502            func_wrapper._closer = self._closer
503            a = func_wrapper
504        if not isinstance(a, int):
505            setattr(self, name, a)
506        return a
507
508    # The underlying __enter__ method returns the wrong object
509    # (self.file) so override it to return the wrapper
510    def __enter__(self):
511        self.file.__enter__()
512        return self
513
514    # Need to trap __exit__ as well to ensure the file gets
515    # deleted when used in a with statement
516    def __exit__(self, exc, value, tb):
517        result = self.file.__exit__(exc, value, tb)
518        self.close()
519        return result
520
521    def close(self):
522        """
523        Close the temporary file, possibly deleting it.
524        """
525        self._closer.close()
526
527    # iter() doesn't use __getattr__ to find the __iter__ method
528    def __iter__(self):
529        # Don't return iter(self.file), but yield from it to avoid closing
530        # file as long as it's being used as iterator (see issue #23700).  We
531        # can't use 'yield from' here because iter(file) returns the file
532        # object itself, which has a close method, and thus the file would get
533        # closed when the generator is finalized, due to PEP380 semantics.
534        for line in self.file:
535            yield line
536
537
538def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
539                       newline=None, suffix=None, prefix=None,
540                       dir=None, delete=True, *, errors=None):
541    """Create and return a temporary file.
542    Arguments:
543    'prefix', 'suffix', 'dir' -- as for mkstemp.
544    'mode' -- the mode argument to io.open (default "w+b").
545    'buffering' -- the buffer size argument to io.open (default -1).
546    'encoding' -- the encoding argument to io.open (default None)
547    'newline' -- the newline argument to io.open (default None)
548    'delete' -- whether the file is deleted on close (default True).
549    'errors' -- the errors argument to io.open (default None)
550    The file is created as mkstemp() would do it.
551
552    Returns an object with a file-like interface; the name of the file
553    is accessible as its 'name' attribute.  The file will be automatically
554    deleted when it is closed unless the 'delete' argument is set to False.
555    """
556
557    prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
558
559    flags = _bin_openflags
560
561    # Setting O_TEMPORARY in the flags causes the OS to delete
562    # the file when it is closed.  This is only supported by Windows.
563    if _os.name == 'nt' and delete:
564        flags |= _os.O_TEMPORARY
565
566    if "b" not in mode:
567        encoding = _io.text_encoding(encoding)
568
569    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
570    try:
571        file = _io.open(fd, mode, buffering=buffering,
572                        newline=newline, encoding=encoding, errors=errors)
573
574        return _TemporaryFileWrapper(file, name, delete)
575    except BaseException:
576        _os.unlink(name)
577        _os.close(fd)
578        raise
579
580if _os.name != 'posix' or _sys.platform == 'cygwin':
581    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
582    # while it is open.
583    TemporaryFile = NamedTemporaryFile
584
585else:
586    # Is the O_TMPFILE flag available and does it work?
587    # The flag is set to False if os.open(dir, os.O_TMPFILE) raises an
588    # IsADirectoryError exception
589    _O_TMPFILE_WORKS = hasattr(_os, 'O_TMPFILE')
590
591    def TemporaryFile(mode='w+b', buffering=-1, encoding=None,
592                      newline=None, suffix=None, prefix=None,
593                      dir=None, *, errors=None):
594        """Create and return a temporary file.
595        Arguments:
596        'prefix', 'suffix', 'dir' -- as for mkstemp.
597        'mode' -- the mode argument to io.open (default "w+b").
598        'buffering' -- the buffer size argument to io.open (default -1).
599        'encoding' -- the encoding argument to io.open (default None)
600        'newline' -- the newline argument to io.open (default None)
601        'errors' -- the errors argument to io.open (default None)
602        The file is created as mkstemp() would do it.
603
604        Returns an object with a file-like interface.  The file has no
605        name, and will cease to exist when it is closed.
606        """
607        global _O_TMPFILE_WORKS
608
609        if "b" not in mode:
610            encoding = _io.text_encoding(encoding)
611
612        prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
613
614        flags = _bin_openflags
615        if _O_TMPFILE_WORKS:
616            try:
617                flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT
618                fd = _os.open(dir, flags2, 0o600)
619            except IsADirectoryError:
620                # Linux kernel older than 3.11 ignores the O_TMPFILE flag:
621                # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory
622                # with O_RDWR|O_DIRECTORY fails with IsADirectoryError, a
623                # directory cannot be open to write. Set flag to False to not
624                # try again.
625                _O_TMPFILE_WORKS = False
626            except OSError:
627                # The filesystem of the directory does not support O_TMPFILE.
628                # For example, OSError(95, 'Operation not supported').
629                #
630                # On Linux kernel older than 3.11, trying to open a regular
631                # file (or a symbolic link to a regular file) with O_TMPFILE
632                # fails with NotADirectoryError, because O_TMPFILE is read as
633                # O_DIRECTORY.
634                pass
635            else:
636                try:
637                    return _io.open(fd, mode, buffering=buffering,
638                                    newline=newline, encoding=encoding,
639                                    errors=errors)
640                except:
641                    _os.close(fd)
642                    raise
643            # Fallback to _mkstemp_inner().
644
645        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
646        try:
647            _os.unlink(name)
648            return _io.open(fd, mode, buffering=buffering,
649                            newline=newline, encoding=encoding, errors=errors)
650        except:
651            _os.close(fd)
652            raise
653
654class SpooledTemporaryFile:
655    """Temporary file wrapper, specialized to switch from BytesIO
656    or StringIO to a real file when it exceeds a certain size or
657    when a fileno is needed.
658    """
659    _rolled = False
660
661    def __init__(self, max_size=0, mode='w+b', buffering=-1,
662                 encoding=None, newline=None,
663                 suffix=None, prefix=None, dir=None, *, errors=None):
664        if 'b' in mode:
665            self._file = _io.BytesIO()
666        else:
667            encoding = _io.text_encoding(encoding)
668            self._file = _io.TextIOWrapper(_io.BytesIO(),
669                            encoding=encoding, errors=errors,
670                            newline=newline)
671        self._max_size = max_size
672        self._rolled = False
673        self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
674                                   'suffix': suffix, 'prefix': prefix,
675                                   'encoding': encoding, 'newline': newline,
676                                   'dir': dir, 'errors': errors}
677
678    __class_getitem__ = classmethod(_types.GenericAlias)
679
680    def _check(self, file):
681        if self._rolled: return
682        max_size = self._max_size
683        if max_size and file.tell() > max_size:
684            self.rollover()
685
686    def rollover(self):
687        if self._rolled: return
688        file = self._file
689        newfile = self._file = TemporaryFile(**self._TemporaryFileArgs)
690        del self._TemporaryFileArgs
691
692        pos = file.tell()
693        if hasattr(newfile, 'buffer'):
694            newfile.buffer.write(file.detach().getvalue())
695        else:
696            newfile.write(file.getvalue())
697        newfile.seek(pos, 0)
698
699        self._rolled = True
700
701    # The method caching trick from NamedTemporaryFile
702    # won't work here, because _file may change from a
703    # BytesIO/StringIO instance to a real file. So we list
704    # all the methods directly.
705
706    # Context management protocol
707    def __enter__(self):
708        if self._file.closed:
709            raise ValueError("Cannot enter context with closed file")
710        return self
711
712    def __exit__(self, exc, value, tb):
713        self._file.close()
714
715    # file protocol
716    def __iter__(self):
717        return self._file.__iter__()
718
719    def close(self):
720        self._file.close()
721
722    @property
723    def closed(self):
724        return self._file.closed
725
726    @property
727    def encoding(self):
728        return self._file.encoding
729
730    @property
731    def errors(self):
732        return self._file.errors
733
734    def fileno(self):
735        self.rollover()
736        return self._file.fileno()
737
738    def flush(self):
739        self._file.flush()
740
741    def isatty(self):
742        return self._file.isatty()
743
744    @property
745    def mode(self):
746        try:
747            return self._file.mode
748        except AttributeError:
749            return self._TemporaryFileArgs['mode']
750
751    @property
752    def name(self):
753        try:
754            return self._file.name
755        except AttributeError:
756            return None
757
758    @property
759    def newlines(self):
760        return self._file.newlines
761
762    def read(self, *args):
763        return self._file.read(*args)
764
765    def readline(self, *args):
766        return self._file.readline(*args)
767
768    def readlines(self, *args):
769        return self._file.readlines(*args)
770
771    def seek(self, *args):
772        return self._file.seek(*args)
773
774    def tell(self):
775        return self._file.tell()
776
777    def truncate(self, size=None):
778        if size is None:
779            self._file.truncate()
780        else:
781            if size > self._max_size:
782                self.rollover()
783            self._file.truncate(size)
784
785    def write(self, s):
786        file = self._file
787        rv = file.write(s)
788        self._check(file)
789        return rv
790
791    def writelines(self, iterable):
792        file = self._file
793        rv = file.writelines(iterable)
794        self._check(file)
795        return rv
796
797
798class TemporaryDirectory:
799    """Create and return a temporary directory.  This has the same
800    behavior as mkdtemp but can be used as a context manager.  For
801    example:
802
803        with TemporaryDirectory() as tmpdir:
804            ...
805
806    Upon exiting the context, the directory and everything contained
807    in it are removed.
808    """
809
810    def __init__(self, suffix=None, prefix=None, dir=None,
811                 ignore_cleanup_errors=False):
812        self.name = mkdtemp(suffix, prefix, dir)
813        self._ignore_cleanup_errors = ignore_cleanup_errors
814        self._finalizer = _weakref.finalize(
815            self, self._cleanup, self.name,
816            warn_message="Implicitly cleaning up {!r}".format(self),
817            ignore_errors=self._ignore_cleanup_errors)
818
819    @classmethod
820    def _rmtree(cls, name, ignore_errors=False):
821        def onerror(func, path, exc_info):
822            if issubclass(exc_info[0], PermissionError):
823                try:
824                    if path != name:
825                        _resetperms(_os.path.dirname(path))
826                    _resetperms(path)
827
828                    try:
829                        _os.unlink(path)
830                    # PermissionError is raised on FreeBSD for directories
831                    except (IsADirectoryError, PermissionError):
832                        cls._rmtree(path, ignore_errors=ignore_errors)
833                except FileNotFoundError:
834                    pass
835            elif issubclass(exc_info[0], FileNotFoundError):
836                pass
837            else:
838                if not ignore_errors:
839                    raise
840
841        _shutil.rmtree(name, onerror=onerror)
842
843    @classmethod
844    def _cleanup(cls, name, warn_message, ignore_errors=False):
845        cls._rmtree(name, ignore_errors=ignore_errors)
846        _warnings.warn(warn_message, ResourceWarning)
847
848    def __repr__(self):
849        return "<{} {!r}>".format(self.__class__.__name__, self.name)
850
851    def __enter__(self):
852        return self.name
853
854    def __exit__(self, exc, value, tb):
855        self.cleanup()
856
857    def cleanup(self):
858        if self._finalizer.detach() or _os.path.exists(self.name):
859            self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors)
860
861    __class_getitem__ = classmethod(_types.GenericAlias)
862