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 if isinstance(arg, bytes): 92 if return_type is str: 93 raise TypeError("Can't mix bytes and non-bytes in " 94 "path components.") 95 return_type = bytes 96 else: 97 if return_type is bytes: 98 raise TypeError("Can't mix bytes and non-bytes in " 99 "path components.") 100 return_type = str 101 if return_type is None: 102 return str # tempfile APIs return a str by default. 103 return return_type 104 105 106def _sanitize_params(prefix, suffix, dir): 107 """Common parameter processing for most APIs in this module.""" 108 output_type = _infer_return_type(prefix, suffix, dir) 109 if suffix is None: 110 suffix = output_type() 111 if prefix is None: 112 if output_type is str: 113 prefix = template 114 else: 115 prefix = _os.fsencode(template) 116 if dir is None: 117 if output_type is str: 118 dir = gettempdir() 119 else: 120 dir = gettempdirb() 121 return prefix, suffix, dir, output_type 122 123 124class _RandomNameSequence: 125 """An instance of _RandomNameSequence generates an endless 126 sequence of unpredictable strings which can safely be incorporated 127 into file names. Each string is eight characters long. Multiple 128 threads can safely use the same instance at the same time. 129 130 _RandomNameSequence is an iterator.""" 131 132 characters = "abcdefghijklmnopqrstuvwxyz0123456789_" 133 134 @property 135 def rng(self): 136 cur_pid = _os.getpid() 137 if cur_pid != getattr(self, '_rng_pid', None): 138 self._rng = _Random() 139 self._rng_pid = cur_pid 140 return self._rng 141 142 def __iter__(self): 143 return self 144 145 def __next__(self): 146 c = self.characters 147 choose = self.rng.choice 148 letters = [choose(c) for dummy in range(8)] 149 return ''.join(letters) 150 151def _candidate_tempdir_list(): 152 """Generate a list of candidate temporary directories which 153 _get_default_tempdir will try.""" 154 155 dirlist = [] 156 157 # First, try the environment. 158 for envname in 'TMPDIR', 'TEMP', 'TMP': 159 dirname = _os.getenv(envname) 160 if dirname: dirlist.append(dirname) 161 162 # Failing that, try OS-specific locations. 163 if _os.name == 'nt': 164 dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), 165 _os.path.expandvars(r'%SYSTEMROOT%\Temp'), 166 r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) 167 else: 168 dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) 169 170 # As a last resort, the current directory. 171 try: 172 dirlist.append(_os.getcwd()) 173 except (AttributeError, OSError): 174 dirlist.append(_os.curdir) 175 176 return dirlist 177 178def _get_default_tempdir(): 179 """Calculate the default directory to use for temporary files. 180 This routine should be called exactly once. 181 182 We determine whether or not a candidate temp dir is usable by 183 trying to create and write to a file in that directory. If this 184 is successful, the test file is deleted. To prevent denial of 185 service, the name of the test file must be randomized.""" 186 187 namer = _RandomNameSequence() 188 dirlist = _candidate_tempdir_list() 189 190 for dir in dirlist: 191 if dir != _os.curdir: 192 dir = _os.path.abspath(dir) 193 # Try only a few names per directory. 194 for seq in range(100): 195 name = next(namer) 196 filename = _os.path.join(dir, name) 197 try: 198 fd = _os.open(filename, _bin_openflags, 0o600) 199 try: 200 try: 201 with _io.open(fd, 'wb', closefd=False) as fp: 202 fp.write(b'blat') 203 finally: 204 _os.close(fd) 205 finally: 206 _os.unlink(filename) 207 return dir 208 except FileExistsError: 209 pass 210 except PermissionError: 211 # This exception is thrown when a directory with the chosen name 212 # already exists on windows. 213 if (_os.name == 'nt' and _os.path.isdir(dir) and 214 _os.access(dir, _os.W_OK)): 215 continue 216 break # no point trying more names in this directory 217 except OSError: 218 break # no point trying more names in this directory 219 raise FileNotFoundError(_errno.ENOENT, 220 "No usable temporary directory found in %s" % 221 dirlist) 222 223_name_sequence = None 224 225def _get_candidate_names(): 226 """Common setup sequence for all user-callable interfaces.""" 227 228 global _name_sequence 229 if _name_sequence is None: 230 _once_lock.acquire() 231 try: 232 if _name_sequence is None: 233 _name_sequence = _RandomNameSequence() 234 finally: 235 _once_lock.release() 236 return _name_sequence 237 238 239def _mkstemp_inner(dir, pre, suf, flags, output_type): 240 """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" 241 242 names = _get_candidate_names() 243 if output_type is bytes: 244 names = map(_os.fsencode, names) 245 246 for seq in range(TMP_MAX): 247 name = next(names) 248 file = _os.path.join(dir, pre + name + suf) 249 _sys.audit("tempfile.mkstemp", file) 250 try: 251 fd = _os.open(file, flags, 0o600) 252 except FileExistsError: 253 continue # try again 254 except PermissionError: 255 # This exception is thrown when a directory with the chosen name 256 # already exists on windows. 257 if (_os.name == 'nt' and _os.path.isdir(dir) and 258 _os.access(dir, _os.W_OK)): 259 continue 260 else: 261 raise 262 return (fd, _os.path.abspath(file)) 263 264 raise FileExistsError(_errno.EEXIST, 265 "No usable temporary file name found") 266 267 268# User visible interfaces. 269 270def gettempprefix(): 271 """The default prefix for temporary directories.""" 272 return template 273 274def gettempprefixb(): 275 """The default prefix for temporary directories as bytes.""" 276 return _os.fsencode(gettempprefix()) 277 278tempdir = None 279 280def gettempdir(): 281 """Accessor for tempfile.tempdir.""" 282 global tempdir 283 if tempdir is None: 284 _once_lock.acquire() 285 try: 286 if tempdir is None: 287 tempdir = _get_default_tempdir() 288 finally: 289 _once_lock.release() 290 return tempdir 291 292def gettempdirb(): 293 """A bytes version of tempfile.gettempdir().""" 294 return _os.fsencode(gettempdir()) 295 296def mkstemp(suffix=None, prefix=None, dir=None, text=False): 297 """User-callable function to create and return a unique temporary 298 file. The return value is a pair (fd, name) where fd is the 299 file descriptor returned by os.open, and name is the filename. 300 301 If 'suffix' is not None, the file name will end with that suffix, 302 otherwise there will be no suffix. 303 304 If 'prefix' is not None, the file name will begin with that prefix, 305 otherwise a default prefix is used. 306 307 If 'dir' is not None, the file will be created in that directory, 308 otherwise a default directory is used. 309 310 If 'text' is specified and true, the file is opened in text 311 mode. Else (the default) the file is opened in binary mode. 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 __class_getitem__ = classmethod(_types.GenericAlias) 647 648 def _check(self, file): 649 if self._rolled: return 650 max_size = self._max_size 651 if max_size and file.tell() > max_size: 652 self.rollover() 653 654 def rollover(self): 655 if self._rolled: return 656 file = self._file 657 newfile = self._file = TemporaryFile(**self._TemporaryFileArgs) 658 del self._TemporaryFileArgs 659 660 pos = file.tell() 661 if hasattr(newfile, 'buffer'): 662 newfile.buffer.write(file.detach().getvalue()) 663 else: 664 newfile.write(file.getvalue()) 665 newfile.seek(pos, 0) 666 667 self._rolled = True 668 669 # The method caching trick from NamedTemporaryFile 670 # won't work here, because _file may change from a 671 # BytesIO/StringIO instance to a real file. So we list 672 # all the methods directly. 673 674 # Context management protocol 675 def __enter__(self): 676 if self._file.closed: 677 raise ValueError("Cannot enter context with closed file") 678 return self 679 680 def __exit__(self, exc, value, tb): 681 self._file.close() 682 683 # file protocol 684 def __iter__(self): 685 return self._file.__iter__() 686 687 def close(self): 688 self._file.close() 689 690 @property 691 def closed(self): 692 return self._file.closed 693 694 @property 695 def encoding(self): 696 return self._file.encoding 697 698 @property 699 def errors(self): 700 return self._file.errors 701 702 def fileno(self): 703 self.rollover() 704 return self._file.fileno() 705 706 def flush(self): 707 self._file.flush() 708 709 def isatty(self): 710 return self._file.isatty() 711 712 @property 713 def mode(self): 714 try: 715 return self._file.mode 716 except AttributeError: 717 return self._TemporaryFileArgs['mode'] 718 719 @property 720 def name(self): 721 try: 722 return self._file.name 723 except AttributeError: 724 return None 725 726 @property 727 def newlines(self): 728 return self._file.newlines 729 730 def read(self, *args): 731 return self._file.read(*args) 732 733 def readline(self, *args): 734 return self._file.readline(*args) 735 736 def readlines(self, *args): 737 return self._file.readlines(*args) 738 739 def seek(self, *args): 740 return self._file.seek(*args) 741 742 def tell(self): 743 return self._file.tell() 744 745 def truncate(self, size=None): 746 if size is None: 747 self._file.truncate() 748 else: 749 if size > self._max_size: 750 self.rollover() 751 self._file.truncate(size) 752 753 def write(self, s): 754 file = self._file 755 rv = file.write(s) 756 self._check(file) 757 return rv 758 759 def writelines(self, iterable): 760 file = self._file 761 rv = file.writelines(iterable) 762 self._check(file) 763 return rv 764 765 766class TemporaryDirectory(object): 767 """Create and return a temporary directory. This has the same 768 behavior as mkdtemp but can be used as a context manager. For 769 example: 770 771 with TemporaryDirectory() as tmpdir: 772 ... 773 774 Upon exiting the context, the directory and everything contained 775 in it are removed. 776 """ 777 778 def __init__(self, suffix=None, prefix=None, dir=None): 779 self.name = mkdtemp(suffix, prefix, dir) 780 self._finalizer = _weakref.finalize( 781 self, self._cleanup, self.name, 782 warn_message="Implicitly cleaning up {!r}".format(self)) 783 784 @classmethod 785 def _rmtree(cls, name): 786 def onerror(func, path, exc_info): 787 if issubclass(exc_info[0], PermissionError): 788 def resetperms(path): 789 try: 790 _os.chflags(path, 0) 791 except AttributeError: 792 pass 793 _os.chmod(path, 0o700) 794 795 try: 796 if path != name: 797 resetperms(_os.path.dirname(path)) 798 resetperms(path) 799 800 try: 801 _os.unlink(path) 802 # PermissionError is raised on FreeBSD for directories 803 except (IsADirectoryError, PermissionError): 804 cls._rmtree(path) 805 except FileNotFoundError: 806 pass 807 elif issubclass(exc_info[0], FileNotFoundError): 808 pass 809 else: 810 raise 811 812 _shutil.rmtree(name, onerror=onerror) 813 814 @classmethod 815 def _cleanup(cls, name, warn_message): 816 cls._rmtree(name) 817 _warnings.warn(warn_message, ResourceWarning) 818 819 def __repr__(self): 820 return "<{} {!r}>".format(self.__class__.__name__, self.name) 821 822 def __enter__(self): 823 return self.name 824 825 def __exit__(self, exc, value, tb): 826 self.cleanup() 827 828 def cleanup(self): 829 if self._finalizer.detach(): 830 self._rmtree(self.name) 831 832 __class_getitem__ = classmethod(_types.GenericAlias) 833