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