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 272 273# User visible interfaces. 274 275def gettempprefix(): 276 """The default prefix for temporary directories as string.""" 277 return _os.fsdecode(template) 278 279def gettempprefixb(): 280 """The default prefix for temporary directories as bytes.""" 281 return _os.fsencode(template) 282 283tempdir = None 284 285def _gettempdir(): 286 """Private accessor for tempfile.tempdir.""" 287 global tempdir 288 if tempdir is None: 289 _once_lock.acquire() 290 try: 291 if tempdir is None: 292 tempdir = _get_default_tempdir() 293 finally: 294 _once_lock.release() 295 return tempdir 296 297def gettempdir(): 298 """Returns tempfile.tempdir as str.""" 299 return _os.fsdecode(_gettempdir()) 300 301def gettempdirb(): 302 """Returns tempfile.tempdir as bytes.""" 303 return _os.fsencode(_gettempdir()) 304 305def mkstemp(suffix=None, prefix=None, dir=None, text=False): 306 """User-callable function to create and return a unique temporary 307 file. The return value is a pair (fd, name) where fd is the 308 file descriptor returned by os.open, and name is the filename. 309 310 If 'suffix' is not None, the file name will end with that suffix, 311 otherwise there will be no suffix. 312 313 If 'prefix' is not None, the file name will begin with that prefix, 314 otherwise a default prefix is used. 315 316 If 'dir' is not None, the file will be created in that directory, 317 otherwise a default directory is used. 318 319 If 'text' is specified and true, the file is opened in text 320 mode. Else (the default) the file is opened in binary mode. 321 322 If any of 'suffix', 'prefix' and 'dir' are not None, they must be the 323 same type. If they are bytes, the returned name will be bytes; str 324 otherwise. 325 326 The file is readable and writable only by the creating user ID. 327 If the operating system uses permission bits to indicate whether a 328 file is executable, the file is executable by no one. The file 329 descriptor is not inherited by children of this process. 330 331 Caller is responsible for deleting the file when done with it. 332 """ 333 334 prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) 335 336 if text: 337 flags = _text_openflags 338 else: 339 flags = _bin_openflags 340 341 return _mkstemp_inner(dir, prefix, suffix, flags, output_type) 342 343 344def mkdtemp(suffix=None, prefix=None, dir=None): 345 """User-callable function to create and return a unique temporary 346 directory. The return value is the pathname of the directory. 347 348 Arguments are as for mkstemp, except that the 'text' argument is 349 not accepted. 350 351 The directory is readable, writable, and searchable only by the 352 creating user. 353 354 Caller is responsible for deleting the directory when done with it. 355 """ 356 357 prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) 358 359 names = _get_candidate_names() 360 if output_type is bytes: 361 names = map(_os.fsencode, names) 362 363 for seq in range(TMP_MAX): 364 name = next(names) 365 file = _os.path.join(dir, prefix + name + suffix) 366 _sys.audit("tempfile.mkdtemp", file) 367 try: 368 _os.mkdir(file, 0o700) 369 except FileExistsError: 370 continue # try again 371 except PermissionError: 372 # This exception is thrown when a directory with the chosen name 373 # already exists on windows. 374 if (_os.name == 'nt' and _os.path.isdir(dir) and 375 _os.access(dir, _os.W_OK)): 376 continue 377 else: 378 raise 379 return file 380 381 raise FileExistsError(_errno.EEXIST, 382 "No usable temporary directory name found") 383 384def mktemp(suffix="", prefix=template, dir=None): 385 """User-callable function to return a unique temporary file name. The 386 file is not created. 387 388 Arguments are similar to mkstemp, except that the 'text' argument is 389 not accepted, and suffix=None, prefix=None and bytes file names are not 390 supported. 391 392 THIS FUNCTION IS UNSAFE AND SHOULD NOT BE USED. The file name may 393 refer to a file that did not exist at some point, but by the time 394 you get around to creating it, someone else may have beaten you to 395 the punch. 396 """ 397 398## from warnings import warn as _warn 399## _warn("mktemp is a potential security risk to your program", 400## RuntimeWarning, stacklevel=2) 401 402 if dir is None: 403 dir = gettempdir() 404 405 names = _get_candidate_names() 406 for seq in range(TMP_MAX): 407 name = next(names) 408 file = _os.path.join(dir, prefix + name + suffix) 409 if not _exists(file): 410 return file 411 412 raise FileExistsError(_errno.EEXIST, 413 "No usable temporary filename found") 414 415 416class _TemporaryFileCloser: 417 """A separate object allowing proper closing of a temporary file's 418 underlying file object, without adding a __del__ method to the 419 temporary file.""" 420 421 file = None # Set here since __del__ checks it 422 close_called = False 423 424 def __init__(self, file, name, delete=True): 425 self.file = file 426 self.name = name 427 self.delete = delete 428 429 # NT provides delete-on-close as a primitive, so we don't need 430 # the wrapper to do anything special. We still use it so that 431 # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. 432 if _os.name != 'nt': 433 # Cache the unlinker so we don't get spurious errors at 434 # shutdown when the module-level "os" is None'd out. Note 435 # that this must be referenced as self.unlink, because the 436 # name TemporaryFileWrapper may also get None'd out before 437 # __del__ is called. 438 439 def close(self, unlink=_os.unlink): 440 if not self.close_called and self.file is not None: 441 self.close_called = True 442 try: 443 self.file.close() 444 finally: 445 if self.delete: 446 unlink(self.name) 447 448 # Need to ensure the file is deleted on __del__ 449 def __del__(self): 450 self.close() 451 452 else: 453 def close(self): 454 if not self.close_called: 455 self.close_called = True 456 self.file.close() 457 458 459class _TemporaryFileWrapper: 460 """Temporary file wrapper 461 462 This class provides a wrapper around files opened for 463 temporary use. In particular, it seeks to automatically 464 remove the file when it is no longer needed. 465 """ 466 467 def __init__(self, file, name, delete=True): 468 self.file = file 469 self.name = name 470 self.delete = delete 471 self._closer = _TemporaryFileCloser(file, name, delete) 472 473 def __getattr__(self, name): 474 # Attribute lookups are delegated to the underlying file 475 # and cached for non-numeric results 476 # (i.e. methods are cached, closed and friends are not) 477 file = self.__dict__['file'] 478 a = getattr(file, name) 479 if hasattr(a, '__call__'): 480 func = a 481 @_functools.wraps(func) 482 def func_wrapper(*args, **kwargs): 483 return func(*args, **kwargs) 484 # Avoid closing the file as long as the wrapper is alive, 485 # see issue #18879. 486 func_wrapper._closer = self._closer 487 a = func_wrapper 488 if not isinstance(a, int): 489 setattr(self, name, a) 490 return a 491 492 # The underlying __enter__ method returns the wrong object 493 # (self.file) so override it to return the wrapper 494 def __enter__(self): 495 self.file.__enter__() 496 return self 497 498 # Need to trap __exit__ as well to ensure the file gets 499 # deleted when used in a with statement 500 def __exit__(self, exc, value, tb): 501 result = self.file.__exit__(exc, value, tb) 502 self.close() 503 return result 504 505 def close(self): 506 """ 507 Close the temporary file, possibly deleting it. 508 """ 509 self._closer.close() 510 511 # iter() doesn't use __getattr__ to find the __iter__ method 512 def __iter__(self): 513 # Don't return iter(self.file), but yield from it to avoid closing 514 # file as long as it's being used as iterator (see issue #23700). We 515 # can't use 'yield from' here because iter(file) returns the file 516 # object itself, which has a close method, and thus the file would get 517 # closed when the generator is finalized, due to PEP380 semantics. 518 for line in self.file: 519 yield line 520 521 522def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, 523 newline=None, suffix=None, prefix=None, 524 dir=None, delete=True, *, errors=None): 525 """Create and return a temporary file. 526 Arguments: 527 'prefix', 'suffix', 'dir' -- as for mkstemp. 528 'mode' -- the mode argument to io.open (default "w+b"). 529 'buffering' -- the buffer size argument to io.open (default -1). 530 'encoding' -- the encoding argument to io.open (default None) 531 'newline' -- the newline argument to io.open (default None) 532 'delete' -- whether the file is deleted on close (default True). 533 'errors' -- the errors argument to io.open (default None) 534 The file is created as mkstemp() would do it. 535 536 Returns an object with a file-like interface; the name of the file 537 is accessible as its 'name' attribute. The file will be automatically 538 deleted when it is closed unless the 'delete' argument is set to False. 539 """ 540 541 prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) 542 543 flags = _bin_openflags 544 545 # Setting O_TEMPORARY in the flags causes the OS to delete 546 # the file when it is closed. This is only supported by Windows. 547 if _os.name == 'nt' and delete: 548 flags |= _os.O_TEMPORARY 549 550 if "b" not in mode: 551 encoding = _io.text_encoding(encoding) 552 553 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) 554 try: 555 file = _io.open(fd, mode, buffering=buffering, 556 newline=newline, encoding=encoding, errors=errors) 557 558 return _TemporaryFileWrapper(file, name, delete) 559 except BaseException: 560 _os.unlink(name) 561 _os.close(fd) 562 raise 563 564if _os.name != 'posix' or _sys.platform == 'cygwin': 565 # On non-POSIX and Cygwin systems, assume that we cannot unlink a file 566 # while it is open. 567 TemporaryFile = NamedTemporaryFile 568 569else: 570 # Is the O_TMPFILE flag available and does it work? 571 # The flag is set to False if os.open(dir, os.O_TMPFILE) raises an 572 # IsADirectoryError exception 573 _O_TMPFILE_WORKS = hasattr(_os, 'O_TMPFILE') 574 575 def TemporaryFile(mode='w+b', buffering=-1, encoding=None, 576 newline=None, suffix=None, prefix=None, 577 dir=None, *, errors=None): 578 """Create and return a temporary file. 579 Arguments: 580 'prefix', 'suffix', 'dir' -- as for mkstemp. 581 'mode' -- the mode argument to io.open (default "w+b"). 582 'buffering' -- the buffer size argument to io.open (default -1). 583 'encoding' -- the encoding argument to io.open (default None) 584 'newline' -- the newline argument to io.open (default None) 585 'errors' -- the errors argument to io.open (default None) 586 The file is created as mkstemp() would do it. 587 588 Returns an object with a file-like interface. The file has no 589 name, and will cease to exist when it is closed. 590 """ 591 global _O_TMPFILE_WORKS 592 593 if "b" not in mode: 594 encoding = _io.text_encoding(encoding) 595 596 prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) 597 598 flags = _bin_openflags 599 if _O_TMPFILE_WORKS: 600 try: 601 flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT 602 fd = _os.open(dir, flags2, 0o600) 603 except IsADirectoryError: 604 # Linux kernel older than 3.11 ignores the O_TMPFILE flag: 605 # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory 606 # with O_RDWR|O_DIRECTORY fails with IsADirectoryError, a 607 # directory cannot be open to write. Set flag to False to not 608 # try again. 609 _O_TMPFILE_WORKS = False 610 except OSError: 611 # The filesystem of the directory does not support O_TMPFILE. 612 # For example, OSError(95, 'Operation not supported'). 613 # 614 # On Linux kernel older than 3.11, trying to open a regular 615 # file (or a symbolic link to a regular file) with O_TMPFILE 616 # fails with NotADirectoryError, because O_TMPFILE is read as 617 # O_DIRECTORY. 618 pass 619 else: 620 try: 621 return _io.open(fd, mode, buffering=buffering, 622 newline=newline, encoding=encoding, 623 errors=errors) 624 except: 625 _os.close(fd) 626 raise 627 # Fallback to _mkstemp_inner(). 628 629 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) 630 try: 631 _os.unlink(name) 632 return _io.open(fd, mode, buffering=buffering, 633 newline=newline, encoding=encoding, errors=errors) 634 except: 635 _os.close(fd) 636 raise 637 638class SpooledTemporaryFile: 639 """Temporary file wrapper, specialized to switch from BytesIO 640 or StringIO to a real file when it exceeds a certain size or 641 when a fileno is needed. 642 """ 643 _rolled = False 644 645 def __init__(self, max_size=0, mode='w+b', buffering=-1, 646 encoding=None, newline=None, 647 suffix=None, prefix=None, dir=None, *, errors=None): 648 if 'b' in mode: 649 self._file = _io.BytesIO() 650 else: 651 encoding = _io.text_encoding(encoding) 652 self._file = _io.TextIOWrapper(_io.BytesIO(), 653 encoding=encoding, errors=errors, 654 newline=newline) 655 self._max_size = max_size 656 self._rolled = False 657 self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering, 658 'suffix': suffix, 'prefix': prefix, 659 'encoding': encoding, 'newline': newline, 660 'dir': dir, 'errors': errors} 661 662 __class_getitem__ = classmethod(_types.GenericAlias) 663 664 def _check(self, file): 665 if self._rolled: return 666 max_size = self._max_size 667 if max_size and file.tell() > max_size: 668 self.rollover() 669 670 def rollover(self): 671 if self._rolled: return 672 file = self._file 673 newfile = self._file = TemporaryFile(**self._TemporaryFileArgs) 674 del self._TemporaryFileArgs 675 676 pos = file.tell() 677 if hasattr(newfile, 'buffer'): 678 newfile.buffer.write(file.detach().getvalue()) 679 else: 680 newfile.write(file.getvalue()) 681 newfile.seek(pos, 0) 682 683 self._rolled = True 684 685 # The method caching trick from NamedTemporaryFile 686 # won't work here, because _file may change from a 687 # BytesIO/StringIO instance to a real file. So we list 688 # all the methods directly. 689 690 # Context management protocol 691 def __enter__(self): 692 if self._file.closed: 693 raise ValueError("Cannot enter context with closed file") 694 return self 695 696 def __exit__(self, exc, value, tb): 697 self._file.close() 698 699 # file protocol 700 def __iter__(self): 701 return self._file.__iter__() 702 703 def close(self): 704 self._file.close() 705 706 @property 707 def closed(self): 708 return self._file.closed 709 710 @property 711 def encoding(self): 712 return self._file.encoding 713 714 @property 715 def errors(self): 716 return self._file.errors 717 718 def fileno(self): 719 self.rollover() 720 return self._file.fileno() 721 722 def flush(self): 723 self._file.flush() 724 725 def isatty(self): 726 return self._file.isatty() 727 728 @property 729 def mode(self): 730 try: 731 return self._file.mode 732 except AttributeError: 733 return self._TemporaryFileArgs['mode'] 734 735 @property 736 def name(self): 737 try: 738 return self._file.name 739 except AttributeError: 740 return None 741 742 @property 743 def newlines(self): 744 return self._file.newlines 745 746 def read(self, *args): 747 return self._file.read(*args) 748 749 def readline(self, *args): 750 return self._file.readline(*args) 751 752 def readlines(self, *args): 753 return self._file.readlines(*args) 754 755 def seek(self, *args): 756 return self._file.seek(*args) 757 758 def tell(self): 759 return self._file.tell() 760 761 def truncate(self, size=None): 762 if size is None: 763 self._file.truncate() 764 else: 765 if size > self._max_size: 766 self.rollover() 767 self._file.truncate(size) 768 769 def write(self, s): 770 file = self._file 771 rv = file.write(s) 772 self._check(file) 773 return rv 774 775 def writelines(self, iterable): 776 file = self._file 777 rv = file.writelines(iterable) 778 self._check(file) 779 return rv 780 781 782class TemporaryDirectory: 783 """Create and return a temporary directory. This has the same 784 behavior as mkdtemp but can be used as a context manager. For 785 example: 786 787 with TemporaryDirectory() as tmpdir: 788 ... 789 790 Upon exiting the context, the directory and everything contained 791 in it are removed. 792 """ 793 794 def __init__(self, suffix=None, prefix=None, dir=None, 795 ignore_cleanup_errors=False): 796 self.name = mkdtemp(suffix, prefix, dir) 797 self._ignore_cleanup_errors = ignore_cleanup_errors 798 self._finalizer = _weakref.finalize( 799 self, self._cleanup, self.name, 800 warn_message="Implicitly cleaning up {!r}".format(self), 801 ignore_errors=self._ignore_cleanup_errors) 802 803 @classmethod 804 def _rmtree(cls, name, ignore_errors=False): 805 def onerror(func, path, exc_info): 806 if issubclass(exc_info[0], PermissionError): 807 def resetperms(path): 808 try: 809 _os.chflags(path, 0) 810 except AttributeError: 811 pass 812 _os.chmod(path, 0o700) 813 814 try: 815 if path != name: 816 resetperms(_os.path.dirname(path)) 817 resetperms(path) 818 819 try: 820 _os.unlink(path) 821 # PermissionError is raised on FreeBSD for directories 822 except (IsADirectoryError, PermissionError): 823 cls._rmtree(path, ignore_errors=ignore_errors) 824 except FileNotFoundError: 825 pass 826 elif issubclass(exc_info[0], FileNotFoundError): 827 pass 828 else: 829 if not ignore_errors: 830 raise 831 832 _shutil.rmtree(name, onerror=onerror) 833 834 @classmethod 835 def _cleanup(cls, name, warn_message, ignore_errors=False): 836 cls._rmtree(name, ignore_errors=ignore_errors) 837 _warnings.warn(warn_message, ResourceWarning) 838 839 def __repr__(self): 840 return "<{} {!r}>".format(self.__class__.__name__, self.name) 841 842 def __enter__(self): 843 return self.name 844 845 def __exit__(self, exc, value, tb): 846 self.cleanup() 847 848 def cleanup(self): 849 if self._finalizer.detach() or _os.path.exists(self.name): 850 self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors) 851 852 __class_getitem__ = classmethod(_types.GenericAlias) 853