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